# Vaults

Vaults keep credentials out of agent code. Attach vault ids to a session, and Sandbox0 projects the matching credentials into network policy for that session.

Official reference: [Claude Managed Agents vaults](https://platform.claude.com/docs/en/managed-agents/vaults).

<Callout variant="info">
Managed Agents stores vault credential secret payloads as encrypted opaque secret maps at rest. Read APIs return public metadata and auth shape only, not raw secret values. Sandbox0 services decrypt secret material only when resolving runtime credential projection.
</Callout>

## LLM Vaults

Every running session should attach exactly one LLM vault. The LLM vault selects the agent harness and model provider endpoint.

```typescript
const llmVault = 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",
    },
});

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

| Metadata key | Required | Meaning |
|--------------|----------|---------|
| `sandbox0.managed_agents.role` | Yes | Must be `llm` for an LLM vault |
| `sandbox0.managed_agents.engine` | Yes | `claude`, `codex`, or `openai-agents` |
| `sandbox0.managed_agents.llm_base_url` | No | Model provider base URL |

The LLM credential must be an unbound `static_bearer` credential. Do not set `mcp_server_url` on LLM credentials.

<Callout variant="info">
The `as any` cast on unbound `static_bearer` credentials is intentional for current Anthropic TypeScript SDK types. Sandbox0 LLM and generic HTTP credential vaults omit `mcp_server_url`.
</Callout>

## Generic Credential Vaults

Use credential vaults when the agent needs authenticated outbound access to an external HTTP service.

```typescript
const apiVault = await client.beta.vaults.create({
    display_name: "Example API",
    metadata: {
        "sandbox0.managed_agents.role": "credential",
        "sandbox0.managed_agents.kind": "http_headers",
        "sandbox0.managed_agents.version": "1",
        "sandbox0.managed_agents.target_domains": "api.example.com",
        "sandbox0.managed_agents.protocol": "https",
        "sandbox0.managed_agents.tls_mode": "terminate-reoriginate",
        "sandbox0.managed_agents.failure_policy": "fail-closed",
        "sandbox0.managed_agents.headers_json": "{\"authorization\":\"{{ .authorization }}\"}",
    },
});

await client.beta.vaults.credentials.create(apiVault.id, {
    display_name: "Example API token",
    auth: {
        type: "static_bearer",
        token: process.env.EXAMPLE_API_TOKEN!,
    } as any,
});
```

Credential vaults can use `static_bearer` or `mcp_oauth` credentials. Sandbox0 resolves secret values and projects headers only for the target domains.

## MCP Credentials

For MCP servers, the credential auth includes `mcp_server_url`.

```typescript
await client.beta.vaults.credentials.create(vault.id, {
    display_name: "MCP token",
    auth: {
        type: "static_bearer",
        token: process.env.MCP_TOKEN!,
        mcp_server_url: "https://mcp.example.com/sse",
    },
});
```

## Runtime Injection

Sandbox0 injects credentials through egress auth and compatibility environment variables:

| Harness | Compatibility environment |
|--------|---------------------------|
| `claude` | `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL` |
| `codex` | `CODEX_API_KEY`, `OPENAI_API_KEY`, and `openai_base_url` harness config |
| `openai-agents` | `OPENAI_API_KEY`, `OPENAI_BASE_URL`, and `openai_base_url` harness config |

The environment variables may contain placeholders. The real token is projected by Sandbox0-managed credential policy when the sandbox contacts the configured host.

For `openai-agents`, the runtime expects an OpenAI Responses-compatible base URL. If the provider exposes a different API shape, use an external AI gateway that presents an OpenAI Responses-compatible endpoint and store the gateway base URL in `sandbox0.managed_agents.llm_base_url`.

## Next Steps

<CardGroup>
  <Card title="Agent Harnesses" href="/docs/managed-agents/agent-harnesses" cta="Continue">
    Choose the runtime adapter that should execute each managed session.
  </Card>

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