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

# Sessions

> A single, directly-controlled run of an agent.

A session is one run of an [agent](/docs/concepts/agents). You control it directly: send input, stream [events](/docs/concepts/events-and-streaming), interrupt it, adjust its budget, and read the files it produced. State is durable — a session can run for hours, survive restarts, and sit idle for days at storage cost only.

## Lifecycle

Sessions progress through these statuses:

| Status      | Description                                                                                                                                              |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `queued`    | Created and accepted; the first turn has not started yet.                                                                                                |
| `running`   | The agent is actively executing a turn.                                                                                                                  |
| `idle`      | The turn yielded control and the session is **resumable** — waiting for input, a tool confirmation, or its next scheduled fire. Carries a `stop_reason`. |
| `completed` | The agent declared the task done. Non-`running`, like `idle`.                                                                                            |
| `failed`    | An unrecoverable error ended the run.                                                                                                                    |
| `cancelled` | The run was canceled with `cancel`. Terminal.                                                                                                            |

<Note>
  There is no mandatory "deliver" step. When a turn yields control the session goes **`idle`** with a `stop_reason` and stays resumable — you can send more input for days. It reaches **`completed`** only when the agent declares the task done. Anything worth keeping is written to [Files](/docs/capabilities/files) via `publish_file`; scratch work stays in the session's sandbox.
</Note>

## Create a session

A session inherits its agent's configuration. The simplest create is empty and starts `idle`, then you send it work. To start a session **`running` in a single call**, pass an initial `message` — it is enqueued as the first input and the agent begins its first turn immediately.

<CodeGroup>
  ```bash CLI theme={"system"}
  # One call: create and start running
  vetta session create --agent Refunder --message "Refund order #4821"
  ```

  ```typescript TypeScript theme={"system"}
  const session = await vetta.sessions.create({
    agent: agent.id,
    message: "Refund order #4821",
  });
  ```

  ```bash cURL theme={"system"}
  curl -fsSL https://api.vetta.sh/v1/sessions \
    -H "authorization: Bearer $VETTA_API_KEY" \
    -H "content-type: application/json" \
    -d '{ "agent_id": "agt_7Q...", "message": "Refund order #4821" }'
  ```
</CodeGroup>

You can still create a session without input and drive it in two steps — useful when you want to attach resources or start streaming before the first turn:

<CodeGroup>
  ```bash CLI theme={"system"}
  vetta session create --agent Refunder --window immediate --budget-usd 2.00
  # ... then, when ready ...
  vetta session send --session $SID --message "Refund order #4821"
  ```

  ```typescript TypeScript theme={"system"}
  const session = await vetta.sessions.create({
    agent: agent.id,
    window: "immediate",
    budgetMicroUsd: "2000000", // $2.00 — whole micro-USD; never a bare number
  });
  await session.send("Refund order #4821");
  ```
</CodeGroup>

Both forms accept the same creation options — completion window (`immediate` / `priority` / `loose`), a session budget, agent overrides, and the attachable resources below.

### Attach resources at create

Beyond the agent's own configuration, a create call can bind extra resources to the session:

| Field       | What it does                                                                                                                                                                                                                          |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `computer`  | *(coming soon)* Reuse an existing [computer](/docs/capabilities/computer) (`cmp_...`) instead of provisioning a fresh sandbox.                                                                                                             |
| `skills`    | *(coming soon)* [Skills](/docs/capabilities/skills) to mount for this run, on top of the agent's — today skills are set on the agent.                                                                                                      |
| `vault_ids` | *(coming soon)* [Vaults](/docs/identity/overview) whose secrets the session may read. Today a session reaches vault credentials through the [MCP connector](/docs/capabilities/tools#mcp-connector); a session-level grant is not yet accepted. |
| `outcome`   | *(Phase 4)* An outcome (`out_...`) to grade the run against a rubric.                                                                                                                                                                 |
| `metadata`  | Arbitrary key-value pairs stored on the session and echoed on its events.                                                                                                                                                             |

```typescript TypeScript theme={"system"}
const session = await vetta.sessions.create({
  agent: agent.id,
  message: "Draft the Q3 refund report",
  computer: "cmp_3f...",
  skills: ["pdf-forms"],
  outcome: "out_9k...",            // Phase 4
  metadata: { ticket: "OPS-4821" },
});
```

### Override agent configuration for a session

*(Coming soon.)* Session-local `overrides` for the agent's `model`, `system`, `skills`, `tools`, or `computer` are not yet accepted on create — today you pin behavior with `agent_version` or create a new agent version. When overrides land they will be **session-local** and never propagate back to the agent or its [versions](/docs/concepts/agents#versioning).

```typescript TypeScript theme={"system"}
const session = await vetta.sessions.create({
  agent: agent.id,
  overrides: { model: "zai-org/GLM-5.2-FP8", system: "Escalate anything ambiguous." },
});
```

Override semantics:

* **Arrays replace in full — they are not merged.** Passing `skills` or `tools` in `overrides` swaps the agent's list wholesale rather than unioning with it.
* **`model` cannot be cleared.** You may point a session at a different model, but every session has one; passing an empty value is rejected.
* **Nothing flows back.** When the session ends, the agent definition is exactly as it was before.

## Send work and stream

```typescript TypeScript theme={"system"}
await session.send("Refund order #4821");

for await (const e of session.stream()) {
  if (e.type === "message.delta") process.stdout.write(e.text);
  if (e.type === "tool.completed") console.log(`\n[tool] ${e.name}`);
  if (e.type === "session.idle") break;
}
```

The stream is resumable by **sequence**: reconnect with `session.stream({ fromSeq })` to replay everything after a `seq` you already handled — no gaps, no duplicates. See [Events & streaming](/docs/concepts/events-and-streaming).

## Session budgets

A session can carry its own cap, independent of the agent's period budget. When the running total reaches the cap, the session **pauses**: it goes `idle` with `stop_reason: "budget_paused"` and stops pricing new calls. Raising the cap — or removing it entirely — **auto-resumes** the paused session from exactly where it stopped, with no need to re-send the last message. See [Budgets](/docs/concepts/budgets).

```bash CLI theme={"system"}
vetta session budget --session $SID --usd 5.00   # raise → auto-resumes
```

## Stop reasons

Every time a session goes `idle`, the `session.idle` [event](/docs/concepts/events-and-streaming) and the session record carry a `stop_reason` — a string describing why the turn ended:

| `stop_reason`         | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                  |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `end_turn`            | The agent finished the turn and has nothing left to do. The normal, healthy resting state.                                                                                                                                                                                                                                                                                                                               |
| `awaiting_input`      | The turn ended with nothing left to do and the session is waiting for whatever you send next. Nothing specific is owed — when the agent needs a particular answer it reports `awaiting_answer` instead.                                                                                                                                                                                                                  |
| `awaiting_approval`   | The agent called a tool gated by an [`ask` policy](/docs/concepts/policies) and is waiting on your confirmation. Reply with an allow/deny to resume — see [Awaiting-approval loop](/docs/concepts/session-operations#awaiting-approval-loop).                                                                                                                                                                                      |
| `budget_paused`       | A [session or agent budget](/docs/concepts/budgets) cap was reached. Raise or remove the cap to auto-resume.                                                                                                                                                                                                                                                                                                                  |
| `interrupted`         | You [interrupted](/docs/concepts/session-operations#interrupting) the turn; it stopped at the next commit boundary.                                                                                                                                                                                                                                                                                                           |
| `max_iterations`      | The turn hit its step/iteration cap for a single slice. Send another message to continue.                                                                                                                                                                                                                                                                                                                                |
| `context_exhausted`   | The turn produced neither a message nor a tool call. Reported honestly rather than as `end_turn`, which would claim the task was finished.                                                                                                                                                                                                                                                                               |
| `awaiting_delegation` | A [coordinator](/docs/team/coordinator) yielded because every thread it [delegated](/docs/team/delegation) to is still running. Nobody is being asked for anything, so no reply unblocks it — the children finishing does.                                                                                                                                                                                                         |
| `awaiting_answer`     | The agent asked you a question and cannot continue without the answer. What is being asked is a `pending_actions` entry with `kind: "question"`, carrying the prompt and one to three fields — see [Awaiting-answer loop](/docs/concepts/session-operations#awaiting-answer-loop). Reported only when *every* parked row is a question; a session parked on both reports `awaiting_approval` and still carries the questions. |
| `error`               | An unrecoverable error ended the turn.                                                                                                                                                                                                                                                                                                                                                                                   |

## Retrieving results after idle

When a session goes `idle`, its durable outputs are the [files it published](/docs/capabilities/files), its [event history](/docs/concepts/events-and-streaming), and — when an [output schema](#structured-results) is set — a typed `structured_output`. Scratch work stays in the session's sandbox and is not returned — the agent promotes anything worth keeping with `publish_file`.

<CodeGroup>
  ```bash CLI theme={"system"}
  vetta file list --session $SID            # artifacts this session published
  vetta session events --session $SID        # replay the full transcript (resumable --from-seq)
  ```

  ```typescript TypeScript theme={"system"}
  const s = await vetta.sessions.get(session.id);
  if (s.status === "idle") {
    const files = await vetta.files.list({ sessionId: s.id });
    for (const f of files) console.log(f.id, f.name);   // fil_...
  }
  ```
</CodeGroup>

## Structured results

By default an agent's durable output is the files it published plus its event history. When you also want a machine-readable result, set an **`output_schema`** (a JSON Schema) — on the agent as a default, or per session as an override. When the session goes `idle` having satisfied the schema, the session object carries a typed **`structured_output`** object alongside its files and events, so a caller can read the result directly instead of parsing the transcript.

```typescript TypeScript theme={"system"}
const session = await vetta.sessions.create({
  agent: agent.id,
  message: "Refund order #4821 and report the outcome.",
  outputSchema: {
    type: "object",
    properties: {
      refunded: { type: "boolean" },
      amount_micro_usd: { type: "integer" },
    },
    required: ["refunded"],
  },
});

const s = await vetta.sessions.get(session.id);
if (s.status === "idle" && s.structured_output) {
  console.log(s.structured_output.refunded, s.structured_output.amount_micro_usd);
}
```

The same typed `structured_output` is included on the [`session.idle` deployment payload](/docs/capabilities/deployments), so an unattended fire returns a structured result without a transcript replay.

## Cost and usage

Every session object carries its running cost and token usage, so you never have to reconstruct spend from the transcript. `consumed_micro_usd` is the cumulative cost in integer [micro-USD](/docs/concepts/budgets), and `token_usage` breaks the model tokens into the five metered tiers — `input`, `cache_write`, `cache_read`, `output`, and `reasoning`. A `session.usage` [event](/docs/concepts/events-and-streaming) is emitted before every idle or terminal transition, and the fuller export path is described in [Observability](/docs/capabilities/observability).

```json theme={"system"}
{
  "id": "ses_4a...",
  "status": "idle",
  "stop_reason": "end_turn",
  "consumed_micro_usd": 12530000,
  "token_usage": { "input": 41230, "cache_write": 2048, "cache_read": 18900, "output": 3120, "reasoning": 900 },
  "last_seq": 128
}
```

## Update the agent mid-session

*(Coming soon.)* Session-local updates to `tools` and `mcp_servers` while a session is `idle` are not yet served — today, changing tools means a new agent version (or a new session). When this lands, updates will be a full replacement of the provided array and session-local.

## Create parameters

<ParamField path="agent" type="string" required>The [agent](/docs/concepts/agents) to run. Accepts a name or an `agt_` id.</ParamField>
<ParamField path="message" type="string">Initial input. When present, the session starts `running` instead of `idle`.</ParamField>
<ParamField path="window" type="string" default="agent default">Override the [completion window](/docs/concepts/completion-window): `immediate`, `priority`, or `loose`.</ParamField>
<ParamField path="budget_usd" type="number">A session-local spend cap. On the wire this is sent as integer micro-USD (`budget_micro_usd`); the CLI `--budget-usd` and SDK helpers convert dollars client-side. Reaching it pauses the session with `stop_reason: "budget_paused"`.</ParamField>
<ParamField path="output_schema" type="object">A JSON Schema for a [structured result](#structured-results). Overrides the agent's default. When set, the idle session carries a typed `structured_output`.</ParamField>
<ParamField path="overrides" type="object">*(coming soon)* Session-local replacements for the agent's `model`, `system`, `skills`, `tools`, or `computer`. Arrays replace in full; `model` cannot be cleared.</ParamField>
<ParamField path="computer" type="string">*(coming soon)* An existing computer (`cmp_...`) to attach instead of a fresh sandbox.</ParamField>
<ParamField path="skills" type="string[]">*(coming soon)* Skills to mount for this run.</ParamField>
<ParamField path="vault_ids" type="string[]">*(coming soon)* Vaults the session may read secrets from — not yet accepted on create.</ParamField>
<ParamField path="outcome" type="string">*(Phase 4)* An outcome (`out_...`) to grade the run against a rubric.</ParamField>
<ParamField path="metadata" type="object">Arbitrary key-value pairs stored on the session and echoed on its events.</ParamField>

<Card title="Next: session operations" icon="gear" href="/docs/concepts/session-operations">
  Retrieve, list, interrupt, archive, and delete sessions.
</Card>
