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, and nothing else about your call changes when you change it. Unlike models, this catalogue is a constant of the deploy — a harness needs an adapter compiled in — so it does not change without a release.
The loops themselves are described in Harnesses — what each one is, and
which of them holds a sandbox between turns. This page is the wire contract.
The harness object
string
The value you pass as
harness on an agent.string
A display name, for a picker.
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.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.string
ga, or preview when the loop runs but its contract may still move.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.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.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.boolean
The loop can hold a tool call and wait for a decision on tool confirmations. A harness with
false cannot serve a toolset whose permission is ask.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.boolean
The loop emits incremental
message.delta events. With false you still get message.completed — the answer arrives whole rather than as it is written.boolean
The tools Vetta contributes reach the loop’s model — the team tools, an agent’s
mcp_servers, a connected account’s 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 Vetta 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: Vetta’s 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.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.All four are on the object.
injected_tools is the one that decides whether an agent can lead a team, because the team tools arrive the same way as MCP servers and Connections. The per-harness values for all four are in Harness capabilities.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.has_more is always false — but the envelope is the same as every other listing, so one loop reads both this and models.
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 is404 — 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 needapprovals. If you require a structured answer, you needstructured_output. If the agent leads a team, declares MCP servers, or acts through a connected account, you needinjected_tools— every published harness has it, so in practice this question is about the two limits that come withapprovals: 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.