# Agent Harnesses

An agent harness is the Sandbox0 runtime adapter behind a Managed Agents session.

The public API still uses the Claude Managed Agents object model. The harness decides where the agent loop runs, which model API shape it expects, how credentials are projected, and how tool events are mapped back to the Managed Agents event stream.

Official references:

- [Claude Managed Agents quickstart](https://platform.claude.com/docs/en/managed-agents/quickstart)
- [Claude Managed Agents agent setup](https://platform.claude.com/docs/en/managed-agents/agent-setup)

## Execution Models

Sandbox0 supports two execution models.

| Model | How it works | Harnesses |
|-------|--------------|---------|
| Agent in sandbox | The agent runtime process runs inside the per-session Sandbox0 sandbox. The sandbox contains the agent process, workspace, tools, and harness state. | `claude`, `codex` |
| Sandbox as tool | A resident runtime service runs the agent loop outside the sandbox. The sandbox is claimed lazily and exposed to the agent as tools such as `bash`. | `openai-agents` |

Use agent in sandbox when you want the agent process itself to live with the workspace. This is the most direct fit for coding agents that expect local files, shell commands, home-directory state, and long-lived process state inside the sandbox.

Use sandbox as tool when you want to embed an agent into a product workflow or control plane. The agent harness stays in a managed runtime service, while Sandbox0 provides isolated tool execution only when the agent needs to inspect files or run commands.

## Supported Harnesses

| Harness | Execution model | Runtime adapter | Model API shape | Best fit |
|--------|-----------------|-----------------|-----------------|----------|
| `claude` | Agent in sandbox | Claude Agent SDK wrapper | Anthropic-compatible | Claude Code style coding agents and Anthropic-compatible providers |
| `codex` | Agent in sandbox | Codex app-server wrapper | OpenAI-compatible | Codex app-server sessions that should keep Codex state inside the workspace |
| `openai-agents` | Sandbox as tool | Resident OpenAI Agents Python runtime | OpenAI Responses-compatible | Product copilots and agent workflows built on the OpenAI Agents SDK |

## Retry Behavior

All supported harnesses report observable automatic retry attempts through the same Managed Agents events: `session.error` with `error.retry_status.type = "retrying"`, `session.status_rescheduled`, then `session.status_running` if the run resumes.

| Harness | Retry signal used by Sandbox0 |
|--------|-------------------------------|
| `claude` | Claude Agent SDK `system` messages with `subtype = "api_retry"` |
| `codex` | Codex app-server `error` notifications with `willRetry = true` |
| `openai-agents` | OpenAI Agents SDK runner-managed `ModelRetrySettings` policy decisions |

Sandbox0 disables hidden OpenAI Python client retries for the `openai-agents` runtime and routes model retries through the OpenAI Agents SDK retry policy so retry state is visible in the session event stream.

## Select A Harness

The session harness is selected by the attached LLM vault. The metadata key remains `sandbox0.managed_agents.engine` for compatibility:

```typescript
const claudeVault = await client.beta.vaults.create({
    display_name: "Claude LLM",
    metadata: {
        "sandbox0.managed_agents.role": "llm",
        "sandbox0.managed_agents.engine": "claude",
        "sandbox0.managed_agents.llm_base_url": "https://api.anthropic.com",
    },
});
```

For `codex`:

```typescript
const codexVault = await client.beta.vaults.create({
    display_name: "Codex LLM",
    metadata: {
        "sandbox0.managed_agents.role": "llm",
        "sandbox0.managed_agents.engine": "codex",
        "sandbox0.managed_agents.llm_base_url": "https://api.openai.com/v1",
    },
});
```

For `openai-agents`:

```typescript
const openAIAgentsVault = await client.beta.vaults.create({
    display_name: "OpenAI Agents LLM",
    metadata: {
        "sandbox0.managed_agents.role": "llm",
        "sandbox0.managed_agents.engine": "openai-agents",
        "sandbox0.managed_agents.llm_base_url": "https://api.openai.com/v1",
    },
});
```

Add the model provider token to the selected LLM vault:

```typescript
await client.beta.vaults.credentials.create(openAIAgentsVault.id, {
    display_name: "Model provider API key",
    auth: {
        type: "static_bearer",
        token: process.env.MODEL_API_KEY!,
    } as any,
});
```

Use the vault id for the harness you want. LLM credentials must be unbound `static_bearer` credentials; do not set `mcp_server_url` for the model provider token.

Attach exactly one LLM vault to the session:

```typescript
const session = await client.beta.sessions.create({
    agent: agent.id,
    environment_id: environment.id,
    vault_ids: [openAIAgentsVault.id],
});
```

If no LLM vault selects a harness, Sandbox0 defaults to `claude`.

## AI Gateway Integration

Managed Agents does not require Sandbox0 to own model-provider routing. You can put a third-party AI gateway between the selected agent harness and the model provider when you need protocol normalization, request logs, caching, retry policy, rate limits, budget controls, or bring-your-own-key storage.

Choose the gateway endpoint that matches the selected harness:

| Harness | Gateway endpoint must expose |
|--------|------------------------------|
| `claude` | Anthropic Messages-compatible API |
| `codex` | OpenAI-compatible API |
| `openai-agents` | OpenAI Responses-compatible API |

If you only need to bridge a Claude Code-compatible provider into an OpenAI-style harness, LLMProxy is the simplest option. The hosted tool does not require a Sandbox0 account, an LLMProxy login, or gateway-side setup. Use the LLMProxy URL as the LLM vault base URL, keep the upstream provider token in the vault credential, and let the selected runtime call it directly.

<CardGroup>
  <Card title="LLMProxy" href="/docs/managed-agents/llmproxy" cta="Open docs">
    Use the free no-login protocol bridge for Claude-compatible providers and OpenAI-style harnesses.
  </Card>
</CardGroup>

The gateway can route to whichever upstream providers it supports. For example, Cloudflare AI Gateway, LiteLLM Proxy, Portkey, Helicone, Kong AI Gateway, Envoy AI Gateway, TrueFoundry, and similar products can sit behind an LLM vault as long as the configured gateway endpoint speaks the API shape required by the harness.

In this setup, the LLM vault stores the gateway base URL and the gateway API token. Provider keys should usually live in the AI gateway through BYOK, virtual keys, or gateway-managed billing. Sandbox0 still owns the Managed Agents API, session truth, sandbox lifecycle, workspace state, network policy, and runtime credential projection.

```typescript
const cloudflareAccountId = process.env.CLOUDFLARE_ACCOUNT_ID!;

const cloudflareGatewayVault = await client.beta.vaults.create({
    display_name: "OpenAI Agents through Cloudflare AI Gateway",
    metadata: {
        "sandbox0.managed_agents.role": "llm",
        "sandbox0.managed_agents.engine": "openai-agents",
        "sandbox0.managed_agents.llm_base_url": `https://api.cloudflare.com/client/v4/accounts/${cloudflareAccountId}/ai/v1`,
    },
});

await client.beta.vaults.credentials.create(cloudflareGatewayVault.id, {
    display_name: "Cloudflare AI Gateway token",
    auth: {
        type: "static_bearer",
        token: process.env.CLOUDFLARE_API_TOKEN!,
    } as any,
});
```

Configure the agent model to the gateway's model identifier, such as `anthropic/claude-sonnet-4` on Cloudflare AI Gateway or the model alias configured in LiteLLM, Portkey, or another gateway.

<Callout variant="warning">
Do not point a harness at a gateway endpoint with the wrong API shape. For example, the `openai-agents` harness needs an OpenAI Responses-compatible endpoint even if the gateway routes the request to an Anthropic model upstream.
</Callout>

## Claude Harness

The Claude harness runs the Claude Agent SDK wrapper inside the session sandbox. It expects an Anthropic-compatible API. Use it when the provider already exposes the Anthropic Messages API shape and you want Claude Code style behavior.

Sandbox0 sets compatibility environment values such as `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, and `ANTHROPIC_BASE_URL`, then injects the real credential through egress auth for the configured LLM host.

## Codex Harness

The Codex harness launches Codex app-server inside the session sandbox. It expects an OpenAI-compatible model endpoint. Sandbox0 stores Codex home and thread state under the session workspace so runtime state stays session-scoped.

For Minimax-compatible endpoints, Sandbox0 detects the provider from the LLM base URL and configures Codex provider settings accordingly.

## OpenAI Agents Harness

The `openai-agents` harness uses a resident Python runtime service built on the official OpenAI Agents SDK. The runtime receives the session snapshot from the Managed Agents gateway, runs the agent loop in the runtime service, and claims a Sandbox0 sandbox only when the agent needs sandbox tools.

This is the sandbox as tool model. The session still has durable Managed Agents event history, but the agent process is not the same process as the sandbox. The sandbox is an isolated tool target for commands and workspace work.

The harness expects an OpenAI Responses-compatible endpoint. If the target provider does not expose that API shape directly, use an AI gateway that provides an OpenAI Responses-compatible surface and routes to the provider upstream.

<Callout variant="info">
For self-hosted deployments, configure the OpenAI Agents runtime callback base URL to an internal gateway URL when possible. The runtime sends session events back to the Managed Agents gateway; routing that callback through a public edge can introduce avoidable policy and timeout failures.
</Callout>

## Harness Configuration

Agent harness behavior can be configured by deployment defaults and internal harness config. Application-level harness selection should normally happen through the LLM vault, not by putting reserved Sandbox0 keys into session metadata.

<Callout variant="warning">
Do not use `sandbox0.managed_agents.engine` as session metadata. Reserved `sandbox0.managed_agents.*` keys are only supported on vault metadata today.
</Callout>

## Next Steps

<CardGroup>
  <Card title="Vaults" href="/docs/managed-agents/vaults" cta="Continue">
    Store the selected harness, model gateway URL, and credential material.
  </Card>

  <Card title="Compatibility" href="/docs/managed-agents/compatibility" cta="Continue">
    Review supported behavior and current compatibility boundaries.
  </Card>
</CardGroup>
