SSE: agent run changes

Server-Sent Events stream for run changes for a specific agent. Supports cookie auth and API key auth via ?token=apst_... query parameter. The caller must hold runs:read or runs:read-all in the space (for an API key, among its scopes); without either the stream is refused with 403.

Event types: run_update (status change), run_log (log entry), run_metric (running cumulative cost + token usage), connection_update (INSERT/UPDATE/DELETE on integration_connections, actor-scoped to the caller's own rows). Heartbeat: a named SSE event: ping frame (empty data) sent immediately on connect and every 30s thereafter.

Each SSE frame carries an id: field of the form ${subscriberId}:${monotonic}. Ids are globally unique across reconnects (each new EventSource gets a fresh subscriberId). Client-side dedup on id is safe. Server-side replay via Last-Event-ID is NOT implemented — reconnect lands on the live tail; missed events are not replayed.

Channel selection: pass channels= with a comma-separated subset (e.g. channels=run_update,connection_update) to receive only those frames. The filter is applied server-side before serialization. Omit it to receive every channel the caller may receive. Note that dropping run_log is what keeps a dashboard-wide stream off the per-log firehose.

Run visibility: run_update, run_log and run_metric carry only the runs the caller may read — every run in the space with runs:read-all, otherwise the runs the caller launched. The single-run stream refuses a run the caller may not read with 404, the same answer as GET /api/runs/{id}.

GET/api/realtime/agents/{packageId}/runs

Authorization

better-auth.session_token<token>

Cookie session from Better Auth. Requires X-Org-Id header for org-scoped routes.

In: cookie

Path Parameters

packageId*string

Agent package ID

Query Parameters

orgId*string

Organization ID. Required for SSE auth (cookies cannot carry X-Org-Id header on EventSource).

Formatuuid
view_as?string

Role preview for this stream — the same value, grammar and refusals as the X-View-As header (see that parameter). It is a query parameter here because EventSource cannot send headers — presenting it as the X-View-As header on these routes is 400 invalid_view_as. Sessions only: with ?token=apst_… it is 400 view_as_unsupported. A stream opened under a persona sees what that role would see and stops where that role would stop (403 not_a_space_member, or 404 for a private space), and carries X-View-As-Active: 1.

spaceId?string

Space ID. Required for cookie auth (SSE cannot send X-Space-Id header). Not needed for API key auth (space resolved from key).

token?string

API key (apst_ prefix) for SSE authentication. EventSource cannot send Authorization headers, so API key auth uses this query parameter instead.

verbose?boolean

When true, include full payload with result and data fields. Default (false) strips large user-content fields for safer consumption by external agents.

Defaultfalse
channels?string

Comma-separated list of SSE channels to subscribe to (run_update, run_log, run_metric, connection_update, chat_session_update). Omit to receive every channel the caller may receive (default). Unknown names are ignored; if nothing is recognised the stream falls back to that same default. Declaring only the channels you consume avoids fanning the run_log firehose out to a stream that discards it.

curl -X GET "https://your-instance/api/realtime/agents/string/runs?orgId=497f6eca-6276-4993-bfeb-53cbbbba6f08"
"string"

{
  "type": "https://docs.appstrate.dev/errors/invalid-view-as",
  "title": "Invalid View-As Header",
  "status": 400,
  "detail": "X-View-As could not be parsed: space and role must be provided together",
  "code": "invalid_view_as",
  "param": "X-View-As",
  "request_id": "req_abc123"
}

{
  "type": "https://docs.appstrate.dev/errors/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Invalid or missing session",
  "code": "unauthorized",
  "request_id": "req_abc123"
}
{
  "type": "https://docs.appstrate.dev/errors/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "Insufficient permissions",
  "code": "forbidden",
  "request_id": "req_abc123"
}
{
  "type": "https://docs.appstrate.dev/errors/not-found",
  "title": "Not Found",
  "status": 404,
  "detail": "Resource not found",
  "code": "not_found",
  "request_id": "req_abc123"
}