Skip to main content
Everything you can do in the AgentOS panel — deploy agents, start runs, decide approvals, run evals, read memory and the audit log — is also an HTTP API under /v0. This section is the reference for callers: your backend, scripts and CI.
Agents themselves talk to a different set of routes with their run token (x-agentos-run-token): holds, state, memory, files, events, child runs and results. Those are described with the agent contract in Build.

Base URL

Every route lives under your installation’s address plus /v0:
Most routes name an environment in the path: /v0/envs/{env}/…, where {env} is the environment’s name (default, staging, prod…). An object of another environment is a 404 there, even when you can see it elsewhere. A few routes are addressed by an id that already belongs to one environment, such as /v0/deploys/{deploy_id}. The OpenAPI description is at /v0/openapi.json, browsable at /v0/docs. Both need you to be signed in to the panel.

Authentication

Every request carries an API key. Scripts and other systems use a service account: a tenant admin creates one on the Users page, gives it a role in each environment it calls, and issues an API key. The key is shown once.
Revoking the key or deactivating the service account takes effect at once. See Users and API keys. A request without a valid key answers 401 unauthorized.

Roles

Access is decided per environment. Without any role there, every route of that environment answers 403 forbidden.

Errors

Every error under /v0 has the same JSON shape:
A 422 also lists every problem it found, one per field:
Some errors carry more keys, such as deploy_id on a refused upload or keys on a config_mismatch; each page lists them. Branch on code, not on message: messages are written for people and may change. A body that isn’t valid JSON, contains NaN or Infinity, has a number too large to represent, or has a NUL character (\u0000) in a string is a 422 invalid_request.

Unknown query parameters

Query parameters a route doesn’t know are refused with 422, naming each one, so a misspelt filter never silently returns everything:

Pagination

Lists are newest first and take limit and before. Pass the id of the last item you received as before to get the next page:
A page shorter than limit is the last one. Memory and the audit log page with a next value in the answer instead; their pages say how.

Idempotency

Starting a run takes an optional Idempotency-Key header (up to 200 characters). The same key from the same caller with the same body returns the same run instead of starting a second one, so a retry after a network error is safe. Reusing a key with a different body is a 409 idempotency_key_reused. See Runs.

Server-sent events

Deploys and runs can be followed live as server-sent events:
Each event has an id (its sequence number), an event (its type) and data ({seq, type, at, data}). The stream ends after the final event (deploy.finished, or run.completed / run.failed / run.cancelled). To resume after a dropped connection, reconnect with the header Last-Event-ID: <the last id you saw>; the stream replays what came after it. Once you have seen the final event, the route answers 204, so a browser EventSource stops reconnecting.

Endpoints