> ## 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

> A reusable, versioned configuration that defines an agent's persona and capabilities.

export const Flow = ({steps, note}) => <div style={{
  margin: "1.5rem 0"
}}>
    <div style={{
  display: "flex",
  flexWrap: "wrap",
  alignItems: "stretch",
  gap: "8px"
}}>
      {steps.map((s, i) => <div key={i} style={{
  display: "flex",
  alignItems: "center",
  gap: "8px"
}}>
          <div style={{
  border: "1px solid rgba(0,0,0,0.10)",
  padding: "10px 14px",
  background: s.accent ? "rgba(0,0,0,0.04)" : "#ffffff",
  minWidth: "84px",
  textAlign: "center"
}}>
            <div style={{
  fontSize: "13px",
  fontWeight: 500,
  color: "#000000"
}}>{s.t}</div>
            {s.d ? <div style={{
  fontSize: "12px",
  color: "#777777",
  marginTop: "2px"
}}>{s.d}</div> : null}
          </div>
          {i < steps.length - 1 ? <span style={{
  color: "#777777",
  fontSize: "16px"
}}>→</span> : null}
        </div>)}
    </div>
    {note ? <div style={{
  fontSize: "12px",
  color: "#777777",
  marginTop: "10px"
}}>{note}</div> : null}
  </div>;

An **agent** is a reusable, versioned configuration. It bundles the model, [harness](/docs/how-vetta-is-built#the-three-layers), system prompt, tools, skills, [computer](/docs/computer/index), and [budget](/docs/concepts/budgets) that shape how the agent behaves during a [session](/docs/concepts/sessions). You create an agent once and reference it by ID each time you start a session — the agent is the *definition*, the session is a single *run* of it.

## Create an agent

<CodeGroup>
  ```bash CLI theme={"system"}
  vetta agent create \
    --name "Refunder" \
    --model zai-org/GLM-5.2-FP8 \
    --harness pi \
    --computer box \
    --skill refund-policy \
    --budget-usd 50 --max-task-usd 5 --budget-period month \
    --window immediate \
    --system "You process refunds."
  ```

  ```typescript TypeScript theme={"system"}
  const computer = await vetta.computers.create({ name: "box", size: "medium" });

  const agent = await vetta.agents.create({
    name: "Refunder",
    model: "zai-org/GLM-5.2-FP8",
    harness: "pi",
    computer: computer.id,
    skills: ["refund-policy"],
    budget: { capMicroUsd: "50000000", maxTaskMicroUsd: "5000000", period: "month" }, // $50 / $5
    window: "immediate",
    system: "You process refunds.",
  });
  ```

  ```bash cURL theme={"system"}
  curl -fsSL https://api.vetta.sh/v1/agents \
    -H "authorization: Bearer $VETTA_API_KEY" \
    -H "content-type: application/json" \
    -d '{
      "name": "Refunder",
      "model": "zai-org/GLM-5.2-FP8",
      "harness": "pi",
      "computer": "cmp_...",
      "skills": ["refund-policy"],
      "budget": { "cap_micro_usd": 50000000, "max_task_micro_usd": 5000000, "period": "month" },
      "window": "immediate",
      "system": "You process refunds."
    }'
  ```
</CodeGroup>

The response echoes your configuration and adds `id`, `current_version`, `created_at`, `updated_at`, and `archived_at`. `current_version` starts at 1 and increments each time an update changes the agent.

## Define an agent as a file

An agent is a **declarative configuration**, so the recommended way to manage it is a checked-in **`.agent.yaml`** file. The whole config — model, harness, prompt, tools, budget, policies — lives in one file you can review, diff, and version-control alongside your code. The CLI reads it on `create`, `update`, and `apply`.

```yaml refunder.agent.yaml theme={"system"}
name: Refunder
description: Processes customer refunds within policy and escalates edge cases.
model:
  id: zai-org/GLM-5.2-FP8
  effort: medium
harness: pi
window: immediate
system: |
  You process refunds. Always confirm the order first, then apply the
  refund-policy skill. Escalate anything ambiguous rather than guessing.
# Or keep the prompt in its own file:
# system_file: ./refunder.system.md
computer: box            # a computer name or id
skills:
  - refund-policy
  - escalation-matrix
tools:
  default_config:
    permission: allow
  configs:
    bash:   { enabled: true, permission: ask }
    remove: { enabled: true, permission: ask }
budget:
  # authored in dollars for readability; the CLI converts to integer micro-USD on the wire
  cap_usd: 50
  max_task_usd: 5
  period: month
policies:
  primitives: { computer: true, browser: true, files: true }
  connections: { mode: allowlist, list: [crm, tracker] }
on_idle: https://acme.dev/hooks/refunder-idle
metadata:
  team: support
```

<CodeGroup>
  ```bash Create from file theme={"system"}
  # from a file, or piped over stdin
  vetta agent create -f refunder.agent.yaml
  vetta agent create < refunder.agent.yaml
  ```

  ```bash Apply (declarative) theme={"system"}
  # create-or-update by name; omits version → last write wins.
  # Ideal for a CI job that syncs checked-in agent definitions.
  vetta agent apply -f refunder.agent.yaml
  ```

  ```bash Export to file theme={"system"}
  # round-trip: write the live config back out as YAML
  vetta agent show Refunder --format yaml > refunder.agent.yaml
  ```
</CodeGroup>

<Info>
  **`apply` is the GitOps path.** It upserts by `name` and omits `version`, so the checked-in file is the source of truth (last write wins) — exactly what a CI apply loop wants. For interactive edits where you don't want to clobber a concurrent change, use `update` with `--expected-version` (a mismatch is a `409`). See [versioning](#versioning) below.
</Info>

## Agent, session, run

An agent is a durable definition; work happens in sessions that reference it. One agent backs many sessions and cron [deployments](/docs/capabilities/deployments), each independently budgeted, streamed, and controlled.

<Flow
  steps={[
{ t: "Agent", d: "definition · v1 → v2 → v3", accent: true },
{ t: "Session", d: "one run" },
{ t: "Events", d: "streamed" },
{ t: "Idle", d: "resume later" }
]}
  note="Versions are immutable snapshots; a running session pins the version it started on."
/>

## Versioning

Every change to an agent's configuration produces a new **immutable version**. A version is a frozen snapshot of the whole config — model, system prompt, tools, skills, window, budget, and metadata — identified by an integer that increments from 1. Nothing about a past version ever mutates, which is what lets a long-running session or a scheduled deployment keep behaving exactly as it did the day it started.

* **Optimistic concurrency.** Supply `expected_version` to apply the update only if nothing else changed it in the meantime; a mismatch returns `409` with `code: "version_conflict"`. Omit it to apply unconditionally (last write wins) — the path a declarative `apply` loop uses.
* **Omitted fields are preserved.** Send only what you want to change.
* **Array fields** (`tools`, `skills`, `identity`) are fully replaced by the new array.
* **No-op detection.** If an update produces no change, no new version is created.
* **Sessions and deployments pin a version.** A running session keeps the config it started with; a [deployment](/docs/capabilities/deployments) can pin a specific `agent_version` for staged rollout. New versions apply only to new work.

Each version is retrievable in full, so you can read or diff exactly what a past run used, and you can **roll back** by promoting a past version — rollback creates a *new* version whose config equals the target, rather than mutating history.

<CodeGroup>
  ```bash CLI theme={"system"}
  vetta agent update Refunder --system "You process refunds. Always confirm the order first."
  vetta agent versions Refunder                 # full history, newest first
  vetta agent versions Refunder --version 2     # the full config snapshot of v2
  vetta agent rollback Refunder --to 2          # creates a new version equal to v2
  ```

  ```typescript TypeScript theme={"system"}
  const updated = await vetta.agents.update(agent.id, {
    expectedVersion: agent.current_version,     // 409 version_conflict on a stale value
    system: "You process refunds. Always confirm the order first.",
  });

  const v2 = await vetta.agents.getVersion(agent.id, 2); // immutable snapshot
  await vetta.agents.rollback(agent.id, { toVersion: 2 });
  ```
</CodeGroup>

## Lifecycle

| Operation         | Behavior                                                                                               |
| ----------------- | ------------------------------------------------------------------------------------------------------ |
| **Update**        | Generates a new version when the configuration changes; optimistic-concurrency via `expected_version`. |
| **List versions** | Returns the full version history, newest first.                                                        |
| **Get version**   | Returns the immutable config snapshot of a specific version.                                           |
| **Roll back**     | Creates a new version whose config equals a past version.                                              |
| **Archive**       | Makes the agent read-only. Existing sessions keep running; new sessions cannot reference it.           |
| **Spend**         | Returns the agent's metered spend, optionally broken down by component.                                |

## Configuration reference

<ParamField path="name" type="string" required>
  A human-readable name for the agent.
</ParamField>

<ParamField path="model" type="string | object" required>
  The model that powers the agent. A model ID string, or an object such as `{ "id": "zai-org/GLM-5.2-FP8", "effort": "high" }`. See [Model router & inference](/docs/concepts/model-router).
</ParamField>

<ParamField path="harness" type="string" default="pi">
  The [harness](/docs/how-vetta-is-built#the-three-layers) — the agent loop that drives each turn. `pi` is the only value today and the default. The runtime beneath it (durability, tools, budget, policy) is the same whichever harness you pick.
</ParamField>

<ParamField path="budget" type="object" required>
  Spend limits, in integer micro-USD on the wire. An agent cannot be created without one. See [Budgets](/docs/concepts/budgets).

  <Expandable title="budget">
    <ParamField path="cap_micro_usd" type="integer" required>Total cap for the budget period, in micro-USD.</ParamField>
    <ParamField path="max_task_micro_usd" type="integer" required>Per-task ceiling, in micro-USD; a single session cannot exceed this.</ParamField>
    <ParamField path="period" type="string" required>`day`, `week`, or `month`.</ParamField>
  </Expandable>
</ParamField>

<ParamField path="system" type="string">
  A system prompt that defines the agent's behavior and persona. Distinct from the user messages that describe the work.
</ParamField>

<ParamField path="window" type="string" default="immediate">
  Default [completion window](/docs/concepts/completion-window): `immediate`, `priority`, or `loose`. Overridable per session.
</ParamField>

<ParamField path="computer" type="string">
  ID of a [computer](/docs/computer/index) the agent runs on.
</ParamField>

<ParamField path="skills" type="string[]">
  [Skills](/docs/capabilities/skills) that supply domain context with progressive disclosure.
</ParamField>

<ParamField path="tools" type="object">
  The [tools](/docs/capabilities/tools) available to the agent, as a single toolset object: a `default_config` plus per-tool `configs`, each entry `{ enabled, permission }` where `permission` is `allow`, `ask`, or `deny`. See [Policies](/docs/concepts/policies#per-tool-permission-policy). Built-ins are enabled by capability; [MCP](/docs/capabilities/tools#mcp-connector) and [connection](/docs/identity/connections) tools register under the same keys.
</ParamField>

<ParamField path="mcp_servers" type="object[]">
  MCP servers the agent can reach, referenced by [`mcp_toolset`](/docs/capabilities/tools#mcp-connector).
</ParamField>

<ParamField path="identity" type="string[]">
  One or more [identities](/docs/identity/overview) the agent can act as.
</ParamField>

<ParamField path="multiagent" type="object">
  <span>**Phase 3.**</span> A coordinator declaration listing the agents this agent can delegate to.
</ParamField>

<ParamField path="output_schema" type="object">
  A default JSON Schema for a [structured result](/docs/concepts/sessions#structured-results). When set, a session goes idle carrying a typed `structured_output`; a session can override it per run.
</ParamField>

<ParamField path="description" type="string">A description of what the agent does.</ParamField>
<ParamField path="metadata" type="object">Arbitrary key-value pairs for your own tracking.</ParamField>

<Card title="Next: runtime & durability" icon="cpu" href="/docs/concepts/runtime">
  How the harness drives each turn, and how the runtime makes it durable.
</Card>
