---
title: コンパクションと思考の保持
url: https://platform.claude.com/docs/ja/build-with-claude/compaction-thinking-blocks
description: 思考の保持に対応したモデルで、オンデマンドコンパクション後に保持されたターン内の思考ブロックが有効なままとなる条件と、その確認方法について説明します。
featureMetadata:
  status: beta
  betaHeader: compact-2026-09-04
  supportedModels:
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-fable-5
    - claude-mythos-5
    - claude-mythos-preview
    - claude-opus-5-5
    - claude-opus-5
    - claude-opus-4-8
    - claude-opus-4-7
    - claude-opus-4-6
    - claude-sonnet-5-5
    - claude-sonnet-5
    - claude-sonnet-4-6
    - claude-haiku-5-5
  supportedPlatforms:
    Claude API: beta
    Claude Platform on AWS: beta
    Google Cloud: beta
    Microsoft Foundry: beta
---

「[preserved thinking](https://platform.claude.com/docs/ja/build-with-claude/preserved-thinking)」（思考の保持）に対応したモデルに「thinking blocks」（思考ブロック）を送り返し、かつ「compaction」（コンパクション）ブロックの後にターンを残す場合を除き、このページは読み飛ばしてください。「kept turns」（残したターン）とは、ブロックの後に続くターンのことです。[直近のターンを保持するコンパクション](https://platform.claude.com/docs/ja/build-with-claude/compaction-keep-recent-turns)のようにコンパクションリクエストから除外した最近のターン、または[バックグラウンドでのコンパクション](https://platform.claude.com/docs/ja/build-with-claude/compaction-background)のように要約の作成中に届いたターンがこれにあたります。

思考の保持に対応したモデルは、以前の思考ブロックを、それを生成した会話と照合してチェックします。要約はその会話の一部を置き換えますが、APIが要約を作成した場合、チェックはその置き換えを受け入れるため、残したターン内の思考は有効なままでいられます。

## 残した思考が有効なままとなる条件

残したターン内の思考ブロックは、次のすべてが成り立つ間、有効なままとなります。

* **コンパクションリクエストが思考の保持に対応したモデルで実行されること。** この条件は、最新のものだけでなく、思考ブロックが生成されて以降のすべてのコンパクションリクエストに適用されます。これを満たす方法の1つは、すべてのコンパクションリクエストを、会話で使用しているモデルに送信することです。
* **残したターンが要約されたメッセージの直後に続き、それらを変更せずに送信すること。** 残した各メッセージは、履歴にあるとおりそのまま送信してください。最後の要約されたメッセージと最初の残したメッセージの間で、メッセージを省略したり追加したりしないでください。また、最初の残したメッセージは最後の要約されたメッセージとは異なるロールである必要があり、会話途中の `role: "system"` メッセージであってはなりません。そうでない場合、APIはそれを最後の要約されたメッセージにマージします。最初の残したメッセージを正しく設定する方法の1つは、すでに送信したリクエストの `messages` をそのままコンパクションすることです。その場合、残したターンはそのリクエストに対するClaudeの返信から始まります。
* **`system` と、`defer_loading: true` が指定されていない `tools` が変更されないこと。** これらは、コンパクションリクエストと、残した思考を生成したリクエストとで同じであり、その後に続くリクエストでも同じままです。[システムプロンプトまたはツールを変更する](https://platform.claude.com/docs/ja/build-with-claude/compaction-thinking-blocks#change-the-system-prompt-or-tools)では、それらを安全に変更する方法を説明しています。

条件が満たされない場合でも、コンパクション時には何も失敗せず、いずれにしてもAPIは後続のリクエストでブロックを受け入れます。失敗が発生するのは、APIがチェックを適用する状況で残した思考を送信する最初の後続リクエストです。デフォルトでは400エラーとなり、リクエストで `thinking.block_binding.prefix_mismatch_behavior` を `"drop_block"` に設定している場合は思考ブロックが破棄されます。Message Batches APIでは、このフィールドを未設定のままにしたアイテムは失敗しません。チェックがデフォルトで適用される場合、APIは代わりにブロックを破棄します。[無効なブロックに対するAPIの処理](https://platform.claude.com/docs/ja/build-with-claude/preserved-thinking#mismatch-behavior)では両方の結果を説明しており、[APIがチェックを適用する条件](https://platform.claude.com/docs/ja/build-with-claude/preserved-thinking#enforcement)ではどのリクエストがチェックされるかを説明しています。

## 古い思考を壊さずに再度コンパクションする

ターンを残したまま[再度コンパクション](https://platform.claude.com/docs/ja/build-with-claude/compaction-on-demand#compact-again)できます。新しいブロックは、古い要約と、コンパクションリクエスト内でそれに続くすべてのメッセージをカバーし、そのリクエストから除外したターンは新しいブロックの残したターンになります。

[残した思考の条件](https://platform.claude.com/docs/ja/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid)の1つ目は、思考ブロックが生成されて以降のすべてのコンパクションを対象とするため、2回のコンパクションを通じて残したターンでは、両方のコンパクションが思考の保持に対応したモデルで実行されている必要があります。

思考ブロックが生成される前のコンパクションは、その思考ブロックには影響しません。ブロックが配置された後に生成された思考はそのブロックに紐付けられ、条件を満たす後続のコンパクションを通じて有効なままとなります。

## システムプロンプトまたはツールを変更する

後続のリクエストでは、コンパクションリクエストとは異なる `system`、異なる `tools`、または異なるモデルを使用でき、その場合でもAPIはブロックを受け入れます。このような変更は残したターン内の思考を無効にする可能性がありますが、それ以外の影響はありません。

残した思考を無効にせずに `system` または `tools` を変更するには、まず会話全体をコンパクションして、ターンが残らないようにします。その後、次のリクエストでそれらを変更します。

`system` や `tools` に手を加えずに指示を追加したり利用可能なツールを変更したりするには、[プレフィックスを編集せずに変更を加える](https://platform.claude.com/docs/ja/build-with-claude/preserved-thinking#replace-prefix-edits)で説明されているように、変更を `messages` に追加します。

要約されたターン内にある会話途中のシステムメッセージも要約されるため、そのテキストによる指示は置き換え後には適用されなくなります。それらが設定した[メッセージごとのeffort](https://platform.claude.com/docs/ja/build-with-claude/effort#change-effort-mid-conversation-beta)レベルも引き継がれません。後続のメッセージがレベルを設定するまで、ターンはリクエストのトップレベルの `output_config.effort`、または設定していない場合はモデルのデフォルトで実行されます。指示やeffortレベルを有効なままにするには、残したターンに続く最初の新しい `user` ターンの直後に、`role: "system"` メッセージで再度記述してください。それらのターン内のツール変更は、コンパクションリクエストが `inline-tools-2026-09-15` も含んでいる場合、自動的に引き継がれます。返されたブロックはその正味の効果を `tool_changes` フィールドに記録するため、ブロックは変更せずに送り返してください。ブロックに `tool_changes` フィールドがない場合は、同じ方法でそれらのツール変更を再度記述してください。ブロックと残したターンの間に配置されたシステムメッセージは、それらのターンの思考を壊します。

## 残した思考が保持されたことを確認する

コンパクションのレスポンスからは、残した思考が有効かどうかはわかりません。それがわかるのは置き換え後の最初のリクエストです。テストで確認するには、次の手順を実行します。

1. 思考を有効にして短い会話を行います。APIがチェックを実行するモデルを使用し（[APIがチェックを適用する条件](https://platform.claude.com/docs/ja/build-with-claude/preserved-thinking#enforcement)を参照）、すべてのステップでそのモデルを使用してください。思考ブロックを読み取れないモデルは、エラーを出さずにそのブロックを破棄するためです。
2. 古いターンをコンパクションし、思考ブロックを含むターンを少なくとも1つ残します。
3. 次のリクエストを送信します。ブロックを先頭に、次に残したターン、その後に新しい `user` メッセージを配置し、`thinking.block_binding.prefix_mismatch_behavior` を `"error"` に設定します。
4. 結果を確認します。`input_transformations` 配列が空の200レスポンスは、チェックに失敗した思考ブロックや破棄された思考ブロックがなかったことを意味します。ブロックが別の会話に紐付けられていることを示す400エラーは、そのようなブロックがあったことを意味します。メッセージは最初に失敗したブロックのパスから始まり、[無効なブロックに対するAPIの処理](https://platform.claude.com/docs/ja/build-with-claude/preserved-thinking#mismatch-behavior)にその全文が示されています。

`prefix_mismatch_behavior` フィールドには、[`compact-2026-09-04` ベータヘッダー](https://platform.claude.com/docs/ja/build-with-claude/compaction-on-demand#request-a-summary)に加えて `thinking-binding-controls-2026-08-01` ベータヘッダーが必要です。このフィールドを設定すると、チェックがデフォルトで有効になっていないアカウントでも、そのリクエストはチェックの対象になります。

次のプログラムは4つのステップを実行します。残したターンに含まれる思考ブロックの数と、`input_transformations` のエントリ数を出力します。エントリがなければ、残した思考が保持されたことを意味します。

<CodeGroup exclude="shell">
  ```python Python
  from anthropic.types.beta import BetaMessageParam, BetaThinkingConfigParam

  client = anthropic.Anthropic()

  # Claude Fable 5.1 は、送り返された思考を会話と照合する最初のモデルです。
  MODEL = "claude-fable-5-1"
  BETAS = ["compact-2026-09-04", "thinking-binding-controls-2026-08-01"]
  SYSTEM = "You help plan a recipe app's release. Keep answers short."
  # "error" を指定すると、チェックに失敗した思考ブロックによりリクエストが400で失敗します。
  THINKING: BetaThinkingConfigParam = {
      "type": "adaptive",
      "block_binding": {"prefix_mismatch_behavior": "error"},
  }

  # 1. 思考を有効にして短い会話を行います。
  history: list[BetaMessageParam] = [
      {"role": "user", "content": "What are the main entities in the app's data model?"}
  ]
  first = client.beta.messages.create(
      model=MODEL,
      max_tokens=8192,
      system=SYSTEM,
      betas=BETAS,
      thinking=THINKING,
      messages=history,
  )
  history += [
      {"role": "assistant", "content": first.content},
      {
          "role": "user",
          "content": "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?",
      },
  ]
  second = client.beta.messages.create(
      model=MODEL,
      max_tokens=8192,
      system=SYSTEM,
      betas=BETAS,
      thinking=THINKING,
      messages=history,
  )
  history.append({"role": "assistant", "content": second.content})
  thinking_blocks = sum(block.type == "thinking" for block in second.content)
  print(f"Thinking blocks in the kept turn: {thinking_blocks}")

  # 2. 最初のターンを要約します。2番目のターンはリクエストに含めません。
  summary = client.beta.messages.create(
      model=MODEL,
      max_tokens=4096,
      system=SYSTEM,
      betas=BETAS,
      thinking=THINKING,
      messages=history[:2],
      compaction={"type": "summarize"},
  )
  if summary.stop_reason != "compaction":
      raise SystemExit(f"No summary: {summary.stop_reason}")

  # 3. 保持したターンの前にブロックを配置し、次の質問をします。
  history = [
      {"role": "assistant", "content": summary.content},
      *history[2:],
      {"role": "user", "content": "Which day should the release go out?"},
  ]
  third = client.beta.messages.create(
      model=MODEL,
      max_tokens=8192,
      system=SYSTEM,
      betas=BETAS,
      thinking=THINKING,
      messages=history,
  )

  # 4. 破棄されたブロックがなく200が返れば、保持した思考は有効です。
  print(f"Dropped thinking blocks: {len(third.input_transformations)}")
  ```

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

  // Claude Fable 5.1 は、送り返された thinking を会話と照合する最初のモデルです。
  const model: Anthropic.Model = "claude-fable-5-1";
  const betas: Anthropic.Beta.AnthropicBeta[] = [
    "compact-2026-09-04",
    "thinking-binding-controls-2026-08-01"
  ];
  const systemPrompt = "You help plan a recipe app's release. Keep answers short.";
  // "error" を指定すると、チェックに失敗した thinking ブロックによりリクエストが 400 で失敗します。
  const thinking: Anthropic.Beta.Messages.BetaThinkingConfigParam = {
    type: "adaptive",
    block_binding: { prefix_mismatch_behavior: "error" }
  };

  // 1. thinking を有効にして短い会話を行います。
  let history: Anthropic.Beta.Messages.BetaMessageParam[] = [
    { role: "user", content: "What are the main entities in the app's data model?" }
  ];
  const first = await client.beta.messages.create({
    model,
    max_tokens: 8192,
    system: systemPrompt,
    betas,
    thinking,
    messages: history
  });
  history.push(
    { role: "assistant", content: first.content },
    {
      role: "user",
      content:
        "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?"
    }
  );
  const second = await client.beta.messages.create({
    model,
    max_tokens: 8192,
    system: systemPrompt,
    betas,
    thinking,
    messages: history
  });
  history.push({ role: "assistant", content: second.content });
  const thinkingBlocks = second.content.filter((block) => block.type === "thinking").length;
  console.log(`Thinking blocks in the kept turn: ${thinkingBlocks}`);

  // 2. 最初のターンを要約します。2 番目のターンはリクエストに含めません。
  const summary = await client.beta.messages.create({
    model,
    max_tokens: 4096,
    system: systemPrompt,
    betas,
    thinking,
    messages: history.slice(0, 2),
    compaction: { type: "summarize" }
  });
  if (summary.stop_reason !== "compaction") {
    throw new Error(`No summary: ${summary.stop_reason}`);
  }

  // 3. 保持したターンの前にブロックを置き、次の質問をします。
  history = [
    { role: "assistant", content: summary.content },
    ...history.slice(2),
    { role: "user", content: "Which day should the release go out?" }
  ];
  const third = await client.beta.messages.create({
    model,
    max_tokens: 8192,
    system: systemPrompt,
    betas,
    thinking,
    messages: history
  });

  // 4. ブロックが破棄されずに 200 が返れば、保持した thinking は有効です。
  console.log(`Dropped thinking blocks: ${third.input_transformations?.length ?? 0}`);
  ```

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

  AnthropicClient client = new();

  // Claude Fable 5.1 は、送り返された thinking を会話と照合して検証する最初のモデルです。
  const Model ModelId = Model.ClaudeFable5_1;
  AnthropicBeta[] betas = [AnthropicBeta.Compact2026_09_04, AnthropicBeta.ThinkingBindingControls2026_08_01];
  const string SystemPrompt = "You help plan a recipe app's release. Keep answers short.";
  // "error" を指定すると、検証に失敗した thinking ブロックによりリクエストが 400 で失敗します。
  BetaThinkingConfigAdaptive thinking = new()
  {
      BlockBinding = new() { PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.Error },
  };

  // 1. thinking を有効にして短い会話を行います。
  List<BetaMessageParam> history =
  [
      new() { Role = Role.User, Content = "What are the main entities in the app's data model?" },
  ];
  var first = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = ModelId,
      MaxTokens = 8192,
      System = SystemPrompt,
      Betas = [.. betas],
      Thinking = thinking,
      Messages = history,
  });
  history.AddRange(
  [
      new()
      {
          Role = Role.Assistant,
          Content = first.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
      },
      new()
      {
          Role = Role.User,
          Content = "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?",
      },
  ]);
  var second = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = ModelId,
      MaxTokens = 8192,
      System = SystemPrompt,
      Betas = [.. betas],
      Thinking = thinking,
      Messages = history,
  });
  history.Add(new()
  {
      Role = Role.Assistant,
      Content = second.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
  });
  var thinkingBlocks = second.Content.Count(block => block.TryPickThinking(out _));
  Console.WriteLine($"Thinking blocks in the kept turn: {thinkingBlocks}");

  // 2. 最初のターンを要約します。2 番目のターンはリクエストに含めません。
  var summary = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = ModelId,
      MaxTokens = 4096,
      System = SystemPrompt,
      Betas = [.. betas],
      Thinking = thinking,
      Messages = history[..2],
      Compaction = new BetaCompactionConfig(), // type defaults to "summarize"
  });
  if (summary.StopReason != BetaStopReason.Compaction)
  {
      throw new InvalidOperationException($"No summary: {summary.StopReason?.Raw()}");
  }

  // 3. 保持したターンの前にブロックを配置し、次の質問をします。
  history =
  [
      new()
      {
          Role = Role.Assistant,
          Content = summary.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
      },
      .. history[2..],
      new() { Role = Role.User, Content = "Which day should the release go out?" },
  ];
  var third = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = ModelId,
      MaxTokens = 8192,
      System = SystemPrompt,
      Betas = [.. betas],
      Thinking = thinking,
      Messages = history,
  });

  // 4. ドロップされたブロックがなく 200 が返れば、保持した thinking は有効です。
  Console.WriteLine($"Dropped thinking blocks: {third.InputTransformations?.Count ?? 0}");
  ```

  ```go Go
  ctx := context.Background()
  client := anthropic.NewClient()

  // Claude Fable 5.1 は、送り返された thinking を会話と照合する最初のモデルです。
  const model = anthropic.ModelClaudeFable5_1
  betas := []anthropic.AnthropicBeta{
  	anthropic.AnthropicBetaCompact2026_09_04,
  	anthropic.AnthropicBetaThinkingBindingControls2026_08_01,
  }
  system := []anthropic.BetaTextBlockParam{{Text: "You help plan a recipe app's release. Keep answers short."}}
  // "error" を指定すると、チェックに失敗した thinking ブロックによりリクエストが 400 で失敗します。
  thinking := anthropic.BetaThinkingConfigParamUnion{
  	OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  		BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  			PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorError,
  		},
  	},
  }

  // 1. thinking を有効にして短い会話を行います。
  history := []anthropic.BetaMessageParam{
  	anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What are the main entities in the app's data model?")),
  }
  first, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:     model,
  	MaxTokens: 8192,
  	System:    system,
  	Betas:     betas,
  	Thinking:  thinking,
  	Messages:  history,
  })
  if err != nil {
  	log.Fatal(err)
  }
  history = append(history,
  	first.ToParam(),
  	anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?")),
  )
  second, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:     model,
  	MaxTokens: 8192,
  	System:    system,
  	Betas:     betas,
  	Thinking:  thinking,
  	Messages:  history,
  })
  if err != nil {
  	log.Fatal(err)
  }
  history = append(history, second.ToParam())
  thinkingBlocks := 0
  for _, block := range second.Content {
  	if _, ok := block.AsAny().(anthropic.BetaThinkingBlock); ok {
  		thinkingBlocks++
  	}
  }
  fmt.Printf("Thinking blocks in the kept turn: %d\n", thinkingBlocks)

  // 2. 最初のターンを要約します。2 番目のターンはリクエストに含めません。
  summary, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:     model,
  	MaxTokens: 4096,
  	System:    system,
  	Betas:     betas,
  	Thinking:  thinking,
  	Messages:  history[:2],
  	Compaction: anthropic.BetaCompactionConfigUnionParam{
  		OfSummarize: &anthropic.BetaSummarizeCompactionParam{},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  if summary.StopReason != anthropic.BetaStopReasonCompaction {
  	log.Fatalf("No summary: %s", summary.StopReason)
  }

  // 3. 保持したターンの前にブロックを置き、次の質問をします。
  history = slices.Concat(
  	[]anthropic.BetaMessageParam{summary.ToParam()},
  	history[2:],
  	[]anthropic.BetaMessageParam{anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Which day should the release go out?"))},
  )
  third, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:     model,
  	MaxTokens: 8192,
  	System:    system,
  	Betas:     betas,
  	Thinking:  thinking,
  	Messages:  history,
  })
  if err != nil {
  	log.Fatal(err)
  }

  // 4. ブロックが破棄されずに 200 が返れば、保持した thinking は有効です。
  fmt.Printf("Dropped thinking blocks: %d\n", len(third.InputTransformations))
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaCompactionConfig;
  import com.anthropic.models.beta.messages.BetaContentBlock;
  import com.anthropic.models.beta.messages.BetaMessageParam;
  import com.anthropic.models.beta.messages.BetaStopReason;
  import com.anthropic.models.beta.messages.BetaThinkingBlockBinding;
  import com.anthropic.models.beta.messages.BetaThinkingConfigAdaptive;
  import com.anthropic.models.beta.messages.BetaThinkingPrefixMismatchBehavior;
  import com.anthropic.models.beta.messages.MessageCreateParams;

  // Claude Fable 5.1 は、送り返された思考内容を会話と照合して検証する最初のモデルです。
  static final Model MODEL = Model.CLAUDE_FABLE_5_1;
  static final List<AnthropicBeta> BETAS = List.of(
      AnthropicBeta.COMPACT_2026_09_04,
      AnthropicBeta.THINKING_BINDING_CONTROLS_2026_08_01
  );
  static final String SYSTEM = "You help plan a recipe app's release. Keep answers short.";
  // "error" を指定すると、検証に失敗した thinking ブロックがあるリクエストは 400 で失敗します。
  static final BetaThinkingConfigAdaptive THINKING = BetaThinkingConfigAdaptive.builder()
      .blockBinding(BetaThinkingBlockBinding.builder()
          .prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.ERROR)
          .build())
      .build();

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

      // 1. 思考を有効にして短い会話を行います。
      var history = new ArrayList<BetaMessageParam>();
      history.add(BetaMessageParam.builder()
          .role(BetaMessageParam.Role.USER)
          .content("What are the main entities in the app's data model?")
          .build());
      var firstParams = MessageCreateParams.builder()
          .model(MODEL)
          .maxTokens(8192)
          .system(SYSTEM)
          .betas(BETAS)
          .thinking(THINKING)
          .messages(history)
          .build();
      var first = client.beta().messages().create(firstParams);
      history.add(first.toParam());
      history.add(BetaMessageParam.builder()
          .role(BetaMessageParam.Role.USER)
          .content("Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?")
          .build());
      var secondParams = MessageCreateParams.builder()
          .model(MODEL)
          .maxTokens(8192)
          .system(SYSTEM)
          .betas(BETAS)
          .thinking(THINKING)
          .messages(history)
          .build();
      var second = client.beta().messages().create(secondParams);
      history.add(second.toParam());
      long thinkingBlocks = second.content().stream().filter(BetaContentBlock::isThinking).count();
      IO.println("Thinking blocks in the kept turn: " + thinkingBlocks);

      // 2. 最初のターンを要約します。2 番目のターンはリクエストに含めません。
      var firstTurn = history.subList(0, 2);
      var summaryParams = MessageCreateParams.builder()
          .model(MODEL)
          .maxTokens(4096)
          .system(SYSTEM)
          .betas(BETAS)
          .thinking(THINKING)
          .messages(firstTurn)
          .compaction(BetaCompactionConfig.builder().build()) // type defaults to "summarize"
          .build();
      var summary = client.beta().messages().create(summaryParams);
      if (!summary.stopReason().map(BetaStopReason.COMPACTION::equals).orElse(false)) {
          throw new IllegalStateException("No summary: " + summary.stopReason().orElseThrow());
      }

      // 3. 保持したターンの前にブロックを置き、次の質問をします。
      firstTurn.clear();
      history.addFirst(summary.toParam());
      history.add(BetaMessageParam.builder()
          .role(BetaMessageParam.Role.USER)
          .content("Which day should the release go out?")
          .build());
      var thirdParams = MessageCreateParams.builder()
          .model(MODEL)
          .maxTokens(8192)
          .system(SYSTEM)
          .betas(BETAS)
          .thinking(THINKING)
          .messages(history)
          .build();
      var third = client.beta().messages().create(thirdParams);

      // 4. ブロックが破棄されずに 200 が返れば、保持した思考は有効です。
      IO.println("Dropped thinking blocks: " + third.inputTransformations().map(List::size).orElse(0));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaCompactionConfig;
  use Anthropic\Beta\Messages\BetaMessageParam;
  use Anthropic\Beta\Messages\BetaMessageParam\Role;
  use Anthropic\Beta\Messages\BetaStopReason;
  use Anthropic\Beta\Messages\BetaThinkingBlock;
  use Anthropic\Beta\Messages\BetaThinkingBlockBinding;
  use Anthropic\Beta\Messages\BetaThinkingConfigAdaptive;
  use Anthropic\Beta\Messages\BetaThinkingPrefixMismatchBehavior;

  $client = new Client();

  // Claude Fable 5.1 は、送り返された thinking を会話と照合する最初のモデルです。
  const MODEL = Model::CLAUDE_FABLE_5_1;
  const BETAS = [AnthropicBeta::COMPACT_2026_09_04, AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01];
  const SYSTEM = "You help plan a recipe app's release. Keep answers short.";
  // "error" を指定すると、チェックに失敗した thinking ブロックがある場合、リクエストは 400 で失敗します。
  $thinking = BetaThinkingConfigAdaptive::with(
      blockBinding: BetaThinkingBlockBinding::with(
          prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::ERROR,
      ),
  );

  // 1. thinking を有効にして短い会話を行います。
  $history = [
      BetaMessageParam::with(role: Role::USER, content: "What are the main entities in the app's data model?"),
  ];
  $first = $client->beta->messages->create(
      model: MODEL,
      maxTokens: 8192,
      system: SYSTEM,
      betas: BETAS,
      thinking: $thinking,
      messages: $history,
  );
  $history[] = BetaMessageParam::with(role: Role::ASSISTANT, content: $first->content);
  $history[] = BetaMessageParam::with(
      role: Role::USER,
      content: 'Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?',
  );
  $second = $client->beta->messages->create(
      model: MODEL,
      maxTokens: 8192,
      system: SYSTEM,
      betas: BETAS,
      thinking: $thinking,
      messages: $history,
  );
  $history[] = BetaMessageParam::with(role: Role::ASSISTANT, content: $second->content);
  $thinkingBlocks = count(array_filter($second->content, fn ($block) => $block instanceof BetaThinkingBlock));
  printf("Thinking blocks in the kept turn: %d\n", $thinkingBlocks);

  // 2. 最初のターンを要約します。2 番目のターンはリクエストに含めません。
  $summary = $client->beta->messages->create(
      model: MODEL,
      maxTokens: 4096,
      system: SYSTEM,
      betas: BETAS,
      thinking: $thinking,
      messages: array_slice($history, 0, 2),
      compaction: new BetaCompactionConfig(), // type defaults to 'summarize'
  );
  if ($summary->stopReason !== BetaStopReason::COMPACTION->value) {
      throw new \RuntimeException("No summary: {$summary->stopReason}");
  }

  // 3. 保持したターンの前にブロックを配置し、次の質問をします。
  $history = [
      BetaMessageParam::with(role: Role::ASSISTANT, content: $summary->content),
      ...array_slice($history, 2),
      BetaMessageParam::with(role: Role::USER, content: 'Which day should the release go out?'),
  ];
  $third = $client->beta->messages->create(
      model: MODEL,
      maxTokens: 8192,
      system: SYSTEM,
      betas: BETAS,
      thinking: $thinking,
      messages: $history,
  );

  // 4. 破棄されたブロックがなく 200 が返れば、保持した thinking は受け入れられています。
  printf("Dropped thinking blocks: %d\n", count($third->inputTransformations));
  ```

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

  # Claude Fable 5.1 は、送り返された思考を会話と照合する最初のモデルです。
  MODEL = Anthropic::Model::CLAUDE_FABLE_5_1
  BETAS = [
    Anthropic::AnthropicBeta::COMPACT_2026_09_04,
    Anthropic::AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01
  ]
  SYSTEM = "You help plan a recipe app's release. Keep answers short."
  # "error" を指定すると、チェックに失敗した思考ブロックがあるとリクエストは 400 で失敗します。
  THINKING = Anthropic::Beta::BetaThinkingConfigAdaptive.new(
    block_binding: Anthropic::Beta::BetaThinkingBlockBinding.new(
      prefix_mismatch_behavior: Anthropic::Beta::BetaThinkingPrefixMismatchBehavior::ERROR
    )
  )

  # 1. 思考を有効にして短い会話を行います。
  history = [{ role: "user", content: "What are the main entities in the app's data model?" }]
  first = client.beta.messages.create(
    model: MODEL,
    max_tokens: 8192,
    system_: SYSTEM,
    betas: BETAS,
    thinking: THINKING,
    messages: history
  )
  history += [
    { role: "assistant", content: first.content },
    {
      role: "user",
      content: "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?"
    }
  ]
  second = client.beta.messages.create(
    model: MODEL,
    max_tokens: 8192,
    system_: SYSTEM,
    betas: BETAS,
    thinking: THINKING,
    messages: history
  )
  history << { role: "assistant", content: second.content }
  thinking_blocks = second.content.count { it.is_a?(Anthropic::Beta::BetaThinkingBlock) }
  puts "Thinking blocks in the kept turn: #{thinking_blocks}"

  # 2. 最初のターンを要約します。2 番目のターンはリクエストに含めません。
  summary = client.beta.messages.create(
    model: MODEL,
    max_tokens: 4096,
    system_: SYSTEM,
    betas: BETAS,
    thinking: THINKING,
    messages: history.first(2),
    compaction: { type: "summarize" }
  )
  abort "No summary: #{summary.stop_reason}" unless summary.stop_reason == :compaction

  # 3. 保持したターンの前にブロックを配置し、次の質問をします。
  history = [
    { role: "assistant", content: summary.content },
    *history.drop(2),
    { role: "user", content: "Which day should the release go out?" }
  ]
  third = client.beta.messages.create(
    model: MODEL,
    max_tokens: 8192,
    system_: SYSTEM,
    betas: BETAS,
    thinking: THINKING,
    messages: history
  )

  # 4. 破棄されたブロックがなく 200 が返れば、保持した思考は有効です。
  puts "Dropped thinking blocks: #{third.input_transformations.length}"
  ```
</CodeGroup>

```text Output wrap
Thinking blocks in the kept turn: 1
Dropped thinking blocks: 0
```

本番環境では、`"drop_block"` を使用すると、条件が成り立たない場合でもリクエストが成功し続け、破棄された各ブロックが `reason: "prefix_binding_mismatch"` とともに `input_transformations` に報告されます。`path` が残したターン内にあるエントリは、そのターンの思考が有効でなかったことを意味します。[無効なブロックに対するAPIの処理](https://platform.claude.com/docs/ja/build-with-claude/preserved-thinking#mismatch-behavior)では、何が破棄されるかと、それに対してアラートを出す方法を説明しています。Claude Sonnet 5.5およびClaude Haiku 5.5では、`block_binding` は `thinking: {"type": "adaptive"}` でのみ機能します。Claude Sonnet 5.5で `thinking: {"type": "between_tools"}` とともに、またはClaude Haiku 5.5で `thinking: {"type": "disabled"}` とともにこれを設定したリクエストは、400エラーを返します。それらのリクエストでは、すべての条件が成り立つようにするか、残したターンから `thinking` ブロックと `redacted_thinking` ブロックを削除してください。
