Skip to main content
Once a session exists, use these operations to drive, read, control, or remove it. See Sessions for creating one and its lifecycle.

Retrieve a session

List sessions

Results are paginated. Filter by agent or by deployment_id (each scheduled fire is a session tagged with its deployment), and sort by creation time. Each response includes has_more and a next_cursor; pass next_cursor back as after to fetch the next page. The cursor is null at the end.

Sending input

You drive a session by sending it input. Every input is recorded on the event stream, and if the session is idle it wakes into running. There are four input types:
Stream the session to watch it react to input — reconnect with fromSeq to resume from the last seq you handled without gaps or duplicates. See Events & streaming.

Interrupt and redirect in one call

Inputs can be batched so they land atomically. The common case is steering a running agent: send an interrupt together with a new message. The agent wraps up the current turn cleanly at the next commit boundary — the interrupted turn ends with stop_reason: "end_turn" — and then picks up the redirect.

Awaiting-approval loop

When the agent calls a tool governed by an ask policy, the runtime does not run the tool. Instead the session goes idle with stop_reason: "awaiting_approval" and exposes the waiting call(s) on pending_actions[]. You resolve each one with an allow/deny confirmation; once the last pending action is answered, the session resumes automatically.
Branch on kind, not on name, and not on stop_reason alone. pending_actions[] holds both kinds of park, and a session that stopped on a mix of the two reports awaiting_approval while still carrying question rows — awaiting_answer means every parked row is a question. A loop that sends every entry to tool_confirmations gets a validation_failed on each question, and one that reads only the stop reason silently never asks them.
A held tool consumes no budget while it waits — a session can sit on a confirmation for hours at storage cost only. See Policies for how a tool resolves to ask, and Events & streaming for the tool.confirm event shape.

Awaiting-answer loop

The mirror of the loop above, for the park the agent starts itself. When an agent calls ask_operator the turn stops the same way — idle, rows on pending_actions[], no budget burning — but the row is tagged kind: "question" and carries a question object: the sentence the agent wrote, and one to three fields to fill in.
Three rules a surface that renders a question has to keep:
  • Render from question, never from args. They hold the same content — args is what the model called with and what replays byte-identically — but question is the shape a renderer reads, and it is the one that will keep its meaning if the tool’s arguments ever change.
  • Every field must be answered, with a non-empty value: an agent that could proceed without one of them would not have asked it. A partial answer is validation_failed (400) naming answers.<key>. The escape a person needs is the free-text arm, which is on by default.
  • A choice answer is the option’s words, never an index. The model reads them back as prose. Send string[] for a multiple: true field and a plain string for everything else; the route enforces the arity.
The answer folds into the next turn as the result of the call that asked, carrying the question with it — so the model sees what it asked and what came back, not a bare set of words against an id it no longer remembers.
Not every agent can ask. ask_operator is offered only on a harness that can hold a call open for a person — see Harness capabilities — and an agent whose toolset denies it cannot park this way at all.

Approver and timeouts

Each resolved confirmation records who answered it — the approving principal (a user or API key id) is written to the event and audit trail alongside the decision and any deny reason. This is what lets you prove, after the fact, that a payout or destructive action was signed off by a person rather than silently auto-run. An ask tool does not wait forever. The governing policy sets an ask_timeout_seconds and an on_timeout disposition; if no one answers in the window, the runtime applies it:

Interrupting

A running session must be interrupted before you can update its agent, archive it, or delete it. An interrupt is delivered as an event and stops the current turn at the next commit boundary — you lose at most one turn, never the run. On its own, an interrupt lands the session at idle with stop_reason: "interrupted".

Archiving

Cancelling stops a session and releases its sandbox while preserving its record and its events.
CLI
A session cannot be archived or deleted. There is no vetta session archive and no vetta session delete, and no DELETE /v1/sessions/{id} route behind them — cancel is the only terminal operation. A session’s record and event history are permanent; the sandbox and the files scoped to it are released on cancel.Files the session produced go with the sandbox. Files promoted with publish_file or uploaded to the Files API are organization-scoped and survive. Skills, deployments, webhooks, identities and vaults are independent resources and are unaffected. Publish anything you need to keep before cancelling.

Next: events & streaming

The resumable event model behind every session.