Skip to documentation

API & MCP

Agents & runs (v1)

The /api/v1 surface lets external systems drive KB-grounded agents over authenticated HTTP. It exposes the same durable harness the UI uses. All requests carry a Bearer key — see Authentication. Base URL is your host, e.g. https://your-host/api/v1.

Start a run

Runs are identified by the agent's slug. The default request persists a queued run as the durable handoff record, attempts to send worker work, and immediately returns HTTP 202 with the run id and reattachment URL. If that broker send is interrupted, the worker reconstructs the pinned start from the row at boot or during its minute reconciliation loop.

POST/api/v1/agents/:slug/runsBearer · agents:run

Start a run of the named agent.

Request body

inputrequiredstringThe task or question (min length 1).
conversationIdstringContinue an existing conversation for multi-turn context.
Example requestbash
curl -X POST https://your-host/api/v1/agents/budget-analyst/runs \
  -H "Authorization: Bearer $ELI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":"What changed in the FY26 budget?"}'
Responsejson
// HTTP 202
{ "runId": "01J…", "status": "queued", "stream": "/api/v1/runs/01J…/stream" }

Reattach from any web replica with GET /api/v1/runs/:id/stream. It replays persisted steps, tails the database, and closes on a terminal state; reconnecting does not restart the run.

GET/api/v1/runs/:id/streamBearer · runs:read

Replay and tail a durable run as Server-Sent Events.

Example requestbash
curl -N https://your-host/api/v1/runs/$RUN_ID/stream \
  -H "Authorization: Bearer $ELI_KEY"
reattachment streamtext
data: {"type":"model_call","runId":"01J…","textLength":0,"toolCalls":1}
data: {"type":"tool_call","runId":"01J…","name":"kb_search","ok":true}
data: {"type":"final","runId":"01J…","status":"succeeded","text":"…","citations":[{"docId":"01J…","chunkId":"01J…"}]}

# terminal event is one of:
#   {"type":"final","runId,status,text,citations}
#   {"type":"suspended","runId","approvalId","toolName"}
#   {"type":"error","message":"…"}   e.g. "no-model-configured"

Inline compatibility mode

POST /api/v1/agents/:slug/runs?stream=inline retains the legacy in-request SSE mode for compatible clients. It still passes monthly spend and concurrency admission, but the queued 202 + reattachment path is the durable default.

Terminal statuses

queued · running · succeeded · failed · budget_exceeded (graceful stop; text holds the partial answer) · interrupted · suspended (awaiting a HITL decision — resolve with /approve). Setup failures are persisted on the run and appear as an error event during reattachment.

Read a run

GET/api/v1/runs/:idBearer · runs:read

Fetch a run and its full ordered step trace. A run in another workspace is invisible under RLS → 404.

Example requestbash
curl https://your-host/api/v1/runs/$RUN_ID \
  -H "Authorization: Bearer $ELI_KEY"
Responsejson
{
  "run": {
    "id": "01J…",
    "agentVersionId": "01J…",
    "conversationId": null,
    "status": "succeeded",
    "trigger": "api",
    "input": "What changed in the FY26 budget?",
    "output": { "text": "…", "citations": [  ] },
    "error": null,
    "tokensIn": 4210, "tokensOut": 380,
    "costUsd": "0.021840",
    "apiKeyId": "01J…",
    "configSnapshotId": "…",
    "startedAt": "2026-07-19T14:03:11.204Z",
    "finishedAt": "2026-07-19T14:03:18.902Z"
  },
  "steps": [ { "idx": 0, "kind": "model_call", "modelId": "claude-opus-4-8", "tokensIn": 3800, "tokensOut": 40, "costUsd": "0.0182", "latencyMs": 1420, "status": "ok" },  ]
}
GET/api/v1/runs/:id/stepsBearer · runs:read

Just the ordered steps array (kind = model_call | tool_call | mcp_call | guardrail | approval | retry).

Example requestbash
curl https://your-host/api/v1/runs/$RUN_ID/steps \
  -H "Authorization: Bearer $ELI_KEY"
Responsejson
{ "steps": [ { "idx": 0, "kind": "model_call",  }, { "idx": 1, "kind": "tool_call", "name": "kb_search", "status": "ok",  } ] }

Cancel a run

POST/api/v1/runs/:id/cancelBearer · agents:run

Cooperatively cancel a running run. Worker runs poll a DB cancel-flag between steps.

Example requestbash
curl -X POST https://your-host/api/v1/runs/$RUN_ID/cancel \
  -H "Authorization: Bearer $ELI_KEY"
Responsejson
{ "cancelled": true }

Resolve an approval

When a run is suspended, record the human decision. The transition from pending approval to queued continuation is atomic and idempotently reconciled to pg-boss; continue reading the same reattachment stream.

POST/api/v1/runs/:id/approveBearer · agents:run

Resolve a suspended HITL approval and queue its durable worker continuation.

Request body

approvalIdrequiredstringThe approval to resolve (from the suspended event).
decisionrequired"allow" | "deny"Allow executes the tool; deny returns an error result to the model.
notestringOptional reviewer note, stored on the approval.
Example requestbash
curl -X POST https://your-host/api/v1/runs/$RUN_ID/approve \
  -H "Authorization: Bearer $ELI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"approvalId":"01J…","decision":"allow"}'
Responsejson
// HTTP 202
{ "runId": "01J…", "approvalId": "01J…", "status": "queued" }

Attach feedback

POST/api/v1/runs/:id/feedbackBearer · agents:run

Attach human feedback to a completed run. Returns 201 with the feedback id.

Request body

kindrequired"thumb" | "rating" | "correction" | "edit" | "citation_flag"The feedback kind.
valuejsonKind-specific payload, e.g. { "rating": 4 } or { "thumb": "up" }.
notestringOptional free-text note.
Example requestbash
curl -X POST https://your-host/api/v1/runs/$RUN_ID/feedback \
  -H "Authorization: Bearer $ELI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kind":"thumb","value":{"thumb":"up"}}'
Responsejson
{ "id": "01J…" }   // HTTP 201

Error handling

All endpoints share the conventions in Errors & rate limits: 401 for a bad key, 403 for a missing scope, 404 for an unknown/other-workspace run, 400 for an invalid body, 402 when the monthly spend cap denies admission, and 429 when the active-run cap is full.