Start a run
POST /v0/envs/{env}/agents/{agent}/capabilities/{capability}/runs
A run can be started three ways: answer at once and follow it, wait for the result, or stream the agent’s own response.
Body
any
required
The capability’s input. It must match the capability’s input schema, or the request is a
422 listing the problems (at most 50) and no run is created. At most 1 MiB.string
A session you created with Create a session: this run is its next turn.
Query
boolean
default:"false"
Wait for the run to end or to be held for a person, for the capability’s timeout plus 5 seconds and at most 5 minutes, then answer
200 with the run, whatever its status is by then (completed, failed, held, or still queued / running). It never hangs.boolean
default:"false"
Answer with exactly what the agent returns, as it arrives. Not together with
wait. See Passthrough.202 {"run_id", "status": "queued"}. Follow the run with Follow a run or poll Get a run.
Runs always use the agent’s live version. Your installation limits how many runs execute at once; extra runs stay queued until one ends.
Idempotency
Send anIdempotency-Key header (up to 200 characters) to make a retry safe: the same key from the same caller with the same body returns the run it started the first time instead of starting another. The same key with a different agent, capability, input, metadata or session_id is a 409 idempotency_key_reused.
Passthrough
With?passthrough=true the answer is the agent’s own response, relayed as it is written: its status code, its Content-Type and its body byte for byte. That makes it easy to put a chat UI in front of an agent: your backend starts the run with its API key and hands the response to the browser unchanged, and the browser reads the agent’s own stream format — for example the Vercel AI SDK’s useChat reading a UI message stream — with no mapping. See Streaming for the agent side.
- The response carries the agent’s
Content-Type,Cache-Control,Content-Language,Content-Disposition,X-Accel-BufferingandX-Vercel-AI-*headers (no others), plusX-AgentOS-Run-Idwith the run’s id andContent-Security-Policy: sandbox, so an agent’s HTML can’t run as a page of the platform. - It is a normal run otherwise: the same authentication, input validation, idempotency, events and holds.
- A response that broke off, or passed 10 MiB, ends without its last chunk, so your HTTP client reports an error; GET the run to learn how it ended. A cancelled run’s stream is cut the same way within about a second.
- Closing the connection doesn’t stop the run. Cancel it if you want it stopped.
- A run held for a person mid-answer ends its stream as the agent ends it; the output after the decision is read with Get a run.
- When there is nothing to relay — the agent was never reached, the run was cancelled before it answered, or an
Idempotency-Keynames a run started without passthrough — the answer is the run, as?wait=truegives it. - The relayed bytes are kept for 10 minutes after the agent’s last write, so replaying the same
Idempotency-Keywithin that time streams the response again. - An agent status code HTTP can’t carry (outside 100–599) is a
502 agent_bad_status; the run goes on. - Output guardrails check the run’s output when it completes, which is after the bytes were relayed: what was already streamed can’t be recalled.
Errors
A guardrail block names the guardrail, the checkpoint and the hit id, so you can find it on the Guardrails page:
Get a run
GET /v0/envs/{env}/runs/{run_id}
The run object
string
r_ followed by a number.string
The agent’s name.
string
The capability that ran.
string
The version it ran on (
v3). A run stays on the version it started on, even across a deploy.string
queued, running, held (waiting for a person), completed, failed or cancelled.string | null
The session it is a turn of.
any
The input, masked if a guardrail masked it.
any
The output once
completed. A run that failed with invalid_output keeps the output the agent sent; a run whose output a guardrail blocked has output: null.object | null
object
Yours, as sent.
string
ISO 8601 times, UTC.
object | null
object
{llm_calls, input_tokens, output_tokens, cost} of the run’s model calls; cost in USD.Error codes
A failed run’serror.code is either the agent’s own code (see the agent contract) or one of these:
List runs
GET /v0/envs/{env}/agents/{agent}/runs
The agent’s runs, newest first. Experiment runs aren’t listed (get them by id).
integer
default:"20"
1–100.
string
A
run_id: only older runs.string
queued, running, held, completed, failed or cancelled.string
Only the runs of this end user.
422.
Follow a run
GET /v0/envs/{env}/runs/{run_id}/events
The run’s timeline as server-sent events. The stream ends after the final event; reconnect with Last-Event-ID to resume, 204 once you have seen the end.
Model call reports (
llm.call, tool.call, tool.result) can land just after the run ended. GET the run for its final usage.
Cancel a run
POST /v0/envs/{env}/runs/{run_id}/cancel
Cancel a queued, running or held run. It is cancelled at once: the agent’s run token stops working, its open hold is cancelled, and whatever the agent still answers is dropped. The cancel reaches the run’s unfinished child runs at every depth too; each one’s run.cancelled event says because: "parent r_N was cancelled". A run that completes or fails normally leaves its children running.
run.cancelled records who cancelled it ({by}: a user, a service account, or system).

