---
title: Compactación y pensamiento preservado
url: https://platform.claude.com/docs/es/build-with-claude/compaction-thinking-blocks
description: Cuándo siguen siendo válidos los bloques de pensamiento de los turnos conservados después de la compactación bajo demanda en modelos con pensamiento preservado, y cómo comprobarlo.
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
---

Omite esta página a menos que envíes bloques de pensamiento de vuelta a un modelo con ["preserved thinking" (pensamiento preservado)](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking) y conserves turnos después del bloque de compactación. Los "kept turns" (turnos conservados) son los turnos que siguen al bloque: turnos recientes que dejaste fuera de la solicitud de compactación, como en [Compactación que conserva los turnos recientes](https://platform.claude.com/docs/es/build-with-claude/compaction-keep-recent-turns), o turnos que llegaron mientras se escribía el resumen, como en [Compactación en segundo plano](https://platform.claude.com/docs/es/build-with-claude/compaction-background).

Los modelos con pensamiento preservado comprueban los bloques de pensamiento anteriores contra la conversación que los produjo. Un resumen reemplaza parte de esa conversación, pero la comprobación acepta el intercambio cuando la API escribió el resumen, por lo que el pensamiento de los turnos conservados puede seguir siendo válido.

## Condiciones para que el pensamiento conservado siga siendo válido

Los bloques de pensamiento de los turnos conservados siguen siendo válidos mientras se cumplan todas estas condiciones:

* **La solicitud de compactación se ejecuta en un modelo con pensamiento preservado.** Esta condición abarca cada solicitud de compactación desde que se produjo un bloque de pensamiento, no solo la más reciente. Una forma de cumplirla es enviar cada solicitud de compactación al modelo que usa la conversación.
* **Los turnos conservados siguen directamente a los mensajes resumidos, y los envías sin cambios.** Envía cada mensaje conservado exactamente como está en tu historial. No omitas ni agregues ningún mensaje entre el último mensaje resumido y el primero conservado. El primer mensaje conservado también debe tener un rol diferente al del último mensaje resumido, y no puede ser un mensaje `role: "system"` a mitad de la conversación. De lo contrario, la API lo fusiona con el último mensaje resumido. Una forma de acertar con el primer mensaje conservado es compactar exactamente los `messages` de una solicitud que ya enviaste. Así, los turnos conservados comienzan con la respuesta de Claude a esa solicitud.
* **`system` y las `tools` no marcadas con `defer_loading: true` no cambian.** Son las mismas en la solicitud de compactación que en las solicitudes que produjeron el pensamiento conservado, y siguen siendo las mismas en las solicitudes posteriores. [Cambiar la indicación del sistema o las herramientas](https://platform.claude.com/docs/es/build-with-claude/compaction-thinking-blocks#change-the-system-prompt-or-tools) explica cómo cambiarlas de forma segura.

Si una condición no se cumple, nada falla al compactar, y la API acepta el bloque en las solicitudes posteriores de todos modos. El fallo llega en la primera solicitud posterior que envía el pensamiento conservado donde la API aplica la comprobación: un error 400 de forma predeterminada, o bloques de pensamiento descartados si la solicitud establece `thinking.block_binding.prefix_mismatch_behavior` en `"drop_block"`. En la Message Batches API, un elemento que deja el campo sin establecer no falla. Donde la comprobación se aplica de forma predeterminada, la API descarta los bloques en su lugar. [Qué hace la API con un bloque no válido](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#mismatch-behavior) describe ambos resultados, y [Cuándo aplica la API la verificación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#enforcement) indica qué solicitudes se comprueban.

## Compactar de nuevo sin romper el pensamiento anterior

Puedes [compactar de nuevo](https://platform.claude.com/docs/es/build-with-claude/compaction-on-demand#compact-again) y conservar turnos: el nuevo bloque abarca el resumen anterior y cada mensaje que lo sigue en la solicitud de compactación, y cualquier turno que dejes fuera de esa solicitud es un turno conservado del nuevo bloque.

La primera de las [condiciones para el pensamiento conservado](https://platform.claude.com/docs/es/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) cuenta cada compactación desde que se produjo un bloque de pensamiento, por lo que un turno que conservas a lo largo de dos compactaciones necesita que ambas se hayan ejecutado en un modelo con pensamiento preservado.

Las compactaciones anteriores a la producción de un bloque de pensamiento no cuentan en su contra. El pensamiento producido después de que un bloque está en su lugar queda vinculado a ese bloque, y sigue siendo válido a lo largo de las compactaciones posteriores que cumplan las condiciones.

## Cambiar la indicación del sistema o las herramientas

Una solicitud posterior puede usar un `system` diferente, `tools` diferentes o un modelo diferente al de la solicitud de compactación, y la API sigue aceptando el bloque. Un cambio así puede invalidar el pensamiento de los turnos conservados, pero no tiene ningún otro efecto.

Para cambiar `system` o `tools` sin invalidar ningún pensamiento conservado, primero compacta toda la conversación, de modo que no se conserve ningún turno. Luego cámbialos en la siguiente solicitud.

Para agregar una instrucción o cambiar las herramientas disponibles sin tocar `system` ni `tools`, añade el cambio a `messages`, como se describe en [Hacer cambios sin editar el prefijo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#replace-prefix-edits).

Los mensajes del sistema a mitad de la conversación dentro de los turnos resumidos también se resumen, por lo que sus instrucciones de texto dejan de aplicarse después del intercambio. Un nivel de [esfuerzo por mensaje](https://platform.claude.com/docs/es/build-with-claude/effort#change-effort-mid-conversation-beta) que establezcan tampoco se traslada: hasta que un mensaje posterior establezca un nivel, los turnos se ejecutan con el `output_config.effort` de nivel superior de la solicitud, o con el valor predeterminado del modelo si no estableces uno. Para mantener vigente una instrucción o un nivel de esfuerzo, vuelve a indicarlo en un mensaje `role: "system"` directamente después del primer turno `user` nuevo que sigue a los turnos conservados. Los cambios de herramientas dentro de esos turnos se trasladan por sí solos cuando la solicitud de compactación también incluye `inline-tools-2026-09-15`: el bloque devuelto registra su efecto neto en su campo `tool_changes`, así que envía el bloque de vuelta sin modificar. Si el bloque no tiene un campo `tool_changes`, vuelve a indicar esos cambios de herramientas de la misma manera. Un mensaje del sistema colocado entre el bloque y los turnos conservados rompe su pensamiento.

## Comprobar que el pensamiento conservado se mantuvo

La respuesta de compactación no indica si el pensamiento conservado se mantiene. La primera solicitud después del intercambio sí lo hace. Para comprobarlo en tus pruebas:

1. Mantén una conversación corta con el pensamiento activado. Usa un modelo en el que la API ejecute la comprobación (consulta [Cuándo aplica la API la verificación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#enforcement)), y úsalo en cada paso, porque un modelo que no puede leer un bloque de pensamiento lo descarta sin ningún error.
2. Compacta los turnos más antiguos y conserva al menos un turno que contenga un bloque de pensamiento.
3. Envía la siguiente solicitud, con el bloque primero, luego el turno conservado y después un nuevo mensaje `user`, y con `thinking.block_binding.prefix_mismatch_behavior` establecido en `"error"`.
4. Lee el resultado. Una respuesta 200 cuyo arreglo `input_transformations` está vacío significa que ningún bloque de pensamiento falló la comprobación ni fue descartado. Un error 400 que indica que el bloque está vinculado a una conversación diferente significa que alguno sí lo hizo. El mensaje comienza con la ruta del primer bloque que falló, y [Qué hace la API con un bloque no válido](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#mismatch-behavior) lo muestra completo.

El campo `prefix_mismatch_behavior` necesita el encabezado beta `thinking-binding-controls-2026-08-01` además del [encabezado beta `compact-2026-09-04`](https://platform.claude.com/docs/es/build-with-claude/compaction-on-demand#request-a-summary). Establecer el campo también incluye la solicitud en la comprobación en las cuentas donde la comprobación no está activada de forma predeterminada.

El siguiente programa ejecuta los cuatro pasos. Imprime cuántos bloques de pensamiento contiene el turno conservado y cuántas entradas tiene `input_transformations`; ninguna entrada significa que el pensamiento conservado se mantuvo:

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

  client = anthropic.Anthropic()

  # Claude Fable 5.1 es el primer modelo que verifica el pensamiento reenviado contra la conversación.
  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."
  # Con "error", un bloque de pensamiento que no pasa la verificación hace que la solicitud falle con un 400.
  THINKING: BetaThinkingConfigParam = {
      "type": "adaptive",
      "block_binding": {"prefix_mismatch_behavior": "error"},
  }

  # 1. Mantén una conversación corta con el pensamiento activado.
  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. Resume el primer turno. El segundo turno queda fuera de la solicitud.
  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. Coloca el bloque delante del turno conservado y haz la siguiente pregunta.
  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. Un 200 sin bloques descartados significa que el pensamiento conservado se mantuvo.
  print(f"Dropped thinking blocks: {len(third.input_transformations)}")
  ```

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

  // Claude Fable 5.1 es el primer modelo que verifica el pensamiento reenviado contra la conversación.
  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.";
  // Con "error", un bloque de pensamiento que no pasa la verificación hace que la solicitud falle con un 400.
  const thinking: Anthropic.Beta.Messages.BetaThinkingConfigParam = {
    type: "adaptive",
    block_binding: { prefix_mismatch_behavior: "error" }
  };

  // 1. Mantén una conversación breve con el pensamiento activado.
  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. Resume el primer turno. El segundo turno queda fuera de la solicitud.
  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. Coloca el bloque delante del turno conservado y haz la siguiente pregunta.
  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. Un 200 sin bloques descartados significa que el pensamiento conservado se mantuvo.
  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 es el primer modelo que verifica el pensamiento reenviado contra la conversación.
  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.";
  // Con "error", un bloque de pensamiento que no pasa la verificación hace que la solicitud falle con un 400.
  BetaThinkingConfigAdaptive thinking = new()
  {
      BlockBinding = new() { PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.Error },
  };

  // 1. Mantén una conversación corta con el pensamiento activado.
  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. Resume el primer turno. El segundo turno queda fuera de la solicitud.
  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. Coloca el bloque delante del turno conservado y haz la siguiente pregunta.
  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. Un 200 sin bloques descartados significa que el pensamiento conservado se mantuvo.
  Console.WriteLine($"Dropped thinking blocks: {third.InputTransformations?.Count ?? 0}");
  ```

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

  // Claude Fable 5.1 es el primer modelo que verifica el pensamiento reenviado contra la conversación.
  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."}}
  // Con "error", un bloque de pensamiento que no pasa la verificación hace que la solicitud falle con un 400.
  thinking := anthropic.BetaThinkingConfigParamUnion{
  	OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  		BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  			PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorError,
  		},
  	},
  }

  // 1. Mantén una conversación breve con el pensamiento activado.
  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. Resume el primer turno. El segundo turno queda fuera de la solicitud.
  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. Coloca el bloque delante del turno conservado y haz la siguiente pregunta.
  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. Un 200 sin bloques descartados significa que el pensamiento conservado se mantuvo.
  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 es el primer modelo que verifica el pensamiento reenviado contra la conversación.
  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.";
  // Con "error", un bloque de pensamiento que no pasa la verificación hace que la solicitud falle con un 400.
  static final BetaThinkingConfigAdaptive THINKING = BetaThinkingConfigAdaptive.builder()
      .blockBinding(BetaThinkingBlockBinding.builder()
          .prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.ERROR)
          .build())
      .build();

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

      // 1. Mantén una conversación corta con el pensamiento activado.
      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. Resume el primer turno. El segundo turno queda fuera de la solicitud.
      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. Coloca el bloque delante del turno conservado y haz la siguiente pregunta.
      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. Un 200 sin bloques descartados significa que el pensamiento conservado se mantuvo.
      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 es el primer modelo que verifica el pensamiento reenviado contra la conversación.
  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.";
  // Con "error", un bloque de pensamiento que no pasa la verificación hace que la solicitud falle con un 400.
  $thinking = BetaThinkingConfigAdaptive::with(
      blockBinding: BetaThinkingBlockBinding::with(
          prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::ERROR,
      ),
  );

  // 1. Mantén una conversación corta con el pensamiento activado.
  $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. Resume el primer turno. El segundo turno queda fuera de la solicitud.
  $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. Coloca el bloque delante del turno conservado y haz la siguiente pregunta.
  $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. Un 200 sin bloques descartados significa que el pensamiento conservado se mantuvo.
  printf("Dropped thinking blocks: %d\n", count($third->inputTransformations));
  ```

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

  # Claude Fable 5.1 es el primer modelo que verifica el pensamiento reenviado contra la conversación.
  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."
  # Con "error", un bloque de pensamiento que no pasa la verificación hace que la solicitud falle con un 400.
  THINKING = Anthropic::Beta::BetaThinkingConfigAdaptive.new(
    block_binding: Anthropic::Beta::BetaThinkingBlockBinding.new(
      prefix_mismatch_behavior: Anthropic::Beta::BetaThinkingPrefixMismatchBehavior::ERROR
    )
  )

  # 1. Mantén una conversación breve con el pensamiento activado.
  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. Resume el primer turno. El segundo turno queda fuera de la solicitud.
  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. Coloca el bloque delante del turno conservado y haz la siguiente pregunta.
  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. Un 200 sin bloques descartados significa que el pensamiento conservado se mantuvo.
  puts "Dropped thinking blocks: #{third.input_transformations.length}"
  ```
</CodeGroup>

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

En producción, `"drop_block"` mantiene las solicitudes funcionando correctamente cuando una condición no se cumple, e informa cada bloque descartado en `input_transformations` con `reason: "prefix_binding_mismatch"`. Una entrada cuyo `path` cae en un turno conservado significa que el pensamiento de ese turno no se mantuvo. [Qué hace la API con un bloque no válido](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#mismatch-behavior) describe qué se descarta y explica cómo generar alertas al respecto. En Claude Sonnet 5.5 y Claude Haiku 5.5, `block_binding` funciona solo con `thinking: {"type": "adaptive"}`. Una solicitud que lo establece con `thinking: {"type": "between_tools"}` en Claude Sonnet 5.5, o con `thinking: {"type": "disabled"}` en Claude Haiku 5.5, devuelve un error 400. En esas solicitudes, asegúrate de que se cumplan todas las condiciones, o elimina los bloques `thinking` y `redacted_thinking` de los turnos conservados.
