도구

도구 (Tools)

Claude Managed Agents는 클로드가 세션 안에서 자율적으로 사용할 수 있는 내장 도구 세트를 제공해요. 에이전트 구성에서 어떤 도구를 사용할지 지정해서 가용 범위를 제어할 수 있어요. 또한 사용자 정의 도구(custom tool)도 지원하며, MCP 서버의 도구를 주려면 MCP connector를 사용하면 돼요.

출처: 문서

본문

Claude Managed Agents는 클로드가 세션 안에서 자율적으로 사용할 수 있는 내장 도구 세트를 제공해요. 에이전트 구성에서 도구를 지정해 어떤 것을 사용할 수 있는지 제어하세요.

Claude Managed Agents는 사용자 정의 도구도 지원해요. 여러분의 애플리케이션이 이 도구를 별도로 실행하고 결과를 클로드에게 반환하며, 클로드는 그 결과로 작업을 계속해요. MCP 서버의 도구를 에이전트에 주려면 대신 MCP connector를 사용하세요.

Available tools

에이전트 도구세트에는 다음 도구들이 포함돼요. 에이전트 구성에 도구세트를 포함하면 모두 기본 활성화됩니다. configs 배열의 각 항목은 Name 열 값인 name으로 식별되며, 같은 값의 선택적 type 필드를 받아요. web_searchweb_fetch 항목은 추가 설정을 받으며, Restrict web search and web fetch domains를 참고하세요.

Tool Name Description
Bash bash Execute bash commands in a shell session
Read read Read a file from the sandbox filesystem
Write write Write a file to the sandbox filesystem
Edit edit Perform string replacement in a file
Glob glob Fast file pattern matching using glob patterns
Grep grep Text search using regex patterns
Web fetch web_fetch Fetch content from a URL
Web search web_search Search the web for information

도구 출력이 100,000자(약 25,000토큰)를 넘으면 자동으로 샌드박스의 파일에 기록돼요. 모델은 파일 경로가 포함된 잘린 미리보기를 받고, 거기서 전체 내용을 읽을 수 있어요.

Configuring the toolset

에이전트를 만들 때 agent_toolset_20260401로 전체 도구세트를 활성화하세요. 특정 도구를 비활성화하거나 설정을 덮어쓰려면 configs 배열을 사용하세요. 각 구성 항목은 도구 호출이 확인 없이 실행되는지, 확인이 필요한지, 서버가 개별적으로 평가하는지를 제어하는 permission_policy도 설정할 수 있어요. 사용 가능한 정책 유형은 Permission policies를 참고하세요.

web_searchweb_fetch의 구성 항목도 도메인 필터와 기타 웹 설정을 받아요. Restrict web search and web fetch domains를 참고하세요.

```bash cURL agent=$(curl -fsSL https://api.anthropic.com/v1/agents \ -H "x-api-key: $ANTHR...KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01" \ -H "content-type: application/json" \ -d @- <<'EOF' { "name": "Coding Assistant", "model": "claude-opus-5-5", "tools": [ { "type": "agent_toolset_20260401", "configs": [ {"name": "web_fetch", "enabled": false} ] } ] } EOF ) ``` ```bash CLI ant apply agent.md ```
<File filename="agent.md">
  ```markdown
  ---
  name: Coding Assistant
  model: claude-opus-5-5
  tools:
    - type: agent_toolset_20260401
      configs:
        - name: web_fetch
          enabled: false
  ---
  ```
</File>
agent = client.beta.agents.create(
    name="Coding Assistant",
    model="claude-opus-5-5",
    tools=[
        {
            "type": "agent_toolset_20260401",
            "configs": [
                {"name": "web_fetch", "enabled": False},
            ],
        },
    ],
)
const agent = await client.beta.agents.create({
  name: "Coding Assistant",
  model: "claude-opus-5-5",
  tools: [
    {
      type: "agent_toolset_20260401",
      configs: [{ name: "web_fetch", enabled: false }]
    }
  ]
});
using Anthropic.Models.Beta.Agents;

var agent = await client.Beta.Agents.Create(new()
{
    Name = "Coding Assistant",
    Model = new("claude-opus-5-5"),
    Tools =
    [
        new BetaManagedAgentsAgentToolset20260401Params
        {
            Type = "agent_toolset_20260401",
            Configs =
            [
                new BetaManagedAgentsWebFetchToolConfigParams { Enabled = false },
            ],
        },
    ],
});
agent, err := client.Beta.Agents.New(ctx, anthropic.BetaAgentNewParams{
	Name: "Coding Assistant",
	Model: anthropic.BetaManagedAgentsModelConfigParams{
		ID: "claude-opus-5-5",
	},
	Tools: []anthropic.BetaAgentNewParamsToolUnion{{
		OfAgentToolset20260401: &anthropic.BetaManagedAgentsAgentToolset20260401Params{
			Type: anthropic.BetaManagedAgentsAgentToolset20260401ParamsTypeAgentToolset20260401,
			Configs: []anthropic.BetaManagedAgentsAgentToolConfigParamsUnion{{
				OfWebFetch: &anthropic.BetaManagedAgentsWebFetchToolConfigParams{
					Enabled: anthropic.Bool(false),
				},
			}},
		},
	}},
})
if err != nil {
	panic(err)
}
_ = agent
import com.anthropic.models.beta.agents.*;

var agent = client.beta().agents().create(AgentCreateParams.builder()
    .name("Coding Assistant")
    .model(BetaManagedAgentsModel.CLAUDE_OPUS_5_5)
    .addTool(BetaManagedAgentsAgentToolset20260401Params.builder()
        .type(BetaManagedAgentsAgentToolset20260401Params.Type.AGENT_TOOLSET_20260401)
        .addConfig(BetaManagedAgentsWebFetchToolConfigParams.builder()
            .enabled(false)
            .build())
        .build())
    .build());
use Anthropic\Beta\Agents\BetaManagedAgentsAgentToolset20260401Params;
use Anthropic\Beta\Agents\BetaManagedAgentsWebFetchToolConfigParams;

$agent = $client->beta->agents->create(
    name: 'Coding Assistant',
    model: 'claude-opus-5-5',
    tools: [
        BetaManagedAgentsAgentToolset20260401Params::with(
            type: 'agent_toolset_20260401',
            configs: [
                BetaManagedAgentsWebFetchToolConfigParams::with(enabled: false),
            ],
        ),
    ],
);
agent = client.beta.agents.create(
  name: "Coding Assistant",
  model: "claude-opus-5-5",
  tools: [
    {
      type: :agent_toolset_20260401,
      configs: [
        {name: :web_fetch, enabled: false}
      ]
    }
  ]
)

Disabling specific tools

도구를 비활성화하려면 에이전트의 tools 배열에 있는 도구세트 객체의 구성 항목에서 enabled: false를 설정하세요:

{
  "type": "agent_toolset_20260401",
  "configs": [
    { "name": "web_fetch", "enabled": false },
    { "name": "web_search", "enabled": false }
  ]
}

Enabling only specific tools

default_config 객체는 세트의 모든 도구에 대한 기준선을 설정하고, 도구별 configs 항목이 그것을 덮어써요. 모두 꺼둔 상태로 시작해 필요한 것만 활성화하려면 default_config.enabledfalse로 설정하세요:

{
  "type": "agent_toolset_20260401",
  "default_config": { "enabled": false },
  "configs": [
    { "name": "bash", "enabled": true },
    { "name": "read", "enabled": true },
    { "name": "write", "enabled": true }
  ]
}

Restrict web search and web fetch domains

에이전트의 웹 도구가 도달할 수 있는 사이트를 제어하려면 도구세트 configs 배열의 web_searchweb_fetch 항목에 allowed_domains(도구가 이 호스트에만 도달) 또는 blocked_domains(도구가 이 호스트에 절대 도달 못 함)를 설정하세요. 각 도구는 자체 목록을 가지므로 web_searchweb_fetch는 서로 다른 제한을 가질 수 있어요. 나열된 도메인은 그 호스트와 모든 하위 도메인을 포함해요. 런타임에 목록이 허용하지 않는 URL에 대한 web_fetch 호출은 에이전트에게 오류 결과를 반환해요(agent.tool_result 이벤트에서 is_error: true, url_not_allowed 오류 코드를 명명한 콘텐츠와 함께). web_search는 목록이 허용하지 않는 결과를 생략해요.

다음 도구세트는 web_search를 두 사이트로 제한하고 결과를 지역화하며, web_fetch에 대해 한 호스트를 차단하고 컨텍스트에 들어가는 가져온 콘텐츠의 양을 제한해요:

{
  "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
    }
  ]
}
In the Python, TypeScript, Go, Java, C#, Ruby, and PHP SDKs, each `configs` entry is typed per tool: a union with one member per built-in tool, discriminated by `type`. `type` is optional when you construct an entry (the server infers it from `name`) and always present on responses. This typing does not change the JSON that an entry serializes to, so a request whose entries set only `name`, `enabled`, and `permission_policy` is valid with or without `type`. In SDKs where you construct entries from typed values rather than plain dictionaries or hashes (Go, Java, C#, and PHP), the element type of `configs` is the union itself: build each entry from its per-tool member type.

다음 요청은 이 도구세트로 에이전트를 만들고 응답에서 configs 배열을 출력해요:

```bash cURL agent=$(curl -fsSL https://api.anthropic.com/v1/agents \ -H "x-api-key: $ANTHR...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" ``` ```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>
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))
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));
  }
}
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));
    }
}
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))
	}
}
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));
        }
    }
}
use Anthropic\Beta\Agents\BetaManagedAgentsAgentToolset20260401;
use Anthropic\Beta\Agents\BetaManagedAgentsAgentToolset20260401Params;
use Anthropic\Beta\Agents\BetaManagedAgentsUserLocation;
use Anthropic\Beta\Agents\BetaManagedAgentsWebFetchToolConfigParams;
use Anthropic\Beta\Agents\BetaManagedAgentsWebSearchToolConfigParams;
// ...

$client = new Client();

$agent = $client->beta->agents->create(
    name: 'Research Agent',
    model: 'claude-opus-5-5',
    tools: [
        BetaManagedAgentsAgentToolset20260401Params::with(
            type: 'agent_toolset_20260401',
            configs: [
                BetaManagedAgentsWebSearchToolConfigParams::with(
                    allowedDomains: ['docs.example.com', 'arxiv.org'],
                    userLocation: BetaManagedAgentsUserLocation::with(
                        country: 'US',
                        timezone: 'America/Los_Angeles',
                    ),
                ),
                BetaManagedAgentsWebFetchToolConfigParams::with(
                    blockedDomains: ['ads.example.com'],
                    maxContentTokens: 50_000,
                ),
            ],
        ),
    ],
);

foreach ($agent->tools as $tool) {
    if ($tool instanceof BetaManagedAgentsAgentToolset20260401) {
        echo json_encode($tool->configs, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), PHP_EOL;
    }
}
client = Anthropic::Client.new

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
        }
      ]
    }
  ]
)

case agent.tools.first
in Anthropic::Models::Beta::BetaManagedAgentsAgentToolset20260401 => toolset
  puts JSON.pretty_generate(toolset.configs.map(&:to_h))
end
[`ant apply`](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/apply) creates the agent and prints its ID, not the `configs` array.

Claude Console에서는 에이전트 양식의 Built-in tools 카드에서 web_searchweb_fetch 행으로 허용·차단 도메인을 설정하고, 에이전트 구성의 Raw 뷰에서 max_content_tokensuser_location을 설정하세요.

enabledpermission_policy 외에도 웹 도구 항목은 다음 설정을 받아요:

Setting Applies to Description
allowed_domains web_search, web_fetch The only hosts the tool can reach. Cannot be combined with blocked_domains on the same entry.
blocked_domains web_search, web_fetch Hosts the tool cannot reach.
max_content_tokens web_fetch Caps the amount of fetched page content included in the context. Must be a positive integer. See content limits.
user_location web_search Localizes search results. An object with the same fields as the Messages API user_location parameter.
An environment's [`networking`](https://platform.claude.com/docs/en/managed-agents/environments#networking) settings control the sandbox's own outbound traffic. They do not affect `web_search` or `web_fetch`, which run on Anthropic's servers whether the environment is a cloud or self-hosted sandbox. The per-tool `allowed_domains` and `blocked_domains` lists are the way to restrict what these tools can reach. Organization-level web search and web fetch settings in the Claude Console apply to the Messages API and do not apply to Managed Agents sessions. To restrict an agent's web tools, configure `allowed_domains` or `blocked_domains` on its toolset instead.

Domain list rules

  • Set either allowed_domains or blocked_domains on an entry, not both. An entry that sets both is rejected.
  • Each list holds 1 to 64 domains, each 1 to 255 characters. An empty list is rejected: to apply no restriction, omit the field or send null.
  • Each domain is a registrable domain name, or a subdomain of one, written as a plain hostname: ASCII letters, digits, hyphens, underscores, and dots, with no scheme, port, credentials, wildcard, or whitespace, no label that begins or ends with a hyphen, and no path other than the optional web_search path suffix described later in this list. Use example.com, not https://example.com, example.com:443, or *.example.com. Hostnames are compared without regard to case, and a single trailing / is ignored.
  • A listed domain matches that host and its subdomains: example.com covers docs.example.com, but docs.example.com does not cover example.com or api.example.com. A leading www. is a subdomain like any other, so www.example.com does not cover example.com; list the bare domain to cover both.
  • IP addresses are not accepted in any form, whether IPv4, IPv6, bracketed, or numeric shorthand such as 127.1. List the site's domain name instead.
  • A bare top-level domain or registry suffix such as com, co.uk, or gov.uk is rejected, and so is a single-label name such as intranet. List a full domain such as example.co.uk.
  • localhost and hosts ending in .localhost, .local, .internal, .localdomain, or .invalid are rejected.
  • Use the xn-- (Punycode) form for internationalized domain names; a domain that contains non-ASCII characters is rejected.
  • A web_fetch domain cannot include a path: use example.com, not example.com/*. A web_search domain can carry a path suffix such as example.com/blog, in which the path cannot contain spaces, ?, #, or any of the characters $ , | ^ !. Prefer plain hostnames for web_search too, because the search provider matches path suffixes as URL patterns rather than as strict host rules.
  • Duplicate domains within a list are rejected. www.example.com and example.com count as different domains; see the earlier matching rule for what each covers.

When settings are validated

형식과 한도 위반은 에이전트를 만들거나 업데이트할 때, 그리고 tools를 제공하는 세션을 만들거나 업데이트할 때 400 invalid_request_error로 거부돼요. 예를 들어 두 목록을 모두 설정한 항목의 메시지에는 Only one of allowed_domains or blocked_domains may be set.이, 빈 목록의 메시지에는 allowed_domains: Empty list of domains is ambiguous. Provide at least one domain or null.이 포함돼요. 형식 규칙을 어기는 도메인 메시지는 목록과 0부터 시작하는 위치를 명명해요. 예: allowed_domains.0: IP addresses are not supported; provide a plain hostname like "example.com".

같은 요청은 검색·가져오기 공급자에 의존하는 세 가지 설정도 거부해요: Anthropic 크롤러가 접근하도록 허용되지 않는 allowed_domains의 도메인, 검색 공급자가 지원하지 않는 user_location.country(메시지는 user_location.country: not a country the search provider supports로 끝남), 유효한 IANA 이름이 아닌 user_location.timezone. 세션은 도구를 처음 초기화할 때 구성을 다시 확인해요. 이전에 받아들여진 설정이 그 시점에 더 이상 유효하지 않으면 세션은 session.error 이벤트를 발행하고 재시도 없이 idle로 돌아가요. 세션의 도구를 업데이트해 설정을 고치고, 새 세션이 수정된 구성으로 시작하도록 에이전트도 업데이트한 다음, 새 user.message를 보내 계속하세요.

Multiagent sessions, outcomes, and mid-session updates

multiagent 세션에서는 스레드에 적용되는 모든 도메인 목록이 동시에 강제돼요: 코디네이터 로스터의 에이전트는 자신의 allowed_domains·blocked_domains, 호출한 에이전트의 것, 그리고 코디네이터의 현재 목록에 의해 제약받아요.

  • Allowlists combine to the domains that all of them cover, and blocklists add together, so a roster agent can narrow what a tool reaches but never widen it. For example, a roster agent that sets blocked_domains keeps the coordinator's allowed_domains and blocks those hosts within it, and a roster agent that sets its own allowed_domains can reach only the hosts that both its list and the coordinator's list cover.
  • If the combined allowlists have no domain in common, the tool stays available to that agent but every call fails with a url_not_allowed error stating that no domain is permitted, and the tool description tells the model so. Keep each roster agent's allowlist inside the coordinator's to avoid this.
  • max_content_tokens and user_location are not combined: a thread uses the value from its own tool configuration if set, otherwise from the agent that called it, otherwise from the coordinator's current configuration.
  • A {"type": "self"} roster entry has no web settings of its own and follows the coordinator's current settings.
  • The grader in outcome-driven sessions runs without web_search and web_fetch, regardless of these settings.
  • You can change the lists on an idle session by updating its tools. The new lists apply to the rest of the session; in a multiagent session, every thread applies them from its next turn, while a roster agent's own lists stay as its agent definition set them when the session was created.

Differences from the Messages API tools

이 설정들은 Messages API 서버 도구의 도메인 필터링과 같은 allowed_domains·blocked_domains 용어를 사용하지만, Managed Agents에서는 다음과 같은 차이가 있어요:

  • Each list is capped at 64 domains.
  • Domains listed for web_fetch cannot include a path.
  • Domains must be ASCII: use the xn-- (Punycode) form for internationalized domain names. The Messages API accepts Unicode entries, though it recommends against them.
  • max_uses, citations, and cache_control are not available on the toolset.

Custom tools

내장 도구 외에도 사용자 정의 도구를 정의할 수 있어요. 사용자 정의 도구는 Messages API의 user-defined client tools와 유사해요.

각 사용자 정의 도구는 계약을 정의해요: 어떤 작업이 가능하고 무엇을 반환하는지 지정하면, 클로드가 언제·어떻게 호출할지 결정해요. 모델은 그 자체로 아무것도 실행하지 않아요. 구조화된 요청을 발행하면 여러분의 코드가 작업을 실행하고, 결과가 대화로 다시 흘러들어와요. 세션 중에 사용자 정의 도구 호출을 받고 결과를 반환하는 방법은 Session event stream을 참고하세요.

세션이 셀프 호스팅 샌드박스에서 실행된다면 환경 워커가 네트워크 안의 MCP 서버를 감싸는 도구를 포함해 샌드박스에서 사용자 정의 도구를 서빙할 수 있어요.

```bash cURL agent=$(curl -fsSL https://api.anthropic.com/v1/agents \ -H "x-api-key: $ANTHR...KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01" \ -H "content-type: application/json" \ -d @- <<'EOF' { "name": "Weather Agent", "model": "claude-opus-5-5", "tools": [ { "type": "agent_toolset_20260401" }, { "type": "custom", "name": "get_weather", "description": "Get current weather for a location", "input_schema": { "type": "object", "properties": { "location": {"type": "string", "description": "City name"} }, "required": ["location"] } } ] } EOF ) ``` ```bash CLI ant apply agent.md ```
<File filename="agent.md">
  ```markdown
  ---
  name: Weather Agent
  model: claude-opus-5-5
  tools:
    - type: agent_toolset_20260401
    - type: custom
      name: get_weather
      description: Get current weather for a location
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  ---
  ```
</File>
agent = client.beta.agents.create(
    name="Weather Agent",
    model="claude-opus-5-5",
    tools=[
        {
            "type": "agent_toolset_20260401",
        },
        {
            "type": "custom",
            "name": "get_weather",
            "description": "Get current weather for a location",
            "input_schema": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City name"},
                },
                "required": ["location"],
            },
        },
    ],
)
const agent = await client.beta.agents.create({
  name: "Weather Agent",
  model: "claude-opus-5-5",
  tools: [
    { type: "agent_toolset_20260401" },
    {
      type: "custom",
      name: "get_weather",
      description: "Get current weather for a location",
      input_schema: {
        type: "object",
        properties: { location: { type: "string", description: "City name" } },
        required: ["location"]
      }
    }
  ]
});
using System.Text.Json;
using Anthropic.Models.Beta.Agents;

var agent = await client.Beta.Agents.Create(new()
{
    Name = "Weather Agent",
    Model = new("claude-opus-5-5"),
    Tools =
    [
        new BetaManagedAgentsAgentToolset20260401Params
        {
            Type = "agent_toolset_20260401",
        },
        new BetaManagedAgentsCustomToolParams
        {
            Type = "custom",
            Name = "get_weather",
            Description = "Get current weather for a location",
            InputSchema = new()
            {
                Properties = new Dictionary<string, JsonElement>
                {
                    ["location"] = JsonSerializer.SerializeToElement(
                        new { type = "string", description = "City name" }
                    ),
                },
                Required = ["location"],
            },
        },
    ],
});
agent, err := client.Beta.Agents.New(ctx, anthropic.BetaAgentNewParams{
	Name: "Weather Agent",
	Model: anthropic.BetaManagedAgentsModelConfigParams{
		ID: "claude-opus-5-5",
	},
	Tools: []anthropic.BetaAgentNewParamsToolUnion{{
		OfAgentToolset20260401: &anthropic.BetaManagedAgentsAgentToolset20260401Params{
			Type: anthropic.BetaManagedAgentsAgentToolset20260401ParamsTypeAgentToolset20260401,
		},
	}, {
		OfCustom: &anthropic.BetaManagedAgentsCustomToolParams{
			Type:        anthropic.BetaManagedAgentsCustomToolParamsTypeCustom,
			Name:        "get_weather",
			Description: "Get current weather for a location",
			InputSchema: anthropic.BetaManagedAgentsCustomToolInputSchemaParam{
				Properties: map[string]any{
					"location": map[string]any{
						"type":        "string",
						"description": "City name",
					},
				},
				Required: []string{"location"},
			},
		},
	}},
})
if err != nil {
	panic(err)
}
_ = agent
import com.anthropic.models.beta.agents.*;
import java.util.Map;

var agent = client.beta().agents().create(AgentCreateParams.builder()
    .name("Weather Agent")
    .model(BetaManagedAgentsModel.CLAUDE_OPUS_5_5)
    .addTool(BetaManagedAgentsAgentToolset20260401Params.builder()
        .type(BetaManagedAgentsAgentToolset20260401Params.Type.AGENT_TOOLSET_20260401)
        .build())
    .addTool(BetaManagedAgentsCustomToolParams.builder()
        .type(BetaManagedAgentsCustomToolParams.Type.CUSTOM)
        .name("get_weather")
        .description("Get current weather for a location")
        .inputSchema(BetaManagedAgentsCustomToolInputSchema.builder()
            .properties(BetaManagedAgentsCustomToolInputSchema.Properties.builder()
                .putAdditionalProperty("location", JsonValue.from(Map.of(
                    "type", "string",
                    "description", "City name")))
                .build())
            .addRequired("location")
            .build())
        .build())
    .build());
use Anthropic\Beta\Agents\BetaManagedAgentsAgentToolset20260401Params;
use Anthropic\Beta\Agents\BetaManagedAgentsCustomToolInputSchema;
use Anthropic\Beta\Agents\BetaManagedAgentsCustomToolParams;

$agent = $client->beta->agents->create(
    name: 'Weather Agent',
    model: 'claude-opus-5-5',
    tools: [
        BetaManagedAgentsAgentToolset20260401Params::with(
            type: 'agent_toolset_20260401',
        ),
        BetaManagedAgentsCustomToolParams::with(
            type: 'custom',
            name: 'get_weather',
            description: 'Get current weather for a location',
            inputSchema: BetaManagedAgentsCustomToolInputSchema::with(
                properties: ['location' => ['type' => 'string', 'description' => 'City name']],
                required: ['location'],
            ),
        ),
    ],
);
agent = client.beta.agents.create(
  name: "Weather Agent",
  model: "claude-opus-5-5",
  tools: [
    {type: :agent_toolset_20260401},
    {
      type: :custom,
      name: "get_weather",
      description: "Get current weather for a location",
      input_schema: {
        type: :object,
        properties: {location: {type: "string", description: "City name"}},
        required: ["location"]
      }
    }
  ]
)

에이전트에 사용자 정의 도구를 정의하면, 에이전트가 세션 중에 그것을 호출해요.

Best practices for custom tool definitions

  • Provide extremely detailed descriptions. This is by far the most important factor in tool performance. Your descriptions should explain what the tool does and when to use it (and when not to). Explain what each parameter means and how it affects the tool's behavior. Call out any important caveats or limitations. The more context you can give Claude about your tools, the better it is at determining when and how to use them. Aim for three to four sentences for each tool description, more if the tool is complex.
  • Consolidate related operations into fewer tools. Rather than creating a separate tool for every action (create_pr, review_pr, merge_pr), group them into a single tool with an action parameter. Fewer, more capable tools reduce selection ambiguity and make your tool surface easier for Claude to navigate.
  • Use meaningful namespacing in tool names. When your tools span multiple services or resources, prefix names with the resource (for example, db_query or storage_read). This makes tool selection unambiguous as your library grows.
  • Design tool responses to return only high-signal information. Return semantic, stable identifiers (for example, slugs or UUIDs) rather than opaque internal references, and include only the fields Claude needs to determine its next step. Bloated responses waste context and make it harder for Claude to extract what matters.

Next steps

Connect MCP servers to your agents for access to external tools and data sources. Control when agent and MCP tools execute. Send events, stream responses, and interrupt or redirect your session mid-execution.

더 알아보기 (Learn more)