API reference

List, create, update, and delete configured agents.

Use harness management endpoints from trusted server code or an authorized admin surface.

Endpoints

  • GET /v1/harnesses lists configured agents visible to the Workspace key.
  • POST /v1/harnesses creates a configured agent.
  • GET /v1/harnesses/{id} reads one configured agent.
  • PUT /v1/harnesses/{id} updates one configured agent.
  • DELETE /v1/harnesses/{id} deletes one configured agent. A deleted agent stops at once and is removed 30 days later, with its plugins; until then it can be restored by emailing contact@harnessrouter.ai. A database connection it holds is removed at once, so a restored agent needs it entered again. Its tasks are not deleted with it.

Fields

name, base
Required. The base is one of the ids from GET /v1/bases.
base_label, default_model, system_prompt
The label shown for the base, the model a turn uses when the request names none, and the runtime agent's standing instructions.
mcp_servers, skills, plugins
MCP servers the agent may call, skills it may load, and installed Agent Plugins packages.
disabled_tools
Built-in tool names this agent may not use. How firmly that holds depends on the base; see below.
additional_headers
Header names a caller may pass on a task request. Only names are declared here; the values travel per request.
env
Variables every turn's shell and tools start with. See below.
environment
The environment id whose project every task reads at /env/<slug>.
max_step, timeout_seconds, max_cost_usd
Per-turn budgets. GET /v1/bases returns the defaults: 400 steps, 7200 seconds, 10 USD.

How firmly a disabled tool stays disabled

This depends on the base, and GET /v1/bases says which you are getting: every tool it lists carries an enforcement of either hard or instruction.

hard means the tool is denied by the agent's own runtime and the model cannot reach it. instruction means the runtime offers no per-tool switch, so the disabled list is written into the agent's instructions as a request it is expected to honour.

An instruction is not a boundary

On a base whose tools report instruction, treat the disabled list as a strong steer rather than a control you can rely on. Anything that must not happen belongs behind a credential the task never receives, or a base that enforces it as hard.

Load tools only when needed

An agent with many tools from its plugs can start each task with a short list instead of every tool definition: a few core tools, plus three tools it uses to find the rest, tool_search, tool_describe and tool_call. It finds, reads and calls everything else by name as it works, with the same permissions, approvals and logs as a direct call.

Set it per agent through the API, with lazy and pinned on POST /v1/harnesses/{id}/servers/plugs. The console does not show this setting.

lazy
true gives the short list; false lists every tool. Leave it out to keep the agent's current setting.
pinned
Tools listed by name on every task besides the core tools, at most 8. Name each one as the agent sees it, the plug and the tool joined by an underscore, such as browser_navigate; under tools the names stay bare. Leave it out to keep the current pins.
Fewer than 25 tools
The setting changes nothing, since listing them all costs less than a search. The browser alone has fewer, so the example below shows the request's shape and changes nothing on its own.
Tools left out
A tool you leave out of tools is never found, described or called.
The request's shape, with one pinned tool
POST /v1/harnesses/{id}/servers/plugs
{"plugs": ["browser"], "lazy": true, "pinned": ["browser_navigate"]}

The env channel

env is a map of variable names to values that every turn's shell and tools start with. A value takes one of three forms: a literal; $headers.X-Api-Key, which reads a header the caller sent on that task request and which must be declared in additional_headers; or secret:harness-mcp-<name>, the reference PUT /v1/mcp-secrets/{ref} returns when you store a secret with the service, where {ref} is a name you choose. A stored secret is scoped to your organization.

  • Up to 64 variables.
  • Names beginning HR_, HARNESS_, OPENAI_, ANTHROPIC_, GEMINI_, GOOGLE_, AWS_, AZURE_, LD_ or DYLD_ are reserved, so the platform's own wiring cannot be shadowed.
Values do not reach the model

An env value is given to the shell, never written into the agent's prompt, and is redacted from traces. A key a task needs can travel this way without becoming part of the conversation.

Create shape

Create configured agent
POST /v1/harnesses
Content-Type: application/json

{
  "name": "Contract Review Agent",
  "base": "claude-code",
  "default_model": "<allowed model id>",
  "system_prompt": "<runtime-agent instructions>",
  "mcp_servers": [],
  "skills": []
}

Environment and per-request secrets

A configured agent can carry an env map. Every shell command and tool the agent runs starts with those variables set, so a token, a key or any long exact value reaches the work without ever being written into the prompt. The agent reads it from the shell, and a value that came through a reference never reaches the trace, the stored response or the stream, even when the agent prints it.

A value is resolved on every turn. $headers.X-Name takes the header of that name from the request that started the turn, which must be listed in additional_headers. secret:harness-mcp-<name> (the reference PUT /v1/mcp-secrets/{ref} returns, where {ref} is a name you choose) takes that stored secret. Anything else is used as written, so keep literals to non-secrets such as a region or a mode.

Names
Letters, digits and underscores, up to 64 variables. Names the runtime sets for itself are refused: the HR_, HARNESS_, OPENAI_, ANTHROPIC_, GEMINI_, GOOGLE_, AWS_, AZURE_, LD_ and DYLD_ prefixes, PATH, HOME and the shell's own, the interpreters' import paths, the trust roots and the proxy variables.
Missing header
A $headers reference whose header is absent on a request leaves the variable unset, so a shell test for it says what happened.
Redaction
A value that came through a $headers or secret: reference is replaced with [redacted] in everything that leaves the sandbox: the response body, the stream, the trace and the stored record. A literal is not redacted.
Scope
A secret: reference reads only a secret stored through PUT /v1/mcp-secrets/{ref} in your own organization, never another organization's and never the platform's.
What it protects
The record, not the agent. A value the agent can read, it can also write to a file or send elsewhere if a prompt or a page it reads tells it to. Hand the agent a token scoped to the user and the task, short-lived and least privilege, exactly as you would to a person.
A configured agent with a per-request token
PUT /v1/harnesses/{id}
Content-Type: application/json

{
  "name": "Deploy Agent",
  "base": "codex",
  "additional_headers": ["X-Deploy-Token"],
  "env": {
    "DEPLOY_TOKEN": "$headers.X-Deploy-Token",
    "DEPLOY_REGION": "us-east-1"
  }
}

POST /v1/responses
X-Deploy-Token: <the token for this user>

{ "model": "{id}", "input": "Deploy the current build. The token is in $DEPLOY_TOKEN." }
Open standard

Creating, updating, and deleting configured agents through these endpoints is harness lifecycle management, which UHP places at conformance class Full in its Harnesses chapter. See harness management in the UHP Harnesses chapter.

Create API Key

Ready to run this against a live workspace? Keys take under a minute.