Repository Public
1---2title: Server tools3url: https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools4description: "Work with Anthropic-executed tools: server_tool_use blocks, pause_turn continuation, mixed server and client tool turns, and domain filtering."5---67Server-executed tools share these mechanics: the `server_tool_use` block, `pause_turn` continuation, turns that mix server and client tools, Zero Data Retention (ZDR) eligibility, and domain filtering. For individual tools, see the [tool reference](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference).89## The server\_tool\_use block1011The `server_tool_use` block appears in Claude's response when a server-executed tool runs. Its `id` field uses the `srvtoolu_` prefix to distinguish it from client tool calls:1213```json14{15 "type": "server_tool_use",16 "id": "srvtoolu_01A2B3C4D5E6F7G8H9",17 "name": "web_search",18 "input": { "query": "latest quantum computing breakthroughs" }19}20```2122The API executes the tool internally. You see the call and its result in the response, but you don't handle execution. Unlike client `tool_use` blocks, you don't need to respond with a `tool_result`. The tool's result block (for example, `web_search_tool_result` for web search) follows the `server_tool_use` block in the same assistant turn, paired by `tool_use_id`. If Claude calls one of your client tools at the same time, the `server_tool_use` block appears without its result, and the response ends with `stop_reason: "tool_use"`. The API runs the tool when you return the client `tool_result` blocks in your next request.2324## The server-side loop and pause\_turn2526When using server tools such as web search, the API executes tool calls in a server-side agentic loop. On a long-running turn, the API might pause that loop and return a `pause_turn` stop reason.2728Here's how to handle the `pause_turn` stop reason:2930<CodeGroup>31 ```bash cURL32 # Initial request. If "stop_reason" in the response is "pause_turn", continue33 # the turn by re-sending the request with the assistant content appended to messages.34 curl https://api.anthropic.com/v1/messages \35 -H "x-api-key: $ANTHROPIC_API_KEY" \36 -H "anthropic-version: 2023-06-01" \37 -H "content-type: application/json" \38 -d '{39 "model": "claude-opus-5",40 "max_tokens": 1024,41 "messages": [42 {43 "role": "user",44 "content": "Search for comprehensive information about quantum computing breakthroughs in 2025"45 }46 ],47 "tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}]48 }'49 ```5051 ```bash CLI52 # Initial request. If "stop_reason" in the output is "pause_turn", re-run with53 # the assistant content appended to messages (see the SDK tabs).54 ant messages create <<'YAML'55 model: claude-opus-556 max_tokens: 102457 tools:58 - {type: web_search_20250305, name: web_search, max_uses: 10}59 messages:60 - {role: user, content: "Search for comprehensive information about quantum computing breakthroughs in 2025"}61 YAML62 ```6364 ```python Python65 client = anthropic.Anthropic()6667 # Initial request with web search68 response = client.messages.create(69 model="claude-opus-5",70 max_tokens=1024,71 messages=[72 {73 "role": "user",74 "content": "Search for comprehensive information about quantum computing breakthroughs in 2025",75 }76 ],77 tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],78 )7980 # Check if the response has pause_turn stop reason81 if response.stop_reason == "pause_turn":82 # Continue the conversation with the paused content83 messages = [84 {85 "role": "user",86 "content": "Search for comprehensive information about quantum computing breakthroughs in 2025",87 },88 {"role": "assistant", "content": response.content},89 ]9091 # Send the continuation request92 continuation = client.messages.create(93 model="claude-opus-5",94 max_tokens=1024,95 messages=messages,96 tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],97 )9899 print(continuation)100 else:101 print(response)102 ```103104 ```typescript TypeScript105 const client = new Anthropic();106107 // Initial request with web search108 const response = await client.messages.create({109 model: "claude-opus-5",110 max_tokens: 1024,111 messages: [112 {113 role: "user",114 content:115 "Search for comprehensive information about quantum computing breakthroughs in 2025"116 }117 ],118 tools: [119 {120 type: "web_search_20250305",121 name: "web_search",122 max_uses: 10123 }124 ]125 });126127 // Check if the response has pause_turn stop reason128 if (response.stop_reason === "pause_turn") {129 // Continue the conversation with the paused content130 const messages: Anthropic.MessageParam[] = [131 {132 role: "user",133 content:134 "Search for comprehensive information about quantum computing breakthroughs in 2025"135 },136 { role: "assistant", content: response.content }137 ];138139 // Send the continuation request140 const continuation = await client.messages.create({141 model: "claude-opus-5",142 max_tokens: 1024,143 messages,144 tools: [145 {146 type: "web_search_20250305",147 name: "web_search",148 max_uses: 10149 }150 ]151 });152153 console.log(continuation);154 } else {155 console.log(response);156 }157 ```158159 ```csharp C#160 AnthropicClient client = new();161162 var parameters = new MessageCreateParams163 {164 Model = Model.ClaudeOpus5,165 MaxTokens = 1024,166 Messages = [167 new() {168 Role = Role.User,169 Content = "Search for comprehensive information about quantum computing breakthroughs in 2025"170 }171 ],172 Tools = [new ToolUnion(new WebSearchTool20250305 { MaxUses = 10 })]173 };174175 var response = await client.Messages.Create(parameters);176177 if (response.StopReason?.Value() == StopReason.PauseTurn)178 {179 // Continue the conversation with the paused content180 var continuationParams = new MessageCreateParams181 {182 Model = Model.ClaudeOpus5,183 MaxTokens = 1024,184 Messages = [185 new() {186 Role = Role.User,187 Content = "Search for comprehensive information about quantum computing breakthroughs in 2025"188 },189 new() {190 Role = Role.Assistant,191 Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()192 }193 ],194 Tools = [new ToolUnion(new WebSearchTool20250305 { MaxUses = 10 })]195 };196197 var continuation = await client.Messages.Create(continuationParams);198 Console.WriteLine(continuation);199 }200 else201 {202 Console.WriteLine(response);203 }204 ```205206 ```go Go207 client := anthropic.NewClient()208209 webSearchTool := []anthropic.ToolUnionParam{210 {OfWebSearchTool20250305: &anthropic.WebSearchTool20250305Param{211 MaxUses: anthropic.Int(10),212 }},213 }214215 response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{216 Model: anthropic.ModelClaudeOpus5,217 MaxTokens: 1024,218 Messages: []anthropic.MessageParam{219 anthropic.NewUserMessage(anthropic.NewTextBlock("Search for comprehensive information about quantum computing breakthroughs in 2025")),220 },221 Tools: webSearchTool,222 })223 if err != nil {224 log.Fatal(err)225 }226227 if response.StopReason == anthropic.StopReasonPauseTurn {228 // Pass the paused response back as-is so Claude can continue the turn229 continuation, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{230 Model: anthropic.ModelClaudeOpus5,231 MaxTokens: 1024,232 Messages: []anthropic.MessageParam{233 anthropic.NewUserMessage(anthropic.NewTextBlock("Search for comprehensive information about quantum computing breakthroughs in 2025")),234 response.ToParam(),235 },236 Tools: webSearchTool,237 })238 if err != nil {239 log.Fatal(err)240 }241 fmt.Println(continuation)242 } else {243 fmt.Println(response)244 }245 ```246247 ```java Java248 import com.anthropic.models.messages.StopReason;249 import com.anthropic.models.messages.WebSearchTool20250305;250251 void main() {252 AnthropicClient client = AnthropicOkHttpClient.fromEnv();253254 MessageCreateParams params = MessageCreateParams.builder()255 .model(Model.CLAUDE_OPUS_5)256 .maxTokens(1024L)257 .addUserMessage("Search for comprehensive information about quantum computing breakthroughs in 2025")258 .addTool(WebSearchTool20250305.builder()259 .maxUses(10L)260 .build())261 .build();262263 Message response = client.messages().create(params);264265 if (response.stopReason().isPresent()266 && response.stopReason().get().equals(StopReason.PAUSE_TURN)) {267 MessageCreateParams continuationParams = MessageCreateParams.builder()268 .model(Model.CLAUDE_OPUS_5)269 .maxTokens(1024L)270 .addUserMessage("Search for comprehensive information about quantum computing breakthroughs in 2025")271 .addMessage(response)272 .addTool(WebSearchTool20250305.builder()273 .maxUses(10L)274 .build())275 .build();276277 Message continuation = client.messages().create(continuationParams);278 IO.println(continuation);279 } else {280 IO.println(response);281 }282 }283 ```284285 ```php PHP286 $client = new Client();287288 $response = $client->messages->create(289 maxTokens: 1024,290 messages: [291 [292 'role' => 'user',293 'content' => 'Search for comprehensive information about quantum computing breakthroughs in 2025'294 ]295 ],296 model: 'claude-opus-5',297 tools: [298 [299 'type' => 'web_search_20250305',300 'name' => 'web_search',301 'max_uses' => 10302 ]303 ],304 );305306 if ($response->stopReason === 'pause_turn') {307 $messages = [308 [309 'role' => 'user',310 'content' => 'Search for comprehensive information about quantum computing breakthroughs in 2025'311 ],312 [313 'role' => 'assistant',314 'content' => $response->content315 ]316 ];317318 $continuation = $client->messages->create(319 maxTokens: 1024,320 messages: $messages,321 model: 'claude-opus-5',322 tools: [323 [324 'type' => 'web_search_20250305',325 'name' => 'web_search',326 'max_uses' => 10327 ]328 ],329 );330331 echo $continuation;332 } else {333 echo $response;334 }335 ```336337 ```ruby Ruby338 client = Anthropic::Client.new339340 response = client.messages.create(341 model: "claude-opus-5",342 max_tokens: 1024,343 messages: [344 {345 role: "user",346 content:347 "Search for comprehensive information about quantum computing breakthroughs in 2025"348 }349 ],350 tools: [351 {352 type: "web_search_20250305",353 name: "web_search",354 max_uses: 10355 }356 ]357 )358359 if response.stop_reason == :pause_turn360 messages = [361 {362 role: "user",363 content: "Search for comprehensive information about quantum computing breakthroughs in 2025"364 },365 {366 role: "assistant",367 content: response.content368 }369 ]370371 continuation = client.messages.create(372 model: "claude-opus-5",373 max_tokens: 1024,374 messages: messages,375 tools: [376 {377 type: "web_search_20250305",378 name: "web_search",379 max_uses: 10380 }381 ]382 )383384 puts continuation385 else386 puts response387 end388 ```389</CodeGroup>390391When handling `pause_turn`:392393* **Continue the conversation:** Pass the paused response back as-is in a subsequent request to let Claude continue its turn.394* **Preserve tool state:** Include the same tools in the continuation request. A paused turn can end with a `server_tool_use` block whose tool has not run yet, and the API returns a validation error if that tool is missing from the continuation.395* **Repeat as needed:** A continued turn can pause again. Check `stop_reason` on each response and continue until you get a different stop reason, capping the number of continuations as you would any retry loop.396397For the other `stop_reason` values and general handling patterns, see [Stop reasons and fallback](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons).398399## Mixing server tools and client tools in one turn400401Claude can call a server tool and a client tool in the same group of parallel tool calls, for example, `web_fetch` together with a user-defined tool. A client tool is any tool that your code executes and that produces a `tool_use` block, whether it is user-defined or an Anthropic-schema client tool such as the [Bash tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/bash-tool). When that happens, the API does not run the server tool. It returns immediately so that you can run the client tool first:402403* `stop_reason` is `"tool_use"`, not `"pause_turn"`.404* `content` contains the `server_tool_use` block and the client `tool_use` block, but no result block for the server tool: that call is not finished.405* There is no other marker. Detect the state by looking for a `server_tool_use` block whose `id` has no matching result block in the response. An `mcp_tool_use` block from the [MCP connector](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector) behaves the same way. Server tool calls that already have their result block in the same response are complete and need nothing from you.406407<Note>408 With [programmatic tool calling](https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling), the same response shape means something different. The client `tool_use` block comes from code that is running in the `code_execution` tool rather than from Claude directly, and its `caller` field names the `code_execution` block that called it. That code has already started: it is paused waiting for your `tool_result` blocks, and sending them resumes the execution instead of starting a deferred tool. The `code_execution` block's own result block arrives once the code finishes, which can take more than one round of tool results. The follow-up user message itself is the same in both cases; with programmatic tool calling, also pass back the `id` from the response's `container` field, as that page shows.409</Note>410411```json412{413 "stop_reason": "tool_use",414 "content": [415 {416 "type": "text",417 "text": "I'll fetch the article and check your system at the same time."418 },419 {420 "type": "server_tool_use",421 "id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",422 "name": "web_fetch",423 "input": { "url": "https://example.com/article" }424 },425 {426 "type": "tool_use",427 "id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",428 "name": "run_command",429 "input": { "command": "uname -a" }430 }431 ]432}433```434435To continue the turn, run the client tools and send a user message whose content is only the `tool_result` blocks, one for each `tool_use` block in that response. Keep the same `tools` array: a resume request that no longer defines the waiting server tool fails with a 400 whose message ends ``but no `web_fetch` tool was provided``.436437```json438{439 "role": "user",440 "content": [441 {442 "type": "tool_result",443 "tool_use_id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",444 "content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"445 }446 ]447}448```449450The API attaches your results to the still-open assistant turn, runs the deferred server tool (for paused code execution, resumes it), and then lets Claude continue. For a server tool Claude called directly, the next response begins with the result block that answers the previous response's `server_tool_use` `id`, followed by the newly generated content and a fresh `stop_reason`:451452```json453{454 "stop_reason": "end_turn",455 "content": [456 {457 "type": "web_fetch_tool_result",458 "tool_use_id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",459 "content": {460 "type": "web_fetch_result",461 "url": "https://example.com/article",462 "content": {463 "type": "document",464 "source": {465 "type": "text",466 "media_type": "text/plain",467 "data": "Full text content of the article..."468 }469 }470 }471 },472 {473 "type": "text",474 "text": "The article argues that... and your machine is running Linux..."475 }476 ]477}478```479480A `server_tool_use` block and its result block pair up by `tool_use_id`, not by position: in this flow they arrive in two different responses, and the `server_tool_use` block is not repeated in the second one. On later requests, keep the whole exchange in your `messages` array in order: the first response as an `assistant` message, the `tool_result` user message, and then the next response as another `assistant` message, the same way you accumulate any other tool-use exchange.481482<Warning>483 The follow-up user message must contain nothing except `tool_result` blocks. A block added after the results, such as text, tells the API that the assistant turn is over. For a server tool Claude called directly, that leaves the turn with an unresolved server tool call, and the request fails with a 400 `invalid_request_error`:484485 ```text wrap486 `web_fetch` tool use with id `srvtoolu_01HxbWnMRmbWyMfUtJKC45rA` was found without a corresponding `web_fetch_tool_result` block487 ```488489 A follow-up that puts content before the results, answers only some of the client `tool_use` IDs, or contains no `tool_result` blocks at all fails earlier, with the client tool error described in [Handle tool calls](https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls):490491 ```text wrap492 `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01PjgRJLbXrXEMZwDNYLnBqk. Each `tool_use` block must have a corresponding `tool_result` block in the next message.493 ```494495 To give Claude more input, send it as a separate user message after the turn completes.496</Warning>497498**How this differs from `pause_turn`:** A [`pause_turn` response](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#the-server-side-loop-and-pause-turn) can also end with a `server_tool_use` block that has not run, but it never leaves a client `tool_use` block waiting on you, so you continue it by re-sending the assistant content as-is. A response that leaves a client `tool_use` block waiting on you never has a `stop_reason` of `pause_turn`: when Claude stops to call your tools, `stop_reason` is `tool_use`, and you continue it by sending the client `tool_result` blocks rather than by re-sending the response. In both cases the API runs the pending server tool at the start of the next request.499500The following example enables web fetch together with a user-defined `run_command` tool and handles the mixed response:501502<CodeGroup>503 ```bash cURL504 # If "stop_reason" is "tool_use" and a server_tool_use block has no matching505 # result block, that call is not finished. Run the client tools, then POST506 # again with one more user message containing only their tool_result blocks507 # and the same tools array (see the SDK tabs).508 curl https://api.anthropic.com/v1/messages \509 -H "x-api-key: $ANTHROPIC_API_KEY" \510 -H "anthropic-version: 2023-06-01" \511 -H "content-type: application/json" \512 -d '{513 "model": "claude-opus-4-8",514 "max_tokens": 1024,515 "messages": [516 {517 "role": "user",518 "content": "Summarize https://example.com/article and run uname -a to tell me what system this is on."519 }520 ],521 "tools": [522 {"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5},523 {524 "name": "run_command",525 "description": "Run a shell command on this computer and return its output.",526 "input_schema": {527 "type": "object",528 "properties": {"command": {"type": "string", "description": "The command to run"}},529 "required": ["command"]530 }531 }532 ]533 }'534 ```535536 ```bash CLI537 # If "stop_reason" is "tool_use" and a server_tool_use block has no matching538 # result block, run the client tools and re-run with a user message of only539 # their tool_result blocks appended (see the SDK tabs).540 ant messages create <<'YAML'541 model: claude-opus-4-8542 max_tokens: 1024543 messages:544 - role: user545 content: "Summarize https://example.com/article and run uname -a to tell me what system this is on."546 tools:547 - {type: web_fetch_20250910, name: web_fetch, max_uses: 5}548 - name: run_command549 description: Run a shell command on this computer and return its output.550 input_schema:551 type: object552 properties:553 command: {type: string, description: The command to run}554 required: [command]555 YAML556 ```557558 ```python Python559 client = anthropic.Anthropic()560561 tools = [562 {"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5},563 {564 "name": "run_command",565 "description": "Run a shell command on this computer and return its output.",566 "input_schema": {567 "type": "object",568 "properties": {569 "command": {"type": "string", "description": "The command to run"}570 },571 "required": ["command"],572 },573 },574 ]575 messages = [576 {577 "role": "user",578 "content": "Summarize https://example.com/article and run uname -a to tell me what system this is on.",579 }580 ]581582 response = client.messages.create(583 model="claude-opus-4-8", max_tokens=1024, tools=tools, messages=messages584 )585586 tool_results = [587 {588 "type": "tool_result",589 "tool_use_id": block.id,590 # Run your tool here. This example returns a fixed string.591 "content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux",592 }593 for block in response.content594 if block.type == "tool_use"595 ]596597 if response.stop_reason == "tool_use" and tool_results:598 # A server_tool_use block with no result block in this response is not finished; its result arrives in a later response.599 # Send back only the client tool_result blocks, with the same tools.600 continuation = client.messages.create(601 model="claude-opus-4-8",602 max_tokens=1024,603 tools=tools,604 messages=[605 *messages,606 {"role": "assistant", "content": response.content},607 {"role": "user", "content": tool_results},608 ],609 )610 # If a web_fetch was deferred, it runs on this request and its611 # web_fetch_tool_result is the first block of continuation.content.612 print(continuation)613 else:614 print(response)615 ```616617 ```typescript TypeScript618 const client = new Anthropic();619620 const webFetchTool = {621 type: "web_fetch_20250910",622 name: "web_fetch",623 max_uses: 5624 } as const;625 const runCommandTool: Anthropic.Tool = {626 name: "run_command",627 description: "Run a shell command on this computer and return its output.",628 input_schema: {629 type: "object" as const,630 properties: {631 command: { type: "string", description: "The command to run" }632 },633 required: ["command"]634 }635 };636 const messages: Anthropic.MessageParam[] = [637 {638 role: "user",639 content:640 "Summarize https://example.com/article and run uname -a to tell me what system this is on."641 }642 ];643644 const response = await client.messages.create({645 model: "claude-opus-4-8",646 max_tokens: 1024,647 tools: [webFetchTool, runCommandTool],648 messages649 });650651 const toolResults: Anthropic.ToolResultBlockParam[] = [];652 for (const block of response.content) {653 if (block.type === "tool_use") {654 toolResults.push({655 type: "tool_result",656 tool_use_id: block.id,657 // Run your tool here. This example returns a fixed string.658 content: "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"659 });660 }661 }662663 if (response.stop_reason === "tool_use" && toolResults.length > 0) {664 // A server_tool_use block with no result block in this response is not finished; its result arrives in a later response.665 // Send back only the client tool_result blocks, with the same tools.666 const continuation = await client.messages.create({667 model: "claude-opus-4-8",668 max_tokens: 1024,669 tools: [webFetchTool, runCommandTool],670 messages: [671 ...messages,672 { role: "assistant", content: response.content },673 { role: "user", content: toolResults }674 ]675 });676 // If a web_fetch was deferred, it runs on this request and its677 // web_fetch_tool_result is the first block of continuation.content.678 console.log(continuation);679 } else {680 console.log(response);681 }682 ```683684 ```csharp C#685 AnthropicClient client = new();686687 List<ToolUnion> tools =688 [689 new ToolUnion(new WebFetchTool20250910() { MaxUses = 5 }),690 new ToolUnion(new Tool()691 {692 Name = "run_command",693 Description = "Run a shell command on this computer and return its output.",694 InputSchema = new InputSchema()695 {696 Properties = new Dictionary<string, JsonElement>697 {698 ["command"] = JsonSerializer.SerializeToElement(699 new { type = "string", description = "The command to run" }700 ),701 },702 Required = ["command"],703 },704 }),705 ];706 MessageParam userMessage = new()707 {708 Role = Role.User,709 Content = "Summarize https://example.com/article and run uname -a to tell me what system this is on."710 };711712 var response = await client.Messages.Create(new MessageCreateParams713 {714 Model = Model.ClaudeOpus4_8,715 MaxTokens = 1024,716 Tools = tools,717 Messages = [userMessage]718 });719720 var toolResults = new List<ContentBlockParam>();721 foreach (var block in response.Content)722 {723 if (block.TryPickToolUse(out var toolUse))724 {725 toolResults.Add(new ContentBlockParam(new ToolResultBlockParam()726 {727 ToolUseID = toolUse.ID,728 // Run your tool here. This example returns a fixed string.729 Content = "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux",730 }));731 }732 }733734 if (response.StopReason?.Value() == StopReason.ToolUse && toolResults.Count > 0)735 {736 // A server_tool_use block with no result block in this response is not finished; its result arrives in a later response.737 // Send back only the client tool_result blocks, with the same tools.738 var continuation = await client.Messages.Create(new MessageCreateParams739 {740 Model = Model.ClaudeOpus4_8,741 MaxTokens = 1024,742 Tools = tools,743 Messages =744 [745 userMessage,746 new()747 {748 Role = Role.Assistant,749 Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()750 },751 new() { Role = Role.User, Content = new MessageParamContent(toolResults) }752 ]753 });754 // If a web_fetch was deferred, it runs on this request and its755 // web_fetch_tool_result is the first block of continuation.Content.756 Console.WriteLine(continuation);757 }758 else759 {760 Console.WriteLine(response);761 }762 ```763764 ```go Go765 client := anthropic.NewClient()766767 tools := []anthropic.ToolUnionParam{768 {OfWebFetchTool20250910: &anthropic.WebFetchTool20250910Param{769 MaxUses: anthropic.Int(5),770 }},771 {OfTool: &anthropic.ToolParam{772 Name: "run_command",773 Description: anthropic.String("Run a shell command on this computer and return its output."),774 InputSchema: anthropic.ToolInputSchemaParam{775 Properties: map[string]any{776 "command": map[string]any{777 "type": "string",778 "description": "The command to run",779 },780 },781 Required: []string{"command"},782 },783 }},784 }785 userMessage := anthropic.NewUserMessage(anthropic.NewTextBlock("Summarize https://example.com/article and run uname -a to tell me what system this is on."))786787 response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{788 Model: anthropic.ModelClaudeOpus4_8,789 MaxTokens: 1024,790 Tools: tools,791 Messages: []anthropic.MessageParam{userMessage},792 })793 if err != nil {794 log.Fatal(err)795 }796797 var toolResults []anthropic.ContentBlockParamUnion798 for _, block := range response.Content {799 if toolUse, ok := block.AsAny().(anthropic.ToolUseBlock); ok {800 // Run your tool here. This example returns a fixed string.801 output := "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"802 toolResults = append(toolResults, anthropic.NewToolResultBlock(toolUse.ID, output, false))803 }804 }805806 if response.StopReason == anthropic.StopReasonToolUse && len(toolResults) > 0 {807 // A server_tool_use block with no result block in this response is not finished; its result arrives in a later response.808 // Send back only the client tool_result blocks, with the same tools.809 continuation, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{810 Model: anthropic.ModelClaudeOpus4_8,811 MaxTokens: 1024,812 Tools: tools,813 Messages: []anthropic.MessageParam{814 userMessage,815 response.ToParam(),816 anthropic.NewUserMessage(toolResults...),817 },818 })819 if err != nil {820 log.Fatal(err)821 }822 // If a web_fetch was deferred, it runs on this request and its823 // web_fetch_tool_result is the first block of continuation.Content.824 fmt.Println(continuation)825 } else {826 fmt.Println(response)827 }828 ```829830 ```java Java831 void main() {832 AnthropicClient client = AnthropicOkHttpClient.fromEnv();833834 Tool runCommandTool = Tool.builder()835 .name("run_command")836 .description("Run a shell command on this computer and return its output.")837 .inputSchema(Tool.InputSchema.builder()838 .properties(JsonValue.from(Map.of(839 "command", Map.of("type", "string", "description", "The command to run")840 )))841 .putAdditionalProperty("required", JsonValue.from(List.of("command")))842 .build())843 .build();844 String prompt = "Summarize https://example.com/article and run uname -a to tell me what system this is on.";845846 Message response = client.messages().create(MessageCreateParams.builder()847 .model(Model.CLAUDE_OPUS_4_8)848 .maxTokens(1024L)849 .addTool(WebFetchTool20250910.builder().maxUses(5L).build())850 .addTool(runCommandTool)851 .addUserMessage(prompt)852 .build());853854 List<ContentBlockParam> toolResults = new ArrayList<>();855 for (ContentBlock block : response.content()) {856 block.toolUse().ifPresent(toolUse -> toolResults.add(ContentBlockParam.ofToolResult(857 ToolResultBlockParam.builder()858 .toolUseId(toolUse.id())859 // Run your tool here. This example returns a fixed string.860 .content("Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux")861 .build()862 )));863 }864865 boolean isToolUse = response.stopReason()866 .map(StopReason.TOOL_USE::equals)867 .orElse(false);868 if (isToolUse && !toolResults.isEmpty()) {869 // A server_tool_use block with no result block in this response is not finished; its result arrives in a later response.870 // Send back only the client tool_result blocks, with the same tools.871 Message continuation = client.messages().create(MessageCreateParams.builder()872 .model(Model.CLAUDE_OPUS_4_8)873 .maxTokens(1024L)874 .addTool(WebFetchTool20250910.builder().maxUses(5L).build())875 .addTool(runCommandTool)876 .addUserMessage(prompt)877 .addMessage(response)878 .addUserMessageOfBlockParams(toolResults)879 .build());880 // If a web_fetch was deferred, it runs on this request and its881 // web_fetch_tool_result is the first block of continuation.content().882 IO.println(continuation);883 } else {884 IO.println(response);885 }886 }887 ```888889 ```php PHP890 $client = new Client();891892 $tools = [893 ['type' => 'web_fetch_20250910', 'name' => 'web_fetch', 'max_uses' => 5],894 [895 'name' => 'run_command',896 'description' => 'Run a shell command on this computer and return its output.',897 'input_schema' => [898 'type' => 'object',899 'properties' => [900 'command' => ['type' => 'string', 'description' => 'The command to run']901 ],902 'required' => ['command']903 ]904 ]905 ];906 $userMessage = ['role' => 'user', 'content' => 'Summarize https://example.com/article and run uname -a to tell me what system this is on.'];907908 $response = $client->messages->create(909 maxTokens: 1024,910 messages: [$userMessage],911 model: 'claude-opus-4-8',912 tools: $tools,913 );914915 $toolResults = [];916 foreach ($response->content as $block) {917 if ($block->type === 'tool_use') {918 $toolResults[] = [919 'type' => 'tool_result',920 'tool_use_id' => $block->id,921 // Run your tool here. This example returns a fixed string.922 'content' => 'Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux'923 ];924 }925 }926927 if ($response->stopReason === 'tool_use' && count($toolResults) > 0) {928 // A server_tool_use block with no result block in this response is not finished; its result arrives in a later response.929 // Send back only the client tool_result blocks, with the same tools.930 $continuation = $client->messages->create(931 maxTokens: 1024,932 messages: [933 $userMessage,934 ['role' => 'assistant', 'content' => $response->content],935 ['role' => 'user', 'content' => $toolResults],936 ],937 model: 'claude-opus-4-8',938 tools: $tools,939 );940 // If a web_fetch was deferred, it runs on this request and its941 // web_fetch_tool_result is the first block of $continuation->content.942 echo $continuation;943 } else {944 echo $response;945 }946 ```947948 ```ruby Ruby949 client = Anthropic::Client.new950951 tools = [952 { type: "web_fetch_20250910", name: "web_fetch", max_uses: 5 },953 {954 name: "run_command",955 description: "Run a shell command on this computer and return its output.",956 input_schema: {957 type: "object",958 properties: {959 command: { type: "string", description: "The command to run" }960 },961 required: ["command"]962 }963 }964 ]965 user_message = {966 role: "user",967 content: "Summarize https://example.com/article and run uname -a to tell me what system this is on."968 }969970 response = client.messages.create(971 model: "claude-opus-4-8",972 max_tokens: 1024,973 tools: tools,974 messages: [user_message]975 )976977 tool_results = []978 response.content.each do |block|979 next unless block.type == :tool_use980981 tool_results << {982 type: "tool_result",983 tool_use_id: block.id,984 # Run your tool here. This example returns a fixed string.985 content: "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"986 }987 end988989 if response.stop_reason == :tool_use && !tool_results.empty?990 # A server_tool_use block with no result block in this response is not finished; its result arrives in a later response.991 # Send back only the client tool_result blocks, with the same tools.992 continuation = client.messages.create(993 model: "claude-opus-4-8",994 max_tokens: 1024,995 tools: tools,996 messages: [997 user_message,998 { role: "assistant", content: response.content },999 { role: "user", content: tool_results }1000 ]1001 )1002 # If a web_fetch was deferred, it runs on this request and its1003 # web_fetch_tool_result is the first block of continuation.content.1004 puts continuation1005 else1006 puts response1007 end1008 ```1009</CodeGroup>10101011This code is also correct when Claude does not mix the two kinds of call. A turn with only client `tool_use` blocks takes the same continuation path, and a turn with only server tool calls needs no client `tool_result` blocks from you: its result blocks are normally already present, and one that comes back suspended, such as a [`pause_turn` response](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#the-server-side-loop-and-pause-turn), is re-sent as-is instead.10121013## ZDR and allowed\_callers10141015The basic versions of web search (`web_search_20250305`) and web fetch (`web_fetch_20250910`) are eligible for [Zero Data Retention (ZDR)](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention).10161017The `_20260209` and later versions with dynamic filtering are **not** ZDR-eligible by default because dynamic filtering relies on code execution internally.10181019To use a `_20260209` or later server tool with ZDR, disable dynamic filtering by setting `"allowed_callers": ["direct"]` on the tool:10201021```json1022{1023 "type": "web_search_20260209",1024 "name": "web_search",1025 "allowed_callers": ["direct"]1026}1027```10281029This restricts the tool to direct invocation only, bypassing the internal code execution step.10301031`allowed_callers` controls how a tool can be invoked: directly by Claude (`"direct"`), from inside a code execution container (for example, `"code_execution_20260120"`), or both. The `_20260209` versions of the web tools default to the code execution caller only; earlier versions default to `["direct"]`. On models that don't support programmatic tool calling, these versions require `allowed_callers: ["direct"]`; without it the API returns a validation error that says to set it.10321033<Note>1034 Even when web fetch is used in a ZDR-eligible configuration, website publishers might retain any parameters passed to the URL if Claude fetches content from their site.1035</Note>10361037## Domain filtering10381039Server tools that access the web accept `allowed_domains` and `blocked_domains` parameters to control which domains Claude can reach. Both are fields on the tool object:10401041```json1042{1043 "type": "web_search_20250305",1044 "name": "web_search",1045 "allowed_domains": ["example.com", "docs.python.org"]1046}1047```10481049When using domain filters:10501051* Domains should not include the HTTP/HTTPS scheme (use `example.com` instead of `https://example.com`).1052* Subdomains are automatically included (`example.com` covers `docs.example.com`).1053* Specific subdomains restrict results to only that subdomain (`docs.example.com` returns only results from that subdomain, not from `example.com` or `api.example.com`).1054* Subpaths are supported for web search and match anything after the path (`example.com/blog` matches `example.com/blog/post-1`).1055* Web fetch matches on the domain only: an entry that includes a path never matches a web fetch URL.1056* You can use either `allowed_domains` or `blocked_domains`, but not both in the same request.10571058**Wildcard support:**10591060* Wildcards (`*`) are not allowed in the domain itself, only in the path after it.1061* Valid: `example.com/*`, `example.com/*/articles`1062* Invalid: `*.example.com`, `ex*.com`10631064Invalid domain formats are rejected at request time with a 400 `invalid_request_error`.10651066<Note>1067 Request-level domain restrictions work together with any organization-level domain restrictions configured in Claude Console. Request-level `allowed_domains` must be a subset of the organization-level allowed list; entries outside it cause the API to return a validation error. A request-level allowed list that includes a domain your organization blocks is rejected with a `400` error that names the conflicting entries.1068</Note>10691070<Warning>1071 Unicode characters in domain names can bypass domain filters through homograph attacks: `аmazon.com` (with a Cyrillic `а`) looks identical to `amazon.com` but is a different domain. Use ASCII-only domain names in allow and block lists, and audit existing entries for non-ASCII characters.1072</Warning>10731074[Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) uses the same `allowed_domains` and `blocked_domains` fields on the `web_search` and `web_fetch` entries of the agent toolset. On Managed Agents, each list holds at most 64 entries, domains listed for `web_fetch` cannot include a path, and fields specific to the Messages API tools, such as `max_uses`, `citations`, and `cache_control`, are not available. See [Restrict web search and web fetch domains](https://platform.claude.com/docs/en/managed-agents/tools#restrict-web-search-and-web-fetch-domains) for the full rules.10751076Organization-level web search and web fetch settings in the Claude Console apply to Messages API requests only; they do not apply to Managed Agents sessions, which use only the per-tool lists on the agent toolset.10771078## Dynamic filtering with code execution10791080The `_20260209` and later versions of web search and web fetch use code execution internally to apply dynamic filters against search results.10811082<Note>1083 You don't need to add a `code_execution` tool for these versions: when dynamic filtering runs, the API provisions code execution for the request automatically, and both tools share a single execution container. If you do include one, use `code_execution_20260120` or later; the API rejects older code execution versions alongside these web tool versions.1084</Note>10851086## Streaming server-tool events10871088Server-tool events stream as part of the normal server-sent events (SSE) flow. A `server_tool_use` block that Claude calls directly streams like a client `tool_use` block: a `content_block_start` event followed by `input_json_delta` events. The result block arrives complete in a single `content_block_start` event, with no deltas.10891090See [Streaming](https://platform.claude.com/docs/en/build-with-claude/streaming) for the full event reference. Individual tool pages document tool-specific event names where they differ.10911092## Batch requests10931094All server tools support batch processing. In a batch, the agentic loop runs just as it does for synchronous requests, with a higher per-turn iteration limit. If the loop reaches that limit, the response ends with `stop_reason: "pause_turn"`; you can continue it by submitting a follow-up request with the returned content. See [Server tools and the agentic loop](https://platform.claude.com/docs/en/build-with-claude/batch-processing#server-tools-and-the-agentic-loop) for details.10951096Common batch workloads include enriching a dataset with information from the web, checking a large set of documents against current sources, and running analysis code over many files.10971098## Next steps10991100<CardGroup cols={2}>1101 <Card title="Troubleshooting tool use" icon="wrench" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/troubleshooting-tool-use">1102 Fix the most common tool-use errors with symptom-to-fix diagnostic tables.1103 </Card>11041105 <Card title="Web search tool" icon="magnifying-glass" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool">1106 Search the web and cite results.1107 </Card>11081109 <Card title="Web fetch tool" icon="download" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool">1110 Fetch and read content from specific URLs to augment Claude's context with live web content.1111 </Card>11121113 <Card title="Code execution tool" icon="terminal" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/code-execution-tool">1114 Run Python and bash code in a sandboxed container to analyze data, generate files, and iterate on solutions.1115 </Card>11161117 <Card title="Tool search tool" icon="compass" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool">1118 Discover and load tools on demand.1119 </Card>1120</CardGroup>1121