Writes events to a session: user messages, interrupts, tool approvals, and function result backfills. The request body contains only the top-level input field, which is an array of events (length 1-50).
Prerequisites
A session must already be created. For details, see Create Session.
Endpoint
POST /sessions/{session_id}/events
The request body contains only one top-level field input, which is an array of events (length 1-50). Each event must contain at least role and type.
Request body structure
Client event types
type | role | Required fields | Purpose |
|---|---|---|---|
message | user | content (array) | Sends a user message, triggering the agent to enter running state |
interrupt | user | role, type | Interrupts the current turn; the session returns to idle. Optional top-level session_thread_id (in multi-agent scenarios, targets a specific sub-thread) |
tool_approval_response | user | content (exactly one data block) | Responds to a tool approval. data must contain batch_id (matches the tool_approval_request batch_id), call_id (the tool call ID to rule on), and result (allow | deny). Optional deny_message (only for deny, passed back to the model as tool output). batch_id and call_id together identify an approval (composite identity, both non-empty, minLength: 1). Multiple tool_approval_response in the same request must belong to the same batch_id. Tool approval is only supported on the main agent, not sub-agents |
function_call_output | tool | content (single data block with call_id + output) | Backfills the result of a self-hosted function. Optional top-level is_error and session_thread_id |
tool_call_output | tool | content (single data block with call_id + output) | Backfills the result of a self-hosted platform built-in tool. Same structure as function_call_output; optional is_error and session_thread_id |
During a pending tool approval, mixed inputs are handled on two separate branches and neither approval takes effect (the current batch still exists,
pending_call_ids remain unchanged): (1) sending tool_approval_response together with a plain message in the same batch results in a pending_tool_approval_unresolved event/terminal state; (2) sending tool_approval_response together with interrupt is rejected due to control-message conflict, with error code invalid_tool_approval. Neither is a synchronous 4xx of this POST; observe via the SSE event stream or GET /events. interrupt and a plain message may be sent together in the same request (semantics: end the current approval batch first, then start chatting).ContentBlock: message content
content is an array of ContentBlocks. Each block is distinguished by type and must use exactly one carrier.
type | Mutually exclusive fields | Description |
|---|---|---|
text | text | Plain text |
image | image_url | file_id | Image, enters the model's vision channel: public URL or uploaded file ID (dereferenced to a temporary URL, rendered for this turn only, not persisted) |
video | video_url | file_id | Video, enters the model's vision channel: public URL or uploaded file ID |
audio | data + format | file_id | Audio: only appears in server-side pushes/responses (as a tool output attachment); cannot be sent as client input |
file | file_id + filename | File: uploaded file ID, requires filename (used for the sandbox path and file manifest). Base64 input is not supported. The file is materialized to the session sandbox by the platform, and the model reads it on demand. file_id is the persistent source of truth |
data | data (object) | Structured data (JSON). Server-side status events also use this carrier |
refusal | refusal | Model refusal message; only appears in server-side pushes |
Example: send a text message
Response
200 OK means the events were accepted (enqueued). It does not mean the agent has started processing or that an approval ruling has taken effect — especially for tool_approval_response, acceptance does not mean the approval has been applied. Observe actual processing results via the SSE event stream or GET /events.
Response fields
| Field | Type | Description |
|---|---|---|
data | array<object> | Array of echoed accepted events, aligned with the request input order; echo only means enqueued, not that it has been processed or that a ruling has taken effect |
data[].object | string | Object type, always message |
data[].id | string | Server-assigned message ID, format msg_<ULID> |
data[].created_at | string | Server write time, ISO 8601 |
data[].role | string | Event role, echoes the user (or tool) from the request |
data[].type | string | Event type, echoes the type of the sent event (e.g., sending message echoes message; sending tool_approval_response echoes tool_approval_response), not always message |
data[].status | string | Write status, always completed |
data[].content | array<object> | ContentBlock array, same structure as the request |
request_id | string | Unique identifier for this request |