Skip to main content
A run is one call of one capability of an agent. You start it with an input that must match the capability’s input schema; AgentOS calls the agent’s live version and records the output or error, every model call with its tokens and cost, and every event along the way. Starting and cancelling runs needs the member or admin role; reading them needs any role.

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.
object
Your own tags, returned with the run and in webhooks. An object of at most 16 KiB.

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.
Without either, the answer is 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 an Idempotency-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.
Never put an API key in a browser. Call this from your backend and relay the response.
  • The response carries the agent’s Content-Type, Cache-Control, Content-Language, Content-Disposition, X-Accel-Buffering and X-Vercel-AI-* headers (no others), plus X-AgentOS-Run-Id with the run’s id and Content-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-Key names a run started without passthrough — the answer is the run, as ?wait=true gives it.
  • The relayed bytes are kept for 10 minutes after the agent’s last write, so replaying the same Idempotency-Key within 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:
A masking guardrail doesn’t refuse the run; it stores the input masked.

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.
string | null
The end user it is for: its session’s, or for a child run its parent’s. See Sessions.
string | null
For a child run, the run that started it.
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
{code, message} once failed or cancelled. See Error codes.
object
Yours, as sent.
string
ISO 8601 times, UTC.
object | null
While held: {hold_id, intent, expires_at}, the hold it waits on. Decide it with the Holds API.
object
{llm_calls, input_tokens, output_tokens, cost} of the run’s model calls; cost in USD.

Error codes

A failed run’s error.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.
Any other query parameter is a 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.
The answer is the run. run.cancelled records who cancelled it ({by}: a user, a service account, or system).