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

# Harnesses

> The agent loops an agent can run on — what each one can be admitted for, and what an idle session on it costs.

> [!NOTE]
>
> A **harness** is the agent loop itself: how context is managed, how tools are chosen, how a long task is decomposed and resumed. It is one field on an [agent](https://vetta.sh/docs/api/agents.md), and nothing else about your call changes when you change it. Unlike [models](https://vetta.sh/docs/api/models.md), this catalogue is a constant of the deploy — a harness needs an adapter compiled in — so it does not change without a release.

> [!NOTE]
>
> The loops themselves are described in [Harnesses](https://vetta.sh/docs/concepts/harnesses.md) — what each one is, and
> which of them holds a sandbox between turns. This page is the wire contract.

## The harness object

**base** `string`

The value you pass as `harness` on an agent.

**label** `string`

A display name, for a picker.

**location** `string`

`hosted` runs on our infrastructure. `local` runs on your own machine against your own logged-in account, and is not available to a hosted session.

**billing** `string`

`usage` is metered to your credit balance. `account` bills the account you are already signed in to, so it does not touch your balance.

**status** `string`

`ga`, or `preview` when the loop runs but its contract may still move.

**execution** `string`

Where the loop runs, and therefore **what an idle session costs**. `isolate` runs in the session itself and holds no sandbox between turns. `sandbox` runs the agent on a micro-VM, which the session holds across turns. `local` runs on your machine. This is a different question from `location`, which is about who operates it.

**runnable** `boolean`

Whether a session on it runs **on this deploy**. A harness whose agent is a process also needs a base image, which is per-environment — so the same harness can be runnable in one environment and not another, and this field answers for the one you are talking to. A published harness with `false` is refused when the session starts, with `501` naming the field — so a picker can show it disabled rather than let someone discover it by trying.

**capabilities** `object`

What the loop can be admitted for. See below.

## Capabilities

Harnesses differ, and the differences are load-bearing. Read them before you create an agent.

**approvals** `boolean`

The loop can hold a tool call and wait for a decision on [tool confirmations](https://vetta.sh/docs/api/sessions.md). A harness with `false` cannot serve a toolset whose permission is `ask`.

**structured\_output** `boolean`

The loop can enforce `structured_output_required`. **`vetta` publishes `true` here and cannot yet produce one** — the loop has no submit path, so the pairing is admitted by every gate and fails at the turn. Use `pi` for a typed answer. See [Known gaps](https://vetta.sh/docs/concepts/harness-capabilities.md#known-gaps).

**streaming\_deltas** `boolean`

The loop emits incremental `message.delta`[events](https://vetta.sh/docs/api/events.md). With `false` you still get `message.completed` — the answer arrives whole rather than as it is written.

**injected\_tools** `boolean`

The tools **Naive Managed Agents** contributes reach the loop's model — the [team tools](https://vetta.sh/docs/team/delegation.md), an agent's [`mcp_servers`](https://vetta.sh/docs/api/mcp), a [connected account's](https://vetta.sh/docs/api/connections.md) tools, social publishing and apps — all governed by the agent's `tools` policy under the same names. It does not say by which road: a loop Managed Agents hosts is handed them for the turn, while an agent that is a CLI process in a machine of its own is given a session-scoped tool endpoint to call and keeps its own file, shell and search tools alongside ours. Three limits apply on the second road: Managed Agents' own built-ins (web search and fetch, media generation, skill disclosure, `publish_file`, the managed browser) do not travel it, and — both following from `approvals: false` on those harnesses — a tool whose permission is `ask` is left out rather than gated, and `wait_for_agents` does not pause the turn (the coordinator parks once it goes idle and still opens its threads). See [Harness capabilities](https://vetta.sh/docs/concepts/harness-capabilities.md#platform-injected-tools).

> [!NOTE]
>
> Two configurations are refused earlier than the rest, at `POST`/`PATCH``/v1/agents`, because the agent's own configuration settles them: `multiagent` on a harness with `injected_tools: false` (the coordinator would have no `send_to_agent`) and a non-empty `mcp_servers` on the same (nothing would surface them). Both answer `400``validation_failed` naming the field to change. **No published harness declares `false`,** so neither refusal fires today; they stand as the guard for a base added later.

> [!NOTE]
>
> All four are on the object. `injected_tools` is the one that decides whether an agent can lead a [team](https://vetta.sh/docs/team/overview.md), because the team tools arrive the same way as [MCP servers](https://vetta.sh/docs/api/mcp.md) and [Connections](https://vetta.sh/docs/api/connections.md). The per-harness values for all four are in [Harness capabilities](https://vetta.sh/docs/concepts/harness-capabilities.md).

> [!NOTE]
>
> A session asking for a capability its harness does not declare is refused **at start** with a `400` naming `harness`. It is never a quiet best effort that looks like it worked — an `ask` toolset that silently became `allow` would remove your human-in-the-loop gate with no event and no error to notice it by.

## GET /v1/harnesses

Every harness, including those in preview and those not yet runnable.

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

```json theme={"system"}
{
  "data": [
    {
      "base": "pi",
      "label": "Pi",
      "location": "hosted",
      "billing": "usage",
      "status": "ga",
      "execution": "sandbox",
      "runnable": true,
      "capabilities": {
        "approvals": true,
        "structured_output": true,
        "streaming_deltas": true,
        "injected_tools": true
      }
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

The list is a hand-written table and fits one page, so `has_more` is always `false` — but the envelope is the same as every other listing, so one loop reads both this and [models](https://vetta.sh/docs/api/models.md).

## GET /v1/harnesses/\{id}

One harness, for when you already hold a base and want to know what it can be admitted for.

A base the catalogue does not publish is `404` — including an id reserved in a picker but not yet runnable as a harness.

## Choosing one

Two questions decide it, and they are separate:

* **What must the loop be able to do?** If your toolset uses `ask`, you need `approvals`. If you require a structured answer, you need `structured_output`. If the agent leads a team, declares MCP servers, or acts through a connected account, you need `injected_tools` — every published harness has it, so in practice this question is about the two limits that come with `approvals: false`.
* **What should an idle session cost?** A harness with `execution: "isolate"` holds no sandbox between turns. One with `"sandbox"` holds a micro-VM, because the agent *is* a process running on it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.