Skip to main content
Instead of polling GET /sessions/{id} for the result of a turn, you can include a webhook field in your POST /sessions/{id}/messages request body. When the agent turn completes (successfully, with an error, or on cancellation), the server delivers a WebhookPayload to your URL.

Complete example


WebhookSpec

Fields you include in the webhook property of a MessageRequest.
string
required
The URL the server will POST the WebhookPayload to after the turn completes.
string | null
default:"null"
When set, the server includes an Authorization: Bearer <token> header in the delivery request. Use this to authenticate incoming webhook calls on your end.
boolean
default:"false"
When true, the full conversation history is included as the messages field in the WebhookPayload. Useful if you want the entire transcript without making a separate GET /sessions/{id}/messages call.

WebhookPayload

The JSON body the server POSTs to your webhook URL after the turn completes.
string
required
The session UUID that completed the turn.
string
required
Final status of the turn: "idle" on success or "error" on failure.
ChatMessage | null
The agent’s response message. Populated when status is "idle".
string | null
Error message from the agent. Populated when status is "error".
ChatMessage[] | null
Full conversation history for the session. Only included when include_messages was true in the WebhookSpec. null otherwise.
TraceMetrics | null
Turn metrics from the agent runtime. Included when the runtime has tracing enabled; null otherwise.

TraceMetrics

Metrics collected from the agent runtime and attached to the webhook payload when available.
string | null
Trace identifier for this turn. null if tracing is not enabled.
float
Total wall-clock time for the turn, in seconds.
number
Total number of tokens consumed during the turn across all model calls.
boolean
true if the turn encountered an error, even if it was partially handled.

Delivery behavior

  • Webhooks are delivered asynchronously after the turn completes. Delivery does not block the turn itself or affect the session state.
  • Each delivery attempt uses a 10-second timeout.
  • If delivery fails — due to a network error, a non-2xx response, or a timeout — the failure is logged but does not affect the turn result. The session state remains unchanged and no retry is attempted.
  • When token is set, the delivery request includes an Authorization: Bearer <token> header.
If you need guaranteed delivery, poll GET /sessions/{id} with wait=true as a fallback in case your webhook endpoint is temporarily unavailable.