Skip to content

Events

A session's events are numbered by seq from 1 with no gaps; read them over HTTP or follow them live over WebSocket

{"id":"ev_0123456789abcdef","seq":412,"createdAt":"2026-01-01T12:00:00.000Z","sessionId":"cs_0123456789abcdef","turnId":"tn_0123456789ab","actor":{"id":"usr_...","name":"Ada","via":"opc","client":"opc/0.1.0"},"type":"message.received","data":{"input":"Add a test for the empty case","ifBusy":"steer","delivery":"steered","interruptedTurnIds":[],"declinedAskIds":[]}}

actor is who caused the event (via is slack, opc, dashboard or api), or null. Event types and their data fields: API schema. A client must ignore types it does not know.

Read a range

events.list (GET /sessions/{id}/events) returns events in seq order. To follow a session over HTTP, loop on it with after and waitMs.

GET /sessions/cs_0123456789abcdef/events?after=400&limit=100&types=turn.*,ask.opened
ParamMeaning
afterReturn events with seq greater than this. Default 0, the start of the journal
limit1 to 500 events. Default 100
tailTurnsStart at the last 1 to 50 turns instead; earlierTurns in the result holds the turns before them. Cannot be combined with after
turnIdOnly events of this turn
typesA comma-separated list of types. A trailing * matches a prefix
waitMsWhen there is nothing after after, wait up to this long (at most 60,000) for an event

The result is events, earlierTurns, lastSeq (the journal’s last seq) and hasMore.

hasMoreNext after
trueThe seq of the last event returned
falselastSeq. With a filter, the page may be shorter than the range it covered
ErrorCause
409 cursor_aheadafter is beyond the journal’s last seq: the journal’s epoch changed. See Session journal

Follow live

Attach over WebSocket. Each event arrives as an event notification whose params is the event:

{"jsonrpc":"2.0","method":"event","params":{"id":"ev_...","seq":413,"type":"turn.steered","...":"..."}}

Order on one connection:

  • Events of a session arrive in seq order, each once.
  • The response to sessions.attach arrives before any replayed event.
  • The response to a write arrives before any event of that session the write caused.

When the whole connection closes, reconnect and attach with after set to the last seq processed. A runner starting or stopping does not interrupt the subscription.

ErrorCauseWhat to do
too_far_behindAttach with after more than 10,000 events behindRead the gap with events.list first, or attach with tailTurns

Acknowledge

Send sessions.ack notifications as events are processed:

{"jsonrpc":"2.0","method":"sessions.ack","params":{"sessionId":"cs_0123456789abcdef","seq":413}}

The backlog of a session is its events not yet sent or, once the client has sent an ack, not yet acknowledged. When it passes 10,000 events or 8 MiB, the server detaches that session with too_far_behind.

Deltas

An attach with deltas: true also receives delta notifications. Types: API schema.

PropertyDetail
ContentMessage and reasoning text as it is written, a tool call being prepared and its output, compaction, subagent progress
StorageNo seq, not stored, not replayed
CompletenessEach block of deltas is followed by an event with the whole text (message.completed, reasoning.completed, tool.completed). A client may ignore deltas
BacklogSent only to a subscription that has been sent every event. Deltas of one block that wait are merged

Detached

When the server ends a subscription it sends session.detached with a reason:

reasonCauseWhat to do
too_far_behindThe backlog passed its limitAttach again with after set to the last seq processed
access_lostThe member no longer has access to the sessionNothing
epoch_changedThe journal was rebuilt. The notification carries the new logEpoch and epochStartSeqDiscard events from epochStartSeq on and attach with after set to epochStartSeq - 1
unavailableThe session’s writer could not be reachedAttach again later