20

Stream a run live

Guides & tutorials3 min read

Consume the resumable SSE event stream and render tokens as a run executes.

Open the event stream for a run, render events as they arrive, and make the connection resumable across drops. Prerequisites: a running local stack and an authenticated client (see the first-agent tutorial).

  1. 1

    Create the run

    Use a fresh idempotency key so this run is distinct from any prior attempt.

  2. 2

    Open the event stream

    Attach a handler that receives each event and its sequence frame.

  3. 3

    Render as events arrive

    Treat every event as a UI update, not a final answer, until the run reaches a terminal state.

  4. 4

    Persist the sequence id

    Store the last sequenceId you rendered somewhere durable on the client.

  5. 5

    Reconnect with Last-Event-ID

    On drop, reopen the stream starting from the stored sequence instead of from zero.

Create and stream a run
const run = await client.createRun({  prompt: 'Research Base liquidity and produce a report',  idempotencyKey: crypto.randomUUID(),});let lastSeq = 0;const stop = client.streamRunEvents(run.runId, (event, frame) => {  lastSeq = frame.sequenceId;  render(event);}, { lastEventId: 0 });

Make the stream resumable

Reconnect from the last sequence
function reconnect(runId: string) {  return client.streamRunEvents(runId, (event, frame) => {    lastSeq = frame.sequenceId;    render(event);  }, { lastEventId: lastSeq });}

Resume safely

Persist the last SSE sequence and reconnect with Last-Event-ID. Reuse the original idempotency key when retrying run creation after a timeout, rather than issuing a second run.

Surface interrupts inline

Some tool calls pause the run for a human decision instead of completing outright. Render that as a distinct state in your UI rather than treating a stalled stream as an error.

Branch on the event type
function render(event) {  if (event.type === 'approval.required') {    showApprovalPanel(event);    return;  }  appendToken(event);}
MethodEndpointPurpose
POST/v1/runsCreate an idempotent run
GET/v1/runs/{run_id}/eventsStream resumable SSE events
POST/v1/runs/{run_id}/cancelCancel work across service boundaries

Was this page helpful?

Edit on GitHub