> ## Documentation Index
> Fetch the complete documentation index at: https://vetta.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Agents

> Create, version, run, and inspect reusable agent configurations.

An **agent** is a reusable, versioned configuration: a model, a system prompt, a set of tools and skills, a completion window, and a budget. Sessions and deployments run against an agent. Every update is captured as an immutable [agent version](#versioning) with optimistic concurrency.

## The agent object

<ResponseField name="id" type="string">Unique id (e.g. `agt_01H...`).</ResponseField>
<ResponseField name="object" type="string">Always `agent`.</ResponseField>
<ResponseField name="name" type="string">Human-readable name.</ResponseField>
<ResponseField name="harness" type="string">The [harness](/docs/how-vetta-is-built#the-three-layers) — the agent loop. [`GET /v1/harnesses`](/docs/api/harnesses) publishes the set, what each one can be admitted for, and whether it holds a sandbox between turns.</ResponseField>
<ResponseField name="model" type="string">Model identifier, e.g. `zai-org/GLM-5.2-FP8`. See [the model router](/docs/concepts/model-router).</ResponseField>
<ResponseField name="window" type="string">Default [completion window](/docs/concepts/completion-window): `immediate | priority | loose`.</ResponseField>
<ResponseField name="system" type="string">System prompt.</ResponseField>

<ResponseField name="tools" type="object">
  The toolset configuration. See [Tools](/docs/capabilities/tools).

  <Expandable title="tools">
    <ResponseField name="default_config" type="object">Default `{ permission }` applied to every tool unless overridden. `permission` ∈ `allow` (run silently) · `ask` (pause → `tool.confirm` [event](/docs/api/events)) · `deny` (tool is not offered to the model at all).</ResponseField>
    <ResponseField name="configs" type="object">Per-tool overrides keyed by tool name — a [built-in](/docs/capabilities/tools#built-in-tools) (`bash`, `browser`, `web_search`, `generate_image`, …) or a namespaced `<server>.<tool>`. Each entry is `{ enabled, permission, config? }`.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="mcp_servers" type="object[]">Attached MCP servers the agent may call.</ResponseField>
<ResponseField name="skills" type="string[]">Attached [skill](/docs/api/skills) references. Each entry is a slug or id, optionally suffixed `@version` to pin an immutable version (e.g. `refund-policy@3`). An unpinned reference resolves to the skill's latest version at session start.</ResponseField>
<ResponseField name="multiagent" type="boolean">Whether the agent may coordinate sub-agents.</ResponseField>

<ResponseField name="budget" type="object">
  Required spend controls.

  <Expandable title="budget">
    <ResponseField name="cap_micro_usd" type="integer">Ceiling for the period, in micro-USD.</ResponseField>
    <ResponseField name="max_task_micro_usd" type="integer">Ceiling for a single session/task, in micro-USD.</ResponseField>
    <ResponseField name="period" type="string">Reset window: `day | week | month`.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="output_schema" type="object | null">Optional JSON Schema the agent's final result must satisfy. Sessions inherit it as their default and may override it per run. See [Structured outputs](/docs/capabilities/structured-outputs).</ResponseField>
<ResponseField name="structured_output_required" type="boolean">Whether a run that cannot produce an object conforming to `output_schema` is a failure rather than a plain-text answer. Sessions inherit it and may override it per run.</ResponseField>
<ResponseField name="description" type="string | null">Optional longer description.</ResponseField>
<ResponseField name="metadata" type="object">Arbitrary key/value pairs you attach.</ResponseField>
<ResponseField name="current_version" type="integer">Monotonic version counter. Pass this as `expected_version` on update for optimistic concurrency.</ResponseField>
<ResponseField name="created_at" type="string">Creation timestamp.</ResponseField>

## Create an agent

`POST /v1/agents` → `201 Created`.

<ParamField body="name" type="string" required>Human-readable name.</ParamField>
<ParamField body="model" type="string" required>Model identifier.</ParamField>
<ParamField body="budget" type="object" required>Spend controls (`cap_micro_usd`, `max_task_micro_usd`, `period`). Agents cannot be created without a budget.</ParamField>
<ParamField body="harness" type="string">Defaults to `"pi"`. A harness the deploy cannot run is refused when the session starts, naming the field — see [harnesses](/docs/api/harnesses).</ParamField>
<ParamField body="window" type="string">Default completion window (`immediate | priority | loose`). Defaults to `immediate`.</ParamField>
<ParamField body="system" type="string">System prompt.</ParamField>
<ParamField body="tools" type="object">Toolset config — a `default_config` plus per-tool `configs`. See [the toolset schema](/docs/capabilities/tools).</ParamField>
<ParamField body="mcp_servers" type="object[]">MCP servers to attach.</ParamField>
<ParamField body="skills" type="string[]">Skills to attach. Each entry is a slug/id, optionally `@version` to pin (e.g. `refund-policy@3`).</ParamField>
<ParamField body="multiagent" type="boolean">Enable sub-agent coordination. Defaults to `false`.</ParamField>
<ParamField body="output_schema" type="object">JSON Schema the final result must satisfy. Defaults to `null`. See [Structured outputs](/docs/capabilities/structured-outputs).</ParamField>
<ParamField body="structured_output_required" type="boolean">Treat a non-conforming result as a failure rather than answering in prose. Defaults to `false`; needs an `output_schema`.</ParamField>
<ParamField body="description" type="string">Longer description. Defaults to `null`.</ParamField>
<ParamField body="metadata" type="object">Arbitrary metadata.</ParamField>

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -fsSL https://api.vetta.sh/v1/agents \
    -H "authorization: Bearer sk_live_..." \
    -H "content-type: application/json" \
    -H "idempotency-key: $(uuidgen)" \
    -d '{
      "name": "Refunder",
      "model": "zai-org/GLM-5.2-FP8",
      "window": "immediate",
      "system": "You process refunds.",
      "tools": {
        "default_config": { "permission": "allow" },
        "configs": {
          "browser": { "enabled": true, "permission": "ask", "config": { "allowed_domains": ["*.example.com"] } }
        }
      },
      "skills": ["refund-policy@3"],
      "budget": { "cap_micro_usd": 50000000, "max_task_micro_usd": 5000000, "period": "month" }
    }'
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={"system"}
  {
    "id": "agt_01H8XK...",
    "object": "agent",
    "name": "Refunder",
    "harness": "pi",
    "model": "zai-org/GLM-5.2-FP8",
    "window": "immediate",
    "system": "You process refunds.",
    "tools": {
      "default_config": { "permission": "allow" },
      "configs": {
        "browser": { "enabled": true, "permission": "ask", "config": { "allowed_domains": ["*.example.com"] } }
      }
    },
    "mcp_servers": [],
    "skills": ["refund-policy@3"],
    "multiagent": false,
    "budget": { "cap_micro_usd": 50000000, "max_task_micro_usd": 5000000, "period": "month" },
    "output_schema": null,
    "description": null,
    "metadata": {},
    "current_version": 1,
    "created_at": "2026-08-20T17:00:00Z"
  }
  ```
</ResponseExample>

## Retrieve an agent

`GET /v1/agents/{id}` → `200 OK` with the current configuration, including `current_version`.

```bash theme={"system"}
curl -fsSL https://api.vetta.sh/v1/agents/agt_01H8XK... \
  -H "authorization: Bearer sk_live_..."
```

## List agents

`GET /v1/agents` → `200 OK`, cursor-paginated. See [Pagination](/docs/api/pagination).

```json Response theme={"system"}
{
  "data": [ { "id": "agt_01H...", "name": "Refunder", "current_version": 3 } ],
  "has_more": false,
  "next_cursor": null
}
```

## Update an agent

`PATCH /v1/agents/{id}` → `200 OK`. Applies a partial update and creates a new immutable version. A no-op update creates no new version.

Updates use **optimistic concurrency**: pass the `expected_version` you read. If it no longer matches `current_version`, the API returns `409` with code `version_conflict` and applies nothing. **Omitting `expected_version`** performs an unconditional, last-write-wins apply — use this for declarative CI that reconciles an `.agent.yaml` toward a desired state.

<ParamField body="expected_version" type="integer">The `current_version` you last read. Omit for an unconditional apply.</ParamField>
<ParamField body="system" type="string">Any subset of the mutable fields (`name`, `system`, `model`, `window`, `tools`, `mcp_servers`, `skills`, `multiagent`, `budget`, `output_schema`, `structured_output_required`, `description`, `metadata`). Renaming is deliberately not a config change: a patch that only sets `name` mints no new version.</ParamField>

```bash theme={"system"}
curl -fsSL -X PATCH https://api.vetta.sh/v1/agents/agt_01H8XK... \
  -H "authorization: Bearer sk_live_..." \
  -H "content-type: application/json" \
  -d '{ "expected_version": 1, "system": "You process refunds. Confirm the order first." }'
```

Returns the full [agent object](#the-agent-object) at its new version:

```json Response theme={"system"}
{ "id": "agt_01H8XK...", "object": "agent", "current_version": 2, "system": "You process refunds. Confirm the order first." }
```

### Version conflict (409)

If another writer advanced the version, you get:

```json 409 Conflict theme={"system"}
{
  "error": {
    "type": "conflict",
    "code": "version_conflict",
    "message": "expected_version 1 does not match current_version 2.",
    "request_id": "req_01H9ZZ...",
    "param": "expected_version"
  }
}
```

Refetch the agent, re-apply your change against the fresh `current_version`, and retry.

## The agent-version object

Each update snapshots the full config into an immutable **agent version**. Versions never change once written.

<ResponseField name="version" type="integer">Monotonic version number.</ResponseField>
<ResponseField name="created_at" type="string">When this version was created.</ResponseField>
<ResponseField name="created_by" type="object">The principal that created the version — `{ "type": "user" | "key" | "system", "id": "..." }`.</ResponseField>
<ResponseField name="model" type="string">Model identifier at this version.</ResponseField>
<ResponseField name="system" type="string">System prompt at this version.</ResponseField>
<ResponseField name="window" type="string">Completion window at this version.</ResponseField>
<ResponseField name="tools" type="object">Toolset config at this version.</ResponseField>
<ResponseField name="mcp_servers" type="object[]">MCP servers at this version.</ResponseField>
<ResponseField name="skills" type="string[]">Skill references at this version.</ResponseField>
<ResponseField name="multiagent" type="boolean">Sub-agent coordination flag at this version.</ResponseField>
<ResponseField name="budget" type="object">Budget at this version.</ResponseField>
<ResponseField name="output_schema" type="object | null">Output schema at this version.</ResponseField>
<ResponseField name="structured_output_required" type="boolean">Whether a conforming object was required at this version.</ResponseField>
<ResponseField name="description" type="string | null">Description at this version.</ResponseField>
<ResponseField name="metadata" type="object">Metadata at this version.</ResponseField>

## List versions

`GET /v1/agents/{id}/versions` → `200 OK`. The full immutable version history in one page: this list is **not** paginated — `limit` and `after` are ignored, and the reply always carries `has_more: false`, `next_cursor: null`. Each row is a whole [agent-version object](#the-agent-version-object); versions are addressed by their `version` number, not by an id.

```json Response theme={"system"}
{
  "data": [
    { "version": 2, "created_at": "2026-08-20T18:00:00Z", "created_by": { "type": "user", "id": "usr_01H..." }, "system": "You process refunds. Confirm the order first." },
    { "version": 1, "created_at": "2026-08-20T17:00:00Z", "created_by": { "type": "user", "id": "usr_01H..." }, "system": "You process refunds." }
  ],
  "has_more": false,
  "next_cursor": null
}
```

## Retrieve a version

`GET /v1/agents/{id}/versions/{n}` → `200 OK` with the full [agent-version object](#the-agent-version-object) for version `n`. Use it to inspect or diff a past configuration.

```bash theme={"system"}
curl -fsSL https://api.vetta.sh/v1/agents/agt_01H8XK.../versions/1 \
  -H "authorization: Bearer sk_live_..."
```

```json Response theme={"system"}
{
  "version": 1,
  "created_at": "2026-08-20T17:00:00Z",
  "created_by": { "type": "user", "id": "usr_01H..." },
  "model": "zai-org/GLM-5.2-FP8",
  "system": "You process refunds.",
  "window": "immediate",
  "tools": { "default_config": { "permission": "allow" }, "configs": {} },
  "mcp_servers": [],
  "skills": ["refund-policy@3"],
  "multiagent": false,
  "budget": { "cap_micro_usd": 50000000, "max_task_micro_usd": 5000000, "period": "month" },
  "output_schema": null,
  "structured_output_required": false,
  "description": null,
  "metadata": {}
}
```

## Roll back to a version

`POST /v1/agents/{id}/rollback` → `200 OK`. Creates a **new** version whose config equals an earlier one — history is never rewritten. Returns the full [agent object](#the-agent-object) at that new version.

<ParamField body="to_version" type="integer" required>The version whose config to restore.</ParamField>
<ParamField body="expected_version" type="integer">The `current_version` you last read, for optimistic concurrency. Omit for an unconditional rollback.</ParamField>

```bash theme={"system"}
curl -fsSL https://api.vetta.sh/v1/agents/agt_01H8XK.../rollback \
  -H "authorization: Bearer sk_live_..." \
  -H "content-type: application/json" \
  -d '{ "to_version": 1, "expected_version": 2 }'
```

```json Response theme={"system"}
{ "id": "agt_01H8XK...", "object": "agent", "current_version": 3 }
```

## Spend

`GET /v1/agents/{id}/spend` → `200 OK`. Metered spend for the current budget period, in micro-USD, optionally broken down by component with `?by=component`.

```json Response theme={"system"}
{
  "agent_id": "agt_01H8XK...",
  "period": "month",
  "spent_micro_usd": 12418700,
  "by_component": { "model": 11902000, "computer": 481000, "search": 6474, "media": 390000 }
}
```

## Delete an agent

`DELETE /v1/agents/{id}` → `200 OK`. Removes the agent. Version history is retained for existing sessions.

```bash theme={"system"}
curl -fsSL -X DELETE https://api.vetta.sh/v1/agents/agt_01H8XK... \
  -H "authorization: Bearer sk_live_..."
```

```json Response theme={"system"}
{ "id": "agt_01H8XK...", "object": "agent", "deleted": true }
```

<Card title="Run an agent" icon="play" href="/docs/api/sessions">
  Create a session to run an agent directly.
</Card>
