Skip to main content
A deploy builds a bundle into a new version of an agent, or promotes an existing version. Upload and promote need the admin role in the environment; reading agents and deploys needs any role. For what goes into a bundle, see agentos.yaml; for the panel side, see Deploying.

Version statuses

List agents

GET /v0/envs/{env}/agents

Get an agent

GET /v0/envs/{env}/agents/{agent} The agent with every version and the deploy that produced each one.

Upload a version

POST /v0/envs/{env}/agents/{agent}/versions Upload a bundle as the agent’s next version, as multipart/form-data in the field bundle. The first upload of a name creates the agent. The name in the bundle’s agentos.yaml must equal {agent} in the URL.
string
default:"live"
live: the version becomes the latest once it is healthy, and the previous one stops (its image is kept). candidate: it becomes a candidate; the live version stays live.
string
live or uploaded. Only matters when the upload’s config differs from the live version’s (see below).
The answer is 202 with the deploy_id. Follow the build with Follow a deploy. Once healthy, a live upload becomes the latest version; if the build or the health check fails, the live version is untouched.

When the config differs from the live version

The config in agentos.yaml (models.<role>, prompts.<name>, params.<key>) may have been changed since the live version was deployed — for example, a prompt edited on the Prompts tab, or a model chosen by an eval. To keep such a change from being overwritten by accident, an upload whose config differs from the live version’s is refused until you say which values to keep:
Nothing is stored. Upload again with config=live to keep the live values in the new version’s config, or config=uploaded to use the uploaded ones:
Only keys that both sides have and whose values differ count; a key only one side has is not a difference. The stored agentos.yaml text stays as uploaded either way. Without a live version, or without a difference, config is ignored.

Errors

An invalid bundle lists every problem at once, one per field:

Follow a deploy

GET /v0/deploys/{deploy_id}/events The build as server-sent events: deploy.log ({line}), deploy.step ({step, status}: the steps are spec, build, push and health, each running, passed or failed) and, last, deploy.finished ({status, error?}, succeeded or failed). The stream ends after deploy.finished.
Reconnect with Last-Event-ID to resume; 204 once you have seen deploy.finished.
In CI, follow the events until deploy.finished, then fail the job unless its status is succeeded. Or poll Get a deploy until status is no longer building.

Get a deploy

GET /v0/deploys/{deploy_id}
string
upload, promote, or config (a candidate made from an experiment’s override; see Evals).
string
building, succeeded or failed.
string | null
The version it built or promoted; null for a refused upload.
string
Why it failed; empty otherwise.
array
A refused upload’s field errors ([{field, message}], as in the 422 above); empty otherwise.
array
Things to fix that didn’t stop the deploy, such as secrets the version declares that have no value yet (see Secrets).

List deploys

GET /v0/envs/{env}/agents/{agent}/deploys The agent’s deploys — uploads (refused ones included), promotes and config deploys — newest first.
integer
default:"20"
1–100.
string
A deploy_id: only older deploys.
Each item has the shape of Get a deploy.

Promote a version

POST /v0/envs/{env}/agents/{agent}/versions/{version}/promote Make a version the latest: roll back to the previous (draining) or a retired version, or make a candidate live. Its container is started and health-checked first, without a new build; only then does it take traffic.