Skip to main content
A session is one task run by an agent. Twelve methods, one per route; objects parse with the core SessionSchema. API detail: Sessions, Events.

create

POST /v1/sessions. Creates and starts, with the initial message, in one call.
string
required
The agent to run.
string
required
The initial instruction.
number
Pin an exact version; default is the agent’s current one.
string
Context-window selection.
integer
Spend cap for this session, integer micro-USD.
string
The persona this task acts as — an idn_ id or the persona’s name. Answered as identity_id on the session.
object
JSON schema the final document must match.
boolean
Refuse a would-be clean ending that produced no document matching output_schema.
string
Set when a deployment fired this run.
object
Arbitrary key/value pairs.

list

GET /v1/sessions. SessionFilter adds agent_id, status, stop_reason, deployment_id, parent_session_id and handoff_from to the page query. handoff_from is a session id and lists the top-level sessions that session handed work to, newest first. stop_reason is how you find the sessions a person has to answer. A session held on an ask tool call is status: "idle" like every finished one — what separates it is stop_reason: "awaiting_approval", with the blocked call in pending_actions:
stop_reason: "awaiting_answer" is the same query for the sessions asking you a question rather than for permission — see answer. "budget_paused" is the same question asked about money, and "error" about failure.

get

GET /v1/sessions/{id}.

send

POST /v1/sessions/{id}/messages. Sending to a running session is refused with session_running unless you say which of two things you mean: interrupt: true steers it mid-run; queue: true holds the message in the session’s inbox and it becomes the input of the turn that follows. On an idle session queue is a plain send. The two together are validation_failed.

handoffs

POST /v1/sessions/{id}/handoffs. Hands message from session {id} (the sender, a top-level session of yours) to each named agent, starting a top-level session per target marked metadata.handoff = { from_session, from_agent, key, depth }. Who may be named is the sender’s agent’s handoffs policy — the same admission the model’s send_to_agent goes through. A target that is refused is a row in refusals, not a thrown error; the batch resolves for the rest.
The work a session handed out is client.sessions.list({ handoff_from: root.id }); the work it delegated in-thread is threads.

threads

GET /v1/sessions/{id}/threads. The child sessions a coordinator delegated from {id} with send_to_agent wait: true — parent_session_id is {id}, and they ran on its budget. A handoff (wait: false, or handoffs above) is not here: it is a top-level session of its own, found by handoff_from.

interrupt

POST /v1/sessions/{id}/interrupt. Stops the current turn; an optional message tells the agent why.

confirmTool

POST /v1/sessions/{id}/tool_confirmations. Answers a session paused on a gated tool call. It carries a verdict and no payload, so it cannot answer a question — that is answer, below, and this route refuses a kind: "question" row rather than folding “allow” back at an agent that asked for a mailbox address. scope says how far the allow reaches. Omitted (or "call") it approves this one call. "session" grants the call’s tool for the rest of that session — every later call to the same tool name runs with no confirmation — and nothing else: one tool name, one session, gone when the session ends, never written onto the agent, and never valid on a deny. For a call through the tool invoker (tools_execute) the granted tool is the one named in its tool argument: the same target runs with no confirmation, any other target through the invoker is still confirmed.

answer

POST /v1/sessions/{id}/answers. Answers a session parked on a question it asked you. A session with stop_reason: "awaiting_answer" carries a kind: "question" row in pending_actions, holding the sentence the agent wrote and one to three fields. answers is keyed by those fields’ keys; a value is a string, or an array of them for a multiple choice:
Every key the question asked for must be present — except one the question marked optional, which is answered by leaving the key out entirely rather than by sending an empty string — and no other, so a wake can never find the thing the agent stopped for still missing. A choice answer is not limited to that field’s options: other defaults to true precisely so a person can say what the agent did not think of.

answer

POST /v1/sessions/{id}/answers. Answers a session parked on a question (stop_reason: "awaiting_answer"), keyed by the question’s fields[].key. A sibling of confirmTool, not a variant: a held tool call takes a verb, a question takes a payload.

cancel

POST /v1/sessions/{id}/cancel. Terminal — the session cannot be resumed.

setBudget

PATCH /v1/sessions/{id}/budget, body { cap_micro_usd }. Raise only — a cap at or below what is already consumed would be retroactive and is refused. Integer micro-USD.

events

GET /v1/sessions/{id}/events — the same log client.stream serves, read as pages. after_seq is exclusive, so polling with the last seq you saw never re-reads it.