Streaming events
Tail a session's log over SSE, and pick back up from where you stopped when the connection drops.
The point of a durable event log is that watching it is optional. A run keeps going whether or not anyone is connected, and when you reconnect the log tells you everything you missed.
Reading the log
Two endpoints read the same events. The paged one is for catching up on a session that already happened; the stream is for watching one that is happening.
GET /v1/sessions/{session_id}/events
GET /v1/sessions/{session_id}/events/stream
curl -N "https://api.us.cloud.subako.ai/v1/sessions/$SESSION_ID/events/stream" \
-H "Authorization: Bearer $SUBAKO_SESSION_TOKEN"
Both endpoints take the session token — the id and session_token a
created session returned, held here in SESSION_ID and
SUBAKO_SESSION_TOKEN. An API key works too, but a token that reads one
session is the one to hand a browser.
Where the stream starts
Connecting with no cursor tails from the log’s current head: you see what happens next, and nothing that already happened. That is what you want for a session you are about to drive, and not what you want for one already in flight — there you would miss the run’s opening events and, if the run has finished, receive nothing at all.
after_seq names the starting point, sending events whose sequence number is strictly greater. after_seq=0 replays the whole log and then continues live, which is how you catch up and tail over one connection.
curl -N "https://api.us.cloud.subako.ai/v1/sessions/$SESSION_ID/events/stream?after_seq=0" \
-H "Authorization: Bearer $SUBAKO_SESSION_TOKEN"
Each SSE frame carries three fields:
| Field | What it holds |
|---|---|
id |
The event’s sequence number — what a reconnect resumes from |
event |
The event kind, e.g. message_assistant |
data |
The same body the paged endpoint returns for that event |
Resuming after a drop
Reconnect with Last-Event-ID set to the last sequence number you actually processed. The stream replays from just after it, then continues live.
curl -N "https://api.us.cloud.subako.ai/v1/sessions/$SESSION_ID/events/stream" \
-H "Authorization: Bearer $SUBAKO_SESSION_TOKEN" \
-H "Last-Event-ID: 42"
In the browser, EventSource sends that header for you on reconnect, using the last id it saw. Two rules keep it honest:
Advance your cursor only after you have handled the event
The header is a promise about what you have processed, not about what arrived. Move the cursor at the end of your handler.
Treat events as replayable
A reconnect can hand you an event you already saw if your cursor lagged. Key your UI state off the sequence number rather than appending blindly.
Knowing when a run is over
A run ends in exactly one of three events:
run_completed the turn finished with nothing left to do
run_failed it stopped on an error; `error` carries the text
run_cancelled a cancel request was honored
The stream does not close when a run ends — the session is still there, and appending more input starts another run. If you are waiting for one specific run, watch for its run_id on the terminal event rather than for the connection closing.
POST /v1/sessions/{session_id}/cancel
Cancelling asks the current run to stop. It is a request, not a kill: what has already been committed to the log stays there, and the run ends with run_cancelled when it lands.