secure-deployment changedmanaged-agents/secure-deployment
Nearest release: v2.1.307, published an hour after this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Recorded here
Lines+62added
Lines−62removed
From line
40
where the diff opens
First seen
13 Oct 2026
this site's first read of the page
Recorded edits7to this page, all time
The whole hunk
from line 40, old and new numbered
/
from line 40
4040
4141## Choose where the agent runs
4242
43Where the agent's tools run decides who secures the sandbox: Anthropic, with a cloud environment, or you, with a self-hosted sandbox. To choose between them and learn what reaches Anthropic with each, see [Choosing an agent environment](https://platform.claude.com/docs/en/managed-agents/choosing-an-environment).
43Where the agent's tools run determines who secures the sandbox: Anthropic, with a cloud environment, or you, with a self-hosted sandbox. To choose between them and learn what reaches Anthropic with each, see [Choosing an agent environment](https://platform.claude.com/docs/en/managed-agents/choosing-an-environment).
4444
4545If you use a [self-hosted sandbox](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes), keep these four points in mind:
4646
from line 53
5353
5454## Limit the network
5555
56Set `networking.type` to `limited` and list only the hosts the agent needs in `allowed_hosts`. An environment create request that omits `networking` might get `unrestricted`, so set `networking` in every create request. See [Risks of unrestricted networking](https://platform.claude.com/docs/en/managed-agents/environments#risks-of-unrestricted-networking).
56Use `limited` networking and list only the hosts the agent needs in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). An environment create request that omits `networking` (csharp, go: `Networking`) might get `unrestricted`, so set `networking` (csharp, go: `Networking`) in every create request. See [Risks of unrestricted networking](https://platform.claude.com/docs/en/managed-agents/environments#risks-of-unrestricted-networking).
5757
58Files, memory stores, and GitHub repositories that you attach stay available to the agent regardless of `allowed_hosts`.
58Files, memory stores, and GitHub repositories that you attach stay available to the agent regardless of `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`).
5959
6060The examples on this page use a support agent. It reads a customer's ticket, looks up the order, reads your help center, and drafts a reply. Your application runs the order lookup, which needs no host, so this environment allows one host, the help center, for `web_fetch`:
6161
from line 201
201201
202202A `limited` environment has three networking settings:
203203
204| Setting | What it opens to code in the sandbox | Recommended |
205| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
206| `allowed_hosts` | The hosts you list, for any request | Only the hosts the agent needs, including the host of each MCP server you operate or trust |
207| `allow_package_managers` | The [package manager hosts](https://platform.claude.com/docs/en/managed-agents/environments#package-manager-hosts). They include every repository and path on `github.com`, `gitlab.com`, and `bitbucket.org`, where anyone can publish content and where code in the sandbox can upload files | `false`, unless the environment's `packages` setting lists packages, which requires `true`. If the agent installs packages while it runs, list only the registry hosts it needs in `allowed_hosts` instead |
208| `allow_mcp_servers` | No host. Managed Agents connects to MCP servers from Anthropic's servers | `false`, with the host of each MCP server you operate or trust listed in `allowed_hosts` |
204| Setting | What it opens to code in the sandbox | Recommended |
205| ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
206| `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) | The hosts you list, for any request | Only the hosts the agent needs, including the host of each MCP server you operate or trust |
207| `allow_package_managers` (java, php: `allowPackageManagers`; csharp, go: `AllowPackageManagers`) | The [package manager hosts](https://platform.claude.com/docs/en/managed-agents/environments#package-manager-hosts). They include every repository and path on `github.com`, `gitlab.com`, and `bitbucket.org`, where anyone can publish content and where code in the sandbox can upload files | `false`, unless the environment's `packages` (csharp, go: `Packages`) setting lists packages, which requires `true`. If the agent installs packages while it runs, list only the registry hosts it needs in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) instead |
208| `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) | No host. Managed Agents connects to MCP servers from Anthropic's servers | `false`, with the host of each MCP server you operate or trust listed in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) |
209209
210The `allow_package_managers` and `allow_mcp_servers` settings add no hosts for web search and web fetch.
210The `allow_package_managers` (java, php: `allowPackageManagers`; csharp, go: `AllowPackageManagers`) and `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) settings add no hosts for web search and web fetch.
211211
212Leave `allow_mcp_servers` off, which is the default, and list the host of each MCP server you operate or trust in `allowed_hosts`. Each host you list is also open to code in the sandbox. With `allow_mcp_servers` off, a check at session creation rejects the request if an MCP server's host is not listed. See [Provide authentication at session creation](https://platform.claude.com/docs/en/managed-agents/mcp-connector#provide-authentication-at-session-creation). The same check runs when a session update changes `mcp_servers`.
212Leave `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) off, which is the default, and list the host of each MCP server you operate or trust in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). Each host you list is also open to code in the sandbox. With `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) off, a check at session creation rejects the request if an MCP server's host is not listed. See [Provide authentication at session creation](https://platform.claude.com/docs/en/managed-agents/mcp-connector#provide-authentication-at-session-creation). The same check runs when a session update changes `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`).
213213
214214<Warning>
215215 Network access is granted for each host, not for each operation. The sandbox can send any request to an allowed host, including uploads such as `git push` and package publishing. It can also use any credential the command supplies, even one that someone hid in text the agent reads.
216216</Warning>
217217
218When you choose hosts for `allowed_hosts`, follow these two rules:
218When you choose hosts for `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`), follow these two rules:
219219
220220* List only hosts you operate or trust.
221221* Avoid `*.` wildcards and shared-hosting domains where anyone can publish content.
from line 230
230230
231231## Keep credentials in vaults
232232
233Store every secret in a vault. For each environment variable credential, set the injection location to request headers only and list only the hosts the secret is for. Code in the sandbox sees a placeholder instead of the secret. Managed Agents swaps in the real secret only in outgoing HTTPS requests to the hosts the credential allows. So the secret stays out of direct reach of the model, unless a service sends it back, such as an endpoint that echoes request headers. If the credential's `networking` is `unrestricted`, Managed Agents swaps in the real secret in requests to any host the environment lets the sandbox reach. To use a vault, pass its ID in `vault_ids` when you create the session or deployment.
233Store every secret in a vault. For each environment variable credential, set the injection location to request headers only and list only the hosts the secret is for. Code in the sandbox sees a placeholder instead of the secret. Managed Agents swaps in the real secret only in outgoing HTTPS requests to the hosts the credential allows. So the secret stays out of direct reach of the model, unless a service sends it back, such as an endpoint that echoes request headers. If the credential's `networking` (csharp, go: `Networking`) is `unrestricted`, Managed Agents swaps in the real secret in requests to any host the environment lets the sandbox reach. To use a vault, pass its ID in `vault_ids` (java: `vaultIds`; php: `vaultIDs`; csharp: `VaultIds`; go: `VaultIDs`) when you create the session or deployment.
234234
235| Setting | Set it to | Why | What it does not do |
236| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
237| `injection_location` | `{"header": true, "body": false}`, after you check that the service reads the key from a header | Request bodies are often built from content the agent reads, so a key in a body is more exposed. Name both fields: a create request that omits the object enables both locations, and an update changes only the fields you send | Code can still use the key on every host the credential allows. A service that expects the key in the body receives the placeholder and rejects the request |
238| `networking` on the credential | `limited`, with the exact hosts the key is for | Responses reach the sandbox unredacted, so avoid wildcards, shared-hosting domains, and hosts that echo request headers | It does not open the host. The environment must also allow it |
239| The key's permissions, at the service that issued the key | Only the permissions the agent needs | The agent can do anything the key allows | Not applicable |
240| A mounted repository's GitHub token | A [fine-grained token](https://platform.claude.com/docs/en/managed-agents/github#token-permissions) with the minimum permissions | Code in the sandbox can fetch from and push to the mounted repository with it for the whole session. Grant write access only if the agent must push | Not applicable |
235| Setting | Set it to | Why | What it does not do |
236| -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
237| `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) | `{"header": true, "body": false}`, after you check that the service reads the key from a header | Request bodies are often built from content the agent reads, so a key in a body is more exposed. Name both fields: a create request that omits the object enables both locations, and an update changes only the fields you send | Code can still use the key on every host the credential allows. A service that expects the key in the body receives the placeholder and rejects the request |
238| `networking` (csharp, go: `Networking`) on the credential | `limited`, with the exact hosts the key is for | Responses reach the sandbox unredacted, so avoid wildcards, shared-hosting domains, and hosts that echo request headers | It does not open the host. The environment must also allow it |
239| The key's permissions, at the service that issued the key | Only the permissions the agent needs | The agent can do anything the key allows | Not applicable |
240| A mounted repository's GitHub token | A [fine-grained token](https://platform.claude.com/docs/en/managed-agents/github#token-permissions) with the minimum permissions | Code in the sandbox can fetch from and push to the mounted repository with it for the whole session. Grant write access only if the agent must push | Not applicable |
241241
242242The support agent needs no vault credential, because your application holds the API key for your order API. If your agent does hold a vault credential, see [Add a credential](https://platform.claude.com/docs/en/managed-agents/vaults#add-a-credential) for the request in every language.
243243
244Keep keys out of system prompts, agent definitions, and messages. Do not give the agent a Claude API key or Claude API access token. Even when one is in a vault, code in the sandbox can use it to call the Claude API directly. It can do anything that credential allows, such as starting or deleting sessions, or using web search and web fetch. The agent's tool settings, approvals, and budget do not apply to those calls. In a `limited` environment, code can make these calls only if `allowed_hosts` lets the sandbox reach `api.anthropic.com`.
244Keep keys out of system prompts, agent definitions, and messages. Do not give the agent a Claude API key or Claude API access token. Even when one is in a vault, code in the sandbox can use it to call the Claude API directly. It can do anything that credential allows, such as starting or deleting sessions, or using web search and web fetch. The agent's tool settings, approvals, and budget do not apply to those calls. In a `limited` environment, code can make these calls only if `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) lets the sandbox reach `api.anthropic.com`.
245245
246246Fetch third-party tokens yourself and store them in the vault. A token that code in the sandbox fetches with a stored secret comes back unredacted.
247247
from line 251
251251
252252## Restrict web search and web fetch
253253
254Set `allowed_domains` on `web_fetch` to the sites the agent needs. Any URL the agent fetches can carry data to the site it points to, so this list is a security control. On `web_search`, set `allowed_domains` to the sites you want results from, so that results come only from sites you trust to be accurate. The list does not stop the search query from reaching the search provider. Search results include text from pages, so the list also limits which sites' text reaches the agent. Set `allowed_domains` on both tools for every type of environment.
254Set `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) on `web_fetch` to the sites the agent needs. Any URL the agent fetches can carry data to the site it points to, so this list is a security control. On `web_search`, set `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) to the sites you want results from, so that results come only from sites you trust to be accurate. The list does not stop the search query from reaching the search provider. Search results include text from pages, so the list also limits which sites' text reaches the agent. Set `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) on both tools for every type of environment.
255255
256A `blocked_domains` list blocks the hosts you list and their subdomains, and no other host. The same content can still reach the agent from web archives, caches, mirrors, or related domains you did not list. Do not rely on `blocked_domains` for security. Use `allowed_domains` and name the hosts you trust.
256A `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) list blocks the hosts you list and their subdomains, and no other host. The same content can still reach the agent from web archives, caches, mirrors, or related domains you did not list. Do not rely on `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) for security. Use `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) and name the hosts you trust.
257257
258In a `limited` environment, the `allowed_hosts` list from [Limit the network](https://platform.claude.com/docs/en/managed-agents/secure-deployment#limit-the-network) also limits the web tools. An `unrestricted` environment or a self-hosted sandbox does not limit the web tools.
258In a `limited` environment, the `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) list from [Limit the network](https://platform.claude.com/docs/en/managed-agents/secure-deployment#limit-the-network) also limits the web tools. An `unrestricted` environment or a self-hosted sandbox does not limit the web tools.
259259
260260| In a `limited` environment | Result |
261261| ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
from line 272
272272| `allowed_hosts` (environment) | `*.example.com` | Every subdomain | `example.com` |
273273| `allowed_domains` (web tool) | `example.com` | `example.com` and every subdomain | Other domains |
274274
275If the agent needs a site and all of its subdomains, list both `example.com` and `*.example.com` in `allowed_hosts`, and otherwise list exact hosts. If a tool lists `example.com` and `allowed_hosts` lists only `*.example.com`, the session is created. The check at session creation counts `example.com` as within `*.example.com`, but the tool returns nothing from `example.com` itself. See [Set domain lists on an agent](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#set-domain-lists-on-an-agent) for how the two lists match.
275If the agent needs a site and all of its subdomains, list both `example.com` and `*.example.com` in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`), and otherwise list exact hosts. If a tool lists `example.com` and `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) lists only `*.example.com`, the session is created. The check at session creation counts `example.com` as within `*.example.com`, but the tool returns nothing from `example.com` itself. See [Set domain lists on an agent](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#set-domain-lists-on-an-agent) for how the two lists match.
276276
277277The `web_fetch` tool also opens only URLs that have already appeared in the session:
278278
from line 292
292292
293293In a multiagent session, `web_fetch` opens a URL from another agent only if it reached that agent through a source marked Yes. A custom tool's result from a direct call counts as a source marked Yes. This holds even if Claude wrote its text, for example when the tool repeats its input. A URL can count even when it is written without `https://`, such as `example.com/docs`. The `web_fetch` tool cannot always open a link that shows words instead of its URL, such as "Contact support." If the agent must fetch a URL that has not appeared in the session, send it in a user message.
294294
295This rule reduces the chance that injected text builds a URL that carries private data. End-user text, search results, fetched pages, and custom tool results can still add URLs, so keep `allowed_domains` set. The Messages API applies a similar rule with a different list of sources. See [URL validation](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool#url-validation).
295This rule reduces the chance that injected text builds a URL that carries private data. End-user text, search results, fetched pages, and custom tool results can still add URLs, so keep `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) set. The Messages API applies a similar rule with a different list of sources. See [URL validation](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool#url-validation).
296296
297297A domain list on `web_fetch` does not limit the `bash` tool. [Limit the network](https://platform.claude.com/docs/en/managed-agents/secure-deployment#limit-the-network) as well. See [Domain list rules](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#domain-list-rules).
298298
from line 300
300300
301301Set `auto` on `bash`, `write`, `edit`, and `web_fetch`, and on MCP tools that only read data. Use `always_ask` instead on a tool if you cannot undo its changes outside the sandbox. Also use it on a tool that should not run just because end-user text you relay asks for it. A [permission policy](https://platform.claude.com/docs/en/managed-agents/permission-policies) determines whether a tool call runs, waits for your approval, or is evaluated by the server.
302302
303| Tool | Recommended policy | Why |
304| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
305| `read`, `glob`, `grep` | `always_allow` | They read files in the sandbox and change nothing |
306| `bash`, `write`, `edit` | `auto`. Use `always_ask` on a tool if you cannot undo its changes outside the sandbox. Use `always_ask` on `bash` if you relay end-user text | The agent toolset default is `always_allow`, which runs every call without approval |
307| `web_fetch` | `auto` | A URL the agent fetches can carry data to the site it points to |
308| `web_search` | `always_ask` if the agent handles data you would not want sent in a search query. Otherwise `always_allow` | `allowed_domains` limits which sites results come from, not what the query contains |
309| MCP tools that only read data | `auto`, set for each tool in the toolset's `configs` | The toolset default stays `always_ask`, so a tool the MCP server adds later still waits for approval |
310| MCP tools that change data | `always_ask` | This is the MCP toolset default. Keep it |
311| Custom tools | Your code decides whether each call runs | Permission policies do not apply |
303| Tool | Recommended policy | Why |
304| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
305| `read`, `glob`, `grep` | `always_allow` | They read files in the sandbox and change nothing |
306| `bash`, `write`, `edit` | `auto`. Use `always_ask` on a tool if you cannot undo its changes outside the sandbox. Use `always_ask` on `bash` if you relay end-user text | The agent toolset default is `always_allow`, which runs every call without approval |
307| `web_fetch` | `auto` | A URL the agent fetches can carry data to the site it points to |
308| `web_search` | `always_ask` if the agent handles data you would not want sent in a search query. Otherwise `always_allow` | `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) limits which sites results come from, not what the query contains |
309| MCP tools that only read data | `auto`, set for each tool in the toolset's `configs` (csharp, go: `Configs`) | The toolset default stays `always_ask`, so a tool the MCP server adds later still waits for approval |
310| MCP tools that change data | `always_ask` | This is the MCP toolset default. Keep it |
311| Custom tools | Your code determines whether each call runs | Permission policies do not apply |
312312
313313The toolset in [Give the agent the smallest tool set](https://platform.claude.com/docs/en/managed-agents/secure-deployment#give-the-agent-the-smallest-tool-set) applies these policies.
314314
from line 322
322322
323323## Give the agent the smallest tool set
324324
325Set `default_config.enabled` to `false` and [enable only the tools the agent needs](https://platform.claude.com/docs/en/managed-agents/tools#enabling-only-specific-tools). The agent toolset enables all eight built-in tools by default.
325Set `default_config.enabled` (java, php: `defaultConfig.enabled`; csharp, go: `DefaultConfig.Enabled`) to `false` and [enable only the tools the agent needs](https://platform.claude.com/docs/en/managed-agents/tools#enabling-only-specific-tools). The agent toolset enables all eight built-in tools by default.
326326
327327| Tool | What it does |
328328| ------------------------- | ------------------------------------------------------------------------- |
from line 333
333333
334334The support agent needs three built-in tools: `read` and `write` for its draft, and `web_fetch` for the help center. It looks up orders through a [custom tool](https://platform.claude.com/docs/en/managed-agents/tools#custom-tools), `lookup_order`, that your application runs. Your application holds the API key for your order API, so the agent needs neither `bash` nor a credential.
335335
336The following sample limits `web_fetch` to `help.example.com` with `allowed_domains`. It sets `auto` on `write` and `web_fetch`, as [Approve risky actions](https://platform.claude.com/docs/en/managed-agents/secure-deployment#approve-risky-actions) recommends. If a customer's ticket leads the agent to use these tools, the agent can only change files in the sandbox or open help center pages. That is why neither tool needs `always_ask`. The sample also sets `always_ask` in `default_config`, so a tool you enable later without its own policy uses `always_ask`:
336The following sample limits `web_fetch` to `help.example.com` with `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`). It sets `auto` on `write` and `web_fetch`, as [Approve risky actions](https://platform.claude.com/docs/en/managed-agents/secure-deployment#approve-risky-actions) recommends. If a customer's ticket leads the agent to use these tools, the agent can only change files in the sandbox or open help center pages. That is why neither tool needs `always_ask`. The sample also sets `always_ask` in `default_config` (java, php: `defaultConfig`; csharp, go: `DefaultConfig`), so a tool you enable later without its own policy uses `always_ask`:
337337
338338<CodeGroup defaultLanguage="CLI">
339339 ```bash cURL
from line 763
763763 ```
764764</CodeGroup>
765765
766An [agent update](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-semantics) replaces the whole `tools` array, so send every entry you want to keep.
766An [agent update](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-semantics) replaces the whole `tools` (csharp, go: `Tools`) array, so send every entry you want to keep.
767767
768768An agent update reaches only new sessions, so also check deployments, agents that list this agent, and existing sessions:
769769
770770* A deployment pins an agent version, so point each deployment at the new one.
771* An agent that lists this one in [`subagents.predefined_agents`](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#list-the-subagents) or `workflows.predefined_agents` keeps the version it pinned, so update that agent too.
772* To tighten a session that already exists, [update that session's tools](https://platform.claude.com/docs/en/managed-agents/session-operations#updating-the-agent-configuration). The session must be `idle`, and the update replaces the whole `tools` array. In a multiagent session, new `allowed_domains` and `blocked_domains` lists on the web tools of the agent the session runs also apply to every other agent. They apply from each agent's next turn. Those agents' enabled tools and permission policies do not change. To change those, update each agent, then start a new session.
771* An agent that lists this one in the [`predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (csharp, go: `Subagents`)](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#list-the-subagents) or of `workflows` (csharp, go: `Workflows`) keeps the version it pinned. Update that agent too.
772* To tighten a session that already exists, [update that session's tools](https://platform.claude.com/docs/en/managed-agents/session-operations#updating-the-agent-configuration). The session must be `idle`, and the update replaces the whole `tools` (csharp, go: `Tools`) array. In a multiagent session, new `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) and `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) lists on the web tools of the agent the session runs also apply to every other agent. They apply from each agent's next turn. Those agents' enabled tools and permission policies do not change. To change those, update each agent, then start a new session.
773773
774774Limit MCP servers and custom tools to what the agent needs, too:
775775
776* **MCP servers:** An MCP toolset enables every tool the server exposes by default. Set `default_config.enabled` to `false` and enable named tools, so tools a server adds later stay off. Remove servers the agent does not use. See [MCP connector](https://platform.claude.com/docs/en/managed-agents/mcp-connector#configure-which-mcp-tools-are-available).
776* **MCP servers:** An MCP toolset enables every tool the server exposes by default. Set `default_config.enabled` (java, php: `defaultConfig.enabled`; csharp, go: `DefaultConfig.Enabled`) to `false` and enable named tools, so tools a server adds later stay off. Remove servers the agent does not use. See [MCP connector](https://platform.claude.com/docs/en/managed-agents/mcp-connector#configure-which-mcp-tools-are-available).
777777* **Custom tools:** Your application runs them, and permission policies do not apply. Validate each call's input in your application and limit what the tool can touch.
778778
779779## Keep untrusted input away from powerful tools
from line 780
780780
781781Check which tools and credentials an agent holds whenever it reads untrusted input, which is text that someone outside your team can write. This section uses two terms:
782782
783* **Untrusted input:** Web pages, search results, support tickets, emails, repository files, uploads, MCP server results, and end-user messages that you relay.
784* **Powerful tools:** `bash`, `write`, `edit`, `web_fetch`, `web_search`, MCP tools and custom tools that write or send data, and any tool that uses a credential.
783* **Untrusted input:** Webpages, search results, support tickets, emails, repository files, uploads, MCP server results, and end-user messages that you relay
784* **Powerful tools:** `bash`, `write`, `edit`, `web_fetch`, `web_search`, MCP tools and custom tools that write or send data, and any tool that uses a credential
785785
786786Text in untrusted input can tell the agent to use a powerful tool it holds. The support agent reads tickets, so it reaches your order API only through the custom tool `lookup_order`. Your application checks that the order belongs to the ticket's sender.
787787
from line 788
788788| Input the agent reads | Power it also has | Do this |
789789| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
790790| Tickets, emails, or uploads | `bash` with a credential | Replace `bash` with a custom tool that does one thing. If the agent must keep `bash`, approve each call with `always_ask` |
791| Web pages or search results | Writing files or changing records | Turn off the web tools, or limit them to sites you operate or trust |
791| Webpages or search results | Writing files or changing records | Turn off the web tools, or limit them to sites you operate or trust |
792792| MCP results or repository files | MCP tools that write | Keep the MCP toolset on `always_ask`, and enable only the tools the agent needs |
793793| A mounted GitHub repository | Any tool | Mount only repositories you trust. An agent with `read` loads skills from the repository's `.claude/skills` directory as agent instructions, with no review step. See [Load skills from a GitHub repository](https://platform.claude.com/docs/en/managed-agents/skills#load-skills-from-a-github-repository) |
794794| Any untrusted input | Writing to a [memory store](https://platform.claude.com/docs/en/managed-agents/memory#attach-a-memory-store-to-a-session) | Attach the store as `read_only` unless the agent must write. The default is `read_write`, and later sessions read saved text as trusted memory |
from line 803
803803
804804The split uses three agents:
805805
806| Agent | Reads | Holds | Passes on |
807| -------------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
808| Lead (the agent that the session runs) | Your message, and what the other agents send back | No built-in tools. Its `subagents.predefined_agents` list names the fetcher and the writer | A task to each agent |
809| Fetcher | Web pages and search results | `web_fetch` and `web_search` only, each with `allowed_domains` | Short results, in a format you ask for in its system prompt |
810| Writer | The task from the lead | The tools that write files, run commands, or change records, on `auto` or `always_ask`. No web tools | Its result |
806| Agent | Reads | Holds | Passes on |
807| -------------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
808| Lead (the agent that the session runs) | Your message, and what the other agents send back | No built-in tools. The `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of its `subagents` (csharp, go: `Subagents`) names the fetcher and the writer | A task to each agent |
809| Fetcher | Web pages and search results | `web_fetch` and `web_search` only, each with `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) | Short results, in a format you ask for in its system prompt |
810| Writer | The task from the lead | The tools that write files, run commands, or change records, on `auto` or `always_ask`. No web tools | Its result |
811811
812812The fetcher's results are built from untrusted pages, and the lead can pass their text on to the writer. Keep `auto` or `always_ask` on the writer's tools. The fetcher can still send some of what it reads to the sites on its `web_fetch` list, and to the search provider in its queries.
813813
from line 817
817817
818818Set a budget when you create each session, and decide in advance how you stop an agent.
819819
820| Control | What it does |
821| --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
822| Session budget | A cap on spend at public list prices. At the cap, the session and each [thread](https://platform.claude.com/docs/en/managed-agents/session-threads) pause. Requests in progress can finish and their tool calls still run, so spend can pass the cap. See [When a session reaches its budget](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget) |
823| Deployment budget | The same cap, applied to each session a deployment starts |
824| [`user.interrupt` event](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#interrupt-the-agent) | Stops the model response immediately. A running tool call can finish first. The session goes `idle`, unless a workflow run keeps it `running`, and resumes on your next message. An interrupt ends no workflow run |
825| Archive or delete a session | Archiving keeps the history and blocks new events. Deleting removes the record, events, and sandbox |
826| Pause or archive a deployment | Pausing stops new scheduled runs but still allows manual runs. Archiving ends the schedule permanently. Sessions already running keep running |
827| Archive or delete a vault or credential | Removes the secret from running sessions without a restart. Allow for a delay. The sessions keep running, so interrupt them too. A token the agent already fetched with the secret stays in the sandbox |
820| Control | What it does |
821| --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
822| Session budget | A cap on spend at public list prices. At the cap, the session and each [thread](https://platform.claude.com/docs/en/managed-agents/session-threads) pause. Requests in progress can complete and their tool calls still run, so spend can pass the cap. See [When a session reaches its budget](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget) |
823| Deployment budget | The same cap, applied to each session a deployment starts |
824| [`user.interrupt` event](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#interrupt-the-agent) | Stops the model response immediately. A running tool call can complete first. The session goes `idle`, unless a workflow run keeps it `running`, and resumes on your next message. An interrupt ends no workflow run |
825| Archive or delete a session | Archiving keeps the history and blocks new events. Deleting removes the record, events, and sandbox |
826| Pause or archive a deployment | Pausing stops new scheduled runs but still allows manual runs. Archiving ends the schedule permanently. Sessions already running keep running |
827| Archive or delete a vault or credential | Removes the secret from running sessions without a restart. Allow for a delay. The sessions keep running, so interrupt them too. A token the agent already fetched with the secret stays in the sandbox |
828828
829829To stop a running agent, follow these steps:
830830
from line 837
837837
838838An interrupt does not undo what the agent already did or sent. Archiving an agent does not stop its running sessions.
839839
840A budget's `max_list_cost.amount` is a whole number of US cents written as a string, so `"125"` means $1.25. See [Set a budget at session creation](https://platform.claude.com/docs/en/managed-agents/budgets#set-a-budget-at-session-creation).
840A budget's `max_list_cost.amount` (java, php: `maxListCost.amount`; csharp, go: `MaxListCost.Amount`) is a whole number of US cents written as a string, so `"125"` means $1.25. See [Set a budget at session creation](https://platform.claude.com/docs/en/managed-agents/budgets#set-a-budget-at-session-creation).
841841
842842You cannot add a budget to a session created without one. To change or remove a cap, see [Resume a session at its budget](https://platform.claude.com/docs/en/managed-agents/budgets#resume-a-session-at-its-budget). After you remove a session's cap, you cannot set a new one.
843843
No line in this hunk matches that.