Skip to main content
Deprecated — the company-scoped run ledger (/v1/runs). It drives the legacy orchestration runtime, which is FROZEN — it accepts no new capabilities. The durable runtime enforces policy at the tool boundary, not only at the gateway, and it is the only runtime new work is built on.Use instead: GET /v1/teams/:team/tenants/:tenantUserId/runs — runs are addressed by (team, tenant) nowThese routes keep answering. Nothing is removed and no response shape changes: the deprecation is announced in headers only, which are purely additive. Every response from this router carries Deprecation (RFC 9745 — the value is a Structured Field Date, @ plus epoch seconds, not the boolean true some pre-RFC clients look for), Link rel="deprecation", Warning: 299 and X-Naive-Deprecation-Id: dep.surface.runs. There is no Sunset header, because this is frozen with no sunset date — a Sunset on a frozen row would be a date the platform has not promised.Announced 2026-07-29. Level frozen. The freeze ends when company_containers with provider='hermes' and status='running' reaches zero — not on a date.Replacement surface: the (team, tenant) run ledger — live today.
The company-scoped agent run ledger. Every run is a row; every row has an ordered list of ledger events and a list of artifacts.

Operations

Scoping — read this before you build a dashboard

GET /v1/runs is scoped by the credential, not by the URL. It takes no team and no tenant parameter.
  • A human owner session and the config-root lead agent see every run in the company.
  • A sealed non-privileged agent key sees only its own runs.
  • An unsealed non-root key has no subject and therefore counts nothing.
If you are building a per-tenant view, this endpoint will return other tenants’ runs under an operator key. Use GET /v1/teams/{team}/tenants/{tenantUserId}/runs, which joins through the card to reach the tenant and is correctly scoped.
GET /v1/runs/{id} applies the same rule: a non-privileged agent key may read only its own runs, and any other id returns 404 with the same shape as a genuinely missing run — so the endpoint is not an oracle for which run ids exist.

Completion is compare-and-set

POST /v1/runs/{id}/complete transitions the run to a terminal status exactly once (a compare-and-set on the end timestamp). A repeat call is idempotent and returns the run as the winner left it — it does not error and it does not overwrite.

Appending events

POST /v1/runs/{id}/events is write-guarded. It is allowed for an owner or operator session, the config-root lead agent, the sealed subject that owns the run, or the agent whose id matches the run.
Frames on this ledger take actor_type, actor_id and event_type as free strings from the request body. That is why the durable runtime’s SSE transcript is refused rather than served from here: a live transcript rendered from caller-supplied actor fields is a forgery surface. The durable runtime’s own frame list reads a different table, whose rows are written only by the platform.