Building an Ambient Agent
End-to-end reference architecture for a webhook-triggered ambient agent with cross-system orchestration.
This guide walks through the full architecture of a realistic ambient agent — from webhook listener to notification with action buttons. It’s a reference architecture showing how every piece fits together.
The example: an Incident Response Agent that listens for PagerDuty incidents, classifies severity with an LLM, creates a tracking issue in Jira, and notifies the on-call engineer with options to acknowledge, escalate, or add a note.
The YAML and configurations here are pseudocode — realistic enough to teach the patterns, but not copy-pasteable into Agent Studio. Adapt them to your actual system’s API.
In practice, most of these components are configured through the Agent Studio UI — not written as code. We’re showing code representations here because it’s the clearest way to illustrate the full configuration in a document. When you build, you’ll fill in these same fields through the visual editor.
In Agent Studio, you create an ambient agent by setting a plugin’s Trigger Type to System. See Ambient Agents for the conceptual overview.
Architecture Overview
Component count: 2 connectors, 3 HTTP actions, 1 compound action (with switch, try-catch, LLM classification, and notify), 1 webhook listener, 1 plugin with system trigger.
Step 1: Connectors
Two external systems, two connectors.
Step 2: HTTP Actions
Three actions across the two systems.
Acknowledge PagerDuty Incident
Add Note to PagerDuty Incident
Create Jira Issue
Step 3: Compound Action
This is the core orchestration. It receives the webhook payload, classifies the incident, routes by severity, creates a Jira issue for high/critical incidents, and notifies the on-call engineer.
What’s happening in this compound action
-
LLM classification —
generate_structured_value_actionreturns structured JSON with severity, reasoning, and recommended action. The schema guarantees the output shape. -
Switch routing — Low severity gets auto-triaged (note + early return). Everything else goes through the full flow.
-
Jira issue creation — wrapped in
try_catchso a Jira failure doesn’t break the whole flow. On failure, a PagerDuty note is added instead. -
LOOKUP for priority mapping — converts our severity labels to Jira priority names.
-
User resolution —
mw.get_user_by_emailconverts the assignee email to a Moveworks user object (required fornotify). -
Notify with 3 action button types:
system_action— triggers another action (escalate)conversation_action— starts a conversational process (collect a note from the user)content_action— displays a clickable link (view Jira issue)
Step 4: Webhook Listener
The listener receives PagerDuty webhook events and routes them to the plugin.
PagerDuty sends the signature in the format v1=<hex_digest>. Configure the signing secret in the listener security settings to verify webhook authenticity.
For testing, you can use an unsecured listener (no signature verification). For production, always enable signature verification.
Step 5: Plugin
Webhook data is accessed via parsed_body in the plugin input mapping. Inside the compound action, these values are available as data.<input_arg_name>.
Step 6: Testing
-
Test HTTP actions individually — use the Test button to verify each PagerDuty and Jira action works with sample input.
-
Test the compound action — use the Test button with sample input args mimicking the webhook payload:
-
Test the webhook end-to-end — send a test payload to your listener URL:
For detailed testing and error handling guidance, see Testing & Error Handling.
Key Takeaways
Variations
Scheduled instead of webhook: Replace the webhook trigger with a scheduled trigger that polls PagerDuty for open incidents on an interval. Test the compound action directly using the Test button since you can’t manually fire a schedule.
Approval before escalation: Instead of a system_action button for escalation, use mw.create_generic_approval_request to require manager approval before escalating. See Built-in Actions.
Multiple notification targets: Use mw.batch_get_users_by_email to resolve multiple users, then use a for loop inside the compound action to send individual notifications. Results come back in input order.
Bi-directional sync: When the Jira issue is resolved, fire a second webhook-triggered plugin that resolves the PagerDuty incident. Two plugins, two listeners, shared connectors.