Browse documentationSSE and resume

Streaming

A stream is a moving read model

Server-sent events deliver ordered progress while long-running work continues. Parse event frames, commit the last fully handled position, and project events into your own UI without treating a TCP connection as durable state.

Reconnect from committed progress

Each durable frame carries an SSE id — a numeric sequence on session streams, a cursor string on the file-activity stream. Preserve it only after the event's effects are committed; reconnecting from a merely received position can skip work after a crash. Send the last committed value in Last-Event-ID, or in the query parameter the endpoint reference names when a client cannot set that header (?since= for sessions, ?cursor= for file activity).

for await (const frame of streamEvents({ lastEventId: committedId })) {
  await apply(frame.event)
  if (frame.id !== undefined) {
    committedId = frame.id
    await save(committedId)
  }
}

Expect every ending

A clean terminal event, an idle connection, a network failure, and an explicit interruption are different outcomes. Back off reconnects, stop after a declared terminal state, and fetch canonical state when an event gap cannot be reconciled. A stream that declares no terminal state — the file-activity feed — instead ends every segment with a clean close; resume it from committed progress rather than stopping.

Keep the protocol streamable

Do not buffer the entire response or run it through a JSON-only helper. Preserve content type, status, cancellation, and event boundaries from the HTTP response.