---
title: 壓縮與保留思考
url: https://platform.claude.com/docs/zh-TW/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
---

除非您會將「thinking block」（思考區塊）傳回給具有[「preserved thinking」（保留思考）](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking)的模型，並在「compaction block」（壓縮區塊）之後保留輪次，否則您可以略過本頁。「Kept turns」（保留的輪次）是指緊接在該區塊之後的輪次：您未納入壓縮請求的最近輪次，如[保留最近輪次的壓縮](https://platform.claude.com/docs/zh-TW/build-with-claude/compaction-keep-recent-turns)所述；或是在撰寫摘要期間送達的輪次，如[在背景中進行壓縮](https://platform.claude.com/docs/zh-TW/build-with-claude/compaction-background)所述。

具有保留思考的模型會將先前的思考區塊與產生它們的對話進行比對檢查。摘要會取代該對話的一部分，但當摘要是由 API 撰寫時，檢查會接受這項替換，因此保留輪次中的思考可以維持有效。

## 保留的思考維持有效的條件

保留輪次中的思考區塊在以下所有條件都成立時維持有效：

* **壓縮請求在具有保留思考的模型上執行。** 此條件涵蓋自思考區塊產生以來的每一個壓縮請求，而不僅是最近的一個。滿足此條件的一種方式，是將每個壓縮請求都傳送給對話所使用的模型。
* **保留的輪次直接接在被摘要的訊息之後，且您原封不動地傳送它們。** 請完全依照歷史記錄中的樣子傳送每則保留的訊息。不要在最後一則被摘要的訊息與第一則保留的訊息之間略過或新增任何訊息。第一則保留的訊息也必須與最後一則被摘要的訊息具有不同的角色，且不能是對話中途的 `role: "system"` 訊息。否則，API 會將其合併到最後一則被摘要的訊息中。讓第一則保留訊息正確的一種方式，是精確地壓縮您已傳送過的某個請求的 `messages`。如此一來，保留的輪次便會從 Claude 對該請求的回覆開始。
* **`system` 以及未標記 `defer_loading: true` 的 `tools` 不變。** 它們在壓縮請求上與在產生保留思考的請求上相同，並在後續的請求中保持相同。[變更系統提示或工具](https://platform.claude.com/docs/zh-TW/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/zh-TW/build-with-claude/preserved-thinking#mismatch-behavior)說明這兩種結果，而[API 何時強制執行檢查](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking#enforcement)則說明哪些請求會受到檢查。

## 再次壓縮而不破壞較舊的思考

您可以[再次壓縮](https://platform.claude.com/docs/zh-TW/build-with-claude/compaction-on-demand#compact-again)並保留輪次：新區塊涵蓋舊摘要以及壓縮請求中其後的每則訊息，而您未納入該請求的任何輪次，都是新區塊的保留輪次。

[保留的思考維持有效的條件](https://platform.claude.com/docs/zh-TW/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid)中的第一項會計入自思考區塊產生以來的每一次壓縮，因此您在兩次壓縮中都保留的輪次，需要這兩次壓縮都在具有保留思考的模型上執行。

在思考區塊產生之前進行的壓縮不會對其造成影響。在區塊就位後產生的思考會綁定到該區塊，並在符合條件的後續壓縮中維持有效。

## 變更系統提示或工具

後續請求可以使用與壓縮請求不同的 `system`、不同的 `tools` 或不同的模型，API 仍會接受該區塊。這類變更可能會使保留輪次中的思考失效，但不會有其他影響。

若要變更 `system` 或 `tools` 而不使任何保留的思考失效，請先壓縮整個對話，使沒有任何輪次被保留。然後在下一個請求中變更它們。

若要新增指示或變更可用的工具而不動到 `system` 或 `tools`，請將變更附加到 `messages`，如[在不編輯前綴的情況下進行變更](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking#replace-prefix-edits)所述。

被摘要輪次中的對話中途系統訊息也會被摘要，因此其文字指示在替換後便不再適用。它們所設定的[逐訊息 effort](https://platform.claude.com/docs/zh-TW/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/zh-TW/build-with-claude/preserved-thinking#enforcement)），並在每個步驟都使用該模型，因為無法讀取思考區塊的模型會在不產生錯誤的情況下捨棄它。
2. 壓縮較舊的輪次，並保留至少一個包含思考區塊的輪次。
3. 傳送下一個請求，依序放入區塊、保留的輪次，然後是新的 `user` 訊息，並將 `thinking.block_binding.prefix_mismatch_behavior` 設為 `"error"`。
4. 讀取結果。`input_transformations` 陣列為空的 200 回應，表示沒有任何思考區塊未通過檢查或被捨棄。指出區塊綁定到不同對話的 400 錯誤，則表示有區塊未通過。錯誤訊息的開頭是第一個未通過檢查之區塊的路徑，[API 如何處理失效的區塊](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking#mismatch-behavior)會完整顯示該訊息。

`prefix_mismatch_behavior` 欄位除了需要[`compact-2026-09-04`「beta header」（beta 標頭）](https://platform.claude.com/docs/zh-TW/build-with-claude/compaction-on-demand#request-a-summary)之外，還需要 `thinking-binding-controls-2026-08-01` beta 標頭。在預設未開啟檢查的帳戶上，設定此欄位也會讓請求選擇加入檢查。

以下程式會執行這四個步驟。它會印出保留的輪次包含多少個思考區塊，以及 `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. 摘要第一輪對話。第二輪對話不納入請求中。
  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 是第一個會將回傳的思考內容與對話進行比對檢查的模型。
  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" 時，未通過檢查的思考區塊會使請求失敗並回傳 400。
  const thinking: Anthropic.Beta.Messages.BetaThinkingConfigParam = {
    type: "adaptive",
    block_binding: { prefix_mismatch_behavior: "error" }
  };

  // 1. 在啟用思考的情況下進行一段簡短對話。
  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. 摘要第一輪對話。第二輪對話不納入請求中。
  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 且沒有被捨棄的區塊，表示保留的思考內容有效。
  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 是第一個會將回傳的思考內容與對話進行比對檢查的模型。
  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" 時，未通過檢查的思考區塊會使請求失敗並回傳 400。
  BetaThinkingConfigAdaptive thinking = new()
  {
      BlockBinding = new() { PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.Error },
  };

  // 1. 在啟用思考的情況下進行一段簡短對話。
  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. 摘要第一輪對話。第二輪對話不納入請求中。
  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 且沒有被捨棄的區塊，表示保留的思考內容通過檢查。
  Console.WriteLine($"Dropped thinking blocks: {third.InputTransformations?.Count ?? 0}");
  ```

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

  // Claude Fable 5.1 是第一個會將回傳的思考內容與對話進行比對檢查的模型。
  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" 時，未通過檢查的思考區塊會使請求失敗並回傳 400。
  thinking := anthropic.BetaThinkingConfigParamUnion{
  	OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  		BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  			PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorError,
  		},
  	},
  }

  // 1. 在啟用思考的情況下進行一段簡短對話。
  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. 摘要第一輪對話。第二輪對話不納入請求中。
  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 且沒有被捨棄的區塊，表示保留的思考內容有效。
  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" 時，未通過檢查的思考區塊會使請求失敗並回傳 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. 摘要第一輪對話。第二輪對話不納入請求中。
      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 是第一個會將回傳的思考內容與對話進行比對檢查的模型。
  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" 時，未通過檢查的思考區塊會使請求失敗並回傳 400。
  $thinking = BetaThinkingConfigAdaptive::with(
      blockBinding: BetaThinkingBlockBinding::with(
          prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::ERROR,
      ),
  );

  // 1. 在啟用思考的情況下進行一段簡短對話。
  $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. 摘要第一輪對話。第二輪對話不納入請求中。
  $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 且沒有區塊被捨棄，表示保留的思考內容有效。
  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. 摘要第一輪對話。第二輪對話不納入請求中。
  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"` 可在條件不成立時讓請求持續成功，並在 `input_transformations` 中以 `reason: "prefix_binding_mismatch"` 回報每個被捨棄的區塊。若某個項目的 `path` 落在保留的輪次中，表示該輪次的思考未能成立。[API 如何處理失效的區塊](https://platform.claude.com/docs/zh-TW/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` 區塊。
