Detected country: US
logo
Sign InGet Early Access
GuideRecipesDeveloper
‌
‌
‌
logo

Powered by

  • Home
  • Developer Docs
  • Developer foundations
  • How do I stream playbook run events?

How do I stream playbook run events?

2min read

Share

TL;DR: Runs stream as Server-Sent Events. Every frame shares one envelope where the SSE event: name equals data.type. Parse data.type, handle the run lifecycle (run_start, run_delta, run_stop), the step lifecycle (step_start, step_delta, step_stop), input_request when a run parks, and error frames — and ignore any type you don't recognize.

Who this is for

Developers rendering live progress or driving an agent loop from a playbook run.

Where do events come from?

Two endpoints stream the same shared envelope:

  • POST /api/playbooks/:id/execute — events for the run you just started, on the same connection.
  • GET /api/playbooks/:id/runs/stream — events for all runs on a playbook (for observers/dashboards).

The /runs/stream connection opens with a stream_start frame (carrying latestSeq, replayed) and emits a ping keepalive roughly every 15s.

What is the run lifecycle?

typeMeaning
run_startRun begins. run: { id, playbookId, status: "running", totalSteps, stepId? }
run_deltaFriendly status / progress update
run_stopResult for this segment. run: { id, status, success, totalDurationMs?, output?, error? } — status may be completed, failed, cancelled, or suspended (Paused; not terminal)
errorFatal infrastructure fault — always followed by run_stop

run_delta carries a sub-type: status_delta (user-facing message + phase such as bootstrapping, installing_packages, running_step), progress_delta (stepIndex, stepId, message), or phase_delta (machine phase only).

What is the step lifecycle?

typeMeaning
step_startStep opens. step: { id, kind: "code" | "http", language?, description? }, index
step_deltaIncremental output
step_stopStep closes. result.status: completed | failed | skipped

step_delta sub-types: stdout_delta, stderr_delta, route_delta (taken, kind), and agent_activity_delta.

What is input_request?

When a run parks (operator pause or metaphor.waitForInput), Ballet emits an input_request event with the wake payload — typically requestId, stepId, prompt, schema, optional details, and reason (input_request vs operator_pause). A run_stop with status: "suspended" follows. The sandbox is freed; continue the same runId via Studio or POST /api/runs/:id/reply / /resume.

See How do I wake a suspended run with reply or resume?.

How do I handle errors?

Top-level error frames carry error: { type, message, retryable, stepId? } where type is one of bootstrap_error, executor_error, cancelled, timeout, or internal_error. A fatal error is always followed by a run_stop.

Step failures are not top-level errors — a failed step closes normally via step_stop with result.status: "failed". Check step results in addition to the run result.

How do I keep frames in order?

Each run event after the bus assigns it carries a monotonic seq per playbook channel. Use seq to order or de-duplicate frames if your transport may reorder them.

Example

event: run_start
data: {"type":"run_start","seq":1,"runId":"run-abc","run":{"id":"run-abc","playbookId":"pb-xyz","status":"running","totalSteps":2}}

event: step_start
data: {"type":"step_start","seq":3,"runId":"run-abc","index":0,"step":{"id":"fetch","kind":"code","language":"python"}}

event: step_stop
data: {"type":"step_stop","seq":4,"runId":"run-abc","index":0,"stepId":"fetch","result":{"status":"completed","durationMs":842,"output":{}}}

event: input_request
data: {"type":"input_request","seq":5,"runId":"run-abc","requestId":"req-1","stepId":"approve","prompt":"Approve?","reason":"input_request"}

event: run_stop
data: {"type":"run_stop","seq":6,"runId":"run-abc","run":{"id":"run-abc","status":"suspended","success":false}}

Related articles

  • How do I wake a suspended run with reply or resume?
  • How do I pause and resume a playbook run?
  • Run playbooks over the REST API
  • How do I authenticate with the Ballet API?
  • How do I read runs and run history?

Share