AI Automation · Webhooks
See Webhooks (global) → for signing, retry, idempotency.
Event catalog
| Event | Fires when | data keys |
|---|---|---|
flow.run.started | Run transitions from pending to running | runId · flowId · flowSlug · trigger · input |
flow.run.succeeded | Run completed successfully | runId · flowSlug · status · finishedAt · steps[] |
flow.run.failed | Run failed | runId · flowSlug · failedStepId · errorMessage |
flow.run.awaiting_approval | Run paused at a human_approval node | runId · stepId · actionLabel · proposedAction |
generation.started | An llm_step started inference | runId · stepId · model |
generation.completed | An llm_step completed | runId · stepId · tokens · inferenceMs |
generation.failed | An llm_step failed (after retries) | runId · stepId · errorMessage |
conversation.started | New conversation created | conversationId · agentId · context |
conversation.message | Any message posted to a conversation | conversationId · messageId · role · content |
conversation.completed | Conversation marked closed | conversationId |
agent.tool_called | An assistant message requested a tool call | conversationId · messageId · toolCallId · slug · input |
eval.completed | An eval suite completed (advanced feature) | evalId · passRate · summary |
incident.fired | An automation-detected incident fired | incidentId · severity · summary |
incident.refired | Same incident fired again within suppression window | incidentId · count |
incident.acknowledged | Someone acked an incident | incidentId · actorUserId · note |
incident.resolved | Incident resolved | incidentId · resolvedBy · resolution |
incident.escalated | Incident escalated to next tier | incidentId · escalatedTo |
incident.auto_resolved | Self-resolved without action | incidentId |
digest.delivered | Scheduled digest delivered | digestId · channel |
digest.failed | Digest delivery failed | digestId · error |
webhook.test | Test event | source: "test" |
Example: flow.run.succeeded
{
"id": "evt_01HXY...",
"event": "flow.run.succeeded",
"occurredAt": "...",
"orgId": "...",
"data": {
"runId": "run_01HXY...",
"flowId": "flw_01HXY...",
"flowSlug": "ticket-triage-v1",
"status": "succeeded",
"trigger": "webhook",
"finishedAt": "...",
"steps": [
{ "nodeId": "classify", "type": "llm_step", "output": { "parsed": { "category": "...", "urgency": 5 }, "model": "quantum-ai:default", "inferenceMs": 1250 } },
{ "nodeId": "page_oncall", "type": "http_sink", "output": { "statusCode": 200 } }
]
}
}Example: agent.tool_called
{
"id": "evt_01HXY...",
"event": "agent.tool_called",
"occurredAt": "...",
"orgId": "...",
"data": {
"conversationId": "cnv_01HXY...",
"messageId": "msg_01HXY...",
"toolCallId": "tc_01HXY...",
"slug": "list_recent_transactions",
"input": { "customerId": "cus_01HXY...", "limit": 30 }
}
}Your service receives this, executes the tool, posts the result back via POST /api/conversations/{id}/messages with role: tool.
Register
POST
/api/webhooks{
"url": "https://your-app.example.com/webhooks/ai-automation",
"events": ["flow.run.succeeded", "flow.run.failed", "agent.tool_called"],
"silenceWindowSec": 60,
"dedupKey": "${data.runId}"
}Per-subscription dedupe + silence
AI Automation webhook subscriptions support:
| Field | Purpose |
|---|---|
silenceWindowSec | Suppress duplicate events with the same dedupKey within this window (0–86400 sec). |
dedupKey | Template over data — events with the same evaluated key collapse. |
Use for noisy events like conversation.message where you'd rather get one event per conversation per minute than per message.
Auth header
Same as Orchestration — Bearer secret in Authorization:
Authorization: Bearer qe_whsec_...
X-Quantum-Event: flow.run.succeeded
X-Quantum-Delivery: whd_01HXY...