Documentation

Run status

The run-status surface shows what's happening with the agent runs you dispatch to your own local runner daemon — connection state, the current dispatch, live stdout, and the active runtime controls AuditTrail has applied to your gateway-routed traffic. Execution stays on your runner; AuditTrail orchestrates and observes it.

Connection & last dispatch

GET /api/v1/runner/status returns whether a daemon is currently connected, the most-recent open session row, and a summary of the most-recent dispatch (correlation_id, template_id, status, timestamps, resolved trace_id).

json
{
  "connected": true,
  "session": { "id": "…", "token_id": "…", "connected_at": "…", "client_info": {} },
  "last_dispatch": {
    "id": "…", "correlation_id": "…", "template_id": "quickstart",
    "status": "completed", "created_at": "…", "completed_at": "…", "trace_id": "…"
  }
}

Dispatch lifecycle

A dispatch row moves pending → running → {completed | failed | cancelled}. It flips to running on the daemon's first output line and to a terminal status on the daemon's exit frame (exit code 0 → completed, else failed). The dispatch keeps a 500-line FIFO ring buffer of stdout/stderr (stdout_tail_json) and, on completion, the trace_id the run reported so you can jump straight to the trace.

REST surface

routes/runner.py — prefix /api/v1/runner.

MethodPathPurpose
GET/runner/statusConnection + last-dispatch summary
POST/runner/dispatchSend a run to the connected daemon
GET/runner/dispatches/{dispatch_id}Poll status + recent stdout tail
GET/runner/dispatches/{dispatch_id}/streamSSE relay of newly-appended output lines
DELETE/runner/dispatches/{dispatch_id}Cancel (marks cancelled, signals the daemon)

Live output stream

GET /runner/dispatches/{dispatch_id}/stream is a Server-Sent Events relay over the ring buffer. It yields newly-appended lines roughly every 500ms and emits a terminal data: [DONE] frame when the dispatch reaches a terminal status. The loop is bounded (10 minutes) so a runaway dispatch can't hold the connection open forever. The dashboard's run-output tile consumes this stream and auto-scrolls while you're near the bottom.

Cancel

A DELETE marks the dispatch cancelled (if not already terminal) and best-effort sends a cancel frame to the daemon over the WebSocket link, so the daemon can stop the subprocess.

Active runtime controls

The run-status page also surfaces the runtime controls the deployment-action executor currently has applied to your gateway-routed traffic — the read-only projection of switch_model / throttle / disable_flag actions you approved.

GET /api/v1/deployments/actions/runtime-controls returns only your active controls, newest first, each linking back to the deployment_actions row that created it. See Executable actions for how those get written, and the gateway proxy for where they're enforced.

Each control has a Deactivate button on the Run Status page. It calls POST /api/v1/deployments/actions/runtime-controls/{id}/deactivate, which flips the control inactive so the gateway stops enforcing it immediately and it leaves the active list — the operator counterpart to the automatic TTL reaper below, for a control you want to lift by hand. It's a typed-confirm action, and it only affects your own controls (a control owned by another tenant returns 404).

Time-limited controls (TTL)

A control can carry an optional expiry. When the approved action's outcome includes a positive ttl_seconds, the control is written with an expires_at that many seconds in the future; with no ttl_seconds the control is permanent until you deactivate it. Each row in the response exposes expires_at (null for a permanent control).

Expiry is enforced two ways, so it is both immediate and durable:

  • The gateway stops applying an expired control on the very next request — it is skipped fail-open the instant expires_at passes, even before any background sweep runs.
  • A background reaper then flips the expired control's active flag to false and broadcasts runtime_control.expired, so the row drops out of this list and open dashboards update live.

This lets you approve, say, a 15-minute throttle on a misbehaving model that lifts itself automatically — no second action needed to undo it.

Live updates

The daemon link (/api/v1/runner/ws) broadcasts runner.connected / runner.disconnected when the daemon attaches/detaches, and runner.dispatch.output / runner.dispatch.final as a run streams and finishes, so open dashboard tabs update without polling.

Data model

TableHolds
runner_dispatchesOne row per dispatch (template, prompt, status, 500-line stdout ring, trace id)
runner_sessionsPer-connection daemon session (disconnected_at stamped on close)
runtime_controlsActive gateway-enforced controls written by the action executor