May 13, 2026 WebhooksDedupeAsync
Build a webhook triage agent
Receive events, deduplicate delivery attempts, run async triage, and expose a trace per webhook.
Webhook delivery is noisy: providers retry, events arrive late, and downstream systems fail. This cookbook builds a triage agent that deduplicates events and runs async work under a trace.
Scenario
A product receives incident webhooks. The workflow deduplicates events, asks an agent to classify urgency, opens a ticket when needed, and records the result.
What you build
- A webhook entry point.
- Event deduplication.
- Async triage with an agent.
- Idempotent ticket creation.
- A trace link returned to the webhook caller or dashboard.
Workflow shape
@workflow
async def triage_webhook(ctx: WorkflowContext, event: WebhookEvent) -> WebhookOutcome:
deduped = await ctx.step(record_event_once, event.provider_event_id, event)
if deduped.already_seen:
return WebhookOutcome(status="duplicate", original_run_id=deduped.run_id)
classification = await ctx.step(classify_incident_event, event)
if classification.priority == "ignore":
return WebhookOutcome(status="ignored")
ticket = await ctx.step(create_incident_ticket_once, event.provider_event_id, classification)
return WebhookOutcome(status="ticket_created", ticket_id=ticket.id)The provider event ID is the key. It protects both dedupe and ticket creation.
Webhook response
Return quickly with a run ID when the provider requires a fast response.
{
"accepted": true,
"run_id": "run_01JWEBHOOK",
"trace_url": "https://app.agnt5.com/runs/run_01JWEBHOOK"
}The trace becomes the operational record for the asynchronous work.
Production checks
- Duplicate provider deliveries return the original run or receipt.
- Ticket creation uses the provider event ID as an idempotency key.
- The trace includes raw event payload, classification, and side-effect receipt.
- Late events are processed according to explicit business rules.
- Failed events can be replayed locally.