Connection URL
SSE format
Each event consists of three lines separated by a blank line:| Field | Description |
|---|---|
id | Unique event ID, used for resume-on-reconnect |
event | Event type, which determines the structure of data |
data | JSON-encoded event payload |
Event catalog
| Event type | Meaning | When it fires | data shape |
|---|---|---|---|
user.message | A user message was sent | After the client POSTs the event | {"content": [{"type":"text","text":"..."}]} |
user.interrupt | The user interrupted execution | When the client sends an interrupt | {} |
user.define_outcome | The user defined an expected outcome | When the client sets a goal | {"outcome": "..."} |
session.status_running | The Session started running | After a message is received and processing begins | {"status": "running"} |
span.model_request_start | Model request started | When the Agent calls the LLM | {"model": "...", "span_id": "..."} |
agent.thinking | The Agent is thinking | During model inference | {"thinking": "..."} |
agent.message | The Agent replied | When the model emits text | {"content": [{"type":"text","text":"..."}]} |
agent.tool_use | The Agent initiated a built-in tool call | When the model decides to call a built-in tool | See “Tool calls” below |
agent.tool_result | Built-in tool execution result | After tool execution completes | See “Tool calls” below |
agent.custom_tool_use | The Agent requested a client-side custom tool | When the model decides to call a custom tool | See “Tool calls” below |
session.status_idle | The Session went idle | When a turn completes | See “status_idle full schema” below |
span.model_request_end | Model request ended | When the LLM call finishes | {"span_id": "...", "usage": {...}} |
session.error | A Session error occurred | On a runtime exception | {"error": "...", "code": "..."} |
terminated | The Session terminated | When the Session closes or times out | {"reason": "..."} |
data JSON also includes these common fields beyond those listed above: id, type, turn_id (omitted for user.define_outcome), session_id, created_at, processed_at, schema_version.
Typical event lifecycle
A complete conversation turn fires events in this order:Tool calls
Built-in tool calls useagent.tool_use. If the call is allowed and executed by the platform, it later has a matching agent.tool_result in the same turn_id.
agent.tool_use key fields:
id of this event uses the evt_ prefix like other events. When evaluated_permission is ask, use this event id as user.tool_confirmation.tool_use_id.
agent.tool_result key fields:
agent.custom_tool_use and are resolved by your application:
id as user.custom_tool_result.custom_tool_use_id.
Sorting advice: Sort by created_at, then by type (tool_use before tool_result), then by id. Do not rely solely on id ordering — the platform-generated tool_result id may sort lexically before the tool_use id.
status_idle full schema
Thesession.status_idle event carries stop_reason, usage, turn_id, and session_id in addition to status:
stop_reason.type is requires_action and event_ids points to the events that need a client response:
stop_reason.type values include end_turn, cancel, max_turns, and error, depending on the scenario.
Reconnect with after_id
A new SSE connection replays all historical events by default. To receive only new events, pass after_id:
EventSource automatically sends Last-Event-ID on reconnect, and the server uses it to deliver incremental events.
For long-running connections, track the last
id you received and use after_id to resume after disconnects.delta_flush_interval_ms
A query parameter that controls how often agent.message deltas are flushed:
50ms. Higher values reduce event frequency and rendering overhead on the client.
curl examples
- Fresh connection
- Resume with after_id
JavaScript EventSource example
Client implementation tips
- Track the last event ID — update it on every event so you can resume after disconnects.
- Concatenate deltas —
agent.messagemay arrive in streaming deltas; assemble them into the full text on the client. - Watch for
terminated— when received, close the connection and stop reconnecting. - Timeout and reconnect — if 30 seconds pass with no event, close the connection and reconnect to avoid silent stalls.
- Filter events — subscribe only to the event types you care about; ignoring span-level events reduces overhead.
FAQ
Q: I’m getting a flood of historical events on connect. How do I avoid this? A: Passafter_id set to the last event ID you processed. The server will only return events after that ID.
Q: Will the SSE connection close on its own? A: When the Session terminates, the server emits a terminated event and closes the connection. The idle timeout depends on Session configuration.
Q: Can I use WebSockets instead? A: Only SSE is supported today. SSE is lighter for one-way push and natively supports reconnection.
Q: If I set delta_flush_interval_ms too high, will events be dropped? A: No. Deltas are batched, not dropped. Final content remains complete.
Next steps
Start a session
Run an agent against an environment.
Permission policies
Control which tool calls run, ask, or deny.
Tools
Equip your agent with built-in, MCP, and custom tools.
Define outcomes
Tell an agent what success looks like.