tools-web-restrictions changedmanaged-agents/tools-web-restrictions
Nearest release: v2.1.292, published 4 hours before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
## Set domain lists on an agent ## Settings ## When a domain is not permitted ## Domain list rules ### What a listed domain matches ### Domain format ### Path suffixes on web search domains ## Validation errors ### When an accepted setting is no longer valid ## Multiagent and outcome-driven sessions ## Change the lists mid-session ## Differences from the Messages API tools ## Next steps
The whole hunk
523 lines, new pageA whole new page. There's nothing to diff it against, so here is what it says.
---
title: Restrict web search and web fetch domains
url: https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions
description: Control which sites an agent's web search and web fetch tools can reach, cap fetched content, and localize search results.
featureMetadata:
topic:
title: Managed Agents
url: https://platform.claude.com/docs/en/managed-agents/overview
status: beta
betaHeader: managed-agents-2026-04-01
---
To control which sites the agent's web tools can reach, set a domain list on the `web_search` and `web_fetch` entries of the [agent toolset](https://platform.claude.com/docs/en/managed-agents/tools#configuring-the-toolset). Each of these `configs` entries takes one of two lists:
* **`allowed_domains`:** The tool can reach only these hosts.
* **`blocked_domains`:** The tool can never reach these hosts.
Each tool carries its own list, so `web_search` and `web_fetch` can have different restrictions.
<Note>
These per-tool lists are the way to restrict what the web tools can reach. Two other settings do not affect these tools:
* **Environment networking:** An environment's [`networking`](https://platform.claude.com/docs/en/managed-agents/environments#networking) settings control the sandbox's own outbound traffic. `web_search` and `web_fetch` run on Anthropic's servers, whether the environment is a cloud or self-hosted sandbox.
* **Organization settings:** Organization-level web search and web fetch settings in the Claude Console apply to the Messages API. They do not apply to Managed Agents sessions.
</Note>
## Set domain lists on an agent
The following example creates an agent that limits `web_search` to two sites and blocks one host for `web_fetch`. It also sets `user_location` and `max_content_tokens`, which [Settings](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#settings) describes. The example then prints the `configs` array from the response.
<CodeGroup defaultLanguage="CLI">
```bash cURL
agent=$(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 @- <<'EOF'
{
"name": "Research Agent",
"model": "claude-opus-5-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
}
]
}
]
}
EOF
)
jq '.tools[0].configs' <<< "$agent"
```
<CodeGroupItem>
```bash CLI
ant apply agent.md
```
<File filename="agent.md">
```markdown
---
name: Research Agent
model: claude-opus-5-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
---
```
</File>
[`ant apply`](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/apply) creates the agent and prints its ID, not the `configs` array.
</CodeGroupItem>
```python Python
client = Anthropic()
agent = client.beta.agents.create(
name="Research Agent",
model="claude-opus-5-5",
tools=[
{
"type": "agent_toolset_20260401",
"configs": [
{
"name": "web_search",
"allowed_domains": ["docs.example.com", "arxiv.org"],
"user_location": {
"type": "approximate",
"country": "US",
"timezone": "America/Los_Angeles",
},
},
{
"name": "web_fetch",
"blocked_domains": ["ads.example.com"],
"max_content_tokens": 50_000,
},
],
}
],
)
for tool in agent.tools:
if tool.type == "agent_toolset_20260401":
print(json.dumps([config.to_dict() for config in tool.configs], indent=2))
```
```typescript TypeScript
const client = new Anthropic();
const agent = await client.beta.agents.create({
name: "Research Agent",
model: "claude-opus-5-5",
tools: [
{
type: "agent_toolset_20260401",
configs: [
{
name: "web_search",
allowed_domains: ["docs.example.com", "arxiv.org"],
user_location: {
type: "approximate",
country: "US",
timezone: "America/Los_Angeles"
}
},
{
name: "web_fetch",
blocked_domains: ["ads.example.com"],
max_content_tokens: 50_000
}
]
}
]
});
for (const tool of agent.tools) {
if (tool.type === "agent_toolset_20260401") {
console.log(JSON.stringify(tool.configs, null, 2));
}
}
```
```csharp C#
using Anthropic.Models.Beta.Agents;
AnthropicClient client = new();
var agent = await client.Beta.Agents.Create(new()
{
Name = "Research Agent",
Model = BetaManagedAgentsModel.ClaudeOpus5_5,
Tools =
[
new BetaManagedAgentsAgentToolset20260401Params
{
Type = BetaManagedAgentsAgentToolset20260401ParamsType.AgentToolset20260401,
Configs =
[
new BetaManagedAgentsWebSearchToolConfigParams
{
AllowedDomains = ["docs.example.com", "arxiv.org"],
UserLocation = new()
{
Country = "US",
Timezone = "America/Los_Angeles",
},
},
new BetaManagedAgentsWebFetchToolConfigParams
{
BlockedDomains = ["ads.example.com"],
MaxContentTokens = 50_000,
},
],
},
],
});
JsonSerializerOptions jsonOptions = new() { WriteIndented = true };
foreach (var tool in agent.Tools)
{
if (tool.TryPickBetaManagedAgentsAgentToolset20260401(out var toolset))
{
Console.WriteLine(JsonSerializer.Serialize(toolset.Configs, jsonOptions));
}
}
```
```go Go
client := anthropic.NewClient()
ctx := context.Background()
agent, err := client.Beta.Agents.New(ctx, anthropic.BetaAgentNewParams{
Name: "Research Agent",
Model: anthropic.BetaManagedAgentsModelConfigParams{
ID: anthropic.BetaManagedAgentsModelClaudeOpus5_5,
},
Tools: []anthropic.BetaAgentNewParamsToolUnion{{
OfAgentToolset20260401: &anthropic.BetaManagedAgentsAgentToolset20260401Params{
Type: anthropic.BetaManagedAgentsAgentToolset20260401ParamsTypeAgentToolset20260401,
Configs: []anthropic.BetaManagedAgentsAgentToolConfigParamsUnion{
{OfWebSearch: &anthropic.BetaManagedAgentsWebSearchToolConfigParams{
AllowedDomains: []string{"docs.example.com", "arxiv.org"},
UserLocation: anthropic.BetaManagedAgentsUserLocationParam{
Country: anthropic.String("US"),
Timezone: anthropic.String("America/Los_Angeles"),
},
}},
{OfWebFetch: &anthropic.BetaManagedAgentsWebFetchToolConfigParams{
BlockedDomains: []string{"ads.example.com"},
MaxContentTokens: anthropic.Int(50000),
}},
},
},
}},
})
if err != nil {
panic(err)
}
for _, tool := range agent.Tools {
switch toolset := tool.AsAny().(type) {
case anthropic.BetaManagedAgentsAgentToolset20260401:
configs := make([]json.RawMessage, len(toolset.Configs))
for i, config := range toolset.Configs {
configs[i] = json.RawMessage(config.RawJSON())
}
output, err := json.MarshalIndent(configs, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(output))
}
}
```
```java Java
import com.anthropic.models.beta.agents.AgentCreateParams;
import com.anthropic.models.beta.agents.BetaManagedAgentsAgentToolset20260401Params;
import com.anthropic.models.beta.agents.BetaManagedAgentsModel;
import com.anthropic.models.beta.agents.BetaManagedAgentsUserLocation;
import com.anthropic.models.beta.agents.BetaManagedAgentsWebFetchToolConfigParams;
import com.anthropic.models.beta.agents.BetaManagedAgentsWebSearchToolConfigParams;
void main() {
var client = AnthropicOkHttpClient.fromEnv();
var agent = client.beta().agents().create(AgentCreateParams.builder()
.name("Research Agent")
.model(BetaManagedAgentsModel.CLAUDE_OPUS_5_5)
.addTool(BetaManagedAgentsAgentToolset20260401Params.builder()
.type(BetaManagedAgentsAgentToolset20260401Params.Type.AGENT_TOOLSET_20260401)
.addConfig(BetaManagedAgentsWebSearchToolConfigParams.builder()
.allowedDomains(List.of("docs.example.com", "arxiv.org"))
.userLocation(BetaManagedAgentsUserLocation.builder()
.country("US")
.timezone("America/Los_Angeles")
.build())
.build())
.addConfig(BetaManagedAgentsWebFetchToolConfigParams.builder()
.blockedDomains(List.of("ads.example.com"))
.maxContentTokens(50_000)
.build())
.build())
.build());
for (var tool : agent.tools()) {
if (tool.isAgentToolset20260401()) {
var configs = tool.asAgentToolset20260401().configs();
IO.println(ObjectMappers.jsonMapper().valueToTree(configs));
}
}
Cut at 300 lines. The page has the rest.
No line in this hunk matches that.