---
title: Compactação e pensamento preservado
url: https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-thinking-blocks
description: Quando os blocos de pensamento em turnos mantidos após a compactação sob demanda permanecem válidos em modelos com pensamento preservado, e como verificar.
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
---

Ignore esta página, a menos que você envie "thinking blocks" (blocos de pensamento) de volta a um modelo com ["preserved thinking" (pensamento preservado)](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking) e mantenha turnos após o bloco de "compaction" (compactação). "Kept turns" (turnos mantidos) são os turnos que seguem o bloco: turnos recentes que você deixou de fora da solicitação de compactação, como em [Compactação que mantém turnos recentes](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-keep-recent-turns), ou turnos que chegaram enquanto o resumo estava sendo escrito, como em [Compactação em segundo plano](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-background).

Modelos com pensamento preservado verificam blocos de pensamento anteriores em relação à conversa que os produziu. Um resumo substitui parte dessa conversa, mas a verificação aceita a substituição quando a API escreveu o resumo, de modo que o pensamento nos turnos mantidos pode permanecer válido.

## Condições para que o pensamento mantido permaneça válido

Os blocos de pensamento nos turnos mantidos permanecem válidos enquanto todas estas condições forem atendidas:

* **A solicitação de compactação é executada em um modelo com pensamento preservado.** Esta condição abrange todas as solicitações de compactação desde que um bloco de pensamento foi produzido, não apenas a mais recente. Uma maneira de atendê-la é enviar todas as solicitações de compactação para o modelo que a conversa usa.
* **Os turnos mantidos seguem diretamente as mensagens resumidas, e você os envia sem alterações.** Envie cada mensagem mantida exatamente como está no seu histórico. Não pule nem adicione uma mensagem entre a última mensagem resumida e a primeira mantida. A primeira mensagem mantida também deve ter um papel (role) diferente da última mensagem resumida, e não pode ser uma mensagem `role: "system"` no meio da conversa. Caso contrário, a API a mescla na última mensagem resumida. Uma maneira de acertar a primeira mensagem mantida é compactar exatamente as `messages` de uma solicitação que você já enviou. Os turnos mantidos então começam com a resposta de Claude a ela.
* **`system` e as `tools` não marcadas com `defer_loading: true` não mudam.** Eles são os mesmos na solicitação de compactação e nas solicitações que produziram o pensamento mantido, e permanecem os mesmos nas solicitações seguintes. [Alterar o prompt do sistema ou as ferramentas](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-thinking-blocks#change-the-system-prompt-or-tools) explica como alterá-los com segurança.

Se uma condição não for atendida, nada falha quando você compacta, e a API aceita o bloco em solicitações posteriores de qualquer forma. A falha ocorre na primeira solicitação posterior que envia o pensamento mantido onde a API aplica a verificação: um erro 400 por padrão, ou blocos de pensamento descartados se a solicitação definir `thinking.block_binding.prefix_mismatch_behavior` como `"drop_block"`. Na Message Batches API, um item que deixa o campo sem definição não falha. Onde a verificação se aplica por padrão, a API descarta os blocos em vez disso. [O que a API faz com um bloco inválido](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking#mismatch-behavior) descreve ambos os resultados, e [Quando a API aplica a verificação](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking#enforcement) indica quais solicitações são verificadas.

## Compactar novamente sem quebrar pensamentos mais antigos

Você pode [compactar novamente](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#compact-again) e manter turnos: o novo bloco abrange o resumo antigo e todas as mensagens que o seguem na solicitação de compactação, e quaisquer turnos que você deixar de fora dessa solicitação são turnos mantidos do novo bloco.

A primeira das [condições para o pensamento mantido](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) conta todas as compactações desde que um bloco de pensamento foi produzido, então um turno que você mantém ao longo de duas compactações exige que ambas tenham sido executadas em um modelo com pensamento preservado.

Compactações anteriores à produção de um bloco de pensamento não contam contra ele. O pensamento produzido depois que um bloco está em vigor fica vinculado a esse bloco e permanece válido em compactações posteriores que atendam às condições.

## Alterar o prompt do sistema ou as ferramentas

Uma solicitação posterior pode usar um `system` diferente, `tools` diferentes ou um modelo diferente da solicitação de compactação, e a API ainda aceita o bloco. Essa alteração pode invalidar o pensamento nos turnos mantidos, mas não tem nenhum outro efeito.

Para alterar `system` ou `tools` sem invalidar nenhum pensamento mantido, compacte primeiro a conversa inteira, para que nenhum turno seja mantido. Em seguida, altere-os na próxima solicitação.

Para adicionar uma instrução ou alterar as ferramentas disponíveis sem mexer em `system` ou `tools`, anexe a alteração a `messages`, conforme descrito em [Fazer mudanças sem editar o prefixo](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking#replace-prefix-edits).

Mensagens de sistema no meio da conversa dentro dos turnos resumidos também são resumidas, então suas instruções de texto deixam de se aplicar após a substituição. Um nível de [esforço por mensagem](https://platform.claude.com/docs/pt-BR/build-with-claude/effort#change-effort-mid-conversation-beta) que elas definem também não é transferido: até que uma mensagem posterior defina um nível, os turnos são executados com o `output_config.effort` de nível superior da solicitação, ou com o padrão do modelo se você não definir um. Para manter uma instrução ou nível de esforço em vigor, declare-o novamente em uma mensagem `role: "system"` diretamente após o primeiro novo turno `user` que segue os turnos mantidos. Alterações de ferramentas dentro desses turnos são transferidas automaticamente quando a solicitação de compactação também inclui `inline-tools-2026-09-15`: o bloco retornado registra o efeito líquido delas em seu campo `tool_changes`, então envie o bloco de volta sem modificações. Se o bloco não tiver um campo `tool_changes`, declare novamente essas alterações de ferramentas da mesma forma. Uma mensagem de sistema colocada entre o bloco e os turnos mantidos quebra o pensamento deles.

## Verificar se o pensamento mantido continuou válido

A resposta da compactação não informa se o pensamento mantido continua válido. A primeira solicitação após a substituição informa. Para verificar em seus testes:

1. Tenha uma conversa curta com o pensamento ativado. Use um modelo no qual a API executa a verificação (consulte [Quando a API aplica a verificação](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking#enforcement)) e use-o em todas as etapas, porque um modelo que não consegue ler um bloco de pensamento o descarta sem erro.
2. Compacte os turnos mais antigos e mantenha pelo menos um turno que contenha um bloco de pensamento.
3. Envie a próxima solicitação, com o bloco primeiro, depois o turno mantido, depois uma nova mensagem `user`, e com `thinking.block_binding.prefix_mismatch_behavior` definido como `"error"`.
4. Leia o resultado. Uma resposta 200 cujo array `input_transformations` está vazio significa que nenhum bloco de pensamento falhou na verificação ou foi descartado. Um erro 400 que diz que o bloco está vinculado a uma conversa diferente significa que algum falhou. A mensagem começa com o caminho do primeiro bloco que falhou, e [O que a API faz com um bloco inválido](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking#mismatch-behavior) a mostra por completo.

O campo `prefix_mismatch_behavior` precisa do cabeçalho beta `thinking-binding-controls-2026-08-01` além do [cabeçalho beta `compact-2026-09-04`](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#request-a-summary). Definir o campo também inclui a solicitação na verificação em contas onde a verificação não está ativada por padrão.

O programa a seguir executa as quatro etapas. Ele imprime quantos blocos de pensamento o turno mantido contém e quantas entradas `input_transformations` tem; nenhuma entrada significa que o pensamento mantido continuou válido:

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

  client = anthropic.Anthropic()

  # Claude Fable 5.1 é o primeiro modelo que verifica o thinking reenviado em relação à conversa.
  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."
  # Com "error", um bloco de thinking que falha na verificação faz a requisição falhar com um 400.
  THINKING: BetaThinkingConfigParam = {
      "type": "adaptive",
      "block_binding": {"prefix_mismatch_behavior": "error"},
  }

  # 1. Tenha uma conversa curta com o thinking ativado.
  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. Resuma o primeiro turno. O segundo turno fica fora da requisição.
  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. Coloque o bloco antes do turno mantido e faça a próxima pergunta.
  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. Um 200 sem blocos descartados significa que o thinking mantido foi aceito.
  print(f"Dropped thinking blocks: {len(third.input_transformations)}")
  ```

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

  // Claude Fable 5.1 é o primeiro modelo que verifica o thinking reenviado em relação à conversa.
  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.";
  // Com "error", um bloco de thinking que falha na verificação faz a requisição falhar com um 400.
  const thinking: Anthropic.Beta.Messages.BetaThinkingConfigParam = {
    type: "adaptive",
    block_binding: { prefix_mismatch_behavior: "error" }
  };

  // 1. Tenha uma conversa curta com o thinking ativado.
  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. Resuma o primeiro turno. O segundo turno fica fora da requisição.
  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. Coloque o bloco antes do turno mantido e faça a próxima pergunta.
  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. Um 200 sem blocos descartados significa que o thinking mantido foi aceito.
  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 é o primeiro modelo que verifica o thinking reenviado em relação à conversa.
  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.";
  // Com "error", um bloco de thinking que falha na verificação faz a requisição falhar com um 400.
  BetaThinkingConfigAdaptive thinking = new()
  {
      BlockBinding = new() { PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.Error },
  };

  // 1. Tenha uma conversa curta com o thinking ativado.
  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. Resuma o primeiro turno. O segundo turno fica fora da requisição.
  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. Coloque o bloco antes do turno mantido e faça a próxima pergunta.
  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. Um 200 sem blocos descartados significa que o thinking mantido foi aceito.
  Console.WriteLine($"Dropped thinking blocks: {third.InputTransformations?.Count ?? 0}");
  ```

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

  // Claude Fable 5.1 é o primeiro modelo que verifica o thinking reenviado em relação à conversa.
  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."}}
  // Com "error", um bloco de thinking que falha na verificação faz a requisição falhar com um 400.
  thinking := anthropic.BetaThinkingConfigParamUnion{
  	OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  		BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  			PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorError,
  		},
  	},
  }

  // 1. Tenha uma conversa curta com o thinking ativado.
  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. Resuma o primeiro turno. O segundo turno fica fora da requisição.
  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. Coloque o bloco antes do turno mantido e faça a próxima pergunta.
  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. Um 200 sem blocos descartados significa que o thinking mantido foi aceito.
  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 é o primeiro modelo que verifica o thinking reenviado em relação à conversa.
  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.";
  // Com "error", um bloco de thinking que falha na verificação faz a requisição falhar com um 400.
  static final BetaThinkingConfigAdaptive THINKING = BetaThinkingConfigAdaptive.builder()
      .blockBinding(BetaThinkingBlockBinding.builder()
          .prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.ERROR)
          .build())
      .build();

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

      // 1. Tenha uma conversa curta com o thinking ativado.
      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. Resuma o primeiro turno. O segundo turno fica fora da requisição.
      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. Coloque o bloco antes do turno mantido e faça a próxima pergunta.
      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. Um 200 sem blocos descartados significa que o thinking mantido foi aceito.
      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 é o primeiro modelo que verifica o thinking reenviado em relação à conversa.
  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.";
  // Com "error", um bloco de thinking que falha na verificação faz a requisição falhar com um 400.
  $thinking = BetaThinkingConfigAdaptive::with(
      blockBinding: BetaThinkingBlockBinding::with(
          prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::ERROR,
      ),
  );

  // 1. Tenha uma conversa curta com o thinking ativado.
  $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. Resuma o primeiro turno. O segundo turno fica fora da requisição.
  $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. Coloque o bloco antes do turno mantido e faça a próxima pergunta.
  $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. Um 200 sem blocos descartados significa que o thinking mantido foi aceito.
  printf("Dropped thinking blocks: %d\n", count($third->inputTransformations));
  ```

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

  # Claude Fable 5.1 é o primeiro modelo que verifica o thinking reenviado em relação à conversa.
  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."
  # Com "error", um bloco de thinking que falha na verificação faz a requisição falhar com um 400.
  THINKING = Anthropic::Beta::BetaThinkingConfigAdaptive.new(
    block_binding: Anthropic::Beta::BetaThinkingBlockBinding.new(
      prefix_mismatch_behavior: Anthropic::Beta::BetaThinkingPrefixMismatchBehavior::ERROR
    )
  )

  # 1. Tenha uma conversa curta com o thinking ativado.
  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. Resuma o primeiro turno. O segundo turno fica fora da requisição.
  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. Coloque o bloco antes do turno mantido e faça a próxima pergunta.
  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. Um 200 sem blocos descartados significa que o thinking mantido foi aceito.
  puts "Dropped thinking blocks: #{third.input_transformations.length}"
  ```
</CodeGroup>

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

Em produção, `"drop_block"` mantém as solicitações bem-sucedidas quando uma condição não é atendida e relata cada bloco descartado em `input_transformations` com `reason: "prefix_binding_mismatch"`. Uma entrada cujo `path` cai em um turno mantido significa que o pensamento desse turno não se manteve válido. [O que a API faz com um bloco inválido](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking#mismatch-behavior) descreve o que é descartado e explica como gerar alertas sobre isso. No Claude Sonnet 5.5 e no Claude Haiku 5.5, `block_binding` funciona apenas com `thinking: {"type": "adaptive"}`. Uma solicitação que o define com `thinking: {"type": "between_tools"}` no Claude Sonnet 5.5, ou com `thinking: {"type": "disabled"}` no Claude Haiku 5.5, retorna um erro 400. Nessas solicitações, certifique-se de que todas as condições sejam atendidas ou remova os blocos `thinking` e `redacted_thinking` dos turnos mantidos.
