SPB Git

Repository Public

server-tools.md 43.4 KB 1,121 lines markdown

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
Files main
Menu

Theme