New to Claude Skills? Learn how to install them →

Restricting Claude Managed Agents' Web Search and Web Fetch

Claude Managed Agents' web_search and web_fetch tools now accept allowed_domains and blocked_domains, each with its own list. Here's the exact config shape and validation rules.

September 1, 2026
Get Claude Skills
9 min read

Two web tools, each with its own list

Claude Managed Agents' built-in agent_toolset_20260401 includes web_search and web_fetch among its default tools. Both can now be scoped to specific domains directly on the agent or session configuration, allowed_domains to permit only named hosts, blocked_domains to forbid named ones, per Anthropic's tools reference. This guide covers the exact shape of that configuration, the validation rules that decide whether a domain string is even accepted, and how the restrictions behave once a session actually starts using them, including inside a multiagent roster.

Where the setting lives

Domain restrictions are entries in the toolset's configs array, the same array used to enable or disable individual tools. Each web_search or web_fetch entry is identified by name, and accepts an optional type field carrying the same value, which the server infers from name if you leave it out:

{
  "type": "agent_toolset_20260401",
  "configs": [
    {
      "type": "web_search",
      "name": "web_search",
      "allowed_domains": ["docs.example.com", "arxiv.org"],
      "user_location": {
        "type": "approximate",
        "country": "US",
        "timezone": "America/Los_Angeles"
      }
    },
    {
      "type": "web_fetch",
      "name": "web_fetch",
      "blocked_domains": ["ads.example.com"],
      "max_content_tokens": 50000
    }
  ]
}

This example limits web_search to two sites and localises its results to the US, while web_fetch can reach anywhere except one blocked host, with fetched content capped at 50,000 tokens before it enters the context.

A full worked request

Creating an agent with this configuration through the API looks like this:

curl -fsSL https://api.anthropic.com/v1/agents \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: managed-agents-2026-04-01" \
  -H "content-type: application/json" \
  -d '{
    "name": "Research Agent",
    "model": "claude-opus-5",
    "tools": [
      {
        "type": "agent_toolset_20260401",
        "configs": [
          {
            "type": "web_search",
            "name": "web_search",
            "allowed_domains": ["docs.example.com", "arxiv.org"],
            "user_location": {"type": "approximate", "country": "US", "timezone": "America/Los_Angeles"}
          },
          {
            "type": "web_fetch",
            "name": "web_fetch",
            "blocked_domains": ["ads.example.com"],
            "max_content_tokens": 50000
          }
        ]
      }
    ]
  }'

The ant CLI accepts the same shape as YAML, which is worth reaching for if you're version-controlling agent definitions the way ant CLI scripting covers:

name: Research Agent
model: claude-opus-5
tools:
  - type: agent_toolset_20260401
    configs:
      - type: web_search
        name: web_search
        allowed_domains: [docs.example.com, arxiv.org]
        user_location:
          type: approximate
          country: US
          timezone: America/Los_Angeles
      - type: web_fetch
        name: web_fetch
        blocked_domains: [ads.example.com]
        max_content_tokens: 50000

If you'd rather not hand-write JSON or YAML at all, the Claude Console exposes the common case directly: set allowed or blocked domains from the web_search and web_fetch rows of the Built-in tools card on the agent form, and switch to the form's Raw view for the two settings the card doesn't surface, max_content_tokens and user_location.

Four settings, two tools

SettingApplies toWhat it does
allowed_domainsweb_search, web_fetchThe only hosts the tool can reach. Cannot combine with blocked_domains on the same entry.
blocked_domainsweb_search, web_fetchHosts the tool can never reach.
max_content_tokensweb_fetch onlyCaps how much fetched page content enters the context. Must be a positive integer.
user_locationweb_search onlyLocalises search results; same shape as the Messages API's user_location parameter.

What happens when a request is blocked

A web_fetch call for a URL the domain lists don't permit returns an error result to the agent: is_error: true on the agent.tool_result event, with content naming the error code url_not_allowed. web_search, in contrast, doesn't error, it silently omits results the lists don't permit from what it returns, so a search that would otherwise surface a disallowed source just comes back with fewer results rather than failing the call outright.

The domain-matching rule, and its one asymmetry

A listed domain covers that host and all of its subdomains, but not the other way round: example.com covers docs.example.com, api.example.com, and any other subdomain, while listing docs.example.com covers only that subdomain, not the bare example.com or a sibling like api.example.com. A leading www. counts as its own subdomain under this rule too, so www.example.com alone does not cover the bare example.com. List the bare domain if you want both the root and every subdomain, www. included, covered by one entry.

Validation rules that reject a domain outright

Format and limit violations return a 400 invalid_request_error at agent creation, session creation, or an update that supplies tools, before anything runs. Per the reference, the rules are specific enough to be worth having on hand rather than discovering by trial and error:

  • 1 to 64 domains per list, each 1 to 255 characters. An empty list is rejected outright, the documented fix is omitting the field or sending null rather than [] if you mean "no restriction."
  • A plain hostname only: ASCII letters, digits, hyphens, underscores and dots. No scheme (https://), no port (:443), no credentials, no wildcard (*.example.com), and no whitespace. No label may start or end with a hyphen.
  • No IP addresses in any form, IPv4, IPv6, bracketed, or numeric shorthand like 127.1. Use the domain name.
  • No bare top-level domain or registry suffix, com, co.uk, gov.uk are all rejected, and so is a single-label internal name like intranet. A full domain like example.co.uk is required.
  • localhost and anything ending in .localhost, .local, .internal, .localdomain, or .invalid is rejected outright.
  • Internationalised domain names must use Punycode (xn-- form); a domain containing non-ASCII characters is rejected.
  • No duplicates within a list. Note that www.example.com and example.com count as different domains for this rule, consistent with the subdomain-matching asymmetry above.
  • web_fetch domains cannot carry a path. Use example.com, never example.com/*. web_search domains can carry a path suffix, like example.com/blog, though the reference notes the search provider matches this as a URL pattern rather than a strict host rule, so a plain hostname is the more predictable choice for web_search too.

Two more checks happen slightly later, since they depend on external providers rather than pure syntax: a domain in allowed_domains that Anthropic's crawler isn't permitted to access, and a user_location.country or user_location.timezone the search provider doesn't support. If a setting that validated fine earlier is no longer valid when the session first initialises the tool, the session emits a session.error event and returns to idle without retrying; the documented fix is updating the session's tools (and the agent too, so future sessions inherit the correction) before sending a new message to continue.

Multiagent sessions: lists combine, they never widen

In a multiagent session, every domain list bearing on a thread applies at once. A roster agent is bound by its own allowed_domains and blocked_domains, by whatever lists the agent that called it carries, and by the coordinator's current lists, all simultaneously. The combination rule matters: allowlists intersect, blocklists union, so a roster agent can only narrow what it can reach relative to the coordinator, never widen it. If the combined allowlists end up with nothing in common, the tool doesn't disappear, it stays listed, but every call against it fails with url_not_allowed, and Claude sees that constraint reflected in the tool's own description rather than discovering it only after a failed call.

Two settings sit outside this combination logic: max_content_tokens and user_location are not merged across the roster. A thread uses its own tool configuration if set, otherwise falls back to whatever the calling agent set, otherwise to the coordinator's current configuration. A {"type": "self"} roster entry has no web settings of its own at all and simply follows the coordinator's current settings. Worth knowing separately: the grader in an outcome-driven session always runs with web_search and web_fetch unavailable, regardless of any of this configuration.

Changing lists mid-session

You can update the domain lists on an idle session by updating its tools. The new lists apply for the rest of that session; in a multiagent session specifically, every thread picks up the change from its next turn, while a roster agent's own lists stay fixed as its agent definition set them when the session was originally created, they don't get refreshed by a coordinator-level update.

How this differs from the Messages API's own domain filtering

The vocabulary, allowed_domains and blocked_domains, matches domain filtering on the Messages API's server tools exactly, but Managed Agents applies a few extra constraints on top:

  • Each list is capped at 64 domains, a Managed-Agents-specific ceiling.
  • A web_fetch domain can never carry a path, where the equivalent Messages API setting may be more permissive.
  • Domains must be ASCII, Punycode for anything internationalised, where the Messages API accepts Unicode entries directly, though it recommends against them too.
  • max_uses, citations and cache_control, all valid on the Messages API's server tool version, aren't available on the Managed Agents toolset.

One more distinction worth flagging explicitly: organisation-level web search and web fetch settings configured in the Claude Console apply only to the Messages API, not to Managed Agents sessions. If you need an agent's web tools restricted, the allowed_domains/blocked_domains configuration on its own toolset is the only lever, there's no separate org-wide policy that reaches Managed Agents automatically.

Also worth remembering: this doesn't touch sandbox networking

It's easy to conflate this with an environment's own network access, but they're independent controls. An environment's networking setting governs what the sandbox itself can reach, bash commands, custom tool calls hitting internal services, and so on. web_search and web_fetch run on Anthropic's own servers, not inside the sandbox, whether the session's environment is cloud or self-hosted. Locking down an environment's networking setting does nothing to what these two tools can reach; the per-tool domain lists covered here are the only way to restrict them.

Troubleshooting

Agent creation fails with "Only one of allowed_domains or blocked_domains may be set." You've set both on the same entry. Pick one; they're mutually exclusive per entry, and there's no way to combine an allowlist and a blocklist on a single tool.

A web_fetch call returns url_not_allowed unexpectedly. Check the combined multiagent lists, not just the entry you set directly. A roster agent's own allowlist only narrows what the coordinator already permits, so a URL missing from the coordinator's list stays blocked even if your agent's own list would otherwise permit it.

web_search results seem to be missing sources I expected. This is the tool's designed behaviour on a restricted list: it omits disallowed results rather than erroring, so a narrower allowed_domains list quietly reduces what comes back instead of failing the call.

A session errors out with session.error shortly after I changed the domain lists. The session re-validates domain and location settings the first time it initialises the tool. If a setting that passed validation at creation is no longer valid by then, for instance a domain Anthropic's crawler can no longer reach, fix it by updating the session's tools, then send a new message to continue.

Where to go next

For the full built-in toolset these settings sit inside, see Claude Managed Agents explained. For the roster and coordinator mechanics referenced above, see multiagent orchestration in Claude Managed Agents. For how sandbox networking differs from these tool-level restrictions in a self-hosted deployment, see Claude Managed Agents: self-hosted sandboxes vs cloud environments. Browse the current catalogue at getclaudeskills.com/skills.

Frequently asked questions