Claude Platform Docs
Managed AgentsSecurity

Secure your Managed Agents deployment

The settings that limit what your agents can reach and do, most important first.

This guide lists the settings that limit what an agent on Claude Managed Agents can reach and do, most important first. Each section links to the page that covers the setting in full.

SectionSetting or decisionRecommended
Choose where the agent runsCloud or self-hosted sandboxCloud, unless files and processes must stay on your infrastructure
Limit the networkEnvironment networking.typelimited, with only the hosts the agent needs
Keep credentials in vaultsinjection_location and networking on each environment variable credentialRequest headers only, and limited networking with only the hosts the key is for
Restrict web search and web fetchallowed_domains on each web toolAn allowlist on each tool. On web_fetch, list only the sites the agent needs. On web_search, list the sites you want results from
Approve risky actionspermission_policy on each toolauto on bash, write, edit, web_fetch, and MCP tools that only read data. always_ask instead on a tool if you cannot undo its changes outside the sandbox, or if relayed end-user text alone should not make it run
Give the agent the smallest tool setdefault_config.enabled on the agent toolsetfalse, then enable the tools the agent needs
Keep untrusted input away from powerful toolsWhich tools and credentials an agent holds when it reads untrusted inputNo agent that reads untrusted input has a tool on always_allow that writes files, runs commands, or changes records
Set limits and a way to stopbudget on each session and deploymentA cap sized to what you expect a run to cost
Optionally have an offline reviewer read every transcriptAn offline review job you run that reads each session's eventsOptional. A review of each session that went idle or terminated, on a schedule
Monitor sessions and review retentionWebhooks and session deletionAn alert when a session goes idle, reaches its budget, or terminates, and a check of why it went idle. Store the events you want to keep in your own logs, and delete sessions you no longer need

Security risks and sandbox boundaries explains why these settings matter and what they do not protect against. To review and monitor sessions, see Review and monitor agent sessions.

Choose where the agent runs

Choose a cloud environment unless you need files and processes to stay on infrastructure you control. Session history and tool inputs and outputs go to Anthropic either way.

If you use a self-hosted sandbox, keep these four points in mind:

  • Network: Limit the network applies to cloud environments. For a self-hosted sandbox, set the equivalent limits on its traffic in your own firewall. Your firewall does not limit the MCP servers an agent declares, so review them, and any that your application sets for a session.
  • Web tools: The web tools run on Anthropic's servers, so your firewall does not limit them. Limit them with their domain lists. See Restrict web search and web fetch.
  • Credentials: Environment variable credentials are not yet supported with self-hosted sandboxes.
  • Isolation and hardening: You are responsible for isolating sessions from each other, hardening the sandbox image, and storing the environment service key. See the Security model.

Neither option changes the compliance coverage of Managed Agents or how long it keeps session history. See Monitor sessions and review retention.

Limit the network

Set 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.

Files, memory stores, and GitHub repositories that you attach stay available to the agent regardless of allowed_hosts.

The 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:

ant apply environment.yaml
environment.yaml
# yaml-language-server: $schema=https://platform.claude.com/schemas/ant/beta/environment.json
name: support-agent
config:
  type: cloud
  networking:
    type: limited
    allowed_hosts:
      - help.example.com

A limited environment has three networking settings:

SettingWhat it opens to code in the sandboxRecommended
allowed_hostsThe hosts you list, for any requestOnly the hosts the agent needs, including the host of each MCP server you operate or trust
allow_package_managersThe 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 filesfalse, 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
allow_mcp_serversNo host. Managed Agents connects to MCP servers from Anthropic's serversfalse, with the host of each MCP server you operate or trust listed in allowed_hosts

The allow_package_managers and allow_mcp_servers settings add no hosts for web search and web fetch.

Leave 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. The same check runs when a session update changes mcp_servers.

When you choose hosts for allowed_hosts, follow these two rules:

  • List only hosts you operate or trust.
  • Avoid *. wildcards and shared-hosting domains where anyone can publish content.

If the agent keeps bash, set the bash tool's permission policy as Approve risky actions describes.

See Cloud environment setup for every networking setting.

Keep credentials in vaults

Store 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.

SettingSet it toWhyWhat it does not do
injection_location{"header": true, "body": false}, after you check that the service reads the key from a headerRequest 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 sendCode 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
networking on the credentiallimited, with the exact hosts the key is forResponses reach the sandbox unredacted, so avoid wildcards, shared-hosting domains, and hosts that echo request headersIt does not open the host. The environment must also allow it
The key's permissions, at the service that issued the keyOnly the permissions the agent needsThe agent can do anything the key allowsNot applicable
A mounted repository's GitHub tokenA fine-grained token with the minimum permissionsCode 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 pushNot applicable

The 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 for the request in every language.

Keep keys out of system prompts, agent definitions, and messages. Do not give the agent a Claude API key. Even when a Claude API key is in a vault, code in the sandbox can use it to call the Claude API directly. It can do anything that key 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.

Fetch tokens yourself and store them in the vault, because a token that code in the sandbox fetches with a stored secret comes back unredacted.

Keep vaults for workloads with different trust levels in separate workspaces, because any API key with access to a workspace can reference its vaults. Use API keys scoped to one workspace.

See Authenticate with vaults for MCP credentials and rotation.

Restrict web search and web fetch

Set 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.

A 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.

In a limited environment, the allowed_hosts list from Limit the network also limits the web tools. An unrestricted environment or a self-hosted sandbox does not limit the web tools.

In a limited environmentResult
An allowed_domains entry on an enabled web tool is outside allowed_hostsCreating a session fails with a 400 error, and so does a session update that adds such an entry. A session that a deployment starts, on its schedule or by a manual run, is created anyway. The tool then returns nothing from hosts outside allowed_hosts
A web tool has no list of its ownThe tool returns pages and results only from hosts in allowed_hosts. Set allowed_domains on the tool as well
allowed_hosts has no entriesNeither web tool returns a page or a search result
You add a host to allowed_hosts for a web toolThe host is also open to code in the sandbox

The two lists match hosts differently:

ListEntryMatchesDoes not match
allowed_hosts (environment)example.comexample.comwww.example.com
allowed_hosts (environment)*.example.comEvery subdomainexample.com
allowed_domains (web tool)example.comexample.com and every subdomainOther domains

If 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 for how the two lists match.

The web_fetch tool also opens only URLs that have already appeared in the session:

Where the URL appearsweb_fetch can open it
The text of a user message, including end-user text that you relayYes
The description of a user.define_outcome eventYes
The address of a web search resultYes
The text of a page that web_fetch returned earlier (not a PDF), where the full URL is shownYes
The text of a custom tool's result, when Claude called the tool directlyYes, unless the result is marked is_error: true
The system promptNo
The agent's configuration, including allowed_domains entriesNo
Claude's own outputNo
Output of bash and the other sandbox toolsNo
An MCP tool resultNo
A file attached to a user messageNo

In 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.

This 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.

A domain list on web_fetch does not limit the bash tool. Limit the network as well. See Domain list rules.

Approve risky actions

Set 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 determines whether a tool call runs, waits for your approval, or is evaluated by the server.

ToolRecommended policyWhy
read, glob, grepalways_allowThey read files in the sandbox and change nothing
bash, write, editauto. 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 textThe agent toolset default is always_allow, which runs every call without approval
web_fetchautoA URL the agent fetches can carry data to the site it points to
web_searchalways_ask if the agent handles data you would not want sent in a search query. Otherwise always_allowallowed_domains limits which sites results come from, not what the query contains
MCP tools that only read dataauto, set for each tool in the toolset's configsThe toolset default stays always_ask, so a tool the MCP server adds later still waits for approval
MCP tools that change dataalways_askThis is the MCP toolset default. Keep it
Custom toolsYour code decides whether each call runsPermission policies do not apply

The toolset in Give the agent the smallest tool set applies these policies.

The auto policy lets the server run a call, deny it, or pause for approval. A person cannot approve every call in a long run, so the server checks each one instead. Pair auto with limited networking, a key with narrow permissions, a budget, and an alert on idle sessions. auto is not a human checkpoint, so if a person must review a tool's calls before they run, configure always_ask on that tool.

auto treats text in user.message events and the description in a user.define_outcome event as your instruction, including end-user text you relay.

A paused session waits indefinitely, so an unattended session needs a client that answers paused calls or interrupts the session.

Review each paused call before you allow it. A client that allows every call without showing it to a person is the same as always_allow. See Respond to confirmation requests and See how each call was evaluated.

Give the agent the smallest tool set

Set default_config.enabled to false and enable only the tools the agent needs. The agent toolset enables all eight built-in tools by default.

ToolWhat it does
bashRuns any command, including requests to allowed hosts
write, editChange files in the sandbox
read, glob, grepRead files in the sandbox
web_fetch, web_searchReturn pages and search results from the web, through Anthropic's servers

The 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, 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.

The following sample limits web_fetch to help.example.com with allowed_domains. It sets auto on write and web_fetch, as 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:

ant apply agent.md
agent.md
---
name: Support Agent
model: claude-opus-5-5
tools:
  - type: agent_toolset_20260401
    default_config:
      enabled: false
      permission_policy:
        type: always_ask
    configs:
      - name: read
        enabled: true
        permission_policy:
          type: always_allow
      - name: write
        enabled: true
        permission_policy:
          type: auto
      - name: web_fetch
        enabled: true
        allowed_domains: [help.example.com]
        permission_policy:
          type: auto
  - type: custom
    name: lookup_order
    description: Look up one order by its ID. Returns the status, the items, and the delivery date.
    input_schema:
      type: object
      properties:
        order_id:
          type: string
          description: The order ID from the ticket
      required:
        - order_id
---

An agent update replaces the whole tools array, so send every entry you want to keep.

An agent update reaches only new sessions, so also check deployments, agents that list this agent, and existing sessions:

  • A deployment pins an agent version, so point each deployment at the new one.
  • An agent that lists this one in subagents.predefined_agents or workflows.predefined_agents keeps the version it pinned, so update that agent too.
  • To tighten a session that already exists, update that session's tools. 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.

Limit MCP servers and custom tools to what the agent needs, too:

  • 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.
  • 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.

Keep untrusted input away from powerful tools

Check 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:

  • Untrusted input: Web pages, search results, support tickets, emails, repository files, uploads, MCP server results, and end-user messages that you relay.
  • 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.

Text 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.

Input the agent readsPower it also hasDo this
Tickets, emails, or uploadsbash with a credentialReplace bash with a custom tool that does one thing. If the agent must keep bash, approve each call with always_ask
Web pages or search resultsWriting files or changing recordsTurn off the web tools, or limit them to sites you operate or trust
MCP results or repository filesMCP tools that writeKeep the MCP toolset on always_ask, and enable only the tools the agent needs
A mounted GitHub repositoryAny toolMount 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
Any untrusted inputWriting to a memory storeAttach the store as read_only unless the agent must write. The default is read_write, and later sessions read saved text as trusted memory

In a cloud environment, reading a file with read can also load CLAUDE.md and AGENTS.md files as instructions. They load from the file's directory and its parent directories, up to the sandbox's working directory. Files they reference with @ and a path, such as @docs/setup.md, also load, up to five references deep. A reference can point anywhere in the sandbox, for example @/etc/hosts. No setting turns this off except disabling read, so treat a repository, package, or archive that someone outside your team can write as untrusted input.

When an agent must read untrusted input and also act, this guide recommends one of three designs:

  • Split reading from acting. In one multiagent session, a lead agent gives tasks to a fetcher, which reads the web, and a writer, which changes files or records.
  • Give the agent one narrow custom tool. Your application runs the tool, checks its input, and holds the credential. The support agent uses this design, not the split. See Answer tool calls that pause the session.
  • Keep a person in the loop. Use always_ask on the powerful tool so a person approves each call.

The split uses three agents:

AgentReadsHoldsPasses on
Lead (the agent that the session runs)Your message, and what the other agents send backNo built-in tools. Its subagents.predefined_agents list names the fetcher and the writerA task to each agent
FetcherWeb pages and search resultsweb_fetch and web_search only, each with allowed_domainsShort results, in a format you ask for in its system prompt
WriterThe task from the leadThe tools that write files, run commands, or change records, on auto or always_ask. No web toolsIts result

The 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.

Agents in one multiagent session share the sandbox, its files, and the vault credentials, so this split separates only their tools and conversations. For a stronger split, use two sessions with separate environments and vaults. Have your application pass only fixed fields, such as an order ID, between the two sessions.

Set limits and a way to stop

Set a budget when you create each session, and decide in advance how you stop an agent.

ControlWhat it does
Session budgetA cap on spend at public list prices. At the cap, the session and each thread 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
Deployment budgetThe same cap, applied to each session a deployment starts
user.interrupt eventStops 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
Archive or delete a sessionArchiving keeps the history and blocks new events. Deleting removes the record, events, and sandbox
Pause or archive a deploymentPausing stops new scheduled runs but still allows manual runs. Archiving ends the schedule permanently. Sessions already running keep running
Archive or delete a vault or credentialRemoves 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

To stop a running agent, follow these steps:

  1. Send user.interrupt by itself.
  2. For a scheduled agent, also pause the deployment so that no new scheduled run starts. To end the schedule permanently, archive the deployment.
  3. If a key might be exposed, rotate it at the service that issued it.
  4. If the agent has workflow runs open, also send a user.message that asks it to stop them, because an interrupt ends no run. See Interrupt a session with runs open for the tool calls to cancel first.
  5. Wait for the session to go idle. A running session cannot be archived or deleted.
  6. Archive the session to keep its history. Delete it when you no longer need the history.

An interrupt does not undo what the agent already did or sent. Archiving an agent does not stop its running sessions.

A 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.

You cannot add a budget to a session created without one. To change or remove a cap, see Resume a session at its budget. After you remove a session's cap, you cannot set a new one.

A budget caps spending, but it does not limit what the agent does before the cap. To keep workloads with different trust levels apart, use separate workspaces. Give each workload an API key scoped to one workspace, because a key that can reach several workspaces can act in any of them.

See Session budgets, Session operations, and Scheduled deployments.

Next steps

Networking modes, allowed hosts, and package managers.

Approval policies and confirmation requests.

Credential types, injection locations, and rotation.

Caps, resuming at a budget, and budgets on deployments.

Was this page helpful?