Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build LLM-powered apps with the Anthropic Claude API or SDK across Python, TypeScript, Java, Go, Ruby, C#, and PHP.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
shared/managed-agents-tools.md
1# Managed Agents — Tools & Skills23## Tools45### Server tools vs client tools67| Type | Who runs it | How it works |8|---|---|---|9| **Prebuilt Claude Agent tools** (`agent_toolset_20260401`) | Anthropic, on the session's container | File ops, bash, web search, etc. Enable all at once or configure individually with `enabled: true/false`. |10| **MCP tools** (`mcp_toolset`) | Anthropic, on the session's container | Capabilities exposed by connected MCP servers. Grant access per-server via the toolset. |11| **Custom tools** | **You** — your application handles the call and returns results | Agent emits a `agent.custom_tool_use` event, session goes `idle`, you send back a `user.custom_tool_result` event. |1213**Recommendation:** Enable all prebuilt tools via `agent_toolset_20260401`, then disable individually as needed.1415**Versioning:** The toolset is a versioned, static resource. When underlying tools change, a new toolset version is created (hence `_20260401`) so you always know exactly what you're getting.1617### Agent Toolset1819The `agent_toolset_20260401` provides these built-in tools:2021| Tool | Description |22| ---------------------- | ---------------------------------------- |23| `bash` | Execute bash commands in a shell session |24| `read` | Read a file from the local filesystem, including text, images, PDFs, and Jupyter notebooks |25| `write` | Write a file to the local filesystem |26| `edit` | Perform string replacement in a file |27| `glob` | Fast file pattern matching using glob patterns |28| `grep` | Text search using regex patterns |29| `web_fetch` | Fetch content from a URL |30| `web_search` | Search the web for information |3132Enable the full toolset:3334```json35{36"tools": [37{ "type": "agent_toolset_20260401" }38]39}40```4142### Per-Tool Configuration4344Override defaults for individual tools. This example enables everything except bash:4546```json47{48"tools": [49{50"type": "agent_toolset_20260401",51"default_config": { "enabled": true },52"configs": [53{ "name": "bash", "enabled": false }54]55}56]57}58```5960| Field | Required | Description |61|---|---|---|62| `type` | ✅ | `"agent_toolset_20260401"` |63| `default_config` | ❌ | Applied to all tools. `{ "enabled": bool, "permission_policy": {...} }` |64| `configs` | ❌ | Per-tool overrides: `[{ "name": "...", "enabled": bool, "permission_policy": {...} }]` |6566### Permission Policies6768Control when server-executed tools (agent toolset + MCP) run automatically vs wait for approval. Does not apply to custom tools.6970| Policy | Behavior |71|---|---|72| `always_allow` | Tool executes automatically (default) |73| `always_ask` | Session emits `session.status_idle` and pauses until you send a `tool_confirmation` event |7475```json76{77"type": "agent_toolset_20260401",78"default_config": {79"enabled": true,80"permission_policy": { "type": "always_allow" }81},82"configs": [83{ "name": "bash", "permission_policy": { "type": "always_ask" } }84]85}86```8788**Responding to `always_ask`:** Send a `user.tool_confirmation` event with `tool_use_id` from the triggering `agent_tool_use`/`mcp_tool_use` event:8990```json91{ "type": "tool_confirmation", "tool_use_id": "sevt_abc123", "result": "allow" }92{ "type": "tool_confirmation", "tool_use_id": "sevt_def456", "result": "deny", "message": "Read .env.example instead" }93```9495The optional `message` on a deny is delivered to the agent so it can adjust its approach.9697To enable only specific tools, flip the default off and opt-in per tool:9899```json100{101"tools": [102{103"type": "agent_toolset_20260401",104"default_config": { "enabled": false },105"configs": [106{ "name": "bash", "enabled": true },107{ "name": "read", "enabled": true }108]109}110]111}112```113114### Custom Tools (Client-Side)115116Custom tools are executed by **your application**, not Anthropic. The flow:1171181. Agent decides to use the tool → session emits a `agent.custom_tool_use` event with inputs1192. Session goes `idle` waiting for you1203. Your application executes the tool1214. You send back a `user.custom_tool_result` event with the output1225. Session resumes `running`123124No permission policy needed — you're the one executing.125126```json127{128"tools": [129{130"type": "custom",131"name": "get_weather",132"description": "Fetch current weather for a city.",133"input_schema": {134"type": "object",135"properties": {136"city": { "type": "string", "description": "City name" }137},138"required": ["city"]139}140}141]142}143```144145### MCP Servers146147MCP (Model Context Protocol) servers expose standardized third-party capabilities (e.g. Asana, GitHub, Linear). **Configuration is split across agent and vault:**1481491. **Agent creation** declares which servers to connect to (`type`, `name`, `url` — no auth). The agent's `mcp_servers` array has no auth field.1502. **Vault** stores the OAuth credentials. Attach via `vault_ids` on session create.151152This keeps secrets out of reusable agent definitions. Each vault credential is tied to one MCP server URL; Anthropic matches credentials to servers by URL.153154**Agent side — declare servers (no auth):**155156| Field | Required | Description |157|---|---|---|158| `type` | ✅ | `"url"` |159| `name` | ✅ | Unique name — referenced by `mcp_toolset.mcp_server_name` |160| `url` | ✅ | The MCP server's endpoint URL (Streamable HTTP transport) |161162```json163{164"mcp_servers": [165{ "type": "url", "name": "linear", "url": "https://mcp.linear.app/mcp" }166],167"tools": [168{ "type": "mcp_toolset", "mcp_server_name": "linear" }169]170}171```172173**Session side — attach vault:**174175```json176{177"agent": "agent_abc123",178"environment_id": "env_abc123",179"vault_ids": ["vlt_abc123"]180}181```182183> 💡 **Per-tool enablement (empirical):** `mcp_toolset` has been observed accepting `default_config: {enabled: false}` + `configs: [{name, enabled: true}]` for an allowlist pattern. The API ref shows only the minimal `{type, mcp_server_name}` form.184185> ⚠️ **MCP auth tokens ≠ REST API tokens.** Hosted MCP servers (`mcp.notion.com`, `mcp.linear.app`, etc.) typically require **OAuth bearer tokens**, not the service's native API keys. A Notion `ntn_` integration token authenticates against Notion's REST API but will **not** work as a vault credential for the Notion MCP server. These are different auth systems.186187### Vaults — the MCP credential store188189**Vaults** store OAuth credentials (access token + refresh token) that Anthropic auto-refreshes on your behalf via standard OAuth 2.0 `refresh_token` grant. This is the only way to authenticate MCP servers in the launch SDK.190191#### Credentials and the sandbox192193Vaults store credentials; those credentials **never enter the sandbox**. This is a deliberate security boundary — code running in the sandbox (including anything the agent writes) cannot read or exfiltrate a vaulted credential, even under prompt injection. Instead, credentials are injected by Anthropic-side proxies **after** a request leaves the sandbox:194195- **MCP tool calls** are routed through an Anthropic-side proxy that fetches the credential from the vault and adds it to the outbound request.196- **Git operations on attached GitHub repositories** (`git pull`, `git push`, GitHub REST calls) are routed through a git proxy that injects the `github_repository` resource's `authorization_token` the same way.197198**Not yet supported:** running other authenticated CLIs (e.g. `aws`, `gcloud`, `stripe`) directly inside the sandbox. There is currently no way to set container environment variables or expose vault credentials to arbitrary processes. If you need one of these today:199200- **Prefer an MCP server** for that service if one exists — it gets the same vault-backed injection.201- **Otherwise, register a custom tool:** the agent emits `agent.custom_tool_use`, your orchestrator (which already holds the credential) executes the call and returns `user.custom_tool_result` over the same authenticated event stream. No public endpoint is exposed; the sandbox never sees the secret. See `shared/managed-agents-client-patterns.md` → Pattern 9.202203**Do not put API keys in the system prompt or user messages as a workaround** — they persist in the session's event history.204205> Formerly known internally as TATs (Tool/Tenant Access Tokens).206207**Flow:**2082091. Create a vault (`client.beta.vaults.create(...)`) — one per tenant/user, or one shared, depending on your model2102. Add MCP credentials to it (`client.beta.vaults.credentials.create(...)`) — each credential is tied to one MCP server URL2113. Reference the vault on session create via `vault_ids: ["vlt_..."]`2124. Anthropic auto-refreshes tokens before they expire; the agent uses the current access token when calling MCP tools213214**Credential shape**:215216```json217{218"display_name": "Notion (workspace-foo)",219"auth": {220"type": "mcp_oauth",221"mcp_server_url": "https://mcp.notion.com/mcp",222"access_token": "<current access token>",223"expires_at": "2026-04-02T14:00:00Z",224"refresh": {225"refresh_token": "<refresh token>",226"client_id": "<your OAuth client_id>",227"token_endpoint": "https://api.notion.com/v1/oauth/token",228"token_endpoint_auth": { "type": "none" }229}230}231}232```233234The `refresh` block is what enables auto-refresh — `token_endpoint` is where Anthropic posts the `refresh_token` grant. `token_endpoint_auth` is a discriminated union:235236| `type` | Shape | Use when |237|---|---|---|238| `"none"` | `{type: "none"}` | Public OAuth client (no secret) |239| `"client_secret_basic"` | `{type: "client_secret_basic", client_secret: "..."}` | Confidential client, secret via HTTP Basic auth |240| `"client_secret_post"` | `{type: "client_secret_post", client_secret: "..."}` | Confidential client, secret in request body |241242Omit `refresh` entirely if you only have an access token with no refresh capability — it'll work until it expires, then the agent loses access.243244> 💡 **Getting an OAuth token.** How you obtain the initial access and refresh tokens depends on the MCP server — consult its documentation. Once you have them, store them in a vault credential using the shape above; Anthropic auto-refreshes via the `refresh.token_endpoint` from there.245246**Scoping:** Vaults are workspace-scoped. Anyone with developer+ role in the API workspace can create, read (metadata only — secrets are write-only), and attach vaults. `vault_ids` can be set at session **create** time but not via session update (the SDK docstring says "Not yet supported; requests setting this field are rejected").247248---249250## Skills251252Skills are reusable, filesystem-based resources that provide your agent with domain-specific expertise: workflows, context, and best practices that transform general-purpose agents into specialists. Unlike prompts (conversation-level instructions for one-off tasks), skills load on-demand and eliminate the need to repeatedly provide the same guidance across multiple conversations.253254Two types — both work the same way; the agent automatically uses them when relevant to the task at hand:255256| Type | What it is |257|---|---|258| **Pre-built Anthropic skills** | Common document tasks (PowerPoint, Excel, Word, PDF). Reference by name (e.g. `xlsx`). |259| **Custom skills** | Skills you've created in your organization via the Skills API. Reference by `skill_id` + optional `version`. |260261**Max 20 skills per agent.** Agent creation uses `managed-agents-2026-04-01`; the separate Skills API (for managing custom skill definitions) uses `skills-2025-10-02`.262263### Enabling skills on a session264265Skills are attached to the **agent** definition via `agents.create()`:266267```ts268const agent = await client.beta.agents.create(269{270name: "Financial Agent",271model: "claude-opus-4-7",272system: "You are a financial analysis agent.",273skills: [274{ type: "anthropic", skill_id: "xlsx" },275{ type: "custom", skill_id: "skill_abc123", version: "latest" },276],277}278);279```280281Python:282283```python284agent = client.beta.agents.create(285name="Financial Agent",286model="claude-opus-4-7",287system="You are a financial analysis agent.",288skills=[289{"type": "anthropic", "skill_id": "xlsx"},290{"type": "custom", "skill_id": "skill_abc123", "version": "latest"},291]292)293```294295**Skill reference fields:**296297| Field | Anthropic skill | Custom skill |298|---|---|---|299| `type` | `"anthropic"` | `"custom"` |300| `skill_id` | Skill name (e.g. `"xlsx"`, `"docx"`, `"pptx"`, `"pdf"`) | Skill ID from Skills API (e.g. `"skill_abc123"`) |301| `version` | — | `"latest"` or a specific version number |302303### Skills API304305| Operation | Method | Path |306| --------------------- | -------- | ----------------------------------------------- |307| Create Skill | `POST` | `/v1/skills` |308| List Skills | `GET` | `/v1/skills` |309| Get Skill | `GET` | `/v1/skills/{id}` |310| Delete Skill | `DELETE` | `/v1/skills/{id}` |311| Create Version | `POST` | `/v1/skills/{id}/versions` |312| List Versions | `GET` | `/v1/skills/{id}/versions` |313| Get Version | `GET` | `/v1/skills/{id}/versions/{version}` |314| Delete Version | `DELETE` | `/v1/skills/{id}/versions/{version}` |315316