COMPLETED / FAILED / CANCELLED / TIMEOUT. Since PR #234 the legacy agent_runs table is gone; runs are reconstructed from the Crew Journal. The two engines key their journal entries differently, and GET /api/v1/runs and GET /api/v1/runs/{id} read both (#2284):
- An ad-hoc run’s entries (
run.started+ one terminalrun.{completed|failed|cancelled|timeout}) are grouped ontrace_id, which equals the run id. - A routine/pipeline run’s entries (
pipeline.run.started+ one terminalpipeline.run.{completed|failed}) never settrace_id; they’re grouped onactor_idinstead, which the pipeline engine stamps to the run’s own id. There is no dedicatedpipeline.run.cancelled— a run cancelled mid-flight is stillpipeline.run.failed, with the real outcome onpayload.status.
kind: "agent" | "pipeline" so a caller can tell which engine produced it. The HTTP shape otherwise stays the one frontend consumers already know — this widened what rows can appear, not the shape of a row.
GET /api/v1/runs/insights and the stats object embedded in GET /api/v1/runs are not widened by #2284 — both still aggregate ad-hoc runs only (journal.RunInsights / journal.RunStats). That was a deliberate scope limit: unifying cost roll-ups and correlation across the two engines is a separate decision with its own consequences.
Every endpoint is workspace-scoped via the session context.
Runs are read-only — there is no write endpoint. An ad-hoc run comes into existence when the orchestrator emits
run.started and concludes when a terminal run.{completed|failed|cancelled|timeout} lands on the same trace_id. A routine run comes into existence when the pipeline engine emits pipeline.run.started and concludes when pipeline.run.{completed|failed} lands on the same actor_id.Endpoints
List runs
stats) and pagination metadata. Backed by journal.ListRuns — a CTE-grouped read over journal_entries, keyed on trace_id for an ad-hoc run and actor_id for a routine/pipeline run (COALESCE(trace_id, actor_id), #2284) — plus journal.RunStats for the tiles (ad-hoc runs only; see the note above).
Query parameters:
A
kind: "pipeline" row also carries pipeline_slug, the routine it ran (empty for an agent run), and its trigger_type is derived from pipeline_runs.triggered_via in the same USER / CRON / WEBHOOK vocabulary as agent runs.
| page | integer | 1-based page index, default 1. Values below 1 become 1; values above the server’s maximum page are capped. |
| limit | integer | Page size, 1-100, default 50. Out-of-range values fall back to the default. |
Response: 200 OK
mission_id and mission_identifier name the issue the run worked on (from the run.started entry the dispatcher stamps); both are omitted for a chat-only run. crew_slug is what the crew’s page is keyed on. The same fields ride on GET /api/v1/runs/{id}.
Errors:
Fleet insights
run.started
traces only (journal.RunInsights, trace_id IS NOT NULL AND entry_type LIKE 'run.%'), and #2284 deliberately left it that way — see the note at the top of
this page. The handler resolves per-agent counts into a crew rollup and a
display-named top-agents leaderboard (one workspace-scoped agents→crews
join).
Query parameters:
Response:
200 OK
Get a single run
data[] array from GET /api/v1/runs — the handler reuses the same enrichment so dashboard detail views can share the row renderer.
Path parameters:
Response:
200 OK
journal.GetRunByID lookup. A
trace ID from another workspace is treated as not found.
Tenancy
workspace_idis taken from the session context — never from a query parameter.- Cross-tenant trace IDs are filtered out at the journal store (
journal.ListRunsrequires a non-emptyWorkspaceID). - Enrichment lookup (
agents+crews) is workspace-scoped, so an agent ID collision across workspaces (test fixtures, restored backups) cannot attach foreign names to a row.
Related
- Crew Journal guide — full event-type catalog and the
run.*lifecycle. - Journal API — the underlying read surface, including FTS search and SSE live tail with
trace_idfiltering for one run’s spans. crewship journal --trace-id <run-id>— list every span (LLM call, exec, network egress) belonging to one run.