---
title: 伺服器工具
url: https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/server-tools
description: 使用由 Anthropic 執行的工具：server_tool_use 區塊、pause_turn 接續、混合伺服器工具與用戶端工具的回合，以及網域篩選。
---

由伺服器執行的工具共用以下機制：`server_tool_use` 區塊、`pause_turn` 接續、混合伺服器工具與用戶端工具的回合、「Zero Data Retention」（零資料保留），即 ZDR 的適用資格，以及「domain filtering」（網域篩選）。關於個別工具，請參閱[工具參考](https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/tool-reference)。

## server\_tool\_use 區塊

當伺服器執行的工具運行時，`server_tool_use` 區塊會出現在 Claude 的回應中。其 `id` 欄位使用 `srvtoolu_` 前綴，以便與用戶端工具呼叫區分：

```json
{
  "type": "server_tool_use",
  "id": "srvtoolu_01A2B3C4D5E6F7G8H9",
  "name": "web_search",
  "input": { "query": "latest quantum computing breakthroughs" }
}
```

API 會在內部執行該工具。您會在回應中看到呼叫及其結果，但不需要處理執行。與用戶端 `tool_use` 區塊不同，您不需要以 `tool_result` 回應。工具的結果區塊（例如網頁搜尋的 `web_search_tool_result`）會在同一個助理回合中緊接在 `server_tool_use` 區塊之後，並透過 `tool_use_id` 配對。如果 Claude 同時呼叫了您的某個用戶端工具，`server_tool_use` 區塊會在沒有結果的情況下出現，且回應會以 `stop_reason: "tool_use"` 結束。當您在下一個請求中傳回用戶端 `tool_result` 區塊時，API 才會執行該工具。

## 伺服器端迴圈與 pause\_turn

使用網頁搜尋等伺服器工具時，API 會在伺服器端的「agentic loop」（代理迴圈）中執行工具呼叫。在長時間執行的回合中，API 可能會暫停該迴圈並傳回 `pause_turn` 停止原因。

以下說明如何處理 `pause_turn` 停止原因：

<CodeGroup>
  ```bash cURL
  # 初始請求。若回應中的 "stop_reason" 為 "pause_turn"，請繼續
  # 此輪對話：將 assistant 內容附加至 messages 後重新傳送請求。
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [
        {
          "role": "user",
          "content": "Search for comprehensive information about quantum computing breakthroughs in 2025"
        }
      ],
      "tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}]
    }'
  ```

  ```bash CLI
  # 初始請求。若輸出中的 "stop_reason" 為 "pause_turn"，請將
  # assistant 內容附加至 messages 後重新執行（請參閱 SDK 分頁）。
  ant messages create <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  tools:
    - {type: web_search_20250305, name: web_search, max_uses: 10}
  messages:
    - {role: user, content: "Search for comprehensive information about quantum computing breakthroughs in 2025"}
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  # 使用網頁搜尋的初始請求
  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[
          {
              "role": "user",
              "content": "Search for comprehensive information about quantum computing breakthroughs in 2025",
          }
      ],
      tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],
  )

  # 檢查回應的停止原因是否為 pause_turn
  if response.stop_reason == "pause_turn":
      # 以暫停的內容繼續對話
      messages = [
          {
              "role": "user",
              "content": "Search for comprehensive information about quantum computing breakthroughs in 2025",
          },
          {"role": "assistant", "content": response.content},
      ]

      # 傳送接續請求
      continuation = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=1024,
          messages=messages,
          tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],
      )

      print(continuation)
  else:
      print(response)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  // 使用網頁搜尋的初始請求
  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content:
          "Search for comprehensive information about quantum computing breakthroughs in 2025"
      }
    ],
    tools: [
      {
        type: "web_search_20250305",
        name: "web_search",
        max_uses: 10
      }
    ]
  });

  // 檢查回應的 stop reason 是否為 pause_turn
  if (response.stop_reason === "pause_turn") {
    // 以暫停的內容繼續對話
    const messages: Anthropic.MessageParam[] = [
      {
        role: "user",
        content:
          "Search for comprehensive information about quantum computing breakthroughs in 2025"
      },
      { role: "assistant", content: response.content }
    ];

    // 傳送接續請求
    const continuation = await client.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages,
      tools: [
        {
          type: "web_search_20250305",
          name: "web_search",
          max_uses: 10
        }
      ]
    });

    console.log(continuation);
  } else {
    console.log(response);
  }
  ```

  ```csharp C#
  AnthropicClient client = new();

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [
          new() {
              Role = Role.User,
              Content = "Search for comprehensive information about quantum computing breakthroughs in 2025"
          }
      ],
      Tools = [new ToolUnion(new WebSearchTool20250305 { MaxUses = 10 })]
  };

  var response = await client.Messages.Create(parameters);

  if (response.StopReason?.Value() == StopReason.PauseTurn)
  {
      // 以暫停的內容繼續對話
      var continuationParams = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Messages = [
              new() {
                  Role = Role.User,
                  Content = "Search for comprehensive information about quantum computing breakthroughs in 2025"
              },
              new() {
                  Role = Role.Assistant,
                  Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              }
          ],
          Tools = [new ToolUnion(new WebSearchTool20250305 { MaxUses = 10 })]
      };

      var continuation = await client.Messages.Create(continuationParams);
      Console.WriteLine(continuation);
  }
  else
  {
      Console.WriteLine(response);
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  webSearchTool := []anthropic.ToolUnionParam{
  	{OfWebSearchTool20250305: &anthropic.WebSearchTool20250305Param{
  		MaxUses: anthropic.Int(10),
  	}},
  }

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Search for comprehensive information about quantum computing breakthroughs in 2025")),
  	},
  	Tools: webSearchTool,
  })
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == anthropic.StopReasonPauseTurn {
  	// 將暫停的回應原封不動地傳回，讓 Claude 能繼續這一輪對話
  	continuation, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 1024,
  		Messages: []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock("Search for comprehensive information about quantum computing breakthroughs in 2025")),
  			response.ToParam(),
  		},
  		Tools: webSearchTool,
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	fmt.Println(continuation)
  } else {
  	fmt.Println(response)
  }
  ```

  ```java Java
  import com.anthropic.models.messages.StopReason;
  import com.anthropic.models.messages.WebSearchTool20250305;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024L)
          .addUserMessage("Search for comprehensive information about quantum computing breakthroughs in 2025")
          .addTool(WebSearchTool20250305.builder()
              .maxUses(10L)
              .build())
          .build();

      Message response = client.messages().create(params);

      if (response.stopReason().isPresent()
              && response.stopReason().get().equals(StopReason.PAUSE_TURN)) {
          MessageCreateParams continuationParams = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .addUserMessage("Search for comprehensive information about quantum computing breakthroughs in 2025")
              .addMessage(response)
              .addTool(WebSearchTool20250305.builder()
                  .maxUses(10L)
                  .build())
              .build();

          Message continuation = client.messages().create(continuationParams);
          IO.println(continuation);
      } else {
          IO.println(response);
      }
  }
  ```

  ```php PHP
  $client = new Client();

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [
          [
              'role' => 'user',
              'content' => 'Search for comprehensive information about quantum computing breakthroughs in 2025'
          ]
      ],
      model: 'claude-opus-5-5',
      tools: [
          [
              'type' => 'web_search_20250305',
              'name' => 'web_search',
              'max_uses' => 10
          ]
      ],
  );

  if ($response->stopReason === 'pause_turn') {
      $messages = [
          [
              'role' => 'user',
              'content' => 'Search for comprehensive information about quantum computing breakthroughs in 2025'
          ],
          [
              'role' => 'assistant',
              'content' => $response->content
          ]
      ];

      $continuation = $client->messages->create(
          maxTokens: 1024,
          messages: $messages,
          model: 'claude-opus-5-5',
          tools: [
              [
                  'type' => 'web_search_20250305',
                  'name' => 'web_search',
                  'max_uses' => 10
              ]
          ],
      );

      echo $continuation;
  } else {
      echo $response;
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content:
          "Search for comprehensive information about quantum computing breakthroughs in 2025"
      }
    ],
    tools: [
      {
        type: "web_search_20250305",
        name: "web_search",
        max_uses: 10
      }
    ]
  )

  if response.stop_reason == :pause_turn
    messages = [
      {
        role: "user",
        content: "Search for comprehensive information about quantum computing breakthroughs in 2025"
      },
      {
        role: "assistant",
        content: response.content
      }
    ]

    continuation = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: messages,
      tools: [
        {
          type: "web_search_20250305",
          name: "web_search",
          max_uses: 10
        }
      ]
    )

    puts continuation
  else
    puts response
  end
  ```
</CodeGroup>

處理 `pause_turn` 時：

* **繼續對話：** 在後續請求中將暫停的回應原封不動地傳回，讓 Claude 繼續其回合。
* **保留工具狀態：** 在接續請求中包含相同的工具。暫停的回合可能以一個其工具尚未執行的 `server_tool_use` 區塊結束，如果接續請求中缺少該工具，API 會傳回驗證錯誤。
* **視需要重複：** 接續的回合可能會再次暫停。請檢查每個回應的 `stop_reason`，並持續接續直到取得不同的停止原因，同時如同任何重試迴圈一樣，限制接續的次數上限。

關於其他 `stop_reason` 值及一般處理模式，請參閱[停止原因與備援](https://platform.claude.com/docs/zh-TW/build-with-claude/handling-stop-reasons)。

## 在同一回合中混合伺服器工具與用戶端工具

Claude 可以在同一組平行工具呼叫中同時呼叫伺服器工具與用戶端工具，例如將 `web_fetch` 與使用者定義的工具一起呼叫。用戶端工具是指任何由您的程式碼執行並產生 `tool_use` 區塊的工具，無論是使用者定義的工具，還是 Anthropic 定義結構描述的用戶端工具，例如 [Bash 工具](https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/bash-tool)。發生這種情況時，API 不會執行伺服器工具，而是立即傳回，讓您可以先執行用戶端工具：

* `stop_reason` 為 `"tool_use"`，而非 `"pause_turn"`。
* `content` 包含 `server_tool_use` 區塊與用戶端 `tool_use` 區塊，但沒有伺服器工具的結果區塊：該呼叫尚未完成。
* 沒有其他標記。請透過尋找回應中其 `id` 沒有對應結果區塊的 `server_tool_use` 區塊來偵測此狀態。來自 [MCP 連接器](https://platform.claude.com/docs/zh-TW/agents-and-tools/mcp-connector)的 `mcp_tool_use` 區塊行為相同。在同一回應中已有結果區塊的伺服器工具呼叫已經完成，您無需做任何處理。

<Note>
  使用[程式化工具呼叫](https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/programmatic-tool-calling)時，相同的回應形式代表不同的意義。用戶端 `tool_use` 區塊來自在 `code_execution` 工具中執行的程式碼，而非直接來自 Claude，且其 `caller` 欄位會指出呼叫它的 `code_execution` 區塊。該程式碼已經開始執行：它正暫停等待您的 `tool_result` 區塊，傳送這些區塊會恢復執行，而不是啟動延後的工具。`code_execution` 區塊本身的結果區塊會在程式碼執行完畢後送達，這可能需要不只一輪的工具結果。後續的使用者訊息本身在兩種情況下都相同；使用程式化工具呼叫時，還需如該頁面所示，傳回回應中 `container` 欄位的 `id`。
</Note>

```json
{
  "stop_reason": "tool_use",
  "content": [
    {
      "type": "text",
      "text": "I'll fetch the article and check your system at the same time."
    },
    {
      "type": "server_tool_use",
      "id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
      "name": "web_fetch",
      "input": { "url": "https://example.com/article" }
    },
    {
      "type": "tool_use",
      "id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
      "name": "run_command",
      "input": { "command": "uname -a" }
    }
  ]
}
```

若要繼續該回合，請執行用戶端工具，並傳送一則內容僅包含 `tool_result` 區塊的使用者訊息，針對該回應中的每個 `tool_use` 區塊各提供一個。請保持相同的 `tools` 陣列：如果恢復請求不再定義正在等待的伺服器工具，將會失敗並傳回 400，其訊息結尾為 ``but no `web_fetch` tool was provided``。

```json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
      "content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
    }
  ]
}
```

API 會將您的結果附加到仍在進行中的助理回合，執行延後的伺服器工具（若為暫停的程式碼執行，則恢復執行），然後讓 Claude 繼續。對於 Claude 直接呼叫的伺服器工具，下一個回應會以回應前一個回應中 `server_tool_use` `id` 的結果區塊開頭，接著是新產生的內容以及新的 `stop_reason`：

```json
{
  "stop_reason": "end_turn",
  "content": [
    {
      "type": "web_fetch_tool_result",
      "tool_use_id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
      "content": {
        "type": "web_fetch_result",
        "url": "https://example.com/article",
        "content": {
          "type": "document",
          "source": {
            "type": "text",
            "media_type": "text/plain",
            "data": "Full text content of the article..."
          }
        }
      }
    },
    {
      "type": "text",
      "text": "The article argues that... and your machine is running Linux..."
    }
  ]
}
```

`server_tool_use` 區塊與其結果區塊是透過 `tool_use_id` 配對，而非依據位置：在此流程中，它們會出現在兩個不同的回應中，且 `server_tool_use` 區塊不會在第二個回應中重複出現。在後續請求中，請依序將整個交換過程保留在您的 `messages` 陣列中：第一個回應作為 `assistant` 訊息、`tool_result` 使用者訊息，然後下一個回應作為另一則 `assistant` 訊息，就像您累積任何其他工具使用交換一樣。

<Warning>
  後續的使用者訊息除了 `tool_result` 區塊之外不得包含任何內容。在結果之後加入的區塊（例如文字）會告訴 API 助理回合已經結束。對於 Claude 直接呼叫的伺服器工具，這會使該回合留下一個未解決的伺服器工具呼叫，請求將失敗並傳回 400 `invalid_request_error`：

  ```text wrap
  `web_fetch` tool use with id `srvtoolu_01HxbWnMRmbWyMfUtJKC45rA` was found without a corresponding `web_fetch_tool_result` block
  ```

  如果後續訊息將內容放在結果之前、只回應部分用戶端 `tool_use` ID，或完全不包含 `tool_result` 區塊，則會更早失敗，並傳回[處理工具呼叫](https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/handle-tool-calls)中所述的用戶端工具錯誤：

  ```text wrap
  `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.
  ```

  若要提供 Claude 更多輸入，請在回合完成後以另一則使用者訊息傳送。
</Warning>

**這與 `pause_turn` 的差異：** [`pause_turn` 回應](https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/server-tools#the-server-side-loop-and-pause-turn)也可能以尚未執行的 `server_tool_use` 區塊結束，但它絕不會留下等待您處理的用戶端 `tool_use` 區塊，因此您可以透過原封不動地重新傳送助理內容來接續。留下等待您處理的用戶端 `tool_use` 區塊的回應，其 `stop_reason` 絕不會是 `pause_turn`：當 Claude 停下來呼叫您的工具時，`stop_reason` 為 `tool_use`，您需要透過傳送用戶端 `tool_result` 區塊來接續，而不是重新傳送回應。在這兩種情況下，API 都會在下一個請求開始時執行待處理的伺服器工具。

以下範例同時啟用網頁擷取與使用者定義的 `run_command` 工具，並處理混合的回應：

<CodeGroup>
  ```bash cURL
  # 若 "stop_reason" 為 "tool_use"，且某個 server_tool_use 區塊沒有對應的
  # 結果區塊，表示該呼叫尚未完成。請執行用戶端工具，然後再次 POST，
  # 並附上一則僅包含其 tool_result 區塊的 user 訊息
  # 以及相同的 tools 陣列（請參閱 SDK 分頁）。
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [
        {
          "role": "user",
          "content": "Summarize https://example.com/article and run uname -a to tell me what system this is on."
        }
      ],
      "tools": [
        {"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5},
        {
          "name": "run_command",
          "description": "Run a shell command on this computer and return its output.",
          "input_schema": {
            "type": "object",
            "properties": {"command": {"type": "string", "description": "The command to run"}},
            "required": ["command"]
          }
        }
      ]
    }'
  ```

  ```bash CLI
  # 若 "stop_reason" 為 "tool_use"，且某個 server_tool_use 區塊沒有對應的
  # 結果區塊，請執行用戶端工具，並附加一則僅含
  # 其 tool_result 區塊的使用者訊息後重新執行（請參閱 SDK 分頁）。
  ant messages create <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  messages:
    - role: user
      content: "Summarize https://example.com/article and run uname -a to tell me what system this is on."
  tools:
    - {type: web_fetch_20250910, name: web_fetch, max_uses: 5}
    - name: run_command
      description: Run a shell command on this computer and return its output.
      input_schema:
        type: object
        properties:
          command: {type: string, description: The command to run}
        required: [command]
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  tools = [
      {"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5},
      {
          "name": "run_command",
          "description": "Run a shell command on this computer and return its output.",
          "input_schema": {
              "type": "object",
              "properties": {
                  "command": {"type": "string", "description": "The command to run"}
              },
              "required": ["command"],
          },
      },
  ]
  messages = [
      {
          "role": "user",
          "content": "Summarize https://example.com/article and run uname -a to tell me what system this is on.",
      }
  ]

  response = client.messages.create(
      model="claude-opus-5-5", max_tokens=1024, tools=tools, messages=messages
  )

  tool_results = [
      {
          "type": "tool_result",
          "tool_use_id": block.id,
          # 在此執行您的工具。此範例會傳回固定字串。
          "content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux",
      }
      for block in response.content
      if block.type == "tool_use"
  ]

  if response.stop_reason == "tool_use" and tool_results:
      # 若此回應中的 server_tool_use 區塊沒有對應的結果區塊，表示尚未完成；其結果會在後續回應中傳回。
      # 僅傳回用戶端的 tool_result 區塊，並使用相同的工具。
      continuation = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=1024,
          tools=tools,
          messages=[
              *messages,
              {"role": "assistant", "content": response.content},
              {"role": "user", "content": tool_results},
          ],
      )
      # 若 web_fetch 被延後，它會在此請求中執行，且其
      # web_fetch_tool_result 會是 continuation.content 的第一個區塊。
      print(continuation)
  else:
      print(response)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const webFetchTool = {
    type: "web_fetch_20250910",
    name: "web_fetch",
    max_uses: 5
  } as const;
  const runCommandTool: Anthropic.Tool = {
    name: "run_command",
    description: "Run a shell command on this computer and return its output.",
    input_schema: {
      type: "object" as const,
      properties: {
        command: { type: "string", description: "The command to run" }
      },
      required: ["command"]
    }
  };
  const messages: Anthropic.MessageParam[] = [
    {
      role: "user",
      content:
        "Summarize https://example.com/article and run uname -a to tell me what system this is on."
    }
  ];

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    tools: [webFetchTool, runCommandTool],
    messages
  });

  const toolResults: Anthropic.ToolResultBlockParam[] = [];
  for (const block of response.content) {
    if (block.type === "tool_use") {
      toolResults.push({
        type: "tool_result",
        tool_use_id: block.id,
        // 在此執行您的工具。此範例會回傳固定字串。
        content: "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
      });
    }
  }

  if (response.stop_reason === "tool_use" && toolResults.length > 0) {
    // 若此回應中的 server_tool_use 區塊沒有對應的結果區塊，表示尚未完成；其結果會在後續回應中送達。
    // 僅送回用戶端的 tool_result 區塊，並使用相同的工具。
    const continuation = await client.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 1024,
      tools: [webFetchTool, runCommandTool],
      messages: [
        ...messages,
        { role: "assistant", content: response.content },
        { role: "user", content: toolResults }
      ]
    });
    // 若 web_fetch 被延後，它會在此請求中執行，且其
    // web_fetch_tool_result 會是 continuation.content 的第一個區塊。
    console.log(continuation);
  } else {
    console.log(response);
  }
  ```

  ```csharp C#
  AnthropicClient client = new();

  List<ToolUnion> tools =
  [
      new ToolUnion(new WebFetchTool20250910() { MaxUses = 5 }),
      new ToolUnion(new Tool()
      {
          Name = "run_command",
          Description = "Run a shell command on this computer and return its output.",
          InputSchema = new InputSchema()
          {
              Properties = new Dictionary<string, JsonElement>
              {
                  ["command"] = JsonSerializer.SerializeToElement(
                      new { type = "string", description = "The command to run" }
                  ),
              },
              Required = ["command"],
          },
      }),
  ];
  MessageParam userMessage = new()
  {
      Role = Role.User,
      Content = "Summarize https://example.com/article and run uname -a to tell me what system this is on."
  };

  var response = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Tools = tools,
      Messages = [userMessage]
  });

  var toolResults = new List<ContentBlockParam>();
  foreach (var block in response.Content)
  {
      if (block.TryPickToolUse(out var toolUse))
      {
          toolResults.Add(new ContentBlockParam(new ToolResultBlockParam()
          {
              ToolUseID = toolUse.ID,
              // 在此執行您的工具。此範例會回傳固定字串。
              Content = "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux",
          }));
      }
  }

  if (response.StopReason?.Value() == StopReason.ToolUse && toolResults.Count > 0)
  {
      // 若此回應中的 server_tool_use 區塊沒有對應的結果區塊，表示尚未完成；其結果會在後續回應中送達。
      // 僅回傳用戶端的 tool_result 區塊，並使用相同的工具。
      var continuation = await client.Messages.Create(new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Tools = tools,
          Messages =
          [
              userMessage,
              new()
              {
                  Role = Role.Assistant,
                  Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              },
              new() { Role = Role.User, Content = new MessageParamContent(toolResults) }
          ]
      });
      // 若 web_fetch 被延後，它會在此請求中執行，且其
      // web_fetch_tool_result 會是 continuation.Content 的第一個區塊。
      Console.WriteLine(continuation);
  }
  else
  {
      Console.WriteLine(response);
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  tools := []anthropic.ToolUnionParam{
  	{OfWebFetchTool20250910: &anthropic.WebFetchTool20250910Param{
  		MaxUses: anthropic.Int(5),
  	}},
  	{OfTool: &anthropic.ToolParam{
  		Name:        "run_command",
  		Description: anthropic.String("Run a shell command on this computer and return its output."),
  		InputSchema: anthropic.ToolInputSchemaParam{
  			Properties: map[string]any{
  				"command": map[string]any{
  					"type":        "string",
  					"description": "The command to run",
  				},
  			},
  			Required: []string{"command"},
  		},
  	}},
  }
  userMessage := anthropic.NewUserMessage(anthropic.NewTextBlock("Summarize https://example.com/article and run uname -a to tell me what system this is on."))

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Tools:     tools,
  	Messages:  []anthropic.MessageParam{userMessage},
  })
  if err != nil {
  	log.Fatal(err)
  }

  var toolResults []anthropic.ContentBlockParamUnion
  for _, block := range response.Content {
  	if toolUse, ok := block.AsAny().(anthropic.ToolUseBlock); ok {
  		// 在此執行您的工具。此範例會傳回固定字串。
  		output := "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
  		toolResults = append(toolResults, anthropic.NewToolResultBlock(toolUse.ID, output, false))
  	}
  }

  if response.StopReason == anthropic.StopReasonToolUse && len(toolResults) > 0 {
  	// 若此回應中的 server_tool_use 區塊沒有對應的結果區塊，表示尚未完成；其結果會在後續回應中傳回。
  	// 僅傳回用戶端的 tool_result 區塊，並使用相同的 tools。
  	continuation, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 1024,
  		Tools:     tools,
  		Messages: []anthropic.MessageParam{
  			userMessage,
  			response.ToParam(),
  			anthropic.NewUserMessage(toolResults...),
  		},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	// 若 web_fetch 被延後，它會在此請求中執行，且其
  	// web_fetch_tool_result 會是 continuation.Content 的第一個區塊。
  	fmt.Println(continuation)
  } else {
  	fmt.Println(response)
  }
  ```

  ```java Java
  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      Tool runCommandTool = Tool.builder()
          .name("run_command")
          .description("Run a shell command on this computer and return its output.")
          .inputSchema(Tool.InputSchema.builder()
              .properties(JsonValue.from(Map.of(
                  "command", Map.of("type", "string", "description", "The command to run")
              )))
              .putAdditionalProperty("required", JsonValue.from(List.of("command")))
              .build())
          .build();
      String prompt = "Summarize https://example.com/article and run uname -a to tell me what system this is on.";

      Message response = client.messages().create(MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024L)
          .addTool(WebFetchTool20250910.builder().maxUses(5L).build())
          .addTool(runCommandTool)
          .addUserMessage(prompt)
          .build());

      List<ContentBlockParam> toolResults = new ArrayList<>();
      for (ContentBlock block : response.content()) {
          block.toolUse().ifPresent(toolUse -> toolResults.add(ContentBlockParam.ofToolResult(
              ToolResultBlockParam.builder()
                  .toolUseId(toolUse.id())
                  // 在此執行您的工具。此範例會回傳固定字串。
                  .content("Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux")
                  .build()
          )));
      }

      boolean isToolUse = response.stopReason()
          .map(StopReason.TOOL_USE::equals)
          .orElse(false);
      if (isToolUse && !toolResults.isEmpty()) {
          // 若此回應中的 server_tool_use 區塊沒有對應的結果區塊，表示尚未完成；其結果會在後續回應中送達。
          // 僅回傳用戶端的 tool_result 區塊，並使用相同的工具。
          Message continuation = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .addTool(WebFetchTool20250910.builder().maxUses(5L).build())
              .addTool(runCommandTool)
              .addUserMessage(prompt)
              .addMessage(response)
              .addUserMessageOfBlockParams(toolResults)
              .build());
          // 若 web_fetch 被延後，它會在此請求中執行，且其
          // web_fetch_tool_result 會是 continuation.content() 的第一個區塊。
          IO.println(continuation);
      } else {
          IO.println(response);
      }
  }
  ```

  ```php PHP
  $client = new Client();

  $tools = [
      ['type' => 'web_fetch_20250910', 'name' => 'web_fetch', 'max_uses' => 5],
      [
          'name' => 'run_command',
          'description' => 'Run a shell command on this computer and return its output.',
          'input_schema' => [
              'type' => 'object',
              'properties' => [
                  'command' => ['type' => 'string', 'description' => 'The command to run']
              ],
              'required' => ['command']
          ]
      ]
  ];
  $userMessage = ['role' => 'user', 'content' => 'Summarize https://example.com/article and run uname -a to tell me what system this is on.'];

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [$userMessage],
      model: 'claude-opus-5-5',
      tools: $tools,
  );

  $toolResults = [];
  foreach ($response->content as $block) {
      if ($block->type === 'tool_use') {
          $toolResults[] = [
              'type' => 'tool_result',
              'tool_use_id' => $block->id,
              // 在此執行您的工具。此範例會回傳固定字串。
              'content' => 'Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux'
          ];
      }
  }

  if ($response->stopReason === 'tool_use' && count($toolResults) > 0) {
      // 若此回應中的 server_tool_use 區塊沒有對應的結果區塊，表示尚未完成；其結果會在後續回應中送達。
      // 僅回傳用戶端的 tool_result 區塊，並使用相同的 tools。
      $continuation = $client->messages->create(
          maxTokens: 1024,
          messages: [
              $userMessage,
              ['role' => 'assistant', 'content' => $response->content],
              ['role' => 'user', 'content' => $toolResults],
          ],
          model: 'claude-opus-5-5',
          tools: $tools,
      );
      // 若 web_fetch 被延後，它會在此請求中執行，且其
      // web_fetch_tool_result 會是 $continuation->content 的第一個區塊。
      echo $continuation;
  } else {
      echo $response;
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  tools = [
    { type: "web_fetch_20250910", name: "web_fetch", max_uses: 5 },
    {
      name: "run_command",
      description: "Run a shell command on this computer and return its output.",
      input_schema: {
        type: "object",
        properties: {
          command: { type: "string", description: "The command to run" }
        },
        required: ["command"]
      }
    }
  ]
  user_message = {
    role: "user",
    content: "Summarize https://example.com/article and run uname -a to tell me what system this is on."
  }

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    tools: tools,
    messages: [user_message]
  )

  tool_results = []
  response.content.each do |block|
    next unless block.type == :tool_use

    tool_results << {
      type: "tool_result",
      tool_use_id: block.id,
      # 在此執行您的工具。此範例會回傳固定字串。
      content: "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
    }
  end

  if response.stop_reason == :tool_use && !tool_results.empty?
    # 若此回應中的 server_tool_use 區塊沒有對應的結果區塊，表示尚未完成；其結果會在後續回應中送達。
    # 僅送回用戶端的 tool_result 區塊，並使用相同的工具。
    continuation = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      tools: tools,
      messages: [
        user_message,
        { role: "assistant", content: response.content },
        { role: "user", content: tool_results }
      ]
    )
    # 若 web_fetch 被延後，它會在此請求中執行，且其
    # web_fetch_tool_result 會是 continuation.content 的第一個區塊。
    puts continuation
  else
    puts response
  end
  ```
</CodeGroup>

當 Claude 沒有混合這兩種呼叫時，這段程式碼同樣正確。只有用戶端 `tool_use` 區塊的回合會走相同的接續路徑，而只有伺服器工具呼叫的回合則不需要您提供用戶端 `tool_result` 區塊：其結果區塊通常已經存在，而以暫停狀態傳回的回合（例如 [`pause_turn` 回應](https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/server-tools#the-server-side-loop-and-pause-turn)）則改為原封不動地重新傳送。

## ZDR 與 allowed\_callers

網頁搜尋（`web_search_20250305`）與網頁擷取（`web_fetch_20250910`）的基本版本符合[零資料保留（ZDR）](https://platform.claude.com/docs/zh-TW/manage-claude/api-and-data-retention)的適用資格。

具備「dynamic filtering」（動態篩選）的 `_20260209` 及更新版本預設**不**符合 ZDR 適用資格，因為動態篩選在內部依賴程式碼執行。

若要在 ZDR 下使用 `_20260209` 或更新版本的伺服器工具，請在工具上設定 `"allowed_callers": ["direct"]` 以停用動態篩選：

```json
{
  "type": "web_search_20260209",
  "name": "web_search",
  "allowed_callers": ["direct"]
}
```

這會將工具限制為僅能直接呼叫，略過內部的程式碼執行步驟。

`allowed_callers` 控制工具的呼叫方式：由 Claude 直接呼叫（`"direct"`）、從程式碼執行容器內部呼叫（例如 `"code_execution_20260120"`），或兩者皆可。網頁工具的 `_20260209` 版本預設僅允許程式碼執行呼叫者；較早的版本預設為 `["direct"]`。在不支援程式化工具呼叫的模型上，這些版本需要設定 `allowed_callers: ["direct"]`；若未設定，API 會傳回驗證錯誤，提示您進行設定。

<Note>
  即使網頁擷取是在符合 ZDR 資格的設定下使用，如果 Claude 從網站擷取內容，網站發布者仍可能保留傳遞至 URL 的任何參數。
</Note>

## 網域篩選

存取網路的伺服器工具接受 `allowed_domains` 與 `blocked_domains` 參數，以控制 Claude 可以存取哪些網域。兩者都是工具物件上的欄位：

```json
{
  "type": "web_search_20250305",
  "name": "web_search",
  "allowed_domains": ["example.com", "docs.python.org"]
}
```

使用網域篩選時：

* 網域不應包含 HTTP/HTTPS 協定（請使用 `example.com` 而非 `https://example.com`）。
* 子網域會自動包含在內（`example.com` 涵蓋 `docs.example.com`）。
* 指定特定子網域會將結果限制為僅該子網域（`docs.example.com` 只會傳回該子網域的結果，不包含 `example.com` 或 `api.example.com` 的結果）。
* 網頁搜尋支援子路徑，並會比對路徑之後的任何內容（`example.com/blog` 會比對到 `example.com/blog/post-1`）。
* 網頁擷取僅比對網域：包含路徑的項目永遠不會比對到網頁擷取的 URL。
* 您可以使用 `allowed_domains` 或 `blocked_domains`，但不能在同一個請求中同時使用兩者。

**萬用字元支援：**

* 網域本身不允許使用萬用字元（`*`），只能用於網域之後的路徑中。
* 有效：`example.com/*`、`example.com/*/articles`
* 無效：`*.example.com`、`ex*.com`

無效的網域格式會在請求時被拒絕，並傳回 400 `invalid_request_error`。

<Note>
  請求層級的網域限制會與 Claude Console 中設定的任何組織層級網域限制共同運作。請求層級的 `allowed_domains` 必須是組織層級允許清單的子集；超出該清單的項目會導致 API 傳回驗證錯誤。如果請求層級的允許清單包含您組織所封鎖的網域，將會被拒絕並傳回 `400` 錯誤，錯誤中會列出衝突的項目。
</Note>

<Warning>
  網域名稱中的 Unicode 字元可能透過「homograph attacks」（同形異義字攻擊）繞過網域篩選：`аmazon.com`（含有西里爾字母 `а`）看起來與 `amazon.com` 完全相同，但卻是不同的網域。請在允許清單與封鎖清單中僅使用 ASCII 網域名稱，並稽核現有項目是否含有非 ASCII 字元。
</Warning>

[Claude Managed Agents](https://platform.claude.com/docs/zh-TW/managed-agents/overview) 在代理工具集的 `web_search` 與 `web_fetch` 項目上使用相同的 `allowed_domains` 與 `blocked_domains` 欄位。在 Managed Agents 上，每個清單最多可包含 64 個項目，為 `web_fetch` 列出的網域不能包含路徑，且 Messages API 工具特有的欄位（例如 `max_uses`、`citations` 與 `cache_control`）無法使用。完整規則請參閱[網域清單規則](https://platform.claude.com/docs/zh-TW/managed-agents/tools-web-restrictions#domain-list-rules)。

Claude Console 中組織層級的網頁搜尋與網頁擷取設定僅適用於 Messages API 請求。它們不適用於 Managed Agents 工作階段，後者改為使用代理工具集上的個別工具清單。對於在具有 `limited` 網路設定之雲端環境中的工作階段，環境的 `allowed_hosts` 也適用於 `web_search` 與 `web_fetch`；請參閱[網路](https://platform.claude.com/docs/zh-TW/managed-agents/environments#networking)。個別工具清單會在 `allowed_hosts` 所允許的主機範圍內，進一步限制這些工具。

## 搭配程式碼執行的動態篩選

網頁搜尋與網頁擷取的 `_20260209` 及更新版本會在內部使用程式碼執行，對搜尋結果套用動態篩選。

<Note>
  對於這些版本，您不需要加入 `code_execution` 工具：當動態篩選執行時，API 會自動為該請求佈建程式碼執行環境，且兩個工具共用單一執行容器。如果您確實要加入，請使用 `code_execution_20260120` 或更新版本；API 會拒絕與這些網頁工具版本一起使用的較舊程式碼執行版本。
</Note>

## 串流伺服器工具事件

伺服器工具事件會作為一般「server-sent events」（伺服器傳送事件），即 SSE 流程的一部分進行串流。Claude 直接呼叫的 `server_tool_use` 區塊的串流方式與用戶端 `tool_use` 區塊相同：一個 `content_block_start` 事件，接著是 `input_json_delta` 事件。結果區塊會在單一 `content_block_start` 事件中完整送達，沒有任何增量。

完整的事件參考請參閱[串流](https://platform.claude.com/docs/zh-TW/build-with-claude/streaming)。個別工具頁面會記載與此不同的工具特定事件名稱。

## 批次請求

所有伺服器工具都支援「batch processing」（批次處理）。在批次中，代理迴圈的執行方式與同步請求相同，但每個回合的迭代上限較高。如果迴圈達到該上限，回應會以 `stop_reason: "pause_turn"` 結束；您可以透過提交包含所傳回內容的後續請求來接續。詳情請參閱[伺服器工具與代理迴圈](https://platform.claude.com/docs/zh-TW/build-with-claude/batch-processing#server-tools-and-the-agentic-loop)。

常見的批次工作負載包括以網路資訊擴充資料集、根據最新來源檢查大量文件，以及對許多檔案執行分析程式碼。

## 後續步驟

<CardGroup cols={2}>
  <Card title="工具使用疑難排解" icon="wrench" href="https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/troubleshooting-tool-use">
    透過從症狀到修正的診斷表，修正最常見的工具使用錯誤。
  </Card>

  <Card title="網頁搜尋工具" icon="magnifying-glass" href="https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/web-search-tool">
    搜尋網路並引用結果。
  </Card>

  <Card title="網頁擷取工具" icon="download" href="https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/web-fetch-tool">
    從特定 URL 擷取並讀取內容，以即時網路內容擴充 Claude 的上下文。
  </Card>

  <Card title="程式碼執行工具" icon="terminal" href="https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/code-execution-tool">
    在沙箱容器中執行 Python 與 bash 程式碼，以分析資料、產生檔案並反覆改進解決方案。
  </Card>

  <Card title="工具搜尋工具" icon="compass" href="https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/tool-search-tool">
    依需求探索並載入工具。
  </Card>
</CardGroup>
