The session object
string
Unique id (e.g.
ses_01H...).string
The agent this session runs.
integer
The pinned agent version.
string | null
The deployment that created this session, if any.
string | null
The computer this session provisioned for its filesystem and shell tools, or
null when its toolset needs none. It is a real computer — it lists under GET /v1/computers as session {id} and takes exec, snapshot and fs/* — but it belongs to the session: DELETE on it is refused while the session can still run, and it is destroyed when the session ends.string | null
Why the last turn yielded control — see below. Read it whenever the session is not
running; do not treat idle as success.string
Effective completion window for this session.
integer
Per-session cap, in micro-USD. Always set: it falls back to the agent’s
budget.max_task_micro_usd.integer
Cumulative spend on this session so far, in micro-USD.
object
Cumulative token counts across five billed tiers.
object[]
What the session is parked on. One array, two kinds of row, distinguished by
kind — which defaults to "tool", so a row without it is a held tool call.A kind: "tool" row is resolved with tool confirmations and accompanies stop_reason: "awaiting_approval". A kind: "question" row is resolved with answers and accompanies awaiting_answer. A session parked on both reports awaiting_approval and carries both.object | null
JSON Schema the final result must satisfy, inherited from the agent unless overridden at create.
object | null
The typed result, populated when the session goes idle satisfying
output_schema. See Structured outputs.object
Arbitrary key/value pairs.
string | null
When the session first started running.
string | null
When the session reached a terminal state (
completed, failed, cancelled).string
Creation timestamp.
Lifecycle
A session moves through thesestatus values:
Whenever a turn yields control,
stop_reason is set to one of:
idle is resumable and completed is terminal — both are non-running. Always branch on stop_reason rather than treating idle as success. Anything worth keeping is written to Files; scratch work stays in the sandbox.Create a session
POST /v1/sessions → 201 Created. Creates and starts the session. Inherits the agent’s configuration; you may override the window, set a per-session budget, and provide an initial message.
string
required
The agent to run.
integer
Pin a specific version. Defaults to the agent’s
current_version.string
required
Initial input. Starts the first turn immediately.
string
Override the completion window (
immediate | priority | loose).integer
Per-session cap in micro-USD. Work pauses at the cap.
string
Attribute this session to a deployment, so its spend shows under that schedule in the ledger. Defaults to
null.string
The persona this session acts as — an
idn_ id or the persona’s name. The agent must hold a grant to it. Defaults to null.object
JSON Schema the final result must satisfy. Overrides the agent default. See Structured outputs.
boolean
When
true, a session that cannot produce a conforming object goes idle with stop_reason: "error". Overrides the agent default; requires an output_schema on the session or the agent.object
Arbitrary metadata.
Retrieve a session
GET /v1/sessions/{id} → 200 OK with the current status, stop_reason, and usage.
Response
List sessions
GET /v1/sessions → 200 OK, cursor-paginated. Filter with ?agent_id=, ?deployment_id=, and ?status=. See Pagination.
Send input
POST /v1/sessions/{id}/messages → 202 Accepted. Sends input to a session and produces events. The reply is the acceptance, not a session snapshot: the turn has not run yet.
string
required
The message text to send.
boolean
When
true, steer a running session in one call: the current turn stops at its next commit boundary and the new message is applied. This is the common case. Defaults to false.string
Accepted and ignored. De-duplicate a retried send with the
Idempotency-Key header — see Idempotency; this body field does nothing.interrupt, sending to a running session returns 409 with code session_running — interrupt first, or set interrupt: true.
Response
accepted_seq is the session’s event high-water mark at the moment the send was accepted: every event this turn produces has seq > accepted_seq. That is what to wait on — poll GET /v1/sessions/{id}/events?after_seq=143, or wait for the session’s last_seq to pass it. Do not wait on status alone: the send returns before the first event is committed, so a status read taken immediately after can still describe the previous turn.
Interrupt a session
POST /v1/sessions/{id}/interrupt → 200 OK. Stops the current turn at its next commit boundary, preserving history and the sandbox, and returns the session idle with stop_reason: "interrupted". An optional message is applied as the next input. Unlike cancel, the session stays resumable.
string
Optional input to apply after interrupting.
Response
Respond to a tool confirmation
When a tool withpermission: "ask" runs, the session goes idle with stop_reason: "awaiting_approval" and the blocking calls appear in pending_actions. Resolve each with:
POST /v1/sessions/{id}/tool_confirmations → 202 Accepted, carrying the full session object with the resolved call removed from pending_actions. Like a send, the reply is the acceptance: the tool has not run yet.
string
required
allow to run the tool, or deny to reject it.string
On
deny, fed back to the model as the tool result.Response
Answer a question
An agent that needs something from a person parks the turn: the session goes idle withstop_reason: "awaiting_answer" and the question appears in pending_actions as a row with kind: "question", carrying a prompt and one to three fields. Answer it with:
POST /v1/sessions/{id}/answers → 202 Accepted, carrying the full session object with the answered question removed from pending_actions. Scope sessions:write.
string
required
The id from
pending_actions[].tool_call_id on the row you are answering.object
required
One entry per field, keyed by
fields[].key. A string, or an array of strings for a choice field with multiple: true. Every field must be answered.tool_confirmations, not a variant of it. A held tool call is answered with a verb and no payload; a question is answered with a payload and no verb. Posting an answer for a kind: "tool" row is rejected with validation_failed (400) naming tool_call_id, and points you at the other route.
A choice field accepts anything the person types unless it sets other: false, in which case only its listed options are accepted. The values are read back by the model as words, so send the option text and not an index.
Response
Raise the budget
PATCH /v1/sessions/{id}/budget → 200 OK. Scope sessions:write.
A session that hit its cap stops with stop_reason: "budget_paused". Raise the cap and it becomes resumable.
integer
required
The new per-session cap, in micro-USD.
budget_micro_usd.
Errors — validation_failed (400) for a cap that is not a raise; not_found (404); insufficient_credits (402) when the organization cannot cover the new cap.
Cancel a session
POST /v1/sessions/{id}/cancel → 200 OK. Terminally stops the session and moves it to cancelled. Any in-flight turn is stopped. Use interrupt instead if you want to keep the session resumable.
Response
Stream events
List and stream a session’s events, resumable by
seq.