---
title: 会話途中のシステムメッセージとツール変更
url: https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-system-messages
description: 会話の途中でシステム指示やツールの利用可否を変更しても、それ以前のキャッシュ済みプレフィックスを無効化しないようにします。
---

<Note>
  「zero data retention」（ゼロデータ保持）、すなわちZDRがこの機能にどのように適用されるかについては、[APIとデータ保持](https://platform.claude.com/docs/ja/manage-claude/api-and-data-retention)を参照してください。
</Note>

システム指示は通常、会話内のすべてのメッセージより前にあるトップレベルの `system` フィールドに置かれます。この位置は [prompt caching](https://platform.claude.com/docs/ja/build-with-claude/prompt-caching)（プロンプトキャッシング）にとって非常に都合が良いものです。システムプロンプトは安定したプレフィックスの一部となるため、後続のターンはキャッシュにヒットします。一方で、セッションの途中になって初めて必要だと気づいた指示にとっては不向きな位置です。トップレベルの `system` フィールドを編集するとプロンプトの冒頭そのものが変わり、それ以降のすべてについてキャッシュが無効化されるためです。

会話途中のシステムメッセージはこのギャップを埋めます。トップレベルの `system` フィールドを編集する代わりに、新しい指示が関連するようになった会話内の位置に `{"role": "system"}` メッセージを追加します。キャッシュ済みプレフィックスは変わらないため、次のリクエストでも引き続きキャッシュから読み取られ、新しい指示は通常のユーザーテキストとしてではなく、システム指示として適用されます。

<Note>
  会話途中のシステムメッセージは、Claude API、[Claude in Amazon Bedrock](https://platform.claude.com/docs/ja/build-with-claude/claude-in-amazon-bedrock)、および [Google Cloud](https://platform.claude.com/docs/ja/build-with-claude/claude-on-vertex-ai) で利用できます。

  この機能は、Claude Fable 5.1、[Claude Mythos 5.1](https://platform.claude.com/docs/ja/models/mythos-5-1/overview)、Claude Fable 5、[Claude Mythos 5](https://platform.claude.com/docs/ja/models/mythos-5/overview)、Claude Opus 5.5、Claude Opus 4.8、Claude Opus 5、Claude Sonnet 5.5、Claude Haiku 5.5で利用できます。会話途中のシステムメッセージにベータヘッダーは不要です。この機能は Claude Sonnet 5 では利用できません。Claude Sonnet 5 では代わりにトップレベルの `system` フィールドを使用してください。

  [会話途中のツール変更](https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes)は、同じモデルでベータ版として提供されています。Claude APIでは`inline-tools-2026-09-15`ベータヘッダーを送信してください。このヘッダーは[`tool_addition`ブロック内でのツールの定義](https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta)にも対応しています。[この方法で「Model Context Protocol」、すなわちMCPのサーバーを追加する](https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-system-messages#add-an-mcp-server-mid-conversation-beta)には、2つ目のベータヘッダーである`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/ja/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages)（`clear_at`）はベータ版であり、`mid-conversation-system-clear-at-2026-08-21` ベータヘッダーが必要です。会話途中のシステムメッセージと同じモデルおよびプラットフォームで利用できます。
</Note>

## 会話途中のツール変更

`tools`配列は、ハッシュ化されるリクエストプレフィックスの中で、トップレベルの`system`フィールドよりもさらに前に位置します。そのため、これを編集すると会話全体の[プロンプトキャッシュ](https://platform.claude.com/docs/ja/build-with-claude/prompt-caching)が無効になります。会話途中のツール変更は、会話途中のシステムメッセージのツール版です。会話の全期間にわたってツールリストを固定する代わりに、ターンの合間にモデルへ提供するツールを変更できます。まず`tools`でツールセット全体を宣言し、次に`tool_addition`ブロックと`tool_removal`ブロックを使って、会話の特定の時点以降にツールをモデルへ提供したり、提供を取り下げたりします。`tools`配列自体は変わらないため、キャッシュ済みのプレフィックスはそのまま保たれます。会話途中のツール変更はベータ版で、Claude APIでは`inline-tools-2026-09-15`ベータヘッダーを使用します。

`tool_addition`と`tool_removal`は、`role: "system"`メッセージの`content`配列に含めるコンテンツブロックで、同じメッセージ内で`text`ブロックと組み合わせることができます。このメッセージは、他の会話途中のシステムメッセージと同じ配置ルールに従います。ただし、一時停止されたターンの後には追加の制限が1つあります（[制限事項](https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-system-messages#limitations)を参照）。変更は、会話内のその時点以降に適用されます。各ブロックの`tool`フィールドは、ツールを定義するのではなく参照します。`{"type": "tool_reference", "name": "..."}`は、リクエストの`tools`配列で宣言されたツールを名前で指定します。[MCPコネクタ](https://platform.claude.com/docs/ja/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/ja/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta)こともできます。ただし、`mid-conversation-tool-changes-2026-07-01`ヘッダーはこれに対応していません。

`tools` で宣言されたすべてのツールは、`defer_loading: true` を付けて宣言されていない限り、会話の開始時点からモデルに提供されます。`defer_loading: true` を付けると、`tool_addition` ブロックがそのツールを表に出すまで保留されたままになります。`tool_addition` は、以前の `tool_removal` で取り下げられたツールを再度提供することもできます。

次のリクエストは、`tools` で `get_weather` を宣言し、最初のユーザーターンの後に `tool_removal` ブロックでそれを取り下げます。このリクエストは `inline-tools-2026-09-15` ベータヘッダーを送信します。

<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>

### メッセージ内でツールを定義する（ベータ）

`inline-tools-2026-09-15` ベータヘッダーを使用すると、`tool_addition` ブロックでツールを参照で指定する代わりに、完全な定義を含めて値として定義できます。これにより、会話の開始時点では不明なツールや、後でスキーマが変わるツールを、`role: "system"` メッセージを追加するだけで導入できます。`tools` 配列とそれ以前のすべてのメッセージは送信時のまま変わらないため、プロンプトキャッシングは引き続きヒットし、追加したメッセージだけが新しい入力として処理されます。唯一の例外は、遅延されていないツールを1つも含まない `tools` 配列の場合で、これについては後述のルールで説明します。このヘッダーは参照によるツールの追加と削除にも対応しているため、`mid-conversation-tool-changes-2026-07-01` を併せて送信する必要はありません。

定義は、`tool_definition` タイプの `tool` オブジェクトでラップします。`definition` は `tools` のエントリと同じ形式で、カスタムツールや、Anthropic 定義のクライアントツールまたはサーバーツールなどを指定できます。`cache_control` や `defer_loading` を含む通常の設定も使用できます。ベータ期間中は、一部のツールタイプ（コンピュータ使用ツールなど）をまだメッセージ内で定義できず、その旨を示す 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` には遅延読み込みしないツールを少なくとも1つ残します。これにより、後から定義される
  # ツールによって、レンダリングされたプロンプトの先頭が変わることはありません。
  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` には遅延されないツールを少なくとも1つ残してください。そうすれば、後で定義したツールが
      # レンダリングされたプロンプトの先頭を変えることはありません。
      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` には遅延読み込みしないツールを少なくとも1つ残してください。そうすれば、後から
    // 定義したツールによってレンダリングされるプロンプトの先頭が変わることはありません。
    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` には遅延読み込みしないツールを少なくとも1つ残しておきます。これにより、後から定義した
      // ツールがレンダリングされたプロンプトの先頭を変更しなくなります。
      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 には遅延読み込みでないツールを少なくとも1つ残してください。そうすれば、後から定義した
  	// ツールによってレンダリング後のプロンプトの先頭が変わることはありません。
  	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` には遅延読み込みされないツールを少なくとも1つ残してください。こうすることで、後から
          // 定義したツールによって、レンダリングされたプロンプトの先頭が変わらなくなります。
          .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` には遅延読み込みされないツールを少なくとも1つ残してください。これにより、後から定義した
      // ツールがレンダリングされたプロンプトの先頭を変更しなくなります。
      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` には遅延ロードしないツールを少なくとも1つ残しておきます。これにより、後から定義した
    # ツールによってレンダリング後のプロンプトの先頭が変わることはありません。
    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"
  }
}
```

ツールのスキーマを変更する場合や、サーバーツールを新しいバージョンに移行する場合は、同じ名前で異なる定義を送信します。その位置以降は、新しい定義が以前の定義に置き換わります。別のタイプのツールと同じ名前を使用する定義を送信すると、`error.details.error_code` が `tool_name_conflict` に設定された 400 エラーが返されます。同じツールの新しいバージョンは、別のタイプとはみなされません。`tool_removal` では引き続き参照を指定します。削除したツールは、後で再び定義したり提供したりできます。

定義がレンダリングされる位置に関連して、次のルールがあります。

* **事前にわかっているツールは最初に宣言する。** 最初のリクエストの時点でわかっているツールは `tools` に含めてください。まだモデルに見せたくない場合は、`defer_loading: true` を指定し、後で `tool_addition` で参照します。値による定義は、最初のリクエストの時点で不明なツールや、後で変更されるツールだけに使用してください。
* **`tools` には遅延されていないツールを少なくとも1つ残す。** `tools` 配列に遅延されていないツールが1つもない会話も受け付けられます。ただし、値によって最初にツールを定義すると、レンダリングされるプロンプトの先頭が変わるため、そのリクエストではキャッシュが完全にミスします。[ツール検索ツール](https://platform.claude.com/docs/ja/agents-and-tools/tool-use/tool-search-tool)は、遅延されていないツールとしてカウントされます。
* **日付付きのツールタイプには、それぞれのベータヘッダーが引き続き必要。** 値によって定義するサーバーツールに独自のベータヘッダーが必要な場合は、会話内の以降のすべてのリクエストでそのヘッダーを送信してください。
* **`cache_control` はブロックと定義のどちらか一方にのみ指定する。** また、`cache_control` はリクエストのブレークポイント数の上限にカウントされます。遅延された定義には `cache_control` を指定できません。

次のいずれかの上限を超えると、`error.details.error_code` が `available_tools_limit_exceeded` に設定された 400 エラーが返されます。

* いずれかのメッセージの後で、利用可能な遅延ツールが 10,000 個を超えている。
* いずれかのメッセージの後で、最初のユーザーメッセージ以降に定義されたツールのうち利用可能なものが 10,000 個を超えている。
* 最初のユーザーメッセージ以降に送信され、いずれかのメッセージの後でまだ利用可能なツール定義の合計サイズが 4 MB（4,194,304 バイト）を超えている。
* レンダリングされたツールテキストのサイズが 4 MB（4,194,304 バイト）を超えている。

### 会話の途中で MCP サーバーを追加する（ベータ）

会話の途中で [MCP コネクタ](https://platform.claude.com/docs/ja/agents-and-tools/mcp-connector)のサーバーを追加するには、`inline-tools-2026-09-15` に加えて `mcp-client-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?"},
          # この時点以降、カレンダーサーバーのツールを利用可能にします。
          # このブロックはサーバー名を指定するだけで、URLやトークンを保持することはありません。
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_addition",
                      "tool": {
                          "type": "tool_definition",
                          "definition": {
                              "type": "mcp_toolset",
                              "mcp_server_name": "calendar",
                          },
                      },
                  },
              ],
          },
      ],
  )

  # レスポンスはカレンダーサーバーの mcp_tool_listing ブロックから始まるため、
  # content[0] を読むのではなく、各ブロックの type を確認してください。
  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?" },
      // この時点以降、カレンダーサーバーのツールを利用可能にします。
      // このブロックはサーバー名を指定するだけで、URLやトークンを保持することはありません。
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  });

  // レスポンスはカレンダーサーバーの mcp_tool_listing ブロックから始まるため、
  // content[0] を読むのではなく、各ブロックの type を確認してください。
  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?" },
          // この時点以降、カレンダーサーバーのツールを利用可能にします。
          // このブロックはサーバー名を指定するだけで、URLやトークンは保持しません。
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolAdditionBlock
                  {
                      Tool = new BetaToolChangeToolDefinitionParam
                      {
                          Definition = new BetaMcpToolset("calendar"),
                      },
                  },
              ]),
          },
      ],
  });

  // レスポンスはカレンダーサーバーの mcp_tool_listing ブロックから始まるため、
  // Content[0] を読むのではなく、各ブロックの type を確認してください。
  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?")),
  		// この時点以降、カレンダーサーバーのツールを利用可能にします。
  		// このブロックはサーバー名を指定するだけで、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)
  }

  // レスポンスはカレンダーサーバーの mcp_tool_listing ブロックから始まるため、
  // Content[0] を読むのではなく、各ブロックの type を確認してください。
  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?")
          // この時点以降、カレンダーサーバーのツールを利用可能にします。
          // このブロックはサーバー名を指定するだけで、URLやトークンを保持することはありません。
          .addSystemMessageOfBetaContentBlockParams(List.of(
              BetaContentBlockParam.ofToolAddition(BetaRequestToolAdditionBlock.builder()
                  .definitionTool(BetaMcpToolset.builder()
                      .mcpServerName("calendar")
                      .build())
                  .build())))
          .build();

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

      // レスポンスはカレンダーサーバーの mcp_tool_listing ブロックから始まるため、
      // 最初のブロックを読むのではなく、各ブロックの type を確認してください。
      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?"],
          // ここ以降、カレンダーサーバーのツールを利用可能にします。
          // このブロックはサーバー名を指定するだけで、URLやトークンは保持しません。
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_addition',
                      'tool' => [
                          'type' => 'tool_definition',
                          'definition' => [
                              'type' => 'mcp_toolset',
                              'mcp_server_name' => 'calendar',
                          ],
                      ],
                  ],
              ],
          ],
      ],
  );

  // レスポンスはカレンダーサーバーの mcp_tool_listing ブロックから始まるため、
  // content[0] を読むのではなく、各ブロックの type を確認してください。
  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?" },
      # この時点以降、カレンダーサーバーのツールを利用可能にします。
      # このブロックはサーバー名を指定するだけで、URLやトークンは保持しません。
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  )

  # レスポンスはカレンダーサーバーの mcp_tool_listing ブロックから始まるため、
  # content[0] を読むのではなく、各ブロックの type を確認してください。
  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 がサーバーのツールリストを取得したレスポンスは、取得したサーバーごとに 1 つずつ、`mcp_tool_listing` ブロックで始まります。コードで `content[0]` を読み取る場合は、これらのブロックをスキップしてください。アシスタントメッセージはこのブロックを含めて変更せずに送り返し、このブロックを含むすべてのリクエストで `mcp-client-2026-09-15` を送信し続けてください。以降のリクエストでは、サーバーに再度問い合わせる代わりに、記録されたリストが使用されます。ツールセットを自分で固定するには、[MCP サーバーのツールリストをピン留めする](https://platform.claude.com/docs/ja/agents-and-tools/mcp-connector#pin-mcp-tool-list)で説明されているように、そのリストを `mcp_toolset` の `tools` フィールドにコピーします。

`mcp-client-2026-09-15` には `mcp-client-2025-11-20` のすべての機能が含まれているため、両方を送信する必要はありません。これらの機能は Claude API で利用できます。MCP コネクタを使用するリクエストには、引き続き MCP コネクタの[データ保持](https://platform.claude.com/docs/ja/agents-and-tools/mcp-connector#data-retention)の条件が適用されます。

## 会話途中のシステムメッセージを使用するタイミング

[プロンプトキャッシング](https://platform.claude.com/docs/ja/build-with-claude/prompt-caching)は、リクエストプレフィックスを `tools`、次に `system`、次に `messages` の順にハッシュ化します。キャッシュヒットには、キャッシュブレークポイントまでのプレフィックスが最近のリクエストとバイト単位で完全に一致する必要があります。

この順序により、トップレベルの `system` フィールドはハッシュ化されるプレフィックスのほぼ先頭に位置します。一文を追加するだけであっても、これを変更すると異なるハッシュが生成され、リクエストはシステムプロンプトおよびそれ以降のすべてのキャッシュ済みメッセージについてキャッシュミスとなります。

会話途中のシステムメッセージを使えば、代わりにメッセージ履歴の**末尾**に指示を追加できます。新しい指示より前のすべては変更されないため、既存のキャッシュエントリは引き続き一致し、新しいメッセージだけが新規入力として処理されます。

これが重要になる状況をいくつか挙げます。

* **セッション途中のポリシーやペルソナの変更。** 長いエージェントセッションで、数十のキャッシュ済みターンの後に新しい制約（「今後はすべての SQL をパラメータ化クエリとして書くこと」）が必要になる場合。トップレベルの `system` フィールドに追加すると、履歴全体が再処理されます。
* **権威を持たせる必要があるターンごとのコンテキスト。** 鮮度に関する注記、セッションの期限、ツールの利用可否の変更などをシステムレベルの重みで注入したいが、キャッシュ済みプレフィックスに置くには変更頻度が高すぎる場合。
* **積み重なってほしくないターンごとのリマインダー。** ハーネスがツール結果のバッチごとにモデルを促し（「独立した読み取りはまとめてリクエストすること」「ユーザーはしばらくあなたからの応答を受け取っていません」）、モデルには最新のコピーだけを見せたい場合。[ターンスコープのシステムメッセージ](https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages)は 1 ターンだけレンダリングされ、その後は履歴から何も削除することなくコストがゼロになります。
* **アプリケーションが観測した状態変化。** Claude がオペレーターレベルの事実として扱うべき事柄にアプリケーションが気づいた場合。たとえば、ディスク上のファイルが変更された、ユーザーが自動承認設定を切り替えた、利用可能なツールが変わった、残りのトークン予算がしきい値を下回った、などです。
* **エージェントループを中断すべきでないユーザー入力。** Claude が前のリクエストのためにまだツールを実行している間に、ユーザーがフォローアップを入力した場合。次のツール結果の後にそれをシステムメッセージとして中継すると、Claude は新しい入力を切り替えるべき新規リクエストとして扱うのではなく、すでに行っている作業に組み込むことができます。Claude Sonnet 5.5 と Claude Haiku 5.5 では、代わりに同じ `user` メッセージ内の最後の `tool_result` の後に、ユーザーの言葉を `text` ブロックとして追加してください。[ツール結果の後への配置](https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-system-messages#placement-after-tool-results)を参照してください。
* **継続的な許可を与えるモード切り替え。** セッションレベルのモードでは、会話途中のシステムメッセージを使って、マルチエージェントワークフローの自動起動のような高コストな機能に対する継続的な同意を与えることができます。数ターンごとに短いリフレッシャーを送り、モードがオフになったときには終了通知を送ります。具体例については、[オーケストレーションモードを構築する](https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-effort-example)を参照してください。

これらすべてのケースで、指示を通常の `user` メッセージに入れることもでき、Claude はユーザーターンで届いた指示にも従います。違いは優先度です。`user` メッセージはエンドユーザーからのものとして扱われ、`system` メッセージはアプリケーションオペレーターであるあなたからのものとして扱われます。両者が矛盾する場合はシステム指示が優先されるため、エンドユーザーが別のことを求めた場合でも維持されるべきオペレーターレベルの事実や制約には `system` ロールを使用してください。会話途中のシステムメッセージは、トップレベルの `system` フィールドを編集することによるキャッシュミスのコストを払うことなく、そのオペレーターレベルの優先度を保ちます。

## 仕組み

`messages` 配列に `"role": "system"` を持つメッセージを追加します。`content` には、`user` や `assistant` ターンと同様に、プレーンな文字列またはコンテンツブロックを使用します。指示は会話内のその位置以降に適用されます。指示が矛盾する場合、後のシステムメッセージが前のものより優先され、会話途中のシステムメッセージはそれに続くターンについてトップレベルの `system` フィールドより優先されます。

会話全体に適用すべき指示については、引き続きトップレベルの `system` フィールドを設定できます。会話途中のシステムメッセージは、後になって初めて関連するようになる指示、またはキャッシュ済みプレフィックスを無効化せずに追加したい指示のために取っておいてください。

`role: "system"` メッセージには、会話の途中で [effort](https://platform.claude.com/docs/ja/build-with-claude/effort) レベルを変更するための `output_config.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でベータ版として提供されており、`mid-conversation-output-config-2026-07-01` ベータヘッダーが必要です。Amazon Bedrock では、Claude Fable 5.1、Claude Mythos 5.1、Claude Opus 5.5 で、同じベータ値を使用してベータ版として提供されています。Claude Opus 5 は Amazon Bedrock ではこれをサポートしていません。[メッセージごとのエフォート](https://platform.claude.com/docs/ja/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,
    // 自動プロンプトキャッシング：各リクエストはそれまでの会話をキャッシュし、
    // 次のリクエストは変更のないプレフィックスをキャッシュから読み取ります。
    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,
  	// 自動プロンプトキャッシング：各リクエストはそれまでの会話をキャッシュし、
  	// 次のリクエストは変更のないプレフィックスをキャッシュから読み取ります。
  	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)
          // 自動プロンプトキャッシング：各リクエストはそれまでの会話をキャッシュし、
          // 次のリクエストは変更のないプレフィックスをキャッシュから読み取ります。
          .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,
    # 自動プロンプトキャッシング：各リクエストはそれまでの会話をキャッシュし、
    # 次のリクエストは変更のないプレフィックスをキャッシュから読み取ります。
    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/ja/build-with-claude/prompt-caching#automatic-caching)を有効にしています。プロンプトキャッシングはオプトインです。リクエストに `cache_control` フィールド（自動または[明示的なブレークポイント](https://platform.claude.com/docs/ja/build-with-claude/prompt-caching#explicit-cache-breakpoints)）がない場合、何もキャッシュされず、すべてのリクエストが会話全体に対して通常の入力トークン料金を支払います。キャッシングが有効な場合、システムメッセージを追加してもすでにキャッシュ済みのターンは変更されないため、新しい指示を含むリクエストはそれらを再処理するのではなく、引き続きキャッシュから読み取ります。キャッシングには、会話が[キャッシュ可能な最小プロンプト長](https://platform.claude.com/docs/ja/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 エラーが返されます。[`output_config.effort`](https://platform.claude.com/docs/ja/build-with-claude/effort#change-effort-mid-conversation-beta) のみを設定する空の `content` を持つメッセージは、`messages` 内のどこにでも配置できます。連続する `system` メッセージはまとめて判定されるため、コンテンツを含むメッセージの隣にあるエフォートのみのメッセージは、コンテンツのルールに従います。

### ツール結果の後への配置

[エージェントループ](https://platform.claude.com/docs/ja/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」「残りのトークン予算は現在 Y です」）、Claude にそれに基づいて行動させます。Claude はユーザーに不利に働くように見える指示に抵抗するよう訓練されており、その保護はシステムロールにも引き続き適用されるため、「ユーザーが言ったことは無視してください」のような表現は、何が変わったかを述べるよりも効果が低くなります。

このパターンは、会話自身のエンドユーザーからの入力を中継するためのものです。ツール出力、取得したドキュメント、その他のサードパーティコンテンツを渡すために使用しないでください。そうしたコンテンツは `tool_result` ブロックに保持してください（[制限事項](https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-system-messages#limitations)を参照）。

Claude Sonnet 5.5 と Claude Haiku 5.5 では、代わりにユーザーの言葉をユーザーターンで届けてください。これらのモデルはツール結果を介したプロンプトインジェクションに抵抗するよう訓練されているため、ツール結果の直後に置かれたシステムメッセージを信頼できないテキストとして扱い、無視する可能性があります。ユーザーの言葉は、同じ `user` メッセージ内の最後の `tool_result` の後に `text` ブロックとして追加してください。リマインダーなどのハーネスからの通知は、その `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/ja/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/ja/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#mid-turn-user-messages)を参照してください。

### ターンスコープのシステムメッセージ

`role: "system"` メッセージを現在のターンにスコープするには、その `clear_at` フィールドを設定します。次の 2 つの値のいずれかを取ります。

* `"never"`（デフォルト）: メッセージは、それを含むすべてのリクエストでその位置にレンダリングされます。フィールドを省略した場合も同じです。
* `"next_user_message"`: メッセージは**ターンスコープ**になります。そのテキストは、`messages` 内でその後に `role: "user"` メッセージが存在しない間だけレンダリングされます。ここでは `tool_result` ブロックのみを持つユーザーメッセージもユーザーメッセージとして数えられます。後続のユーザーメッセージが存在するようになると、メッセージは**クリア**されます。配列には残りますが、そのリクエストおよびそれ以降のすべてのリクエストで何もレンダリングされず、入力トークンのコストもかかりません。

ターンスコープのシステムメッセージはベータ版です。[ベータヘッダー](https://platform.claude.com/docs/ja/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/ja/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/ja/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."
    }
  ]
}
```

ターンスコープメッセージのルール:

* **クリアされたメッセージはそのまま再送信してください。** クリアされたメッセージも会話履歴の一部です。現在の状態（新しいトークン数、タイムスタンプ）から再構築したり、冗長だとして削除したり、`clear_at` の値を変更したりすることは、以前のメッセージの編集にあたります。その時点からプロンプトキャッシュがミスし、Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5、Claude Haiku 5.5では、それ以降に生成されたすべての思考ブロックが[会話チェック](https://platform.claude.com/docs/ja/build-with-claude/thinking#preserved-in-conversation)に失敗します。
* **テキストのみ。** `content`は1つ以上の`text`ブロック（または文字列）です。ターンスコープのメッセージに`tool_addition`ブロックや`tool_removal`ブロックを含めると400エラーが返され、`output_config`を含めた場合も同様です。これらには、`clear_at`を指定しない別の`role: "system"`メッセージを使用してください。
* **ブロックに`cache_control`を指定できません。** クリアされたメッセージはキャッシュキーに含まれないため、そこにブレークポイントを置いても一致することはありません。例のように、代わりに直前のユーザーターンの最後のブロックにブレークポイントを置いてください。トップレベルの[自動キャッシング](https://platform.claude.com/docs/ja/build-with-claude/prompt-caching#automatic-caching)フィールドは、ブレークポイントを選ぶ際にターンスコープのメッセージをスキップします。メッセージがクリアされるリクエストでは、再利用可能なキャッシュ済みプレフィックスはそのメッセージの前のユーザーターンで終わるため、再処理されるのは、そのメッセージと新しいユーザーメッセージの間にある1つのアシスタントターンだけです。
* **クリアされているかどうかにかかわらず、配置ルールは引き続き適用されます。** ターンスコープのメッセージは、他の会話途中のシステムメッセージと同様に、`user`ターン（またはサーバーツールの結果で終わる`assistant`ターン）の後に配置し、`assistant`ターンの前に置くか、配列の末尾にする必要があります。配列の末尾にあるメッセージは常にレンダリングされます。直後に別の`user`メッセージが続くメッセージは、クリアされたメッセージではなく400エラーになります。1回のツールラウンドの結果はすべて1つのユーザーメッセージにまとめ、リマインダーはその後に配置してください。
* **アシスタントターンではクリアされません。** メッセージの後にあるプレフィル済みまたは[一時停止された](https://platform.claude.com/docs/ja/build-with-claude/handling-stop-reasons#pause-turn)アシスタントターンや、サーバー側のツールループでは、ユーザーメッセージが追加されません。そのため、その継続処理でもメッセージは引き続きレンダリングされます。クライアント側のツールループを通じてリマインダーを表示し続けるには、各`tool_result`メッセージの後にリマインダーを再度追加してください。
* **トークンのカウントは、レンダリングされる内容に基づきます。** クリアされたメッセージは、`usage.input_tokens`にも[トークンカウント](https://platform.claude.com/docs/ja/build-with-claude/token-counting)にも加算されません。
* **インポートされた履歴。** 一度に構築するトランスクリプト（few-shotの例や移行した会話など）では、後ろにすでにアシスタントターンとユーザーメッセージがあるターンスコープのメッセージは、最初のリクエストからクリアされ、一度もレンダリングされません。引き継ぐターンごとのリマインダーにとっては、これが正しい状態です。`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')
```

1つ目は、ベータヘッダーなしで返されるエラーです。Google Cloud と [Claude in Amazon Bedrock](https://platform.claude.com/docs/ja/build-with-claude/claude-in-amazon-bedrock) では、Claude API と同様に `anthropic-beta` ヘッダーでベータ値を送信してください（[ベータヘッダー](https://platform.claude.com/docs/ja/api/beta-headers)を参照）。Amazon Bedrock の [InvokeModel API](https://platform.claude.com/docs/ja/build-with-claude/claude-on-amazon-bedrock-legacy) では、代わりにリクエストボディの `anthropic_beta` 配列に含めてください。

SDK を通じて使用する場合は、`messages` 内の `role: "system"` エントリに `clear_at` (csharp, go: `ClearAt`; java: `.clearAt()`; php: `clearAt`) を設定し、ベータヘッダーを送信します。次の例では、ユーザーターンの後にターンスコープのリマインダーを追加します。次のリクエストで後続のユーザーメッセージが存在するようになると、リマインダーは配列に残りますが、レンダリングされなくなります。

<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/ja/build-with-claude/prompt-caching)は、一緒に使用するように設計されています。

* **キャッシングを明示的に有効にする。** キャッシングは、リクエストに `cache_control`（トップレベルの[自動キャッシング](https://platform.claude.com/docs/ja/build-with-claude/prompt-caching#automatic-caching)フィールド、またはコンテンツブロック上の[明示的なブレークポイント](https://platform.claude.com/docs/ja/build-with-claude/prompt-caching#explicit-cache-breakpoints)）が含まれている場合にのみ行われます。会話途中のシステムメッセージはそれ自体ではキャッシュエントリを作成せず、キャッシングが有効でなければ保持すべき節約もありません。
* **安定したプレフィックスを通常どおりキャッシュする。** リクエスト間で変わらない最後のブロックに `cache_control` を置きます。それがトップレベルの `system` フィールドの末尾であれ、ツール定義の末尾であれ、メッセージ履歴内の安定した位置であれ同様です。
* **ブレークポイントの後にシステムメッセージを追加する。** キャッシュ済みプレフィックスの後に来るため、プレフィックスのハッシュは変わらず、キャッシュは引き続きヒットします。
* **会話途中のシステムメッセージ自体もキャッシュ可能。** 会話に入った時点で、安定した履歴の一部になります。次のターンでは、キャッシュブレークポイントをその先に移動でき（または[自動キャッシング](https://platform.claude.com/docs/ja/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/ja/build-with-claude/thinking#preserved-in-conversation)も無効になります。1ターンだけに適用すべきガイダンスには、[ターンスコープのシステムメッセージ](https://platform.claude.com/docs/ja/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 エラーが返されます。ただし、例外が1つあります。[一時停止された](https://platform.claude.com/docs/ja/build-with-claude/handling-stop-reasons#pause-turn) `assistant` ターン（サーバーツールの結果で終わるもの）の直後では、`text` ブロックは受け付けられますが、`tool_addition` ブロックと `tool_removal` ブロックは受け付けられません。この場合は、まず一時停止されたターンを再開し、その後の `system` メッセージでツール変更を送信してください。`content` が空で、[`output_config.effort`](https://platform.claude.com/docs/ja/build-with-claude/effort#change-effort-mid-conversation-beta) だけを設定するメッセージは、その位置に何もレンダリングしません。このようなメッセージは、最初の位置や、`assistant` ターンと `user` ターンの間など、`messages` 内のどこにでも置くことができます。連続する `system` メッセージはまとめて判定されます。そのため、エフォートのみのメッセージの隣にテキストを含むメッセージを追加すると、グループ全体にコンテンツを含むメッセージのルールが適用されます。
* **ターンスコープのメッセージはテキストのみで、変更せずに再送信する必要がある。** `clear_at: "next_user_message"` メッセージには、`tool_addition`、`tool_removal`、`output_config`、`cache_control` を含めることはできません。また、クリアされた後も、以降のリクエストでは `messages` 内にバイト単位で同一のまま残す必要があります。[ターンスコープのシステムメッセージ](https://platform.claude.com/docs/ja/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages)を参照してください。
* **信頼できないコンテンツには使用しない。** Claude はシステムメッセージの内容をオペレーターの指示として扱い、それに従います。生のツール出力、取得したドキュメント、Web コンテンツなど、会話の外部から得たテキストをシステムメッセージに直接含めないでください。含めると、そのテキストにオペレーターレベルの権限が与えられてしまいます。そのようなデータは `tool_result` ブロックに含め、引き続き[ジェイルブレイクとプロンプトインジェクションの軽減](https://platform.claude.com/docs/ja/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks)のガイダンスに従ってください。

## 関連情報

<CardGroup cols={2}>
  <Card title="プロンプトキャッシング" icon="bolt" href="https://platform.claude.com/docs/ja/build-with-claude/prompt-caching">
    キャッシングの仕組み、ブレークポイントの配置場所、キャッシュ使用量フィールドの読み方。
  </Card>

  <Card title="キャッシュ診断" icon="magnifying-glass" href="https://platform.claude.com/docs/ja/build-with-claude/cache-diagnostics">
    期待したキャッシュヒットが起こらなかったときに、2 つのリクエストがどこで分岐したかを正確に突き止めます。
  </Card>

  <Card title="Messages API の使用" icon="message" href="https://platform.claude.com/docs/ja/build-with-claude/working-with-messages">
    メッセージ構造、マルチターン会話、および `system` フィールド。
  </Card>

  <Card title="プロンプティングのベストプラクティス" icon="text" href="https://platform.claude.com/docs/ja/build-with-claude/prompt-engineering/claude-prompting-best-practices">
    効果的なプロンプトとシステム指示の書き方。
  </Card>

  <Card title="Claude でのツール使用" icon="wrench" href="https://platform.claude.com/docs/ja/agents-and-tools/tool-use/overview">
    `messages` 配列内で `tool_use` および `tool_result` ブロックがどのように構造化されるか。
  </Card>
</CardGroup>
