Webhooks
Webhooks let your systems react to events happening inside Agent Handler. Today Agent Handler emits three events: a Registered User is created, a Registered User is deleted, and a third party sends an inbound webhook that Agent Handler forwards to you. Every outbound webhook is signed, so your endpoint can confirm it came from Agent Handler before trusting the payload.
Outbound webhooks are events from Agent Handler to you, the common case. Inbound webhooks are events from a third party (Slack, Jira, GitHub) to Agent Handler, then forwarded to your outbound webhook so you get one unified event stream.
Outbound webhooks
Setting up a subscription
- Open Connectors → Webhooks.
- Click Add webhook.
- Enter your HTTPS callback URL.
- Select the events to subscribe to (see catalog below).
- Save.
Your endpoint should accept POST requests, parse JSON, and return 2xx on success. A non-2xx response, or a response slower than the timeout, is recorded as a failed delivery (see Delivery and failures).
For local development, webhook.site gives you a temporary URL that captures requests in a browser. Once you’ve confirmed payloads look right, point at your real endpoint.
Event catalog
Agent Handler emits three event types. This table is the complete set.
There are no tool-call, credential, or security-rule webhook events today. Tool-call activity and security violations are visible in the Tool Call Logs and Violations and alerts dashboards, and can be pulled via the logs API.
Payload shape
Every payload shares the same envelope: a hook object with delivery metadata, a data object whose shape depends on the event, and an origin object that is populated only for inbound events.
Verifying the signature
Every outbound webhook is signed with HMAC-SHA256 using a secret you control. The signature is in the X-Webhook-Signature header, hex-encoded. Verify it before trusting the payload, since anyone can POST to a public URL.
Get your signing secret at Webhooks → Verification key. Rotate it from the same page; rotation invalidates all signatures generated with the old key.
The signature is computed over the raw request body exactly as sent. If your framework parses JSON before you see the bytes, configure it to give you the raw body; re-stringifying parsed JSON will produce a different signature.
Delivery and failures
Agent Handler sends each event with a 2-second timeout. A response slower than 2 seconds, a non-2xx status, or a connection error is recorded as a failed delivery.
Failed deliveries are not retried, and there is no replay from the dashboard today. A delivery that fails is not sent again. Build for this:
- Return
2xxas fast as you can and do the real work asynchronously. Holding the connection open to finish processing will blow past the 2-second window and the event is lost. - If you need a guarantee that you’ve seen every Registered User, reconcile against the Registered Users API on a schedule rather than relying on the webhook alone. Treat webhooks as a low-latency signal, not the system of record.
Idempotency
The envelope has no per-delivery unique ID today. hook.id identifies the subscription, not the individual event, so you can’t dedupe on the envelope alone. Because deliveries aren’t retried, duplicates are unlikely, but if you need strict idempotency, derive a key from the event contents, for example hook.event plus data.id plus hook.event_timestamp.
Inbound webhooks
Some Connectors (Slack, Jira, GitHub) emit webhooks to subscribers. Agent Handler can be that subscriber, then forward the event to your outbound webhook as an INBOUND_WEBHOOK_RECEIVED event. You get a single, unified event stream regardless of how many third parties you’re reacting to.
Inbound webhooks are passthrough only. Every inbound subscription must be paired with an outbound subscription that includes INBOUND_WEBHOOK_RECEIVED.
Setup
- Subscribe an outbound webhook to
INBOUND_WEBHOOK_RECEIVED. Add the event to an existing outbound subscription (or create a new one) at Connectors → Webhooks. - Enable inbound webhooks for the Connector. Open the Connector’s detail page; if it supports inbound webhooks, you’ll see a Webhook section. Click Add webhook.
- Connector-specific configuration. Each third party requires different credentials. Slack wants the app’s signing secret; GitHub wants a webhook secret you generate; Jira wants admin access to register the webhook with the third party.
Each Connector’s webhook setup is documented inline in the dashboard. The Slack flow, as a representative example:
- In the Slack app dashboard, copy the signing secret from Basic Information → App Credentials.
- Paste it into the Slack Connector’s webhook field in Agent Handler.
- Agent Handler returns a webhook URL, copy it.
- In Slack, go to Event Subscriptions → Request URL, paste the URL, and select the events you want forwarded.
- Slack verifies the URL automatically. Once verified, events flow Slack → Agent Handler → your outbound endpoint as
INBOUND_WEBHOOK_RECEIVEDpayloads.
Inbound payload shape
For an inbound event, data holds the forwarded third-party body and origin holds the original request Agent Handler received from the third party (method, URL, headers, and body), along with the Connector and Registered User it belongs to. hook.third_party_data_event_type carries the third party’s own event name when the Connector can determine it.
Next
Tag tool calls with session or workflow metadata using Custom headers for MCP.