Skip to main content

List runs

Real rows from the run mirror, newest first, keyset-paged (limit max 200, cursor opaque).
These runs are correctly scoped to your tenant. The run mirror carries a company but not a tenant, so the route joins through the card to reach the tenant. This matters because the older company-scoped ledger at GET /v1/runs is not tenant-scoped: under an operator key it returns every tenant’s runs regardless of which team or tenant you asked about. Use this address, not that one.
status is the run’s recorded outcome; where none is recorded it is ended if the run has an end time and running if it does not. model is null on every row — per-run model selection is a manifest field and no manifest is stored.

One run

Adds summary, error, and two URLs: stream_url is emitted even though the address refuses, because the URL is the correct one and hiding it would make the shape change when the stream lands. Check the status code, not the presence of the field. 404 not_found means no run with that id belongs to this tenant.

The paged transcript

Frames are returned newest first and the cursor pages backwards through history. If you are rendering a transcript top-to-bottom, reverse each page. source is always platform: these rows are written by the API from the runtime mirror, never from a caller’s request body.

Streaming — refused, and why

This is refused rather than approximated, and the three missing pieces are named on the wire. Each one alone would make a stream dishonest:
  1. source is not platform-set on the run-event table a stream would read. That table takes actor_type / actor_id / event_type as free strings from the request body, so an agent key can append a frame claiming to be the owner. Rendering those as a live transcript is a forgery surface — and a stream is what a UI renders as what happened.
  2. No trace_id column. Every frame is supposed to carry one.
  3. No metering on stream open. Usage is recorded when a response finishes, so a stream held open for an hour bills at close and cannot be rate-limited. Shipping the stream before that ships an endpoint with no abuse ceiling.
Use …/runs/{id}/events and poll. It reads a different table — the one whose rows the platform writes — which is why it is safe to serve while the stream is not.

Stopping a run — refused

A legacy run is stopped through the sidecar at POST /v1/companies/{id}/ceo/runs/{runId}/stop, which is the frozen surface and keeps answering. See Orchestration.