Skip to content

Sessions

A suspended session has no runner but still answers reads and records writes; sessions.resume or sending a turn starts it again

Not in the public code yet: launch blocker 4 (API on a self-hosted instance). See API overview.

A session id is cs_ followed by 16 characters. Fields of the Session object: API schema.

Status

statusMeaning
startingThe runtime is starting. runtime.starting events give the phase: computer, then agent
runningA turn is running
waitingAn ask is open
idleNo turn is running
suspendedNo runner holds the session. The host answers reads and records writes

Each change is a session.status_changed event with from and to.

Create and list

HTTP only: POST /sessions with a CreateSessionBody, and GET /sessions.

{"input":"Run the test suite and fix what fails","title":"Fix tests","mode":"acceptEdits","metadata":{"ticket":"ENG-123"}}

Every field is optional (API schema). id is a session id chosen by the client; input is the first message. Accepted values for model, effort, speed and mode are in the session’s capabilities.

Read

sessions.get (GET /sessions/{id}) returns the Session, including the active turn id, queued turns, open asks, running subagents and lastSeq. minSeq waits for the journal: Session journal.

Attach

sessions.attach (WebSocket only) subscribes the connection to the session’s events. It returns the session and its capabilities: models with their effort levels, permission modes, and features.

{"jsonrpc":"2.0","id":1,"method":"sessions.attach","params":{"sessionId":"cs_0123456789abcdef","tailTurns":3,"deltas":true}}
ParamMeaning
afterReplay events with seq greater than this, then follow live
tailTurnsReplay the last 1 to 50 turns instead. earlierTurns in the result holds the turns before them
NeitherLive events only
deltasAlso send delta notifications (text as it is written)
resumeStart the runtime if the session is suspended
readOnlyRefuse writes to this session on this connection (forbidden, reason: "read_only")
RelatedUse
/connect?attach=<sessionId>&tailTurns=3&deltas=1Attaches in the connection URL. The server answers with a sessions.attached notification carrying the same fields, or an error
sessions.detachEnds the subscription
ErrorCause
too_many_attachedThe connection already holds 20 attached sessions
too_far_behindSee Events

Update

sessions.update (PATCH /sessions/{id}) changes any of title, model, effort, speed, mode, archived and metadata. It returns the session and a seq.

{"jsonrpc":"2.0","id":2,"method":"sessions.update","params":{"sessionId":"cs_0123456789abcdef","mode":"plan","metadata":{"ticket":"ENG-124"}}}
ItemRule
metadataKeys (up to 40 characters) are merged one by one. Values are strings of up to 500 characters, or null
session.updated eventchanges maps each changed field to {from, to}. A metadata key is metadata.<key>
Model the harness does not acceptinvalid_request with field: "model". The session stays on its model

Compact

sessions.compact (POST /sessions/{id}/compact) queues a compaction as a turn and returns the same result as turns.send.

instructions (up to 10,000 characters) is passed to the harness’s /compact command. The session.compacted event gives beforeTokens, afterTokens and auto (true when the harness compacted on its own). See Context and compaction.

Suspend

sessions.suspend (POST /sessions/{id}/suspend) stops the session’s runner. The journal and workspace stay on the computer.

State when calledResult
IdleSuspends
A turn is waiting on an askThe turn is interrupted, then the session suspends
A turn is running and no ask is open409 session_busy. Interrupt first
ifIdle: true and the session is not idle, or has running subagents or queued turnsThe session, unchanged
Already suspendedThe session, unchanged

Suspending cancels queued turns, stops running subagents, closes open asks as interrupted, and records runtime.suspended with reason: "requested". The other reasons are idle and lost.

Resume

sessions.resume (POST /sessions/{id}/resume) starts the runtime of a suspended session and returns at once; runtime.starting and runtime.connected events follow. On a session that is not suspended it returns the session unchanged. Sending a turn to a suspended session also starts it.