---
title: 對話中途的系統訊息與工具變更
url: https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages
description: 在對話進行到一半時變更系統指令或工具可用性，而不會使其之前的快取前綴失效。
---

<Note>
  若要了解「zero data retention」（零資料保留），即 ZDR 如何適用於此功能，請參閱 [API 與資料保留](https://platform.claude.com/docs/zh-TW/manage-claude/api-and-data-retention)。
</Note>

系統指示通常位於頂層 `system` 欄位中，排在對話中每則訊息之前。這個位置非常適合[「prompt caching」（提示快取）](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching)：「system prompt」（系統提示）是穩定前綴的一部分，因此後續回合都能命中快取。但如果您在工作階段進行到一半才發現需要某些指示，這個位置就不理想了，因為編輯頂層 `system` 欄位會變更提示的最開頭，並使其後所有內容的快取失效。

對話中途的系統訊息正好能解決這個問題。您不必編輯頂層 `system` 欄位，而是在對話中新指示開始適用的位置附加一則 `{"role": "system"}` 訊息。已快取的前綴保持不變，因此下一個請求仍會從快取讀取它。新指示也仍會作為系統指示套用，而不會被當成一般的使用者文字。

<Note>
  對話中途的系統訊息可在 Claude API、[Claude in Amazon Bedrock](https://platform.claude.com/docs/zh-TW/build-with-claude/claude-in-amazon-bedrock) 和 [Google Cloud](https://platform.claude.com/docs/zh-TW/build-with-claude/claude-on-vertex-ai) 上使用。

  此功能適用於 Claude Fable 5.1、[Claude Mythos 5.1](https://platform.claude.com/docs/zh-TW/models/mythos-5-1/overview)、Claude Fable 5、[Claude Mythos 5](https://platform.claude.com/docs/zh-TW/models/mythos-5/overview)、Claude Opus 5.5、Claude Opus 4.8、Claude Opus 5、Claude Sonnet 5.5 和 Claude Haiku 5.5。對話中系統訊息不需要 beta 標頭。此功能不適用於 Claude Sonnet 5，請在該模型上改用頂層 `system` 欄位。

  [對話中工具變更](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes)在相同模型上處於 beta 階段。在 Claude API 上，請傳送 `inline-tools-2026-09-15` beta 標頭，該標頭也涵蓋[在 `tool_addition` 區塊中定義工具](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta)。[以該方式新增 MCP 伺服器](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#add-an-mcp-server-mid-conversation-beta)需要第二個 beta 標頭 `mcp-client-2026-09-15`，此標頭可在 Claude API 上使用。`mid-conversation-tool-changes-2026-07-01` 標頭適用於以參照方式指名工具的變更，可在 Claude API、Amazon Bedrock 和 Google Cloud 上使用。

  [回合範圍的系統訊息](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages)（`clear_at`）目前為 beta 版，需要 `mid-conversation-system-clear-at-2026-08-21` beta 標頭，適用的模型和平台與對話中途的系統訊息相同。
</Note>

## 對話中途的工具變更

`tools` 陣列在雜湊的請求前綴中位置比頂層 `system` 欄位更早，因此編輯它會使整個對話的[提示快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching)失效。對話中工具變更是對話中系統訊息在工具方面的對應功能。您不必在對話的整個生命週期中固定工具清單，而是可以在輪次之間變更提供給模型的工具：預先在 `tools` 中宣告完整的工具集，然後使用 `tool_addition` 和 `tool_removal` 區塊，從對話中的特定位置起向模型提供某個工具或將其撤回。`tools` 陣列本身永遠不會變更，因此已快取的前綴保持完整。對話中工具變更處於 beta 階段，在 Claude API 上使用 `inline-tools-2026-09-15` beta 標頭。

`tool_addition` 和 `tool_removal` 是 `role: "system"` 訊息之 `content` 陣列中的內容區塊，並且可以與 `text` 區塊混合放在同一則訊息中。該訊息遵循任何對話中系統訊息的放置規則，另外在暫停的輪次之後還有一項額外限制（請參閱[限制](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#limitations)），而變更會從對話中的該位置起生效。每個區塊的 `tool` 欄位是參照工具，而非定義工具：`{"type": "tool_reference", "name": "..."}` 指名在請求的 `tools` 陣列中宣告的工具，而 [MCP connector](https://platform.claude.com/docs/zh-TW/agents-and-tools/mcp-connector) 工具可以使用 `mcp_tool_reference`（`server_name` 和 `name`）個別參照，或使用 `mcp_toolset_reference`（`server_name`）作為整個工具集參照。參照未在 `tools` 中宣告的名稱會傳回 400 錯誤（在 Claude API 上，`error.details.error_code` 會設為 `tool_reference_unresolved`）。`tool_addition` 區塊也可以改為[攜帶工具的完整定義](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta)，但 `mid-conversation-tool-changes-2026-07-01` 標頭不支援此方式。

在 `tools` 中宣告的每個工具，從對話開始時就會提供給模型，除非它以 `defer_loading: true` 宣告，這會使其保持隱藏，直到 `tool_addition` 區塊將其呈現出來。`tool_addition` 也會重新提供先前被 `tool_removal` 撤回的工具。

以下請求在 `tools` 中宣告 `get_weather`，然後在第一個使用者回合之後使用 `tool_removal` 區塊將其撤回。該請求會傳送 `inline-tools-2026-09-15` beta 標頭。

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: inline-tools-2026-09-15" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather for a location.",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "Say OK."
        },
        {
          "role": "system",
          "content": [
            {
              "type": "tool_removal",
              "tool": {"type": "tool_reference", "name": "get_weather"}
            }
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta inline-tools-2026-09-15 \
    --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: Say OK.
    - role: system
      content:
        - type: tool_removal
          tool:
            type: tool_reference
            name: get_weather
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15"],
      # 完整的工具集在一開始就宣告且永不變更，因此
      # 快取的前綴得以保持完整。
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {
              "role": "user",
              "content": "Say OK.",
          },
          # 從此處起撤回 get_weather。此區塊以名稱參照該工具，
          # 而非編輯 `tools`，因此先前的輪次仍保持
          # 位元組完全相同，快取依然能命中。
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_removal",
                      "tool": {"type": "tool_reference", "name": "get_weather"},
                  },
              ],
          },
      ],
  )

  for block in response.content:
      if block.type == "text":
          print(block.text)
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15"],
    // 完整的工具集在一開始就宣告且永不變更，因此
    // 快取的前綴得以保持完整。
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: {
              type: "string",
              description: "City name"
            }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "Say OK." },
      // 從此處起撤回 get_weather。此區塊以名稱參照該
      // 工具，而非修改 `tools`，因此先前的回合保持
      // 逐位元組相同，快取仍可命中。
      {
        role: "system",
        content: [
          {
            type: "tool_removal",
            tool: { type: "tool_reference", name: "get_weather" }
          }
        ]
      }
    ]
  });

  for (const block of response.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15],
      // 完整的工具集在一開始就已宣告且永不變更，因此
      // 快取的前綴得以保持完整。
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "Say OK." },
          // 從此處起撤回 get_weather。此區塊以名稱參照該工具，
          // 而非編輯 `Tools`，因此先前的輪次維持
          // 逐位元組相同，快取仍可命中。
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolRemovalBlock
                  {
                      Tool = new BetaToolChangeToolReference { Name = "get_weather" },
                  },
              ]),
          },
      ],
  });

  foreach (var block in response.Content)
  {
      if (block.TryPickText(out var text))
      {
          Console.WriteLine(text.Text);
      }
  }
  ```

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

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaInlineTools2026_09_15},
  	// 完整的工具集在一開始就宣告且永不變更，因此
  	// 快取的前綴得以保持完整。
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Say OK.")),
  		// 從此處起撤回 get_weather。此區塊以名稱參照
  		// 該工具，而非編輯 Tools，因此先前的輪次保持
  		// 逐位元組相同，快取仍可命中。
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolRemovalBlock(anthropic.BetaToolChangeToolReferenceParam{
  					Name: "get_weather",
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlockParam;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaMessageParam;
  import com.anthropic.models.beta.messages.BetaRequestToolRemovalBlock;
  import com.anthropic.models.beta.messages.BetaTool;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  // ...
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      // 完整的工具集在一開始就已宣告且永不變更，因此
      // 快取的前綴得以保持完整。
      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          .addTool(weatherTool)
          .addUserMessage("Say OK.")
          // 從此處起撤回 get_weather。此區塊以名稱參照
          // 該工具，而非編輯 `tools`，因此先前的輪次維持
          // 逐位元組相同，快取仍可命中。
          .addMessage(BetaMessageParam.builder()
              .role(BetaMessageParam.Role.SYSTEM)
              .contentOfBetaContentBlockParams(List.of(
                  BetaContentBlockParam.ofToolRemoval(BetaRequestToolRemovalBlock.builder()
                      .referenceTool("get_weather")
                      .build())))
              .build())
          .build();

      BetaMessage response = client.beta().messages().create(params);
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  // ...

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [AnthropicBeta::INLINE_TOOLS_2026_09_15],
      // 完整的工具集在一開始就宣告且永不變更，因此
      // 快取的前綴得以保持完整。
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => 'Say OK.'],
          // 從此處起撤回 get_weather。此區塊以名稱參照
          // 該工具，而非編輯 `tools`，因此先前的輪次維持
          // 逐位元組相同，快取仍可命中。
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_removal',
                      'tool' => ['type' => 'tool_reference', 'name' => 'get_weather'],
                  ],
              ],
          ],
      ],
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }
  ```

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

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15],
    # 完整的工具集在一開始就宣告且永不變更，因此
    # 快取的前綴得以保持完整。
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "Say OK." },
      # 從此處起撤回 get_weather。此區塊以名稱參照該工具，
      # 而非編輯 `tools`，因此先前的輪次維持
      # 逐位元組相同，快取仍可命中。
      {
        role: "system",
        content: [
          {
            type: "tool_removal",
            tool: { type: "tool_reference", name: "get_weather" }
          }
        ]
      }
    ]
  )

  response.content.each do |block|
    puts block.text if block.type == :text
  end
  ```
</CodeGroup>

### 在訊息中定義工具（beta）

使用 `inline-tools-2026-09-15` beta 標頭時，`tool_addition` 區塊可以依值定義工具，攜帶其完整定義，而不是依參照指名。這讓您可以透過附加一則 `role: "system"` 訊息，引入在對話開始時未知的工具，或其結構描述稍後會變更的工具。`tools` 陣列和每則較早的訊息都與傳送時完全相同，因此提示快取仍會命中，只有附加的訊息會作為新輸入處理。唯一的例外是沒有任何非延遲工具的 `tools` 陣列，這在下方規則中說明。此標頭也涵蓋依參照新增和移除工具，因此您不需要另外傳送 `mid-conversation-tool-changes-2026-07-01`。

將定義包裝在類型為 `tool_definition` 的 `tool` 物件中。`definition` 是一個 `tools` 項目，例如自訂工具或 Anthropic 定義的用戶端或伺服器工具，並帶有其一般設定，包括 `cache_control` 和 `defer_loading`。在 beta 期間，某些工具類型（包括電腦使用工具）尚無法在訊息中定義，並會傳回說明此情況的 400 錯誤；請在 `tools` 中宣告這些工具，並依參照新增它們。例如，要在對話中途定義自訂工具：

```json
{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": {
          "name": "db_query",
          "description": "Run a read-only SQL query against the analytics database.",
          "input_schema": {
            "type": "object",
            "properties": { "sql": { "type": "string" } },
            "required": ["sql"]
          }
        }
      }
    }
  ]
}
```

從該位置開始，模型可以用呼叫 `tools` 中所宣告工具的相同方式呼叫此工具。再次傳送相同的定義不會造成任何變更，因此用戶端可以安全地重新傳送，例如在重試時。

以下請求將 `get_weather` 保留在 `tools` 中，並在第一個使用者回合之後定義 `db_query`：

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: inline-tools-2026-09-15" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather for a location.",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "How many orders shipped yesterday?"
        },
        {
          "role": "system",
          "content": [
            {
              "type": "tool_addition",
              "tool": {
                "type": "tool_definition",
                "definition": {
                  "name": "db_query",
                  "description": "Run a read-only SQL query against the analytics database.",
                  "input_schema": {
                    "type": "object",
                    "properties": {"sql": {"type": "string"}},
                    "required": ["sql"]
                  }
                }
              }
            }
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta inline-tools-2026-09-15 <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  # 請在 `tools` 中至少保留一個非延遲載入的工具，如此一來，之後才定義的工具
  # 就不會改變轉譯後提示的開頭。
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: How many orders shipped yesterday?
    # 從此處起，以值的方式定義 db_query。`tools` 與
    # 先前的訊息都與送出時完全相同，因此仍會命中快取。
    - role: system
      content:
        - type: tool_addition
          tool:
            type: tool_definition
            definition:
              name: db_query
              description: Run a read-only SQL query against the analytics database.
              input_schema:
                type: object
                properties:
                  sql:
                    type: string
                required:
                  - sql
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15"],
      # 請在 `tools` 中至少保留一個非延遲載入的工具，如此一來，之後才定義的工具
      # 就不會改變轉譯後提示的開頭部分。
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {"role": "user", "content": "How many orders shipped yesterday?"},
          # 從此處開始，直接以值的方式定義 db_query。`tools` 與
          # 先前的訊息都與送出時完全相同，因此仍會命中快取。
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_addition",
                      "tool": {
                          "type": "tool_definition",
                          "definition": {
                              "name": "db_query",
                              "description": "Run a read-only SQL query against the analytics database.",
                              "input_schema": {
                                  "type": "object",
                                  "properties": {"sql": {"type": "string"}},
                                  "required": ["sql"],
                              },
                          },
                      },
                  },
              ],
          },
      ],
  )

  for block in response.content:
      if block.type == "tool_use":
          print(block.name, block.input)
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15"],
    // 請在 `tools` 中保留至少一個非延遲載入的工具，如此一來，之後才定義的工具
    // 就不會改變轉譯後提示的開頭。
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "How many orders shipped yesterday?" },
      // 從此處起，改以值的方式定義 db_query。`tools` 與
      // 先前的訊息皆與送出時完全相同，因此快取仍會命中。
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: {
                name: "db_query",
                description: "Run a read-only SQL query against the analytics database.",
                input_schema: {
                  type: "object",
                  properties: { sql: { type: "string" } },
                  required: ["sql"]
                }
              }
            }
          }
        ]
      }
    ]
  });

  for (const block of response.content) {
    if (block.type === "tool_use") {
      console.log(block.name, JSON.stringify(block.input));
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15],
      // 請在 `Tools` 中至少保留一個非延遲載入的工具，如此一來，之後才定義的工具
      // 就不會改變所渲染提示的開頭部分。
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "How many orders shipped yesterday?" },
          // 從此處起，以值的方式定義 db_query。`Tools` 與
          // 先前的訊息都與送出時完全相同，因此仍可命中快取。
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolAdditionBlock
                  {
                      Tool = new BetaToolChangeToolDefinitionParam
                      {
                          Definition = new BetaTool
                          {
                              Name = "db_query",
                              Description = "Run a read-only SQL query against the analytics database.",
                              InputSchema = new InputSchema
                              {
                                  Properties = new Dictionary<string, JsonElement>
                                  {
                                      ["sql"] = JsonSerializer.SerializeToElement(new { type = "string" }),
                                  },
                                  Required = ["sql"],
                              },
                          },
                      },
                  },
              ]),
          },
      ],
  });

  foreach (var block in response.Content)
  {
      if (block.TryPickToolUse(out var toolUse))
      {
          Console.WriteLine($"{toolUse.Name} {JsonSerializer.Serialize(toolUse.Input)}");
      }
  }
  ```

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

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaInlineTools2026_09_15},
  	// 在 Tools 中至少保留一個非延遲載入的工具，如此一來，之後才定義的工具
  	// 就不會改變轉譯後提示的開頭。
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("How many orders shipped yesterday?")),
  		// 從此處起改以值的方式定義 db_query。Tools 與
  		// 先前的訊息皆與送出時完全相同，因此快取仍會命中。
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolAdditionBlock(anthropic.BetaToolChangeToolDefinitionParam{
  					Definition: anthropic.BetaToolUnionParam{OfTool: &anthropic.BetaToolParam{
  						Name:        "db_query",
  						Description: anthropic.String("Run a read-only SQL query against the analytics database."),
  						InputSchema: anthropic.BetaToolInputSchemaParam{
  							Properties: map[string]any{
  								"sql": map[string]any{"type": "string"},
  							},
  							Required: []string{"sql"},
  						},
  					}},
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  for _, block := range response.Content {
  	if toolUse, ok := block.AsAny().(anthropic.BetaToolUseBlock); ok {
  		fmt.Println(toolUse.Name, toolUse.Input)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlockParam;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaRequestToolAdditionBlock;
  import com.anthropic.models.beta.messages.BetaTool;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  // ...

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

      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      BetaTool dbQueryTool = BetaTool.builder()
          .name("db_query")
          .description("Run a read-only SQL query against the analytics database.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("sql", JsonValue.from(Map.of("type", "string")))
                  .build())
              .addRequired("sql")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          // 請在 `tools` 中至少保留一個非延遲載入的工具，如此一來，之後才定義的工具
          // 就不會改變轉譯後提示的開頭。
          .addTool(weatherTool)
          .addUserMessage("How many orders shipped yesterday?")
          // 從此處開始，以值的方式定義 db_query。`tools` 與
          // 先前的訊息皆與送出時完全相同，因此仍會命中快取。
          .addSystemMessageOfBetaContentBlockParams(List.of(
              BetaContentBlockParam.ofToolAddition(BetaRequestToolAdditionBlock.builder()
                  .definitionTool(dbQueryTool)
                  .build())))
          .build();

      BetaMessage response = client.beta().messages().create(params);
      response.content().stream()
          .flatMap(block -> block.toolUse().stream())
          .forEach(toolUse -> IO.println(toolUse.name() + " " + toolUse._input()));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaToolUseBlock;
  // ...

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [AnthropicBeta::INLINE_TOOLS_2026_09_15],
      // 請在 `tools` 中至少保留一個非延遲載入的工具，如此一來，之後才定義的工具
      // 就不會改變所渲染提示的開頭部分。
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => 'How many orders shipped yesterday?'],
          // 從此處起改以值的方式定義 db_query。`tools` 與
          // 先前的訊息皆與送出時完全相同，因此快取仍會命中。
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_addition',
                      'tool' => [
                          'type' => 'tool_definition',
                          'definition' => [
                              'name' => 'db_query',
                              'description' => 'Run a read-only SQL query against the analytics database.',
                              'input_schema' => [
                                  'type' => 'object',
                                  'properties' => ['sql' => ['type' => 'string']],
                                  'required' => ['sql'],
                              ],
                          ],
                      ],
                  ],
              ],
          ],
      ],
  );

  foreach ($response->content as $block) {
      if ($block instanceof BetaToolUseBlock) {
          echo $block->name, ' ', json_encode($block->input), PHP_EOL;
      }
  }
  ```

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

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15],
    # 請在 `tools` 中至少保留一個非延遲載入的工具，如此一來，之後才定義的工具
    # 就不會改變轉譯後提示的開頭。
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "How many orders shipped yesterday?" },
      # 從此處開始，以值的方式定義 db_query。`tools` 與
      # 先前的訊息皆與送出時完全相同，因此仍會命中快取。
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: {
                name: "db_query",
                description: "Run a read-only SQL query against the analytics database.",
                input_schema: {
                  type: "object",
                  properties: { sql: { type: "string" } },
                  required: ["sql"]
                }
              }
            }
          }
        ]
      }
    ]
  )

  response.content.each do |block|
    puts "#{block.name} #{block.input}" if block.is_a?(Anthropic::Beta::BetaToolUseBlock)
  end
  ```
</CodeGroup>

回應的 `content` 包含新工具的 `tool_use` 區塊，例如：

```json
{
  "type": "tool_use",
  "id": "toolu_01A09q90qw90lq917835lq9",
  "name": "db_query",
  "input": {
    "sql": "SELECT COUNT(*) FROM orders WHERE shipped_at::date = CURRENT_DATE - 1"
  }
}
```

要變更工具的結構描述，或將伺服器工具移至較新版本，請以相同名稱傳送不同的定義。新定義會從該位置開始取代先前的定義。重複使用不同類型工具名稱的定義會傳回 400 錯誤，且 `error.details.error_code` 設為 `tool_name_conflict`。同一工具的較新版本不算是不同類型。`tool_removal` 仍然接受參照，且已移除的工具之後可以再次定義或重新提供。

根據定義的呈現位置，衍生出以下幾項規則：

* **預先宣告您已知的內容。** 您在第一個請求時就已知的工具應放在 `tools` 中；如果模型還不應看到它，請搭配 `defer_loading: true` 和稍後的 `tool_addition` 參照。只有在第一個請求時未知或稍後會變更的工具，才依值定義。
* **在 `tools` 中至少保留一個非延遲工具。** `tools` 陣列中沒有非延遲工具的對話仍會被接受，但它依值定義的第一個工具會變更所呈現提示的開頭，這會在該請求上造成一次完整的快取未命中。[工具搜尋工具](https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/tool-search-tool)算作非延遲工具。
* **帶日期的工具類型保留各自的 beta 標頭。** 如果您依值定義的伺服器工具需要自己的 beta 標頭，請在對話中之後的每個請求上傳送該標頭。
* **`cache_control` 放在區塊上或定義中，不可兩者皆放，** 並計入請求的斷點上限。延遲的定義不能攜帶 `cache_control`。

當超過以下任一限制時，請求會傳回 400 錯誤，且 `error.details.error_code` 設為 `available_tools_limit_exceeded`：

* 在任何訊息之後可用的延遲工具超過 10,000 個。
* 在第一則使用者訊息之後定義、且在任何訊息之後可用的工具超過 10,000 個。
* 在第一則使用者訊息之後傳送、且在任何訊息之後仍可用的工具定義總計超過 4 MB（4,194,304 位元組）。
* 呈現的工具文字大於 4 MB（4,194,304 位元組）。

### 在對話中途新增 MCP 伺服器（beta）

若要在對話進行到一半時新增 [MCP 連接器](https://platform.claude.com/docs/zh-TW/agents-and-tools/mcp-connector)伺服器，請將 `mcp-client-2026-09-15` beta 標頭與 `inline-tools-2026-09-15` 一起傳送。這樣 `tool_addition` 區塊中的 `definition` 就可以是 `mcp_toolset`，讓伺服器的工具無需編輯 `tools` 即可使用。照常在 `mcp_servers` 中列出伺服器的連線詳細資訊，然後在伺服器變為可用的位置附加工具集：

```json
{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": { "type": "mcp_toolset", "mcp_server_name": "calendar" }
      }
    }
  ]
}
```

`mcp_toolset` 物件與您會放在 `tools` 中的物件相同，包括 `default_config` 和 `configs`。`tool_addition` 區塊永遠不會包含伺服器 URL 或權杖。這些資訊保留在 `mcp_servers` 中。

以下請求將 `get_weather` 保留在 `tools` 中，在 `mcp_servers` 中列出行事曆伺服器，並在第一個使用者回合之後新增該伺服器的工具集：

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: inline-tools-2026-09-15,mcp-client-2026-09-15" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "mcp_servers": [
        {
          "type": "url",
          "url": "https://mcp.example.com/calendar",
          "name": "calendar",
          "authorization_token": "YOUR_TOKEN"
        }
      ],
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather for a location.",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "What'\''s on my calendar tomorrow?"
        },
        {
          "role": "system",
          "content": [
            {
              "type": "tool_addition",
              "tool": {
                "type": "tool_definition",
                "definition": {
                  "type": "mcp_toolset",
                  "mcp_server_name": "calendar"
                }
              }
            }
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create \
    --beta inline-tools-2026-09-15,mcp-client-2026-09-15 <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  mcp_servers:
    - type: url
      url: https://mcp.example.com/calendar
      name: calendar
      authorization_token: YOUR_TOKEN
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: What's on my calendar tomorrow?
    # 從此處開始，讓行事曆伺服器的工具可供使用。
    # 此區塊僅指定伺服器名稱，絕不包含 URL 或權杖。
    - role: system
      content:
        - type: tool_addition
          tool:
            type: tool_definition
            definition:
              type: mcp_toolset
              mcp_server_name: calendar
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
      mcp_servers=[
          {
              "type": "url",
              "url": "https://mcp.example.com/calendar",
              "name": "calendar",
              "authorization_token": "YOUR_TOKEN",
          },
      ],
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {"role": "user", "content": "What's on my calendar tomorrow?"},
          # 從此處開始，讓 calendar 伺服器的工具可供使用。
          # 此區塊僅指明伺服器名稱，絕不包含 URL 或權杖。
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_addition",
                      "tool": {
                          "type": "tool_definition",
                          "definition": {
                              "type": "mcp_toolset",
                              "mcp_server_name": "calendar",
                          },
                      },
                  },
              ],
          },
      ],
  )

  # 回應會以 calendar 伺服器的 mcp_tool_listing 區塊開頭，
  # 因此請檢查每個區塊的類型，而非直接讀取 content[0]。
  for block in response.content:
      match block.type:
          case "mcp_tool_listing":
              print(block.mcp_server_name, [tool.name for tool in block.tools])
          case "text":
              print(block.text)
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
    mcp_servers: [
      {
        type: "url",
        url: "https://mcp.example.com/calendar",
        name: "calendar",
        authorization_token: "YOUR_TOKEN"
      }
    ],
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "What's on my calendar tomorrow?" },
      // 從此處開始，讓 calendar 伺服器的工具可供使用。
      // 此區塊僅指明伺服器名稱，絕不包含 URL 或權杖。
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  });

  // 回應會以 calendar 伺服器的 mcp_tool_listing 區塊開頭，
  // 因此請檢查每個區塊的類型，而非直接讀取 content[0]。
  for (const block of response.content) {
    switch (block.type) {
      case "mcp_tool_listing":
        console.log(
          block.mcp_server_name,
          block.tools.map((tool) => tool.name)
        );
        break;
      case "text":
        console.log(block.text);
        break;
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15, AnthropicBeta.McpClient2026_09_15],
      McpServers =
      [
          new BetaRequestMcpServerUrlDefinition
          {
              Url = "https://mcp.example.com/calendar",
              Name = "calendar",
              AuthorizationToken = "YOUR_TOKEN",
          },
      ],
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "What's on my calendar tomorrow?" },
          // 從此處開始，讓 calendar 伺服器的工具可供使用。
          // 此區塊僅指明伺服器名稱，絕不包含 URL 或權杖。
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolAdditionBlock
                  {
                      Tool = new BetaToolChangeToolDefinitionParam
                      {
                          Definition = new BetaMcpToolset("calendar"),
                      },
                  },
              ]),
          },
      ],
  });

  // 回應會以 calendar 伺服器的 mcp_tool_listing 區塊開頭，
  // 因此請檢查每個區塊的類型，而非直接讀取 Content[0]。
  foreach (var block in response.Content)
  {
      if (block.TryPickMcpToolListing(out var listing))
      {
          Console.WriteLine($"{listing.McpServerName} {JsonSerializer.Serialize(listing.Tools.Select(tool => tool.Name))}");
      }
      else if (block.TryPickText(out var text))
      {
          Console.WriteLine(text.Text);
      }
  }
  ```

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

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas: []anthropic.AnthropicBeta{
  		anthropic.AnthropicBetaInlineTools2026_09_15,
  		anthropic.AnthropicBetaMCPClient2026_09_15,
  	},
  	MCPServers: []anthropic.BetaRequestMCPServerURLDefinitionParam{
  		{
  			URL:                "https://mcp.example.com/calendar",
  			Name:               "calendar",
  			AuthorizationToken: anthropic.String("YOUR_TOKEN"),
  		},
  	},
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What's on my calendar tomorrow?")),
  		// 從此處開始，讓 calendar 伺服器的工具可供使用。
  		// 此區塊僅指明伺服器名稱，絕不包含 URL 或權杖。
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolAdditionBlock(anthropic.BetaToolChangeToolDefinitionParam{
  					Definition: anthropic.BetaToolUnionParam{OfMCPToolset: &anthropic.BetaMCPToolsetParam{
  						MCPServerName: "calendar",
  					}},
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  // 回應會以 calendar 伺服器的 mcp_tool_listing 區塊開頭，
  // 因此請檢查每個區塊的類型，而非直接讀取 Content[0]。
  for _, block := range response.Content {
  	switch variant := block.AsAny().(type) {
  	case anthropic.BetaMCPToolListingBlock:
  		var toolNames []string
  		for _, tool := range variant.Tools {
  			toolNames = append(toolNames, tool.Name)
  		}
  		fmt.Println(variant.MCPServerName, toolNames)
  	case anthropic.BetaTextBlock:
  		fmt.Println(variant.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlockParam;
  import com.anthropic.models.beta.messages.BetaMcpTool;
  import com.anthropic.models.beta.messages.BetaMcpToolset;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaRequestMcpServerUrlDefinition;
  import com.anthropic.models.beta.messages.BetaRequestToolAdditionBlock;
  import com.anthropic.models.beta.messages.BetaTool;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  // ...

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

      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          .addBeta(AnthropicBeta.MCP_CLIENT_2026_09_15)
          .addMcpServer(BetaRequestMcpServerUrlDefinition.builder()
              .url("https://mcp.example.com/calendar")
              .name("calendar")
              .authorizationToken("YOUR_TOKEN")
              .build())
          .addTool(weatherTool)
          .addUserMessage("What's on my calendar tomorrow?")
          // 從此處開始，讓 calendar 伺服器的工具可供使用。
          // 此區塊僅指名伺服器，絕不包含 URL 或權杖。
          .addSystemMessageOfBetaContentBlockParams(List.of(
              BetaContentBlockParam.ofToolAddition(BetaRequestToolAdditionBlock.builder()
                  .definitionTool(BetaMcpToolset.builder()
                      .mcpServerName("calendar")
                      .build())
                  .build())))
          .build();

      BetaMessage response = client.beta().messages().create(params);

      // 回應會以 calendar 伺服器的 mcp_tool_listing 區塊開頭，
      // 因此請檢查每個區塊的類型，而非直接讀取第一個區塊。
      for (var block : response.content()) {
          switch (block.type().value()) {
              case MCP_TOOL_LISTING -> {
                  var listing = block.asMcpToolListing();
                  var toolNames = listing.tools().stream().map(BetaMcpTool::name).toList();
                  IO.println(listing.mcpServerName() + " " + toolNames);
              }
              case TEXT -> IO.println(block.asText().text());
          }
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaMCPTool;
  use Anthropic\Beta\Messages\BetaMCPToolListingBlock;
  use Anthropic\Beta\Messages\BetaTextBlock;
  // ...

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [
          AnthropicBeta::INLINE_TOOLS_2026_09_15,
          AnthropicBeta::MCP_CLIENT_2026_09_15,
      ],
      mcpServers: [
          [
              'type' => 'url',
              'url' => 'https://mcp.example.com/calendar',
              'name' => 'calendar',
              'authorization_token' => 'YOUR_TOKEN',
          ],
      ],
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => "What's on my calendar tomorrow?"],
          // 從此處開始，讓 calendar 伺服器的工具可供使用。
          // 此區塊僅指名伺服器，絕不包含 URL 或權杖。
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_addition',
                      'tool' => [
                          'type' => 'tool_definition',
                          'definition' => [
                              'type' => 'mcp_toolset',
                              'mcp_server_name' => 'calendar',
                          ],
                      ],
                  ],
              ],
          ],
      ],
  );

  // 回應會以 calendar 伺服器的 mcp_tool_listing 區塊開頭，
  // 因此請檢查每個區塊的 type，而非直接讀取 content[0]。
  foreach ($response->content as $block) {
      switch (true) {
          case $block instanceof BetaMCPToolListingBlock:
              $toolNames = array_map(fn (BetaMCPTool $tool) => $tool->name, $block->tools);
              echo $block->mcpServerName, ' ', json_encode($toolNames), PHP_EOL;
              break;
          case $block instanceof BetaTextBlock:
              echo $block->text, PHP_EOL;
              break;
      }
  }
  ```

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

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [
      Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15,
      Anthropic::AnthropicBeta::MCP_CLIENT_2026_09_15
    ],
    mcp_servers: [
      {
        type: "url",
        url: "https://mcp.example.com/calendar",
        name: "calendar",
        authorization_token: "YOUR_TOKEN"
      }
    ],
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "What's on my calendar tomorrow?" },
      # 從此處開始，讓 calendar 伺服器的工具可供使用。
      # 此區塊僅指明伺服器名稱，絕不包含 URL 或權杖。
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  )

  # 回應會以 calendar 伺服器的 mcp_tool_listing 區塊開頭，
  # 因此請檢查每個區塊的類型，而非直接讀取 content[0]。
  response.content.each do |block|
    case block
    when Anthropic::Beta::BetaMCPToolListingBlock
      puts "#{block.mcp_server_name} #{block.tools.map(&:name)}"
    when Anthropic::Beta::BetaTextBlock
      puts block.text
    end
  end
  ```
</CodeGroup>

使用 `mcp-client-2026-09-15` 時，若 API 在產生回應時擷取了伺服器的工具清單，該回應會以 `mcp_tool_listing` 區塊開頭，每個被擷取的伺服器各一個。如果您的程式碼讀取 `content[0]`，請略過這些區塊。請原封不動地傳回助理訊息（包括此區塊），並在每個攜帶它的請求上持續傳送 `mcp-client-2026-09-15`。之後的請求便會使用記錄下來的清單，而不會再次詢問伺服器。若要自行固定工具集，請將該清單複製到 `mcp_toolset` 的 `tools` 欄位中，如[固定 MCP 伺服器的工具清單](https://platform.claude.com/docs/zh-TW/agents-and-tools/mcp-connector#pin-mcp-tool-list)所述。

`mcp-client-2026-09-15` 包含 `mcp-client-2025-11-20` 的所有功能，因此您不需要同時傳送兩者。這些功能可在 Claude API 上使用。使用 MCP 連接器的請求仍適用其[資料保留](https://platform.claude.com/docs/zh-TW/agents-and-tools/mcp-connector#data-retention)條款。

## 何時使用對話中途的系統訊息

[提示快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching)會依序對請求前綴進行雜湊：先是 `tools`，接著是 `system`，然後是 `messages`。快取命中要求前綴在快取斷點之前與最近的某個請求逐位元組完全相符。

這個順序意味著頂層 `system` 欄位位於雜湊前綴的最開頭附近。對它的任何變更，即使只是附加一個句子，都會產生不同的雜湊值，而該請求對於系統提示以及其後每一則已快取的訊息都會錯失快取。

對話中途的系統訊息讓您可以改為在訊息歷史的**末端**加入指令。新指令之前的所有內容都保持不變，因此現有的快取項目仍然相符，只有新訊息會被當作新的輸入處理。

以下是幾個這一點很重要的情境：

* **工作階段中途的政策或角色變更。** 一個長時間的代理工作階段在數十個已快取的輪次之後需要一項新的限制（「從現在起，所有 SQL 都寫成參數化查詢」）。將它加入頂層 `system` 欄位會重新處理整個歷史。
* **必須具有權威性的逐輪次上下文。** 您想要以系統層級的權重注入一則時效性備註、工作階段截止時間或工具可用性變更，而它變動得太頻繁，不適合放在快取前綴中。
* **不應堆積的逐輪次提醒。** 某個執行框架（harness）在每批工具結果之後提醒模型（「將獨立的讀取請求一起發出」、「使用者已經有一段時間沒有收到您的回覆了」），並希望模型只看到最新的那一份。[輪次範圍的系統訊息](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages)只會在一個輪次中呈現，之後不耗費任何成本，且不需要從歷史中刪除任何內容。
* **您的應用程式觀察到的狀態變更。** 您的應用程式注意到某件 Claude 應視為操作者層級事實的事情：磁碟上的檔案已變更、使用者切換了自動核准設定、可用工具已變更，或剩餘的 token 預算降到某個門檻以下。
* **不應中斷代理迴圈的使用者輸入。** 使用者在 Claude 仍在為先前的請求執行工具時輸入了後續內容。在下一個工具結果之後將其作為系統訊息轉達，可讓 Claude 將新輸入融入它已在進行的工作中，而不是將其視為需要切換過去的新請求。在 Claude Sonnet 5.5 和 Claude Haiku 5.5 上，請改為將使用者的話語作為 `text` 區塊附加在同一則 `user` 訊息中最後一個 `tool_result` 之後。請參閱[放置於工具結果之後](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#placement-after-tool-results)。
* **授予常設權限的模式切換。** 工作階段層級的模式可以使用對話中途的系統訊息，對某項昂貴的能力（例如自動啟動多代理工作流程）授予常設同意，每隔數個輪次附上簡短的提醒，並在模式關閉時發出退出通知。如需完整範例，請參閱[建構編排模式](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-effort-example)。

在上述所有情況中，您都可以將指令放在一般的 `user` 訊息中，而 Claude 確實會遵循在使用者輪次中送達的指令。差別在於優先順序：`user` 訊息被視為來自終端使用者，而 `system` 訊息被視為來自您，也就是應用程式操作者。當兩者衝突時，系統指令優先，因此對於即使終端使用者要求不同內容也應成立的操作者層級事實與限制，請使用 `system` 角色。對話中途的系統訊息保有這種操作者層級的優先順序，而不必付出編輯頂層 `system` 欄位所造成的快取錯失成本。

## 運作方式

在 `messages` 陣列中新增一則 `"role": "system"` 的訊息。`content` 可使用純字串或內容區塊，與 `user` 或 `assistant` 回合相同。該指示從對話中的該位置開始生效。當指示衝突時，較晚的系統訊息優先於較早的系統訊息，而對話中途系統訊息在其後的回合中優先於頂層 `system` 欄位。

您仍然可以為應套用於整個對話的指示設定頂層 `system` 欄位。請將對話中途系統訊息保留給只在稍後才變得相關的指示，或您想在不使已快取前綴失效的情況下新增的指示。

`role: "system"` 訊息也可以攜帶 `output_config.effort`，以在對話進行途中變更 [effort](https://platform.claude.com/docs/zh-TW/build-with-claude/effort) 等級。此功能在 Claude API 和 Google Cloud 上的 Claude Fable 5.1、Claude Mythos 5.1、Claude Opus 5.5、Claude Opus 5、Claude Sonnet 5.5 和 Claude Haiku 5.5 上處於 beta 階段，並需要 `mid-conversation-output-config-2026-07-01` beta 標頭。在 Amazon Bedrock 上，此功能在 Claude Fable 5.1、Claude Mythos 5.1 和 Claude Opus 5.5 上處於 beta 階段，使用相同的 beta 值。Claude Opus 5 在 Amazon Bedrock 上不支援此功能。請參閱[每則訊息的 effort](https://platform.claude.com/docs/zh-TW/build-with-claude/effort#change-effort-mid-conversation-beta)。

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "cache_control": {"type": "ephemeral"},
      "system": "You are a code review assistant. Be concise.",
      "messages": [
        {
          "role": "user",
          "content": "Review process() in utils.py for performance issues."
        },
        {
          "role": "assistant",
          "content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
        },
        {
          "role": "user",
          "content": "Now review the calling code that invokes process()."
        },
        {
          "role": "system",
          "content": "From now on, every suggestion must include explicit type annotations."
        }
      ]
    }'
  ```

  ```bash CLI
  ant messages create --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  cache_control:
    type: ephemeral
  system: You are a code review assistant. Be concise.
  messages:
    - role: user
      content: Review process() in utils.py for performance issues.
    - role: assistant
      content: >-
        The list comprehension is fine for small inputs. For large inputs,
        consider a generator to avoid materializing the full list.
    - role: user
      content: Now review the calling code that invokes process().
    - role: system
      content: From now on, every suggestion must include explicit type annotations.
  YAML
  ```

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

  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      # 自動 prompt caching（提示快取）：每個請求都會快取目前為止的對話，
      # 下一個請求則會從快取讀取未變更的前綴。
      cache_control={"type": "ephemeral"},
      system="You are a code review assistant. Be concise.",
      messages=[
          {
              "role": "user",
              "content": "Review process() in utils.py for performance issues.",
          },
          {
              "role": "assistant",
              "content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.",
          },
          {
              "role": "user",
              "content": "Now review the calling code that invokes process().",
          },
          # 審查者在工作階段中途發現，所有建議都必須
          # 同時符合團隊嚴格的型別政策。將此
          # 指示附加在這裡，可讓先前的輪次保持逐位元組相同，因此
          # 前一個請求所快取的前綴仍會從快取讀取。
          {
              "role": "system",
              "content": "From now on, every suggestion must include explicit type annotations.",
          },
      ],
  )

  for block in response.content:
      if block.type == "text":
          print(block.text)
  ```

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

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    // 自動 prompt caching（提示快取）：每個請求都會快取目前為止的對話，
    // 下一個請求則從快取讀取未變更的前綴。
    cache_control: { type: "ephemeral" },
    system: "You are a code review assistant. Be concise.",
    messages: [
      {
        role: "user",
        content: "Review process() in utils.py for performance issues."
      },
      {
        role: "assistant",
        content:
          "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
      },
      {
        role: "user",
        content: "Now review the calling code that invokes process()."
      },
      // 審查者在工作階段中途發現，所有建議還必須通過
      // 團隊嚴格的型別檢查政策。將此指示附加在這裡，可讓
      // 先前的輪次保持逐位元組相同，因此前一個請求所快取的前綴
      // 仍可從快取讀取。
      {
        role: "system",
        content: "From now on, every suggestion must include explicit type annotations."
      }
    ]
  });

  const textBlock = response.content.find(
    (block): block is Anthropic.TextBlock => block.type === "text"
  );
  console.log(textBlock?.text);
  ```

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

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      // 自動 prompt caching（提示快取）：每個請求都會快取目前為止的對話，
      // 而下一個請求會從快取讀取未變更的前綴。
      CacheControl = new CacheControlEphemeral(),
      System = "You are a code review assistant. Be concise.",
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = "Review process() in utils.py for performance issues."
          },
          new()
          {
              Role = Role.Assistant,
              Content = "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
          },
          new()
          {
              Role = Role.User,
              Content = "Now review the calling code that invokes process()."
          },
          // 審查者在工作階段中途發現，所有建議也必須通過
          // 團隊嚴格的型別政策。將此指示附加在這裡，可讓
          // 先前的回合保持位元組完全相同，因此前一個請求所快取的前綴
          // 仍會從快取中讀取。
          new()
          {
              Role = Role.System,
              Content = "From now on, every suggestion must include explicit type annotations."
          }
      ]
  };

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

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

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	// 自動 prompt caching（提示快取）：每個請求都會快取目前為止的對話，
  	// 下一個請求則從快取讀取未變更的前綴。
  	CacheControl: anthropic.NewCacheControlEphemeralParam(),
  	System: []anthropic.TextBlockParam{
  		{Text: "You are a code review assistant. Be concise."},
  	},
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Review process() in utils.py for performance issues.")),
  		anthropic.NewAssistantMessage(anthropic.NewTextBlock("The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.")),
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Now review the calling code that invokes process().")),
  		// 審查者在工作階段中途發現，所有建議也必須
  		// 通過團隊嚴格的型別規範。將此指示附加在
  		// 這裡可讓先前的輪次保持逐位元組相同，因此前一個請求
  		// 所快取的前綴仍會從快取讀取。
  		{
  			Role: anthropic.MessageParamRoleSystem,
  			Content: []anthropic.ContentBlockParamUnion{
  				anthropic.NewTextBlock("From now on, every suggestion must include explicit type annotations."),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.messages.CacheControlEphemeral;
  // ...
  import com.anthropic.models.messages.MessageParam;
  // ...
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          // 自動 prompt caching（提示快取）：每個請求都會快取目前為止的對話，
          // 下一個請求則從快取讀取未變更的前綴。
          .cacheControl(CacheControlEphemeral.builder().build())
          .system("You are a code review assistant. Be concise.")
          .addUserMessage("Review process() in utils.py for performance issues.")
          .addAssistantMessage("The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.")
          .addUserMessage("Now review the calling code that invokes process().")
          // 審查者在工作階段中途發現，所有建議還必須通過
          // 團隊嚴格的型別政策。將此指示附加在這裡，可讓
          // 先前的輪次保持逐位元組相同，因此前一個請求所快取的前綴
          // 仍可從快取讀取。
          .addMessage(MessageParam.builder()
              .role(MessageParam.Role.SYSTEM)
              .content("From now on, every suggestion must include explicit type annotations.")
              .build())
          .build();

      Message response = client.messages().create(params);
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  ```

  ```php PHP
  use Anthropic\Messages\CacheControlEphemeral;
  // ...
  $client = new Client();

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [
          ['role' => 'user', 'content' => 'Review process() in utils.py for performance issues.'],
          ['role' => 'assistant', 'content' => 'The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.'],
          ['role' => 'user', 'content' => 'Now review the calling code that invokes process().'],
          // 審查者在工作階段中途意識到，所有建議也必須通過
          // 團隊嚴格的型別政策。將指示附加在此處，可讓
          // 先前的輪次保持逐位元組相同，因此上一個請求所快取的前綴
          // 仍可從快取中讀取。
          ['role' => 'system', 'content' => 'From now on, every suggestion must include explicit type annotations.']
      ],
      model: 'claude-opus-5-5',
      // 自動 prompt caching（提示快取）：每個請求都會快取目前為止的對話，
      // 而下一個請求會從快取讀取未變更的前綴。
      cacheControl: CacheControlEphemeral::with(),
      system: 'You are a code review assistant. Be concise.',
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }
  ```

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

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    # 自動 "prompt caching"（提示快取）：每個請求都會快取目前為止的對話，
    # 而下一個請求會從快取讀取未變更的前綴。
    cache_control: { type: "ephemeral" },
    system: "You are a code review assistant. Be concise.",
    messages: [
      { role: "user", content: "Review process() in utils.py for performance issues." },
      { role: "assistant", content: "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list." },
      { role: "user", content: "Now review the calling code that invokes process()." },
      # 審查者在工作階段中途發現，所有建議也必須通過
      # 團隊嚴格的型別規範。將指示附加於此可讓
      # 先前的回合保持位元組完全相同，因此前一個請求快取的前綴
      # 仍可從快取讀取。
      { role: "system", content: "From now on, every suggestion must include explicit type annotations." }
    ]
  )

  response.content.each do |block|
    puts block.text if block.type == :text
  end
  ```
</CodeGroup>

此範例使用頂層 `cache_control` 欄位啟用[自動快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching#automatic-caching)。提示快取需要主動啟用：如果請求沒有 `cache_control` 欄位（自動或[明確斷點](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching#explicit-cache-breakpoints)），則不會快取任何內容，每個請求都要為完整對話支付一般輸入 token 價格。啟用快取後，附加系統訊息不會改變已快取的回合，因此攜帶新指示的請求仍會從快取讀取它們，而不是重新處理。快取也要求對話達到[最小可快取提示長度](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching#cache-limitations)；像這個範例這麼短的對話低於該長度，因此在對話變長之前，`cache_creation_input_tokens` 和 `cache_read_input_tokens` 會維持為 0。

攜帶內容（`text`、`tool_addition` 或 `tool_removal` 區塊）的對話中途系統訊息必須緊接在 `user` 回合（或以伺服器工具結果結尾的 `assistant` 回合）之後，且必須是 `messages` 中的最後一個項目，或緊接著一個 `assistant` 回合。攜帶 `tool_result` 區塊的 `user` 訊息也算在內：在代理迴圈中，您可以將系統訊息放在工具結果之後、Claude 的下一個回合之前。攜帶內容的訊息放在任何其他位置，包括 `assistant` 的 `tool_use` 區塊與回應它的 `tool_result` 之間，都會傳回 400 錯誤。`content` 為空、僅設定 [`output_config.effort`](https://platform.claude.com/docs/zh-TW/build-with-claude/effort#change-effort-mid-conversation-beta) 的訊息可放在 `messages` 中的任何位置。連續的 `system` 訊息會一併判斷，因此與攜帶內容的訊息相鄰的僅含 effort 的訊息會遵循內容規則。

### 放置於工具結果之後

在[代理迴圈](https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/overview)中，系統訊息放在傳遞工具結果的 `user` 訊息之後。在大多數模型上，這也是您的應用程式可以轉達使用者在 Claude 工作時輸入之內容的位置，讓新的上下文在不重新開始回合的情況下被吸收（關於 Claude Sonnet 5.5 和 Claude Haiku 5.5，請參閱本節結尾）：

```json
[
  { "role": "user", "content": "Run the test suite and fix any failures." },
  {
    "role": "assistant",
    "content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
  },
  {
    "role": "user",
    "content": [
      { "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" }
    ]
  },
  {
    "role": "system",
    "content": "The user sent the following message while you were working: also update the changelog before you finish."
  }
]
```

請將系統內容表述為上下文，而非覆寫使用者的命令。陳述事實（「收到來自使用者的新輸入：X」、「剩餘的 token 預算現在是 Y」），並讓 Claude 據此行動。Claude 經過訓練會抗拒看似與使用者作對的指令，而這項保護同樣適用於系統角色，因此像「忽略使用者所說的話」這類措辭，效果不如直接陳述發生了什麼變化。

此模式用於轉達來自對話本身終端使用者的輸入。請勿用它來傳遞工具輸出、擷取的文件或其他第三方內容；請將這類內容保留在 `tool_result` 區塊中（請參閱[限制](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#limitations)）。

在 Claude Sonnet 5.5 和 Claude Haiku 5.5 上，請改為在使用者回合中傳遞使用者的話語。這些模型經過訓練會抵抗透過工具結果進行的「prompt injection」（提示注入），因此它們可能會將緊接在工具結果之後的系統訊息視為不受信任的文字並加以忽略。請將使用者的話語作為 `text` 區塊附加在同一則 `user` 訊息中最後一個 `tool_result` 之後。將 harness 通知（例如提醒）保留在該 `user` 訊息之後的另一則對話中途系統訊息中，並且絕不要將通知和使用者的話語放在同一個區塊中：

```json
[
  { "role": "user", "content": "Run the test suite and fix any failures." },
  {
    "role": "assistant",
    "content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
  },
  {
    "role": "user",
    "content": [
      { "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" },
      { "type": "text", "text": "Also update the changelog before you finish." }
    ]
  }
]
```

如需此行為的更多資訊，請參閱[為 Claude Sonnet 5.5 撰寫提示](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#mid-turn-user-messages-and-task-budgets) 和[為 Claude Haiku 5.5 撰寫提示](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#mid-turn-user-messages)。

### 回合範圍的系統訊息

若要將 `role: "system"` 訊息的範圍限定在目前回合，請設定其 `clear_at` 欄位。它接受以下兩個值之一：

* `"never"`（預設值）：訊息會在每個包含它的請求中於其位置呈現。省略此欄位的效果相同。
* `"next_user_message"`：訊息為**回合範圍**。只有在 `messages` 中其後沒有 `role: "user"` 訊息時，其文字才會呈現。只攜帶 `tool_result` 區塊的使用者訊息在此也算作使用者訊息。一旦之後出現使用者訊息，該訊息就會被**清除**：它仍留在陣列中，但在該請求及之後的每個請求上都不會呈現任何內容，也不會消耗輸入 token。

回合範圍的系統訊息目前為 beta 版。請包含 [beta 標頭](https://platform.claude.com/docs/zh-TW/api/beta-headers) `mid-conversation-system-clear-at-2026-08-21`。若未包含，`clear_at` 會被視為未知欄位而遭拒絕。

```json
{
  "role": "system",
  "clear_at": "next_user_message",
  "content": "First privately list what you need next; then request every item that doesn't depend on another's result in this one response."
}
```

主要用途是在工具迴圈中提供每回合提醒。每次您希望模型看到提醒時，就在 `tool_result` 訊息之後附加它，並將所有先前的副本保留在原處。模型只會看到最後一則使用者訊息之後的副本，因此提醒永遠不會累積。`messages` 中較早的內容都沒有變更，因此[提示快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching)會持續相符。在 Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5 和 Claude Haiku 5.5 上，這也能讓之後的[思考區塊保持有效](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#preserved-in-conversation)：刪除較早的提醒會變更這些區塊之前的對話，導致對話檢查失敗，而被清除的訊息仍保留在陣列中，使該對話保持不變。

以下請求是代理迴圈中較後面的一個步驟。`messages[3]` 在較早的請求中有呈現，當時它是陣列中的最後一則訊息。一旦 `messages[5]`（之後的使用者訊息）存在，`messages[3]` 就會被清除：已清除的訊息仍留在陣列中，因此 `messages[4]` 中思考區塊之前的對話保持不變，但模型不再看到其文字。`messages[6]` 和 `messages[7]` 都會依序呈現。

```json
{
  "model": "claude-fable-5-1",
  "max_tokens": 16000,
  "messages": [
    { "role": "user", "content": "Fix the failing test." },
    {
      "role": "assistant",
      "content": [
        { "type": "thinking", "thinking": "", "signature": "..." },
        {
          "type": "tool_use",
          "id": "toolu_01",
          "name": "read_file",
          "input": { "path": "test_auth.py" }
        }
      ]
    },
    {
      "role": "user",
      "content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "..." }]
    },
    {
      "role": "system",
      "clear_at": "next_user_message",
      "content": "Request independent reads in one turn."
    },
    {
      "role": "assistant",
      "content": [
        { "type": "thinking", "thinking": "", "signature": "..." },
        {
          "type": "tool_use",
          "id": "toolu_02",
          "name": "read_file",
          "input": { "path": "auth.py" }
        },
        {
          "type": "tool_use",
          "id": "toolu_03",
          "name": "read_file",
          "input": { "path": "tokens.py" }
        }
      ]
    },
    {
      "role": "user",
      "content": [
        { "type": "tool_result", "tool_use_id": "toolu_02", "content": "..." },
        {
          "type": "tool_result",
          "tool_use_id": "toolu_03",
          "content": "...",
          "cache_control": { "type": "ephemeral" }
        }
      ]
    },
    {
      "role": "system",
      "clear_at": "next_user_message",
      "content": "Request independent reads in one turn."
    },
    {
      "role": "system",
      "clear_at": "next_user_message",
      "content": "The shell exited with status 137."
    }
  ]
}
```

回合範圍訊息的規則：

* **逐字重新傳送已清除的訊息。** 已清除的訊息仍是對話歷史的一部分。根據目前狀態重建它（新的 token 計數、時間戳記）、將其視為多餘而捨棄，或變更其 `clear_at` 值，都屬於對較早訊息的編輯。提示快取會從該位置開始未命中，而在 Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5 和 Claude Haiku 5.5 上，其後產生的每個思考區塊都會無法通過[對話檢查](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#preserved-in-conversation)。
* **僅限文字。** `content` 是一個或多個 `text` 區塊（或字串）。在輪次範圍訊息上使用 `tool_addition` 和 `tool_removal` 區塊會傳回 400 錯誤，`output_config` 也是如此。這些內容請使用另一則不含 `clear_at` 的 `role: "system"` 訊息。
* **其區塊上不可有 `cache_control`。** 已清除的訊息永遠不會成為快取鍵的一部分，因此放在其上的中斷點永遠無法相符。請改將中斷點放在前一個使用者輪次的最後一個區塊上，如範例所示。頂層[自動快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching#automatic-caching)欄位在選擇中斷點時會略過輪次範圍訊息。在清除某則訊息的請求中，可重複使用的已快取前綴會在其之前的使用者輪次結束，因此只有該訊息與新使用者訊息之間的那一個助理輪次會被重新處理。
* **放置規則仍然適用**，無論是否已清除。輪次範圍訊息必須跟在 `user` 輪次（或以伺服器工具結果結尾的 `assistant` 輪次）之後，並位於 `assistant` 輪次之前或作為陣列的結尾，與任何對話中系統訊息相同。作為陣列結尾的訊息一律會呈現。直接接著另一則 `user` 訊息的訊息會導致 400 錯誤，而不是被清除：請將一輪工具的所有結果放在同一則使用者訊息中，並將提醒放在其後。
* **助理輪次不會清除它。** 訊息之後的預填或[暫停](https://platform.claude.com/docs/zh-TW/build-with-claude/handling-stop-reasons#pause-turn)助理輪次，或伺服器端工具迴圈，都不會新增使用者訊息，因此該訊息在該延續中仍會呈現。若要在用戶端工具迴圈中持續顯示提醒，請在每則 `tool_result` 訊息之後再次附加它。
* **Token 計數依呈現內容而定。** 已清除的訊息不會增加 `usage.input_tokens` 或 [token 計數](https://platform.claude.com/docs/zh-TW/build-with-claude/token-counting)。
* **匯入的歷史。** 在您一次建構的對話紀錄中（少樣本範例、遷移的對話），若輪次範圍訊息之後已有助理輪次和使用者訊息，它會從第一個請求起就被清除，且永遠不會呈現。對於您要沿用的每輪提醒而言，這是正確的狀態。只有在模型應於每個請求中都看到的訊息上，才不設定 `clear_at`。

驗證錯誤如下：

```text wrap
messages.3.clear_at: Extra inputs are not permitted
messages.3.clear_at: clear_at is only permitted on role 'system' messages
messages.3.clear_at: Input should be 'next_user_message' or 'never'
messages.3: a turn-scoped system message supports text blocks only (clear_at: 'next_user_message')
messages.3: output_config is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
messages.3.content.0: cache_control is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
```

第一個是未包含 beta 標頭時傳回的錯誤。在 Google Cloud 和 [Claude in Amazon Bedrock](https://platform.claude.com/docs/zh-TW/build-with-claude/claude-in-amazon-bedrock) 上，請在 `anthropic-beta` 標頭中傳送 beta 值，與 Claude API 相同（請參閱 [Beta 標頭](https://platform.claude.com/docs/zh-TW/api/beta-headers)）。使用 Amazon Bedrock [InvokeModel API](https://platform.claude.com/docs/zh-TW/build-with-claude/claude-on-amazon-bedrock-legacy) 時，請改將其放在請求主體的 `anthropic_beta` 陣列中。

透過 SDK，請在 `messages` 中的 `role: "system"` 項目上設定 `clear_at` (csharp, go: `ClearAt`; java: `.clearAt()`; php: `clearAt`)，並傳送 beta 標頭。以下範例在使用者回合之後附加一則回合範圍提醒；在下一個請求中，一旦存在較晚的使用者訊息，該提醒仍保留在陣列中，但不再呈現：

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: mid-conversation-system-clear-at-2026-08-21" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5-1",
      "max_tokens": 4096,
      "messages": [
        {"role": "user", "content": "Draft a short status update on the database migration for the team channel."},
        {"role": "system", "clear_at": "next_user_message", "content": "The reader is on call: keep this reply under 50 words."}
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta mid-conversation-system-clear-at-2026-08-21 \
    --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-fable-5-1
  max_tokens: 4096
  messages:
    - role: user
      content: Draft a short status update on the database migration for the team channel.
    # 回合範圍的提醒：僅在本回合呈現，待後續出現使用者訊息後即清除。
    - role: system
      clear_at: next_user_message
      content: "The reader is on call: keep this reply under 50 words."
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-fable-5-1",
      max_tokens=4096,
      messages=[
          {
              "role": "user",
              "content": "Draft a short status update on the database migration for the team channel.",
          },
          # 回合範圍的提醒：僅在本回合呈現，待之後出現新的使用者訊息時即清除。
          {
              "role": "system",
              "clear_at": "next_user_message",
              "content": "The reader is on call: keep this reply under 50 words.",
          },
      ],
      betas=["mid-conversation-system-clear-at-2026-08-21"],
  )

  for block in response.content:
      if block.type == "text":
          print(block.text)
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-fable-5-1",
    max_tokens: 4096,
    messages: [
      {
        role: "user",
        content: "Draft a short status update on the database migration for the team channel."
      },
      // 回合範圍的提醒：在本回合中呈現，待之後出現新的使用者訊息時即清除。
      {
        role: "system",
        clear_at: "next_user_message",
        content: "The reader is on call: keep this reply under 50 words."
      }
    ],
    betas: ["mid-conversation-system-clear-at-2026-08-21"]
  });

  for (const block of response.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeFable5_1,
      MaxTokens = 4096,
      Messages =
      [
          new() { Role = Role.User, Content = "Draft a short status update on the database migration for the team channel." },
          // 回合範圍的提醒：僅在本回合呈現，待後續出現使用者訊息時即清除。
          new()
          {
              Role = Role.System,
              ClearAt = ClearAt.NextUserMessage,
              Content = "The reader is on call: keep this reply under 50 words.",
          },
      ],
      Betas = [AnthropicBeta.MidConversationSystemClearAt2026_08_21],
  });

  foreach (var block in response.Content)
  {
      if (block.TryPickText(out var textBlock))
      {
          Console.WriteLine(textBlock.Text);
      }
  }
  ```

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

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5_1,
  	MaxTokens: 4096,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Draft a short status update on the database migration for the team channel.")),
  		// 回合範圍的提醒：在本回合中呈現，待之後出現使用者訊息時即清除。
  		{
  			Role:    anthropic.BetaMessageParamRoleSystem,
  			ClearAt: anthropic.BetaMessageParamClearAtNextUserMessage,
  			Content: []anthropic.BetaContentBlockParamUnion{anthropic.NewBetaTextBlock("The reader is on call: keep this reply under 50 words.")},
  		},
  	},
  	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMidConversationSystemClearAt2026_08_21},
  })
  if err != nil {
  	log.Fatal(err)
  }

  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaMessageParam;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  import com.anthropic.models.messages.Model;

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

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5_1)
          .maxTokens(4096L)
          .addBeta(AnthropicBeta.MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21)
          .addUserMessage("Draft a short status update on the database migration for the team channel.")
          // 回合範圍的提醒：於本回合呈現，待之後出現使用者訊息時即清除。
          .addMessage(BetaMessageParam.builder()
              .role(BetaMessageParam.Role.SYSTEM)
              .clearAt(BetaMessageParam.ClearAt.NEXT_USER_MESSAGE)
              .content("The reader is on call: keep this reply under 50 words.")
              .build())
          .build();

      BetaMessage response = client.beta().messages().create(params);
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaMessageParam;
  use Anthropic\Client;

  $client = new Client();

  $response = $client->beta->messages->create(
      model: 'claude-fable-5-1',
      maxTokens: 4096,
      messages: [
          BetaMessageParam::with(role: 'user', content: 'Draft a short status update on the database migration for the team channel.'),
          // 回合範圍的提醒：於本回合呈現，待後續出現使用者訊息後即清除。
          BetaMessageParam::with(
              role: 'system',
              clearAt: 'next_user_message',
              content: 'The reader is on call: keep this reply under 50 words.',
          ),
      ],
      betas: [AnthropicBeta::MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21],
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }
  ```

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

  response = client.beta.messages.create(
    model: "claude-fable-5-1",
    max_tokens: 4096,
    messages: [
      {role: "user", content: "Draft a short status update on the database migration for the team channel."},
      # 回合範圍的提醒：僅在本回合呈現，待後續出現使用者訊息後即清除。
      {role: "system", clear_at: :next_user_message, content: "The reader is on call: keep this reply under 50 words."}
    ],
    betas: [Anthropic::AnthropicBeta::MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21]
  )

  response.content.each do |block|
    puts block.text if block.type == :text
  end
  ```
</CodeGroup>

## 與提示快取結合使用

對話中途的系統訊息與[提示快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching)的設計就是要搭配使用：

* **明確啟用快取。** 只有當請求包含 `cache_control` 時才會進行快取。`cache_control` 可以是頂層的[自動快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching#automatic-caching)欄位，也可以是內容區塊上的[明確斷點](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching#explicit-cache-breakpoints)。對話中途系統訊息本身不會建立快取項目；若未啟用快取，也就沒有可保留的節省效益。
* **照常快取穩定的前綴。** 將 `cache_control` 放在各次請求之間保持不變的最後一個區塊上。這個位置可以是頂層 `system` 欄位的結尾、工具定義的結尾，或是訊息歷史中的某個穩定位置。
* **在斷點之後附加系統訊息。** 由於系統訊息位於已快取的前綴之後，因此不會改變前綴雜湊，快取仍會命中。
* **對話中途系統訊息本身也可被快取。** 系統訊息一旦進入對話，就會成為穩定歷史的一部分。在下一個回合中，您可以將快取斷點移到它之後（或依賴[自動快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching#automatic-caching)來完成此操作），系統訊息就會像其他任何回合一樣從快取中讀取。

請避免編輯或移除已傳送的對話中系統訊息。與對較早訊息的任何其他變更一樣，這會使從該位置開始的快取失效。在 Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5 和 Claude Haiku 5.5 上，這也會使之後每個助理回合中的[思考區塊](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#preserved-in-conversation)失效。對於只應套用於單一回合的指引，請使用[回合範圍系統訊息](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages)並將其保留在原處。如果指示需要演進，請附加新的系統訊息，而不是改寫舊的訊息。連續的系統訊息會被接受並視為單一系統區段，整體遵循相同的放置規則。

## 限制

* **不可作為第一則訊息。** 攜帶內容的 `system` 訊息不能是 `messages` 中的第一個項目。對於從一開始就適用的指示，請使用頂層 `system` 欄位。
* **放置位置受到限制。** 攜帶內容（`text`、`tool_addition` 或 `tool_removal` 區塊）的 `system` 訊息必須緊接在 `user` 回合（包括攜帶 `tool_result` 區塊的 `user` 回合）或以伺服器工具結果結尾的 `assistant` 回合之後，並且必須位於 `assistant` 回合之前或作為陣列的結尾。它不能位於 `tool_use` 區塊與其 `tool_result` 之間。放在其他位置會傳回 400 錯誤。有一個例外：緊接在[暫停](https://platform.claude.com/docs/zh-TW/build-with-claude/handling-stop-reasons#pause-turn)的 `assistant` 回合（以伺服器工具結果結尾的回合）之後，不接受 `tool_addition` 和 `tool_removal` 區塊，但接受 `text` 區塊；請先恢復暫停的回合，然後在下一則 `system` 訊息中傳送工具變更。`content` 為空、僅設定 [`output_config.effort`](https://platform.claude.com/docs/zh-TW/build-with-claude/effort#change-effort-mid-conversation-beta) 的訊息在其位置不會呈現任何內容，並且可放在 `messages` 中的任何位置，包括第一個位置，或 `assistant` 回合與 `user` 回合之間。連續的 `system` 訊息會一併判斷，因此在僅含 effort 的訊息旁新增攜帶文字的訊息，會使整組訊息都須遵循內容規則。
* **回合範圍訊息僅限文字，且須逐字重新傳送。** `clear_at: "next_user_message"` 訊息不攜帶 `tool_addition`、`tool_removal`、`output_config` 或 `cache_control`，且一旦被清除，在之後的請求中必須逐位元組保留在 `messages` 中。請參閱[回合範圍系統訊息](https://platform.claude.com/docs/zh-TW/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages)。
* **不適合放置不受信任的內容。** Claude 會將系統內容視為營運者指示並加以遵循。請勿將來自對話外部的文字，例如原始工具輸出、擷取的文件或網頁內容，直接放入系統訊息中；這樣做會賦予該文字營運者層級的權限。請將這些資料保留在 `tool_result` 區塊中，並持續遵循[減輕越獄與提示注入](https://platform.claude.com/docs/zh-TW/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks)的指引。

## 相關內容

<CardGroup cols={2}>
  <Card title="提示快取" icon="bolt" href="https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching">
    快取的運作方式、斷點的放置位置，以及如何解讀快取用量欄位。
  </Card>

  <Card title="快取診斷" icon="magnifying-glass" href="https://platform.claude.com/docs/zh-TW/build-with-claude/cache-diagnostics">
    當您預期的快取命中沒有發生時，找出兩個請求究竟在哪裡產生分歧。
  </Card>

  <Card title="使用 Messages API" icon="message" href="https://platform.claude.com/docs/zh-TW/build-with-claude/working-with-messages">
    訊息結構、多輪對話，以及 `system` 欄位。
  </Card>

  <Card title="提示最佳實務" icon="text" href="https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-engineering/claude-prompting-best-practices">
    撰寫有效的提示與系統指令。
  </Card>

  <Card title="搭配 Claude 的工具使用" icon="wrench" href="https://platform.claude.com/docs/zh-TW/agents-and-tools/tool-use/overview">
    `tool_use` 與 `tool_result` 區塊在 `messages` 陣列中的結構方式。
  </Card>
</CardGroup>
