Sessions and runs
A session is an append-only event log. A run is one pass of the engine over it. Everything you can observe about an agent is an event.
A session is one unit of work: a conversation, a ticket, a background job. It belongs to a workspace, binds an agent version at creation, and holds an append-only log of everything that happened.
A run is one pass of the engine over that log. Appending user input starts a run; the run appends its own events as it goes and ends in exactly one terminal event.
The distinction matters because a session outlives its runs. A run can fail, be cancelled, or lose the connection you were watching it on, and the session is still there with its log intact.
Creating a session
{
"agent_id": "…",
"display_name": "ticket-4192",
"vault_ids": ["…"]
}
agent_iduuid
The agent to run. Its newest live version is bound now and never re-bound.
uuiddisplay_name?string
A human label, up to 200 characters. Empty when omitted.
stringvault_ids?uuid[]
Vaults this session may draw tool credentials from — up to 10, each a live vault in the same workspace.
uuid[]The response carries the session and its first session token, shown once.
Two credentials, two jobs
| API key | Session token | |
|---|---|---|
| Scope | A workspace | One session |
| Carries | The permissions it was minted with | No permissions at all |
| Lives | On your server | Wherever you need it — a browser tab, a worker |
| Expires | When you revoke it, or at expires_at |
At session_token_expires_at |
A session token can read its own session, append input to it, and register clients on it. It cannot list sessions, create one, or touch anything else in the workspace — so handing one to a front end gives that front end exactly one session and nothing more.
Mint more of them as you need them:
POST /v1/sessions/{session_id}/tokens
The event log
Every event carries a sequence number, and the log is the whole truth about a session. Runs are events, messages are events, tool calls and their results are events, a client joining is an event.
GET /v1/sessions/{session_id}/events # paged, newest first by default
GET /v1/sessions/{session_id}/events/stream # SSE, tail and resume
POST /v1/sessions/{session_id}/events # append user input, starting a run
POST /v1/sessions/{session_id}/cancel # ask the current run to stop
See Streaming events for the tailing and resumption rules, and the event reference for every kind.
What a run touches
When a run is claimed, the engine is handed three things, all scoped to that run alone:
The committed log
The engine rebuilds its state from the events already stored, so a run that follows a failed one starts from what actually happened, not from what the previous attempt thought was happening.
A model proxy binding
A URL and a run token, minted fresh at claim time. Your provider key is never handed to the engine — the proxy holds it. A stale attempt’s token stops working the moment the run is re-claimed.
A tool broker binding
A URL, a run token, and the list of server names the bound version grants. Never credentials, never upstream URLs, never policy — the broker resolves all three itself when a call arrives.
Terminal states
| Event | What it means |
|---|---|
run_completed |
The model finished its turn with nothing left to do. |
run_failed |
The run stopped on an error; error carries the text. |
run_cancelled |
A cancel request was honored. |
A session with no run in flight is idle, not finished. Append more input and a new run starts against the same log.