Workbenches is an open standard. Read why
Docs Events

API reference

Events

Every run records an ordered stream of events in the open event protocol, protocol: 0, stored verbatim: protocol, run_id, sequence, timestamp, type, runner, and data. Sequences are gapless from 1. Nothing is appended after a terminal event (run.completed, run.failed, run.cancelled): whichever lands first wins, so a cancel racing a completion records exactly one ending.

Read events#

GET /v1/runs/:id/events

Key runs:read, or session: member.

Query Type Meaning
after integer, at least 0 Return events after this sequence. Default 0.
limit integer, 1 to 500 Default 100.

Response 200, with cache-control: no-store:

{
    "events": [
        {
            "protocol": 0,
            "run_id": "wb_d8m99qyw2e4qqhitfff63f1n",
            "sequence": 1,
            "timestamp": "2026-10-28T14:05:40.112Z",
            "type": "run.started",
            "runner": "opencode",
            "data": {}
        }
    ],
    "next": 1
}

next is the sequence to pass as after for the following page.

Stream events#

Send the same request with Upgrade: websocket to open a stream. The server replays every event after after, then sends each new event as one JSON text frame, and closes with code 1000 after the terminal event.

  • The stream is read only. Send commands over HTTP; see Commands.
  • A socket lives 15 minutes on the credential it connected with. After that, the next frame closes it with code 4001 (reauthenticate) instead; connect again at once with the last sequence you saw as after.
  • A client that disconnects reconnects with the last sequence it saw.
  • A WebSocket upgrade authenticated by a session cookie must come from the dashboard origin, or it is refused with 403. A key with an Authorization header needs no origin.

What events carry#

Events never contain secret values. Before an event is stored, every value injected into the run's sandbox is replaced with [redacted]: the organization's secrets the run received, the runner's password, the image pull token, and the run's GitHub credential.

Notable events for integrations:

Type Meaning
repository.preparing, repository.ready Checkout started and finished, with repository and revision. repository.ready may carry warnings, such as a gh that could not be installed.
input.requested, question.requested The run needs an answer. Its status is needs_input.
plan.updated The agent's whole todo list.
usage.updated Model tokens and cost for a step.
outcome.available The outcome was kept, before the terminal event.
preview.available A server was announced.
delivery.completed The agent opened or updated a pull request: the run, outcome, repository, base revision, branch, base branch, head commit and tree, and pull request. Once per pull request and head commit.
run.completed, run.failed, run.cancelled The end. The terminal event may carry infrastructure, the sandbox's duration and resources.

Realtime#

GET /v1/realtime

Key runs:read, or session: member. A WebSocket on the organization's realtime channel. Every socket in the organization receives every frame.

Query Type Meaning
organization slug For a session.

Each frame is JSON with a type and a topic:

type topic Body
run run:<id> run: id, status, previews, previews_until. Sent when a run moves to needs_input or ends, in a project or not, and when its previews or preview window change. Never a link.
task project:<slug> task: a project task, as in Projects.
project project:<slug> project: a project, as in Projects.
connection connection:<user id> connection: user_id, key_id, client_name. An agent tool a person connected used its key for the first time.

Frames are lossy: a client that reconnects loads current state again. The socket is read only, and one that sends a message is closed. It lives 15 minutes per credential, then closes with 4001 like a run event socket. The MCP wait tool uses this socket to wait on many runs.