---
title: Pensamiento preservado
url: https://platform.claude.com/docs/es/build-with-claude/preserved-thinking
description: El pensamiento preservado permite que un modelo use un bloque de pensamiento de un turno anterior solo si ese modelo o uno de un conjunto fijo de otros modelos lo produjo y nada antes del bloque ha cambiado.
---

El "preserved thinking" (pensamiento preservado) es una propiedad de los modelos Claude más recientes que protege contra la "distillation" (destilación). Determina si el modelo puede usar un bloque de pensamiento que envías de vuelta desde un turno anterior. A partir de Claude Fable 5.1, cuando un bloque `thinking` o `redacted_thinking` vuelve en una solicitud, la API verifica dos cosas en la `signature` del bloque:

* **El modelo puede leer el bloque.** Cada modelo lee sus propios bloques de pensamiento y los de un conjunto fijo de otros modelos. Claude Fable 5.1 lee bloques de Claude Opus 5 y, en la API de Claude, de Claude Opus 5.5; ni Claude Opus 5 ni Claude Opus 5.5 leen bloques de Claude Fable 5.1. Si el modelo actual no puede leer un bloque, la API lo descarta de esa solicitud sin generar un error. Consulta [Cambiar de modelo a mitad de la conversación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#switching-models).
* **Nada antes del bloque de pensamiento ha cambiado.** La indicación del sistema `system` de nivel superior, `tools` y los `messages` anteriores al bloque son su "prefix" (prefijo). Si el prefijo difiere de lo que enviaste cuando se produjo el bloque, ese bloque y todos los bloques de pensamiento posteriores son inválidos, y la API rechaza la solicitud con un error 400 o descarta los bloques inválidos, según lo que elijas. Consulta [Mantener el prefijo sin cambios](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#prefix-check).

Los bloques de pensamiento de Claude Sonnet 5.5 y Claude Haiku 5.5 también están vinculados a la cuenta que los produjo. Consulta [Los bloques de pensamiento permanecen con la cuenta que los produjo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#account-bound-thinking) para saber dónde aplica esto la API.

La verificación del modelo se aplica a todas las cuentas. La API aplica la verificación del prefijo de forma predeterminada para las cuentas creadas a partir del 31 de agosto de 2026, 00:00 UTC. En las cuentas más antiguas, aplica la verificación del prefijo solo en las solicitudes que establecen `thinking.block_binding.prefix_mismatch_behavior`. **Haz que tu integración sea de solo anexar ("append-only") sin importar la antigüedad de tu cuenta**, para que el mismo código funcione en todas las cuentas, incluidas las cuentas más nuevas en las que se aplica de forma predeterminada.

## Quién necesita cambiar algo

No cambia nada para ti si Claude Code, claude.ai, Claude Managed Agents o el Claude Agent SDK construyen tus solicitudes, o si tu código mantiene `system` y `tools` fijos durante una sesión y solo anexa a `messages`. Claude Mythos 5.1 y los modelos anteriores a Claude Fable 5.1 no ejecutan la verificación del prefijo. Si nunca envías bloques de pensamiento de vuelta, la verificación del prefijo no tiene nada que rechazar, y el modelo no recibe nada de su razonamiento anterior.

Revisa tu integración si, entre dos solicitudes de una misma conversación, hace alguna de las siguientes cosas. Cada elemento enlaza a lo que debes hacer en su lugar:

* [Reconstruye la indicación del sistema `system`](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#new-instructions): la fecha, un indicador de modo, instrucciones del proyecto releídas, o un plugin o servidor MCP que se conecta después del primer turno
* [Vuelve a renderizar el contexto en el primer mensaje del usuario](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#changing-context)
* [Borra o acorta resultados de herramientas antiguos, o vuelve a codificar imágenes antiguas](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#server-side-trimming)
* [Resume o descarta turnos antiguos en el cliente](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#custom-compaction-on-the-client) y conserva los turnos recientes con su pensamiento
* [Agrega, elimina o edita entradas en `tools`](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#tool-changes)
* [Agrega un recordatorio a un turno del usuario](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#per-turn-reminders) y luego lo elimina o lo reescribe
* [Descarta algunos bloques `thinking` y conserva los posteriores](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#append-assistant-turns-exactly-as-returned), o los elimina y [luego los vuelve a poner](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#prefix-check)
* [Reconstruye una sesión guardada a partir de plantillas](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#faq) en lugar de reproducir lo que envió

En una cuenta más antigua, ninguno de estos casos produce un error a menos que la solicitud establezca `prefix_mismatch_behavior`, así que una ejecución sin errores con tu propia clave no muestra si tu código está afectado. Si otras personas ejecutan tu herramienta con sus propias claves de API, quienes tengan cuentas más nuevas recibirán el error 400 antes que tú. Para ver lo que ellos ven sin cambiar el comportamiento de tus solicitudes, envía el encabezado beta `thinking-binding-controls-2026-08-01`. En una cuenta más antigua, cada respuesta marca entonces los bloques que no pasan la verificación, y el modelo aún los lee (consulta [Establecer el comportamiento ante discrepancias y leer `input_transformations`](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#preserved-thinking-controls)).

Revisa también tu integración si envía bloques de pensamiento de Claude Sonnet 5.5 o Claude Haiku 5.5 de una cuenta en una solicitud hecha por otra cuenta. Consulta [Los bloques de pensamiento permanecen con la cuenta que los produjo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#account-bound-thinking).

## Cambiar de modelo a mitad de la conversación

Claude Fable 5.1 y Claude Mythos 5.1 leen los bloques de pensamiento producidos por el otro y por modelos Claude anteriores. Ningún otro modelo lee bloques de pensamiento de Claude Fable 5.1 ni de Claude Mythos 5.1.

Claude Opus 5.5 lee bloques de pensamiento de Claude Opus 5, de modelos Opus, Sonnet y Haiku anteriores y, en la API de Claude y Google Cloud, de Claude Sonnet 5.5 y Claude Haiku 5.5, pero no de los modelos Claude Fable ni Claude Mythos. En la API de Claude, Claude Fable 5.1 y Claude Mythos 5.1 leen bloques de pensamiento de Claude Opus 5.5; ningún otro modelo lo hace. Así, una conversación que pasa de Claude Opus 5 a Claude Opus 5.5 conserva su razonamiento, y también lo conserva una que sube de Claude Opus 5.5 a Claude Fable 5.1 o Claude Mythos 5.1 en la API de Claude. Una que pasa de Claude Fable 5.1 o Claude Mythos 5.1 a Claude Opus 5.5, o de Claude Opus 5.5 a cualquier modelo distinto de esos dos, ejecuta los turnos posteriores al cambio sin el razonamiento del modelo anterior. Los bloques se descartan, no se rechazan, como se describe más adelante en esta sección.

Claude Sonnet 5.5 lee bloques de pensamiento de Claude Sonnet 5, Claude Opus 4.8, Claude Haiku 4.5 y modelos anteriores, y, en la API de Claude y Google Cloud, de Claude Haiku 5.5, pero no de Claude Opus 5, Claude Opus 5.5 ni de ningún modelo Claude Fable o Claude Mythos. En la API de Claude y Google Cloud, Claude Opus 5.5 lee bloques de pensamiento de Claude Sonnet 5.5; ningún otro modelo lo hace. Así, una conversación que pasa de Claude Sonnet 5 a Claude Sonnet 5.5 conserva su razonamiento, y también lo conserva una que sube de Claude Sonnet 5.5 a Claude Opus 5.5 en la API de Claude y Google Cloud. Una que pasa a Claude Sonnet 5.5 desde Claude Opus 5, Claude Opus 5.5 o un modelo Claude Fable o Claude Mythos ejecuta los turnos posteriores al cambio sin el razonamiento del modelo anterior. Lo mismo ocurre con cualquier otro cambio que se aleje de Claude Sonnet 5.5, por ejemplo un [fallback del lado del servidor](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback#server-side-fallback) a Claude Sonnet 5.

Claude Haiku 5.5 lee bloques de pensamiento de Claude Sonnet 5, Claude Opus 4.8, Claude Haiku 4.5 y modelos anteriores, pero no de Claude Opus 5, Claude Opus 5.5, Claude Sonnet 5.5 ni de ningún modelo Claude Fable o Claude Mythos. En la Claude API y Google Cloud, Claude Opus 5.5 y Claude Sonnet 5.5 leen bloques de pensamiento de Claude Haiku 5.5; ningún otro modelo lo hace. Así, una conversación que pasa de Claude Haiku 4.5 a Claude Haiku 5.5 conserva su razonamiento, y también lo conserva una que sube de Claude Haiku 5.5 a Claude Opus 5.5 o Claude Sonnet 5.5 en la Claude API y Google Cloud. Una que pasa a Claude Haiku 5.5 desde Claude Opus 5, Claude Opus 5.5, Claude Sonnet 5.5 o un modelo Claude Fable o Claude Mythos ejecuta los turnos posteriores al cambio sin el razonamiento del modelo anterior, y lo mismo ocurre con cualquier otro cambio que se aleje de Claude Haiku 5.5.

* **Una conversación que pasa a Claude Fable 5.1 desde un modelo anterior, o desde Claude Opus 5.5 en la Claude API, conserva su razonamiento.** Los bloques de pensamiento del modelo anterior siguen siendo legibles, por lo que el modelo piensa como de costumbre desde el primer turno después del cambio.
* **Una conversación que pasa de Claude Fable 5.1 a cualquier modelo distinto de Claude Mythos 5.1 pierde el razonamiento de Claude Fable 5.1 para esa solicitud.** Esto ocurre cuando un enrutador envía un turno a un modelo más económico, después de un [fallback por rechazo del clasificador](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback), o durante un [fallback del lado del servidor](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback#server-side-fallback). La API elimina los bloques ilegibles antes de que el prompt llegue al modelo. No se facturan y no cuentan para `input_tokens`.

Sigue enviando el historial completo en cada solicitud, incluidos los bloques de pensamiento, y deja que la API descarte lo que el modelo actual no puede leer. La API nunca edita tu arreglo `messages`, así que los bloques descartados permanecen en tu historial. Cuando el mismo historial vuelve a Claude Fable 5.1, sus bloques vuelven a ser legibles, junto con el pensamiento del modelo anterior. El razonamiento se pierde definitivamente solo si tu cliente elimina los bloques por sí mismo, por ejemplo un harness que quita el pensamiento al cambiar de modelo o que reconstruye el historial a partir de lo que usó cada modelo.

<Frame>
  ![Animación: cambiar a Claude Opus omite el pensamiento de Claude Fable 5.1 en ese turno; al volver, todo se lee de nuevo](https://platform.claude.com/docs/images/preserved-thinking-model-switch.svg)
</Frame>

Con el [encabezado beta](https://platform.claude.com/docs/es/api/beta-headers) `thinking-binding-controls-2026-08-01`, la respuesta enumera cada bloque descartado en un arreglo `input_transformations` de nivel superior con `reason: "model_binding_mismatch"`:

```json
{
  "input_transformations": [
    {
      "type": "thinking_dropped",
      "path": "messages.3.content.0",
      "reason": "model_binding_mismatch"
    }
  ]
}
```

Sin el encabezado, el descarte es silencioso. Esta entrada no es un error en tu integración, y `prefix_mismatch_behavior` no tiene efecto sobre ella: un bloque que el modelo actual no puede leer siempre se descarta.

## Los bloques de pensamiento permanecen con la cuenta que los produjo

Los bloques de pensamiento que produce Claude Sonnet 5.5 o Claude Haiku 5.5 funcionan solo en la cuenta que los produjo, o en una cuenta vinculada a ella. Cuando otra cuenta envía uno de estos bloques, la API descarta el bloque antes de que el modelo lo vea, y la solicitud se completa correctamente. El modelo responde sin el razonamiento de los bloques descartados. Los bloques de modelos anteriores no se ven afectados.

En la API de Claude y Google Cloud, con el [encabezado beta](https://platform.claude.com/docs/es/api/beta-headers) `thinking-binding-controls-2026-08-01`, la respuesta enumera cada bloque descartado en `input_transformations` como una entrada `thinking_dropped` con `reason: "organization_binding_mismatch"`. Sin el encabezado, el descarte es silencioso.

## Mantener el prefijo sin cambios

En Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 y Claude Haiku 5.5, un bloque de pensamiento sigue siendo válido solo mientras todo lo que enviaste antes de él permanezca sin cambios en las solicitudes posteriores. El prefijo verificado tiene tres partes:

* La indicación del sistema `system` de nivel superior
* El conjunto de `tools`
* Cada `message` anterior al bloque

Nota: Con la [compactación](https://platform.claude.com/docs/es/build-with-claude/compaction) del lado del servidor, el prefijo verificado comienza en el bloque de compactación más reciente.

Los parámetros de la solicitud fuera de esos tres campos, como `effort`, `max_tokens`, `output_config`, `tool_choice` y `metadata`, no forman parte de la verificación del prefijo, y tampoco los marcadores `cache_control`. [Qué cuenta como una edición](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#what-counts-as-an-edit) tiene la lista completa.

Los bloques de pensamiento anteriores no están en el prefijo, pero cada bloque de pensamiento registra qué bloque de pensamiento vino antes que él, a lo largo de los turnos. Puedes eliminar bloques de pensamiento del inicio del historial (los más antiguos primero), del final, o todos. Lo que falla es un hueco: los bloques de pensamiento que conserves deben ser una secuencia ininterrumpida de la secuencia original, así que eliminar uno del medio invalida los bloques de pensamiento posteriores. Una vez que elimines un bloque, déjalo fuera. Volver a ponerlo invalida los bloques de pensamiento producidos mientras no estaba.

Mantén `system` y `tools` fijos durante la sesión y trata `messages` como de solo anexar. La misma disciplina mantiene estable el prefijo para el [almacenamiento en caché de prompts](https://platform.claude.com/docs/es/build-with-claude/prompt-caching): las ediciones que invalidan el pensamiento son las mismas que reinician la caché.

### Qué hace la API con un bloque no válido

Lo eliges con `thinking.block_binding.prefix_mismatch_behavior`:

* **`"error"` (el valor predeterminado):** la API rechaza la solicitud con un `invalid_request_error` 400 que nombra el primer bloque que falla.
* **`"drop_block"`:** la API descarta cada bloque que falla y todos los bloques de pensamiento posteriores, y la solicitud se completa correctamente. Los bloques descartados no se facturan. El modelo responde ese turno sin usar el razonamiento de los bloques descartados, y la caché de prompts se reinicia en el punto de la edición. La respuesta enumera cada bloque descartado en `input_transformations` (en el evento `message_start` cuando usas streaming) con `reason: "prefix_binding_mismatch"`.

<Warning>
  `"drop_block"` hace que las solicitudes sigan completándose correctamente, pero no corrige la edición que causó la discrepancia, y tiene un costo. Descartar bloques puede aumentar significativamente los tokens de salida generados, especialmente con niveles de esfuerzo más altos o cuando se descartan bloques en cada turno. Para obtener más información, consulta [Costo en tokens de salida de `"drop_block"`](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#drop-block-cost). Los bloques descartados no se facturan, pero Claude vuelve a crear el razonamiento que ya no puede leer, por lo que genera más tokens de salida. La calidad de la salida también podría cambiar en tareas donde los turnos posteriores se basan en el razonamiento anterior. Usa `"drop_block"` como solución provisional mientras corriges la edición, pero no como configuración a largo plazo.
</Warning>

Cuenta las respuestas de cada sesión cuyo `input_transformations` tenga una entrada `prefix_binding_mismatch`, genera alertas sobre ellas y reemplaza cada edición con el patrón correspondiente en [Hacer cambios sin editar el prefijo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#replace-prefix-edits). En la Message Batches API, un elemento que deja el campo sin establecer no falla. Donde la API aplica la verificación de forma predeterminada, en su lugar descarta los bloques que fallan. Establece `"error"` explícitamente en ese caso si quieres que los elementos del lote fallen.

Tanto el campo como el arreglo `input_transformations` requieren el [encabezado beta](https://platform.claude.com/docs/es/api/beta-headers) `thinking-binding-controls-2026-08-01`. [Establecer el comportamiento ante discrepancias y leer `input_transformations`](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#preserved-thinking-controls) muestra la solicitud en cada SDK.

El mensaje del error 400 comienza así:

```text wrap
messages.1.content.0: Invalid `signature` in `thinking` block. The block is bound to a different conversation. Remove the block, or set `thinking.block_binding.prefix_mismatch_behavior` to "drop_block".
```

Si la solicitud no envió el encabezado beta, el mensaje continúa así:

```text wrap
That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header.
```

Normalmente termina con una oración que indica qué cambió, por ejemplo, que la indicación del sistema `system` o la lista de `tools` difiere de cuando se creó el bloque. [Solución de problemas del pensamiento](https://platform.claude.com/docs/es/build-with-claude/thinking-troubleshooting#error-thinking-block-signature) describe lo que puede indicar esa oración.

Una firma manipulada o que no se puede descifrar es un fallo distinto. Siempre devuelve un 400 (``Invalid `signature` in `thinking` block`` sin ninguna oración sobre la conversación), y `prefix_mismatch_behavior` no se aplica a ella.

#### Costo en tokens de salida de `"drop_block"`

En las pruebas de Anthropic con un benchmark de programación de múltiples turnos, descartar bloques de pensamiento una vez por sesión aumentó los tokens de salida en un 2.5% con esfuerzo bajo, 3.9% con medio, 4.5% con alto y 20.1% con máximo. Descartarlos en cada turno después del primero aumentó los tokens de salida en un 4.6% con esfuerzo bajo, 9.7% con medio, 10.3% con alto y 67.1% con máximo. Estas cifras son estimaciones con amplios márgenes de error, y el impacto en tu carga de trabajo depende de tu harness.

Cuando Claude ya no puede leer el razonamiento de turnos anteriores, vuelve a crear ese razonamiento, por lo que las solicitudes que descartan bloques de pensamiento generan más tokens de salida y pueden tardar más en responder. Un descarte en cada turno cuesta más que un descarte ocasional, y cuánto más depende de tu harness: con qué frecuencia edita el prefijo y cuánto se basa cada turno en el razonamiento anterior.

Antes de depender de `"drop_block"`, ejecuta evaluaciones en tu propia carga de trabajo para medir el aumento. Si es pequeño, `"drop_block"` puede hacer que las solicitudes sigan completándose correctamente mientras corriges la edición. En cualquier caso, corregir la edición con un patrón de [Hacer cambios sin editar el prefijo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#replace-prefix-edits) es una mejor solución a largo plazo.

#### Manejar el error en el código

Este es el `invalid_request_error` 400 mostrado anteriormente en esta sección. No reenvíes el mismo cuerpo: falla de la misma manera cada vez. Reintenta una vez con el encabezado beta y `prefix_mismatch_behavior: "drop_block"`, como solución provisional ([`"drop_block"` puede aumentar los tokens de salida](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#drop-block-cost)), y guarda esa elección con la sesión para que cada solicitud posterior también la envíe, incluso después de un reinicio. En Claude Sonnet 5.5 y Claude Haiku 5.5, `block_binding` funciona solo con `thinking: {"type": "adaptive"}`. Con `between_tools` en Claude Sonnet 5.5, o `thinking: {"type": "disabled"}` en Claude Haiku 5.5, mantén el historial de solo anexar, o elimina los bloques de pensamiento desde el turno editado en adelante. Si no puedes enviar el encabezado beta, elimina todos los bloques `thinking` y `redacted_thinking` del historial una vez, déjalos fuera y continúa. Luego corrige la edición que causó la discrepancia.

### Establecer el comportamiento ante discrepancias y leer `input_transformations`

El [encabezado beta](https://platform.claude.com/docs/es/api/beta-headers) `thinking-binding-controls-2026-08-01` agrega:

* Un arreglo `input_transformations` de nivel superior en cada respuesta
* Un objeto `block_binding` en la configuración de `thinking`, cuyo único campo es `prefix_mismatch_behavior`

`block_binding` se acepta junto con `thinking.type: "adaptive"` y `thinking.type: "enabled"`. En Claude Sonnet 5.5 y Claude Haiku 5.5, `block_binding` solo funciona con `thinking: {"type": "adaptive"}`. Enviarlo con `between_tools` en Claude Sonnet 5.5, o con `thinking: {"type": "disabled"}` en Claude Haiku 5.5, devuelve un error 400. Enviarlo sin el encabezado beta devuelve un error 400 cuyo mensaje termina en `block_binding: Extra inputs are not permitted`. Los modelos que no ejecutan la verificación del prefijo aceptan el objeto e informan solo los descartes de la verificación del modelo, así que un mismo cuerpo de solicitud funciona en todos los modelos. La referencia de la API llama a la verificación del prefijo la verificación de la conversación.

La siguiente solicitud opta por descartar en lugar de rechazar. En un primer turno no hay nada que reproducir, así que `input_transformations` vuelve vacío:

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5-1",
      "max_tokens": 16000,
      "thinking": {
        "type": "adaptive",
        "block_binding": {
          "prefix_mismatch_behavior": "drop_block"
        }
      },
      "messages": [
        {
          "role": "user",
          "content": "What is the greatest common divisor of 1071 and 462?"
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta thinking-binding-controls-2026-08-01 \
    --format yaml <<'YAML'
  model: claude-fable-5-1
  max_tokens: 16000
  thinking:
    type: adaptive
    block_binding:
      prefix_mismatch_behavior: drop_block
  messages:
    - role: user
      content: What is the greatest common divisor of 1071 and 462?
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  response = client.beta.messages.create(
      model="claude-fable-5-1",
      max_tokens=16000,
      thinking={
          "type": "adaptive",
          "block_binding": {"prefix_mismatch_behavior": "drop_block"},
      },
      messages=[
          {
              "role": "user",
              "content": "What is the greatest common divisor of 1071 and 462?",
          }
      ],
      betas=["thinking-binding-controls-2026-08-01"],
  )

  for block in response.content:
      if block.type == "text":
          print(block.text)

  print(f"Input transformations: {len(response.input_transformations or [])}")
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-fable-5-1",
    max_tokens: 16000,
    thinking: {
      type: "adaptive",
      block_binding: { prefix_mismatch_behavior: "drop_block" }
    },
    messages: [
      { role: "user", content: "What is the greatest common divisor of 1071 and 462?" }
    ],
    betas: ["thinking-binding-controls-2026-08-01"]
  });

  for (const block of response.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  console.log(`Input transformations: ${response.input_transformations?.length ?? 0}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(
      new()
      {
          Model = Model.ClaudeFable5_1,
          MaxTokens = 16000,
          Thinking = new BetaThinkingConfigAdaptive
          {
              BlockBinding = new()
              {
                  PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.DropBlock,
              },
          },
          Messages =
          [
              new()
              {
                  Role = Role.User,
                  Content = "What is the greatest common divisor of 1071 and 462?",
              },
          ],
          Betas = [AnthropicBeta.ThinkingBindingControls2026_08_01],
      }
  );

  foreach (var block in response.Content)
  {
      if (block.TryPickText(out var textBlock))
      {
          Console.WriteLine(textBlock.Text);
      }
  }

  Console.WriteLine($"Input transformations: {response.InputTransformations?.Count ?? 0}");
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5_1,
  	MaxTokens: 16000,
  	Thinking: anthropic.BetaThinkingConfigParamUnion{
  		OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  			BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  				PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorDropBlock,
  			},
  		},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What is the greatest common divisor of 1071 and 462?")),
  	},
  	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaThinkingBindingControls2026_08_01},
  })
  if err != nil {
  	log.Fatal(err)
  }

  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  fmt.Printf("Input transformations: %d\n", len(response.InputTransformations))
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaMessage;
  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;
  import com.anthropic.models.messages.Model;

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

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5_1)
          .maxTokens(16000L)
          .addBeta(AnthropicBeta.THINKING_BINDING_CONTROLS_2026_08_01)
          .thinking(BetaThinkingConfigAdaptive.builder()
              .blockBinding(BetaThinkingBlockBinding.builder()
                  .prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.DROP_BLOCK)
                  .build())
              .build())
          .addUserMessage("What is the greatest common divisor of 1071 and 462?")
          .build();

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

      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
      IO.println("Input transformations: "
          + response.inputTransformations().map(List::size).orElse(0));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaThinkingBlockBinding;
  use Anthropic\Beta\Messages\BetaThinkingConfigAdaptive;
  use Anthropic\Beta\Messages\BetaThinkingPrefixMismatchBehavior;
  use Anthropic\Client;

  $client = new Client();

  $response = $client->beta->messages->create(
      model: 'claude-fable-5-1',
      maxTokens: 16000,
      thinking: BetaThinkingConfigAdaptive::with(
          blockBinding: BetaThinkingBlockBinding::with(
              prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::DROP_BLOCK,
          ),
      ),
      messages: [
          ['role' => 'user', 'content' => 'What is the greatest common divisor of 1071 and 462?'],
      ],
      betas: [AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01],
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }

  echo 'Input transformations: ', count($response->inputTransformations ?? []), PHP_EOL;
  ```

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

  response = client.beta.messages.create(
    model: "claude-fable-5-1",
    max_tokens: 16_000,
    thinking: {
      type: "adaptive",
      block_binding: {prefix_mismatch_behavior: "drop_block"}
    },
    messages: [
      {role: "user", content: "What is the greatest common divisor of 1071 and 462?"}
    ],
    betas: [Anthropic::AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01]
  )

  response.content.each do |block|
    puts block.text if block.type == :text
  end

  puts "Input transformations: #{response.input_transformations&.length || 0}"
  ```
</CodeGroup>

```text Output wrap
The greatest common divisor of 1071 and 462 is 21.
Input transformations: 0
```

Con el encabezado beta, cada respuesta de un modelo con capacidad de pensamiento incluye `input_transformations`. Cada entrada identifica un bloque de pensamiento por su `path` (por ejemplo `messages.1.content.0`) e indica un `reason`. Hay dos tipos de entrada:

* **`thinking_dropped`:** la API descarta el bloque antes de que el modelo lo lea, y el bloque no se factura. El `reason` es `prefix_binding_mismatch` o `model_binding_mismatch` (consulta [Cambiar de modelo a mitad de la conversación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#switching-models)). El `reason` también puede ser `organization_binding_mismatch`, lo que significa que el bloque vino de otra cuenta (consulta [Los bloques de pensamiento permanecen con la cuenta que los produjo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#account-bound-thinking)).
* **`thinking_mismatch_allowed`:** el bloque no pasa la verificación del prefijo, pero la API no aplica esa verificación para esta solicitud, así que el bloque llega al modelo sin cambios y se factura. El `reason` siempre es `prefix_binding_mismatch`. Esta entrada aparece solo en solicitudes en las que la API no aplica la verificación de forma predeterminada, como las de una cuenta más antigua (consulta [Cuándo aplica la API la verificación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#enforcement)). Establecer `prefix_mismatch_behavior` en cualquiera de sus valores hace que la solicitud opte por la aplicación, así que una solicitud que lo establece nunca recibe esta entrada.

El arreglo está vacío cuando no se descartó ningún bloque y ninguno falló la verificación del prefijo. Ignora las entradas cuyo `type` o `reason` no reconozcas, porque las verificaciones futuras agregarán valores.

Al usar [streaming](https://platform.claude.com/docs/es/build-with-claude/streaming), el arreglo llega en el objeto `message` del evento `message_start`. Después de un fallback del lado del servidor a mitad del stream, el evento `message_delta` final lo incluye de nuevo con las entradas del modelo que atiende la solicitud. En un [lote de mensajes](https://platform.claude.com/docs/es/build-with-claude/batch-processing), un elemento cuyo bloque falla la verificación del prefijo con un `"error"` explícito se resuelve como `errored`. Un elemento que deja el campo sin establecer no falla. Donde la API aplica la verificación de forma predeterminada, en su lugar descarta los bloques que fallan. El endpoint de [conteo de tokens](https://platform.claude.com/docs/es/build-with-claude/token-counting) ejecuta la misma verificación del prefijo y devuelve el mismo 400.

### Cuándo aplica la API la verificación

La API aplica la verificación del prefijo en Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 y Claude Haiku 5.5 para las cuentas nuevas.

* **Cuentas creadas a partir del 31 de agosto de 2026, 00:00 UTC:** la API verifica las solicitudes a Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 y Claude Haiku 5.5 y aplica `"error"` a menos que establezcas `"drop_block"`. La misma definición de cuenta nueva se aplica a la API de Claude y a las plataformas en la nube.
* **Cuentas más antiguas:** la API aplica la verificación solo en las solicitudes que establecen `prefix_mismatch_behavior`. Establecer el campo hace que una solicitud opte por la aplicación, así que puedes ver lo que ve una cuenta nueva sin crear una. En las solicitudes que lo dejan sin establecer, la API sigue ejecutando la verificación pero deja pasar al modelo los bloques que fallan. Con el encabezado beta, la respuesta enumera cada uno en `input_transformations` como `thinking_mismatch_allowed`, así que puedes encontrar ediciones del prefijo sin cambiar lo que recibe el modelo.

Para saber en qué grupo está tu cuenta, toma una conversación de Claude Fable 5.1 que contenga un bloque de pensamiento, cambia algo antes de ese bloque y envíala a Claude Fable 5.1 sin el encabezado beta ni el campo `block_binding`. Una respuesta 400 que nombra el encabezado significa que en tu cuenta se aplica de forma predeterminada. Una respuesta 200 significa que no. Para confirmarlo, envía la misma solicitud de nuevo con el encabezado beta, todavía sin `block_binding`: la respuesta enumera cada bloque de pensamiento posterior a tu edición en `input_transformations` como `thinking_mismatch_allowed`.

### Qué cuenta como una edición

Cada fila compara dos solicitudes consecutivas:

| Cambio entre solicitudes                                                                                                                                                           | Bloques de pensamiento posteriores                                                                                                                                                                                                                                                                                                                                                                     |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Agregar mensajes al final                                                                                                                                                          | Válidos                                                                                                                                                                                                                                                                                                                                                                                                |
| Agregar una herramienta con `defer_loading: true` a la que nada ha hecho referencia todavía                                                                                        | Válidos                                                                                                                                                                                                                                                                                                                                                                                                |
| Eliminar bloques `thinking` del inicio del historial, del final, o todos                                                                                                           | Válidos (el modelo pierde ese razonamiento)                                                                                                                                                                                                                                                                                                                                                            |
| Cambiar cualquier parámetro de la solicitud fuera de `system`, `tools` y `messages` (`effort`, `max_tokens`, `output_config`, `tool_choice`, `metadata`, `thinking.display`, etc.) | Válidos                                                                                                                                                                                                                                                                                                                                                                                                |
| Agregar, mover o eliminar marcadores `cache_control`                                                                                                                               | Válidos                                                                                                                                                                                                                                                                                                                                                                                                |
| Una URL firmada rotativa que devuelve los mismos bytes                                                                                                                             | Válidos                                                                                                                                                                                                                                                                                                                                                                                                |
| La compactación o la edición de contexto del lado del servidor elimina o reemplaza contenido                                                                                       | Válidos (la verificación compara lo que enviaste, no la copia editada del servidor)                                                                                                                                                                                                                                                                                                                    |
| Un [mensaje del sistema con alcance de turno](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#per-turn-reminders) ya borrado que se deja en su lugar      | Válidos                                                                                                                                                                                                                                                                                                                                                                                                |
| Editar, reordenar o eliminar cualquier mensaje `user`, `assistant` o `system` anterior                                                                                             | Inválidos, excepto cuando el bloque firmado de la [compactación bajo demanda](https://platform.claude.com/docs/es/build-with-claude/compaction-on-demand) reemplaza los mensajes que resume, bajo las [condiciones para que el pensamiento conservado siga siendo válido](https://platform.claude.com/docs/es/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) |
| Volver a renderizar con un valor cambiado el contexto que pusiste en el primer mensaje del usuario                                                                                 | Inválidos para todos los bloques de pensamiento                                                                                                                                                                                                                                                                                                                                                        |
| Borrar o acortar un `tool_result` anterior, volver a codificar una imagen anterior o cambiar la entrada de un `tool_use` anterior                                                  | Inválidos para todos los bloques de pensamiento posteriores                                                                                                                                                                                                                                                                                                                                            |
| Agregar un bloque de texto a un turno del usuario anterior, o eliminar uno que agregaste la vez anterior                                                                           | Inválidos                                                                                                                                                                                                                                                                                                                                                                                              |
| Cambiar la cadena o los bloques de `system` de nivel superior                                                                                                                      | Inválidos                                                                                                                                                                                                                                                                                                                                                                                              |
| Agregar, eliminar, renombrar o editar una herramienta en `tools`                                                                                                                   | Inválidos                                                                                                                                                                                                                                                                                                                                                                                              |
| Eliminar un bloque `thinking` del medio del historial y conservar los posteriores                                                                                                  | Inválidos para todos los bloques de pensamiento posteriores                                                                                                                                                                                                                                                                                                                                            |
| Volver a poner un bloque `thinking` que eliminaste en una solicitud anterior                                                                                                       | Inválidos para los bloques de pensamiento producidos mientras no estaba                                                                                                                                                                                                                                                                                                                                |
| Una URL de imagen o documento que devuelve bytes diferentes en la siguiente solicitud                                                                                              | Inválidos                                                                                                                                                                                                                                                                                                                                                                                              |
| El mismo mensaje con alcance de turno eliminado o reformulado en una solicitud posterior                                                                                           | Inválidos                                                                                                                                                                                                                                                                                                                                                                                              |

### Verificar si tu código edita el prefijo

<Tip>
  **Automatiza esta verificación con la skill de la Claude API.** En la versión más reciente de [Claude Code](https://code.claude.com/docs/en/overview), abre el repositorio que construye tus solicitudes y ejecuta la [skill de la Claude API](https://platform.claude.com/docs/es/agents-and-tools/agent-skills/claude-api-skill#checking-an-integration-for-preserved-thinking) incluida:

  Deja que Claude Code revise tu código por ti

  ```text
  /claude-api preserved-thinking-migration
  ```

  La skill captura algunas de tus propias sesiones de varios turnos y compara solicitudes consecutivas para encontrar dónde tu código edita el prefijo. Luego reproduce las sesiones con `"drop_block"` y cuenta los bloques de pensamiento que descarta la API. Después, la skill corrige una causa a la vez y vuelve a medir tras cada corrección.
</Tip>

Primero, compara lo que envías. Captura los cuerpos de las solicitudes que envía tu integración durante algunos turnos normales, incluida una compactación o un cambio de herramientas. Para cada par de solicitudes consecutivas, compara `system`, `tools` y los `messages` que comparten. Deben ser idénticos hasta los turnos recién anexados.

Luego confírmalo con la API. Agrega el encabezado beta `thinking-binding-controls-2026-08-01`, establece `prefix_mismatch_behavior` en `"drop_block"` y ejecuta una sesión normal de varios turnos a través de tu integración en claude-fable-5-1. El siguiente ejemplo ejecuta dos turnos como debería hacerlo tu integración: `messages` solo crece, cada turno del asistente vuelve exactamente como lo devolvió la API, incluidos los bloques `thinking`, y `block_binding` se establece en cada solicitud. Después de cada turno imprime el número de bloques `thinking` en la respuesta y el número de bloques descartados:

<CodeGroup>
  ```bash cURL
  # Cuenta los bloques de pensamiento en una respuesta y los bloques que la API descartó
  COUNTS='"thinking blocks: \([.content[] | select(.type == "thinking")] | length), " +
    "dropped: \(.input_transformations | length)"'

  FIRST=$(curl -s https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
    -d '{
      "model": "claude-fable-5-1",
      "max_tokens": 16000,
      "thinking": {
        "type": "adaptive",
        "block_binding": { "prefix_mismatch_behavior": "drop_block" }
      },
      "messages": [
        {
          "role": "user",
          "content": "How many positive integers below 500 have exactly 6 positive divisors?"
        }
      ]
    }')
  echo "$FIRST" | jq -r "$COUNTS"

  # Turno 2: el turno del asistente se devuelve exactamente como se recibió, luego el siguiente mensaje del usuario
  MESSAGES=$(jq -n --argjson first "$FIRST" '[
    {
      role: "user",
      content: "How many positive integers below 500 have exactly 6 positive divisors?"
    },
    { role: "assistant", content: $first.content },
    { role: "user", content: "How many of those are odd?" }
  ]')

  jq -n --argjson messages "$MESSAGES" '{
    model: "claude-fable-5-1",
    max_tokens: 16000,
    thinking: {
      type: "adaptive",
      block_binding: { prefix_mismatch_behavior: "drop_block" }
    },
    messages: $messages
  }' | curl -s https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
    -d @- | jq -r "$COUNTS"
  ```

  ```bash CLI
  # Cuenta los bloques de pensamiento en una respuesta y los bloques que la API descartó
  COUNTS='"thinking blocks: \([.content[] | select(.type == "thinking")] | length), " +
    "dropped: \(.input_transformations | length)"'

  FIRST=$(ant beta:messages create --beta thinking-binding-controls-2026-08-01 \
    --format json <<'YAML'
  model: claude-fable-5-1
  max_tokens: 16000
  thinking:
    type: adaptive
    block_binding:
      prefix_mismatch_behavior: drop_block
  messages:
    - role: user
      content: How many positive integers below 500 have exactly 6 positive divisors?
  YAML
  )
  echo "$FIRST" | jq -r "$COUNTS"

  # Turno 2: el turno del asistente se devuelve exactamente como se recibió, luego el siguiente mensaje del usuario
  ant beta:messages create --beta thinking-binding-controls-2026-08-01 \
    --format json <<YAML | jq -r "$COUNTS"
  model: claude-fable-5-1
  max_tokens: 16000
  thinking:
    type: adaptive
    block_binding:
      prefix_mismatch_behavior: drop_block
  messages:
    - role: user
      content: How many positive integers below 500 have exactly 6 positive divisors?
    - role: assistant
      content: $(echo "$FIRST" | jq -c .content)
    - role: user
      content: How many of those are odd?
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  user_turns = [
      "How many positive integers below 500 have exactly 6 positive divisors?",
      "How many of those are odd?",
  ]

  # messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  messages = []
  for user_turn in user_turns:
      messages.append({"role": "user", "content": user_turn})
      response = client.beta.messages.create(
          model="claude-fable-5-1",
          max_tokens=16000,
          thinking={
              "type": "adaptive",
              "block_binding": {"prefix_mismatch_behavior": "drop_block"},
          },
          messages=messages,
          betas=["thinking-binding-controls-2026-08-01"],
      )
      messages.append({"role": "assistant", "content": response.content})
      thinking_blocks = sum(block.type == "thinking" for block in response.content)
      dropped = len(response.input_transformations or [])
      print(f"thinking blocks: {thinking_blocks}, dropped: {dropped}")
  ```

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

  const userTurns = [
    "How many positive integers below 500 have exactly 6 positive divisors?",
    "How many of those are odd?"
  ];

  // messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  const messages: Anthropic.Beta.BetaMessageParam[] = [];
  for (const userTurn of userTurns) {
    messages.push({ role: "user", content: userTurn });
    const response = await client.beta.messages.create({
      model: "claude-fable-5-1",
      max_tokens: 16000,
      thinking: {
        type: "adaptive",
        block_binding: { prefix_mismatch_behavior: "drop_block" }
      },
      messages,
      betas: ["thinking-binding-controls-2026-08-01"]
    });
    messages.push({ role: "assistant", content: response.content });
    const thinkingBlocks = response.content.filter((block) => block.type === "thinking");
    const dropped = response.input_transformations ?? [];
    console.log(`thinking blocks: ${thinkingBlocks.length}, dropped: ${dropped.length}`);
  }
  ```

  ```csharp C#
  AnthropicClient client = new();

  string[] userTurns =
  [
      "How many positive integers below 500 have exactly 6 positive divisors?",
      "How many of those are odd?",
  ];

  // messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  List<BetaMessageParam> messages = [];
  foreach (var userTurn in userTurns)
  {
      messages.Add(new() { Role = Role.User, Content = userTurn });
      var response = await client.Beta.Messages.Create(
          new()
          {
              Model = Model.ClaudeFable5_1,
              MaxTokens = 16000,
              Thinking = new BetaThinkingConfigAdaptive
              {
                  BlockBinding = new()
                  {
                      PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.DropBlock,
                  },
              },
              Messages = messages,
              Betas = [AnthropicBeta.ThinkingBindingControls2026_08_01],
          }
      );
      messages.Add(new()
      {
          Role = Role.Assistant,
          Content = response.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
      });
      var thinkingBlocks = response.Content.Count(block => block.TryPickThinking(out _));
      var dropped = response.InputTransformations?.Count ?? 0;
      Console.WriteLine($"thinking blocks: {thinkingBlocks}, dropped: {dropped}");
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  userTurns := []string{
  	"How many positive integers below 500 have exactly 6 positive divisors?",
  	"How many of those are odd?",
  }

  // messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  messages := []anthropic.BetaMessageParam{}
  for _, userTurn := range userTurns {
  	messages = append(messages, anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(userTurn)))
  	response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  		Model:     anthropic.ModelClaudeFable5_1,
  		MaxTokens: 16000,
  		Thinking: anthropic.BetaThinkingConfigParamUnion{
  			OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  				BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  					PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorDropBlock,
  				},
  			},
  		},
  		Messages: messages,
  		Betas:    []anthropic.AnthropicBeta{anthropic.AnthropicBetaThinkingBindingControls2026_08_01},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	messages = append(messages, response.ToParam())
  	thinkingBlocks := 0
  	for _, block := range response.Content {
  		if block.Type == "thinking" {
  			thinkingBlocks++
  		}
  	}
  	fmt.Printf("thinking blocks: %d, dropped: %d\n", thinkingBlocks, len(response.InputTransformations))
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlock;
  import com.anthropic.models.beta.messages.BetaMessage;
  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;
  import com.anthropic.models.messages.Model;

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

      List<String> userTurns = List.of(
          "How many positive integers below 500 have exactly 6 positive divisors?",
          "How many of those are odd?");

      // La lista de mensajes del builder crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
      MessageCreateParams.Builder conversation = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5_1)
          .maxTokens(16000L)
          .thinking(BetaThinkingConfigAdaptive.builder()
              .blockBinding(BetaThinkingBlockBinding.builder()
                  .prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.DROP_BLOCK)
                  .build())
              .build())
          .addBeta(AnthropicBeta.THINKING_BINDING_CONTROLS_2026_08_01);

      for (String userTurn : userTurns) {
          conversation.addUserMessage(userTurn);
          BetaMessage response = client.beta().messages().create(conversation.build());
          conversation.addMessage(response);
          long thinkingBlocks = response.content().stream()
              .filter(BetaContentBlock::isThinking)
              .count();
          int dropped = response.inputTransformations().map(List::size).orElse(0);
          IO.println("thinking blocks: " + thinkingBlocks + ", dropped: " + dropped);
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaThinkingBlockBinding;
  use Anthropic\Beta\Messages\BetaThinkingConfigAdaptive;
  use Anthropic\Beta\Messages\BetaThinkingPrefixMismatchBehavior;
  use Anthropic\Client;

  $client = new Client();

  $userTurns = [
      'How many positive integers below 500 have exactly 6 positive divisors?',
      'How many of those are odd?',
  ];

  // $messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  $messages = [];
  foreach ($userTurns as $userTurn) {
      $messages[] = ['role' => 'user', 'content' => $userTurn];
      $response = $client->beta->messages->create(
          model: 'claude-fable-5-1',
          maxTokens: 16000,
          thinking: BetaThinkingConfigAdaptive::with(
              blockBinding: BetaThinkingBlockBinding::with(
                  prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::DROP_BLOCK,
              ),
          ),
          messages: $messages,
          betas: [AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01],
      );
      $messages[] = ['role' => 'assistant', 'content' => $response->content];
      $thinkingBlocks = array_filter($response->content, fn ($block) => $block->type === 'thinking');
      $dropped = $response->inputTransformations ?? [];
      echo 'thinking blocks: ', count($thinkingBlocks), ', dropped: ', count($dropped), PHP_EOL;
  }
  ```

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

  user_turns = [
    "How many positive integers below 500 have exactly 6 positive divisors?",
    "How many of those are odd?"
  ]

  # messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  messages = []
  user_turns.each do |user_turn|
    messages << {role: "user", content: user_turn}
    response = client.beta.messages.create(
      model: "claude-fable-5-1",
      max_tokens: 16_000,
      thinking: {
        type: "adaptive",
        block_binding: {prefix_mismatch_behavior: "drop_block"}
      },
      messages: messages,
      betas: [Anthropic::AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01]
    )
    messages << {role: "assistant", content: response.content}
    thinking_blocks = response.content.count { |block| block.type == :thinking }
    dropped = (response.input_transformations || []).length
    puts "thinking blocks: #{thinking_blocks}, dropped: #{dropped}"
  end
  ```
</CodeGroup>

```text Output wrap
thinking blocks: 1, dropped: 0
thinking blocks: 1, dropped: 0
```

Ningún turno descarta un bloque porque nada anterior cambió. Verifica que la primera respuesta contenga un bloque `thinking`. Con el pensamiento adaptativo, algunas respuestas no tienen ninguno. Si ninguna respuesta de la sesión tiene uno, no hay nada que verificar y el conteo de descartados es 0 sin importar lo que cambies, así que vuelve a ejecutar el ejemplo.

Registra `input_transformations` en cada turno de tu propia integración. Cuando la API descarta un bloque, la entrada se ve así:

```json
{
  "input_transformations": [
    {
      "type": "thinking_dropped",
      "path": "messages.1.content.0",
      "reason": "prefix_binding_mismatch"
    }
  ]
}
```

* **Vacío en cada turno de una sesión que contiene bloques `thinking`:** tu integración mantiene el prefijo intacto.
* **`reason: "prefix_binding_mismatch"`:** algo antes del bloque en `path` cambió desde la solicitud anterior. Compara `system`, `tools` y `messages` hasta ese turno para encontrarlo, o vuelve a enviar la solicitud con `"error"`: el 400 normalmente termina con una oración que nombra lo que cambió. Luego busca el reemplazo correspondiente en [Hacer cambios sin editar el prefijo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#replace-prefix-edits).
* **`reason: "model_binding_mismatch"`:** la conversación pasó a un modelo que no puede leer los bloques del modelo anterior. Esto no es una edición del prefijo. Consulta [Cambiar de modelo a mitad de la conversación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#switching-models).
* **`reason: "organization_binding_mismatch"`:** el bloque vino de otra cuenta. Consulta [Los bloques de pensamiento permanecen con la cuenta que los produjo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#account-bound-thinking).

Para ver un fallo a propósito, envía un tercer turno del ejemplo anterior y agrega una indicación del sistema `system` solo a esa solicitud, de modo que difiera de las dos primeras solicitudes, que no tenían ninguna. Con `"drop_block"`, el conteo de descartados ya no es 0: la respuesta tiene una entrada por cada bloque de pensamiento del historial, cada una con `reason: "prefix_binding_mismatch"`. Con `"error"`, la solicitud devuelve el 400 descrito en [Qué hace la API con un bloque no válido](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#mismatch-behavior), y su última oración nombra la indicación del sistema `system`. En las pestañas de cURL y CLI, quita el filtro `jq` para ver el cuerpo del error. Si el conteo sigue siendo 0, no había nada que verificar: confirma que el modelo sea claude-fable-5-1, que la solicitud establezca `block_binding`, que el historial que enviaste contenga bloques `thinking` y que las dos primeras solicitudes no tuvieran indicación del sistema `system`.

Dos turnos simples rara vez muestran el problema. Ejecuta una sesión a través de cada uno de los siguientes casos, con `"error"` establecido para que una regresión haga fallar tu CI:

* La primera compactación o recorte del lado del cliente
* Una herramienta, plugin o servidor MCP que se conecta después del primer turno
* Un cambio de modo o de instrucciones
* Un bucle largo de herramientas, si agregas recordatorios o acortas resultados de herramientas antiguos
* Un cambio a otro modelo y de vuelta
* Un guardado, un reinicio y una reanudación en una fecha posterior

En una cuenta más antigua, también puedes observar el tráfico de producción sin optar por la aplicación: envía el encabezado beta, deja fuera `block_binding` y registra `input_transformations`. Enviar solo el encabezado no cambia lo que recibe el modelo. Cada bloque de pensamiento que viene después del contenido que editaste falla la verificación y recibe su propia entrada `thinking_mismatch_allowed`, con los mismos campos `path` y `reason` que una entrada `thinking_dropped`. Los bloques anteriores a la edición siguen pasando. Una edición de `system` o `tools` viene antes de todos los bloques, así que hace fallar todos los bloques de pensamiento de la solicitud. Una entrada se ve así:

```json
{
  "input_transformations": [
    {
      "type": "thinking_mismatch_allowed",
      "path": "messages.1.content.0",
      "reason": "prefix_binding_mismatch"
    }
  ]
}
```

Ejecuta el siguiente ejemplo desde una [cuenta más antigua](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#enforcement), porque una cuenta más nueva rechaza su tercera solicitud con el 400. El ejemplo envía el encabezado sin `block_binding` y extiende la sesión anterior con una tercera solicitud que agrega una indicación del sistema, lo que cambia el prefijo a propósito. Después de cada turno imprime el número de bloques `thinking` y de bloques marcados:

<CodeGroup>
  ```bash cURL
  # Cuenta los bloques de pensamiento de una respuesta y los que fallaron la verificación del prefijo
  COUNTS='"thinking blocks: \([.content[] | select(.type == "thinking")] | length), " +
    "flagged: \([.input_transformations[] |
      select(.type == "thinking_mismatch_allowed")] | length)"'

  FIRST=$(curl -s https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
    -d '{
      "model": "claude-fable-5-1",
      "max_tokens": 16000,
      "thinking": { "type": "adaptive" },
      "messages": [
        {
          "role": "user",
          "content": "How many positive integers below 500 have exactly 6 positive divisors?"
        }
      ]
    }')
  echo "$FIRST" | jq -r "$COUNTS"

  # Turno 2: el turno del asistente se devuelve tal cual se recibió, seguido del siguiente mensaje del usuario
  MESSAGES=$(jq -n --argjson first "$FIRST" '[
    {
      role: "user",
      content: "How many positive integers below 500 have exactly 6 positive divisors?"
    },
    { role: "assistant", content: $first.content },
    { role: "user", content: "How many of those are odd?" }
  ]')

  SECOND=$(jq -n --argjson messages "$MESSAGES" '{
    model: "claude-fable-5-1",
    max_tokens: 16000,
    thinking: { type: "adaptive" },
    messages: $messages
  }' | curl -s https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
    -d @-)
  echo "$SECOND" | jq -r "$COUNTS"

  # Turno 3: solo esta solicitud agrega una indicación del sistema, lo que cambia el prefijo a propósito
  jq -n --argjson messages "$MESSAGES" --argjson second "$SECOND" '{
    model: "claude-fable-5-1",
    max_tokens: 16000,
    thinking: { type: "adaptive" },
    system: "Answer briefly.",
    messages: ($messages + [
      { role: "assistant", content: $second.content },
      { role: "user", content: "And how many of the odd ones are below 100?" }
    ])
  }' | curl -s https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
    -d @- | jq -r "$COUNTS"
  ```

  ```bash CLI
  # Cuenta los bloques de pensamiento de una respuesta y los que fallaron la verificación del prefijo
  COUNTS='"thinking blocks: \([.content[] | select(.type == "thinking")] | length), " +
    "flagged: \([.input_transformations[] |
      select(.type == "thinking_mismatch_allowed")] | length)"'

  FIRST=$(ant beta:messages create --beta thinking-binding-controls-2026-08-01 \
    --format json <<'YAML'
  model: claude-fable-5-1
  max_tokens: 16000
  thinking:
    type: adaptive
  messages:
    - role: user
      content: How many positive integers below 500 have exactly 6 positive divisors?
  YAML
  )
  echo "$FIRST" | jq -r "$COUNTS"

  # Turno 2: el turno del asistente se devuelve tal cual se recibió, seguido del siguiente mensaje del usuario
  SECOND=$(ant beta:messages create --beta thinking-binding-controls-2026-08-01 \
    --format json <<YAML
  model: claude-fable-5-1
  max_tokens: 16000
  thinking:
    type: adaptive
  messages:
    - role: user
      content: How many positive integers below 500 have exactly 6 positive divisors?
    - role: assistant
      content: $(echo "$FIRST" | jq -c .content)
    - role: user
      content: How many of those are odd?
  YAML
  )
  echo "$SECOND" | jq -r "$COUNTS"

  # Turno 3: solo esta solicitud agrega una indicación del sistema, lo que cambia el prefijo a propósito
  ant beta:messages create --beta thinking-binding-controls-2026-08-01 \
    --format json <<YAML | jq -r "$COUNTS"
  model: claude-fable-5-1
  max_tokens: 16000
  thinking:
    type: adaptive
  system: Answer briefly.
  messages:
    - role: user
      content: How many positive integers below 500 have exactly 6 positive divisors?
    - role: assistant
      content: $(echo "$FIRST" | jq -c .content)
    - role: user
      content: How many of those are odd?
    - role: assistant
      content: $(echo "$SECOND" | jq -c .content)
    - role: user
      content: And how many of the odd ones are below 100?
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  user_turns = [
      "How many positive integers below 500 have exactly 6 positive divisors?",
      "How many of those are odd?",
      "And how many of the odd ones are below 100?",
  ]

  # messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  messages = []
  for turn, user_turn in enumerate(user_turns, start=1):
      messages.append({"role": "user", "content": user_turn})
      response = client.beta.messages.create(
          model="claude-fable-5-1",
          max_tokens=16000,
          thinking={"type": "adaptive"},
          # Solo la última solicitud agrega una indicación del sistema, lo que cambia el prefijo a propósito
          system="Answer briefly." if turn == len(user_turns) else anthropic.omit,
          messages=messages,
          betas=["thinking-binding-controls-2026-08-01"],
      )
      messages.append({"role": "assistant", "content": response.content})
      thinking_blocks = sum(block.type == "thinking" for block in response.content)
      flagged = sum(
          transformation.type == "thinking_mismatch_allowed"
          for transformation in response.input_transformations or []
      )
      print(f"thinking blocks: {thinking_blocks}, flagged: {flagged}")
  ```

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

  const userTurns = [
    "How many positive integers below 500 have exactly 6 positive divisors?",
    "How many of those are odd?",
    "And how many of the odd ones are below 100?"
  ];

  // messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  const messages: Anthropic.Beta.BetaMessageParam[] = [];
  for (const [turnIndex, userTurn] of userTurns.entries()) {
    messages.push({ role: "user", content: userTurn });
    const response = await client.beta.messages.create({
      model: "claude-fable-5-1",
      max_tokens: 16000,
      thinking: { type: "adaptive" },
      // Solo la última solicitud agrega una indicación del sistema, lo que cambia el prefijo a propósito
      system: turnIndex === userTurns.length - 1 ? "Answer briefly." : undefined,
      messages,
      betas: ["thinking-binding-controls-2026-08-01"]
    });
    messages.push({ role: "assistant", content: response.content });
    const thinkingBlocks = response.content.filter((block) => block.type === "thinking");
    const flagged = (response.input_transformations ?? []).filter(
      (transformation) => transformation.type === "thinking_mismatch_allowed"
    );
    console.log(`thinking blocks: ${thinkingBlocks.length}, flagged: ${flagged.length}`);
  }
  ```

  ```csharp C#
  AnthropicClient client = new();

  string[] userTurns =
  [
      "How many positive integers below 500 have exactly 6 positive divisors?",
      "How many of those are odd?",
      "And how many of the odd ones are below 100?",
  ];

  // messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  List<BetaMessageParam> messages = [];
  for (var turnIndex = 0; turnIndex < userTurns.Length; turnIndex++)
  {
      messages.Add(new() { Role = Role.User, Content = userTurns[turnIndex] });
      var response = await client.Beta.Messages.Create(
          new()
          {
              Model = Model.ClaudeFable5_1,
              MaxTokens = 16000,
              Thinking = new BetaThinkingConfigAdaptive(),
              // Solo la última solicitud agrega una indicación del sistema, lo que cambia el prefijo a propósito
              System = turnIndex == userTurns.Length - 1 ? new("Answer briefly.") : null,
              Messages = messages,
              Betas = [AnthropicBeta.ThinkingBindingControls2026_08_01],
          }
      );
      messages.Add(new()
      {
          Role = Role.Assistant,
          Content = response.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
      });
      var thinkingBlocks = response.Content.Count(block => block.TryPickThinking(out _));
      var flagged = response.InputTransformations?.Count(transformation =>
          transformation.TryPickThinkingMismatchAllowed(out _)
      ) ?? 0;
      Console.WriteLine($"thinking blocks: {thinkingBlocks}, flagged: {flagged}");
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  userTurns := []string{
  	"How many positive integers below 500 have exactly 6 positive divisors?",
  	"How many of those are odd?",
  	"And how many of the odd ones are below 100?",
  }

  // messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  messages := []anthropic.BetaMessageParam{}
  for i, userTurn := range userTurns {
  	messages = append(messages, anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(userTurn)))
  	// Solo la última solicitud agrega una indicación del sistema, lo que cambia el prefijo a propósito
  	var system []anthropic.BetaTextBlockParam
  	if i == len(userTurns)-1 {
  		system = []anthropic.BetaTextBlockParam{{Text: "Answer briefly."}}
  	}
  	response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  		Model:     anthropic.ModelClaudeFable5_1,
  		MaxTokens: 16000,
  		Thinking: anthropic.BetaThinkingConfigParamUnion{
  			OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{},
  		},
  		System:   system,
  		Messages: messages,
  		Betas:    []anthropic.AnthropicBeta{anthropic.AnthropicBetaThinkingBindingControls2026_08_01},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	messages = append(messages, response.ToParam())
  	thinkingBlocks := 0
  	for _, block := range response.Content {
  		if block.Type == "thinking" {
  			thinkingBlocks++
  		}
  	}
  	flagged := 0
  	for _, transformation := range response.InputTransformations {
  		if transformation.Type == "thinking_mismatch_allowed" {
  			flagged++
  		}
  	}
  	fmt.Printf("thinking blocks: %d, flagged: %d\n", thinkingBlocks, flagged)
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlock;
  import com.anthropic.models.beta.messages.BetaInputTransformation;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaThinkingConfigAdaptive;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  import com.anthropic.models.messages.Model;

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

      List<String> userTurns = List.of(
          "How many positive integers below 500 have exactly 6 positive divisors?",
          "How many of those are odd?",
          "And how many of the odd ones are below 100?");

      // La lista de mensajes del builder crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
      MessageCreateParams.Builder conversation = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5_1)
          .maxTokens(16000L)
          .thinking(BetaThinkingConfigAdaptive.builder().build())
          .addBeta(AnthropicBeta.THINKING_BINDING_CONTROLS_2026_08_01);

      for (int turnIndex = 0; turnIndex < userTurns.size(); turnIndex++) {
          if (turnIndex == userTurns.size() - 1) {
              // Solo la última solicitud agrega una indicación del sistema, lo que cambia el prefijo a propósito
              conversation.system("Answer briefly.");
          }
          conversation.addUserMessage(userTurns.get(turnIndex));
          BetaMessage response = client.beta().messages().create(conversation.build());
          conversation.addMessage(response);
          long thinkingBlocks = response.content().stream()
              .filter(BetaContentBlock::isThinking)
              .count();
          long flagged = response.inputTransformations().stream()
              .flatMap(List::stream)
              .filter(BetaInputTransformation::isThinkingMismatchAllowed)
              .count();
          IO.println("thinking blocks: " + thinkingBlocks + ", flagged: " + flagged);
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaThinkingConfigAdaptive;
  use Anthropic\Beta\Messages\BetaThinkingMismatchAllowedInputTransformation;
  use Anthropic\Client;

  $client = new Client();

  $userTurns = [
      'How many positive integers below 500 have exactly 6 positive divisors?',
      'How many of those are odd?',
      'And how many of the odd ones are below 100?',
  ];

  // $messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  $messages = [];
  foreach ($userTurns as $turnIndex => $userTurn) {
      $messages[] = ['role' => 'user', 'content' => $userTurn];
      $response = $client->beta->messages->create(
          model: 'claude-fable-5-1',
          maxTokens: 16000,
          thinking: BetaThinkingConfigAdaptive::with(),
          // Solo la última solicitud agrega una indicación del sistema, lo que cambia el prefijo a propósito
          system: $turnIndex === array_key_last($userTurns) ? 'Answer briefly.' : null,
          messages: $messages,
          betas: [AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01],
      );
      $messages[] = ['role' => 'assistant', 'content' => $response->content];
      $thinkingBlocks = array_filter($response->content, fn ($block) => $block->type === 'thinking');
      $flagged = array_filter(
          $response->inputTransformations ?? [],
          fn ($transformation) => $transformation instanceof BetaThinkingMismatchAllowedInputTransformation,
      );
      echo 'thinking blocks: ', count($thinkingBlocks), ', flagged: ', count($flagged), PHP_EOL;
  }
  ```

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

  user_turns = [
    "How many positive integers below 500 have exactly 6 positive divisors?",
    "How many of those are odd?",
    "And how many of the odd ones are below 100?"
  ]

  # messages crece entre turnos: cada turno del asistente se reenvía tal como se devolvió
  messages = []
  user_turns.each_with_index do |user_turn, turn_index|
    messages << {role: "user", content: user_turn}
    # Solo la última solicitud agrega una indicación del sistema, lo que cambia el prefijo a propósito
    system_param = (turn_index == user_turns.length - 1) ? {system_: "Answer briefly."} : {}
    response = client.beta.messages.create(
      model: "claude-fable-5-1",
      max_tokens: 16_000,
      thinking: {type: "adaptive"},
      messages: messages,
      betas: [Anthropic::AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01],
      **system_param
    )
    messages << {role: "assistant", content: response.content}
    thinking_blocks = response.content.count { |block| block.type == :thinking }
    flagged = (response.input_transformations || []).count do |transformation|
      transformation.type == :thinking_mismatch_allowed
    end
    puts "thinking blocks: #{thinking_blocks}, flagged: #{flagged}"
  end
  ```
</CodeGroup>

```text Output wrap
thinking blocks: 1, flagged: 0
thinking blocks: 1, flagged: 0
thinking blocks: 1, flagged: 2
```

La tercera respuesta marca todos los bloques de pensamiento de los turnos anteriores, uno por turno en esta ejecución, porque la nueva indicación del sistema viene antes de todos ellos. El modelo aun así los leyó.

Maneja estas entradas como lo harías con los descartes `prefix_binding_mismatch`. La edición está antes del primer bloque enumerado: compara `system`, `tools` y `messages` hasta el `path` de ese bloque con la solicitud anterior para encontrarla, y luego reemplázala con el patrón correspondiente en [Hacer cambios sin editar el prefijo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#replace-prefix-edits). En una cuenta nueva, o en cualquier solicitud que establezca `prefix_mismatch_behavior`, la API en cambio rechaza la solicitud o descarta los bloques que fallan. Las entradas son un límite inferior de lo que eliminaría la aplicación: con `"drop_block"`, un bloque que falla también arrastra el resto de los bloques de pensamiento de ese turno, y eliminar un bloque puede hacer que el siguiente también falle. Cuando la API solo registra la verificación, juzga cada bloque por separado y enumera un bloque solo si ese bloque falla.

## Hacer cambios sin editar el prefijo

Cada edición común del prefijo tiene un reemplazo que le da al modelo la misma información y deja sin cambios los bytes anteriores, así que el pensamiento posterior sigue siendo válido. Busca en la primera columna la edición que hace tu código hoy:

| En lugar de                                                                                                                              | Usa                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Encabezado beta                                                                                                                                                                                                                                                                |
| ---------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Reconstruir la indicación del sistema `system` de nivel superior                                                                         | Un [mensaje del sistema a mitad de la conversación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#new-instructions)                                                                                                                                                                                                                                                                                                                                                                       | Ninguno                                                                                                                                                                                                                                                                        |
| Volver a renderizar el contexto de tu primer mensaje del usuario (entorno, fecha, memoria, instrucciones del proyecto) en cada solicitud | Renderízalo una vez y vuelve a enviarlo sin cambios. Cuando algo cambie, [pon la nueva versión en el turno más reciente](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#changing-context)                                                                                                                                                                                                                                                                                                  | Ninguno                                                                                                                                                                                                                                                                        |
| Borrar o acortar contenido antiguo de `tool_result`, o volver a codificar imágenes antiguas, en el mismo lugar                           | Acorta un resultado de herramienta o reduce la resolución de una imagen antes de enviarlo por primera vez, no después. Para borrar resultados antiguos más adelante, [recorta el contexto en el servidor](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#server-side-trimming) con `clear_tool_uses_20250919`                                                                                                                                                                              | `context-management-2025-06-27`                                                                                                                                                                                                                                                |
| Inyectar un recordatorio y eliminarlo en la siguiente solicitud                                                                          | Un [mensaje del sistema con alcance de turno](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#per-turn-reminders) (`clear_at: "next_user_message"`)                                                                                                                                                                                                                                                                                                                                         | `mid-conversation-system-clear-at-2026-08-21`                                                                                                                                                                                                                                  |
| Agregar o eliminar entradas en `tools`                                                                                                   | [Bloques `tool_addition` y `tool_removal`](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#tool-changes)                                                                                                                                                                                                                                                                                                                                                                                    | `inline-tools-2026-09-15` (agrega `mcp-client-2026-09-15` cuando la herramienta proviene de un servidor MCP conectado a través del conector MCP), o el más antiguo `mid-conversation-tool-changes-2026-07-01`, que funciona en la API de Claude, Amazon Bedrock y Google Cloud |
| Cambiar `output_config.effort` de nivel superior (reinicia la caché, no afecta el pensamiento)                                           | Un [`output_config` por mensaje](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#effort-changes)                                                                                                                                                                                                                                                                                                                                                                                            | `mid-conversation-output-config-2026-07-01`                                                                                                                                                                                                                                    |
| Descartar o resumir turnos antiguos en el cliente                                                                                        | [Compactación bajo demanda](https://platform.claude.com/docs/es/build-with-claude/compaction-on-demand) para conservar los turnos recientes con su pensamiento, otra [compactación o edición de contexto](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#server-side-trimming) del lado del servidor, o [compactación del lado del cliente](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#custom-compaction-on-the-client) que no conserve pensamiento obsoleto | `compact-2026-09-04`                                                                                                                                                                                                                                                           |
| Una URL de imagen o documento cuyos bytes cambian entre solicitudes                                                                      | Un [`file_id` de la Files API](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#files-by-id), o base64                                                                                                                                                                                                                                                                                                                                                                                       | Ninguno                                                                                                                                                                                                                                                                        |

Todos estos suponen que [envías los turnos del asistente de vuelta exactamente como se devolvieron](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#append-assistant-turns-exactly-as-returned). Los mensajes del sistema a mitad de la conversación, los mensajes del sistema con alcance de turno y los cambios de herramientas no están disponibles en todos los modelos: [Mensajes del sistema y cambios de herramientas a mitad de conversación](https://platform.claude.com/docs/es/build-with-claude/mid-conversation-system-messages) enumera los modelos que los aceptan. Si tu código atiende a varios modelos, sigue editando la indicación del sistema `system` de nivel superior para los modelos que no los aceptan.

Para usar varias betas en una solicitud en la API de Claude, combina sus nombres en un solo encabezado `anthropic-beta`:

```text wrap
anthropic-beta: thinking-binding-controls-2026-08-01,mid-conversation-system-clear-at-2026-08-21,inline-tools-2026-09-15
```

Otras plataformas que ofrecen estas betas usan los mismos nombres. Para enviarlas allí, consulta [Funciones beta en otras plataformas](https://platform.claude.com/docs/es/api/beta-headers#beta-features-on-other-platforms).

### Enviar los turnos del asistente de vuelta exactamente como se devolvieron

Guarda el arreglo `content` de cada respuesta y envíalo de vuelta sin cambios como el turno del asistente: cada tipo de bloque, en el orden recibido, incluidos los bloques `thinking` cuyo campo `thinking` esté vacío. Un serializador que descarta tipos de bloque desconocidos, descarta campos vacíos o reordena bloques edita el prefijo para todos los turnos posteriores.

En Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 y Claude Haiku 5.5, el campo `thinking` está vacío de forma predeterminada y la `signature` lleva el razonamiento, por lo que un serializador que omite bloques vacíos elimina el pensamiento. Si los elimina todos, nada falla y el modelo pierde su razonamiento anterior en cada turno. Si analizas el stream tú mismo, conserva el bloque incluso cuando no llegue texto de pensamiento: se abre, recibe su `signature` en un evento `signature_delta` y se cierra. Un bloque devuelto con una `signature` vacía falla.

### Agregar instrucciones con un mensaje del sistema a mitad de conversación

Algunos harnesses reconstruyen la indicación del sistema `system` de nivel superior en cada solicitud para incluir la hora actual, un presupuesto de tokens, un indicador de modo o contexto del proyecto recién descubierto. Eso invalida todos los bloques de pensamiento de la conversación. En su lugar, congela `system` al inicio de la sesión. Cuando algo cambie, agrega un [mensaje `role: "system"`](https://platform.claude.com/docs/es/build-with-claude/mid-conversation-system-messages) en el punto de `messages` donde el cambio se vuelve cierto:

```json
{
  "role": "system",
  "content": "The user switched the workspace to read-only mode. Do not write files until told otherwise."
}
```

El modelo trata este mensaje con la autoridad de una indicación del sistema, y todo lo anterior permanece sin cambios. En un bucle de herramientas, coloca el mensaje después del mensaje del usuario con el `tool_result`, nunca entre un `tool_use` del asistente y su `tool_result` (consulta [Limitaciones](https://platform.claude.com/docs/es/build-with-claude/mid-conversation-system-messages#limitations)). Una vez enviado, el mensaje forma parte del prefijo para el pensamiento posterior: déjalo en su lugar en las solicitudes posteriores.

### Poner el contexto cambiante en el turno más reciente

Algunos harnesses ponen un bloque de entorno en el primer mensaje del usuario (directorio de trabajo, rama, fecha, memoria, instrucciones del proyecto) y lo vuelven a renderizar en cada solicitud. Cuando cambia cualquier valor, `messages[0]` cambia, y todos los bloques de pensamiento de la conversación dejan de ser válidos. Renderiza ese bloque una vez y reenvíalo tal como estaba. Cuando un valor cambie, indícalo en el turno más reciente: agrega un bloque de texto al mensaje del usuario que estás por enviar, o agrega un [mensaje del sistema a mitad de conversación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#new-instructions) si el cambio proviene de ti como operador.

```json
{
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": "Environment update: the current branch is now release-2."
    },
    { "type": "text", "text": "Run the tests again." }
  ]
}
```

Una vez enviado, ese bloque de texto forma parte del prefijo para el pensamiento posterior: déjalo en su lugar en las solicitudes posteriores.

### Envía recordatorios por turno como mensajes de sistema con alcance de turno

Una edición común del prefijo es el recordatorio por turno: una línea como "solicita las lecturas independientes juntas" o "hace tiempo que no le das una actualización al usuario" que tu código agrega después de cada lote de resultados de herramientas. Para evitar que los recordatorios se acumulen, envía cada recordatorio como un [mensaje del sistema a mitad de conversación](https://platform.claude.com/docs/es/build-with-claude/mid-conversation-system-messages) con `clear_at: "next_user_message"`, colocado después del mensaje del usuario con el `tool_result`. `clear_at` requiere el encabezado beta `mid-conversation-system-clear-at-2026-08-21`. El siguiente arreglo `messages` es la solicitud después de dos llamadas a herramientas y sus resultados. `messages[3]` es el recordatorio de la solicitud anterior, dejado en su lugar, y `messages[6]` es la copia de esta solicitud:

```json
[
  { "role": "user", "content": "Fix the failing test." },
  {
    "role": "assistant",
    "content": [
      { "type": "thinking", "thinking": "", "signature": "..." },
      {
        "type": "tool_use",
        "id": "toolu_01",
        "name": "read_file",
        "input": { "path": "tests/test_auth.py" }
      }
    ]
  },
  {
    "role": "user",
    "content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "..." }]
  },
  {
    "role": "system",
    "clear_at": "next_user_message",
    "content": "Request every independent read in one turn."
  },
  {
    "role": "assistant",
    "content": [
      { "type": "thinking", "thinking": "", "signature": "..." },
      {
        "type": "tool_use",
        "id": "toolu_02",
        "name": "read_file",
        "input": { "path": "src/auth.py" }
      }
    ]
  },
  {
    "role": "user",
    "content": [{ "type": "tool_result", "tool_use_id": "toolu_02", "content": "..." }]
  },
  {
    "role": "system",
    "clear_at": "next_user_message",
    "content": "Request every independent read in one turn."
  }
]
```

Un mensaje del usuario que solo contiene bloques `tool_result` cuenta como el "siguiente mensaje del usuario", así que `messages[3]` ya está borrado. No agrega nada a lo que ve el modelo ni consume tokens de entrada, pero como sigue en el arreglo, el pensamiento de `messages[4]` sigue siendo válido. `messages[6]` es la copia que el modelo ve en este turno. En las solicitudes posteriores, deja ambos donde están y agrega una copia nueva después del siguiente mensaje con `tool_result`.

### Agregar o eliminar herramientas con `tool_addition` y `tool_removal`

Editar el arreglo `tools` a mitad de la sesión invalida los bloques de pensamiento preservados. Deja el arreglo tal como lo enviaste la primera vez. Para cambiar qué herramientas puede usar el modelo, agrega al final un mensaje `role: "system"` que contenga bloques `tool_addition` o `tool_removal`. Estos son [cambios de herramientas a mitad de la conversación](https://platform.claude.com/docs/es/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes) y necesitan el encabezado beta `inline-tools-2026-09-15`, que está disponible en la Claude API. El encabezado anterior `mid-conversation-tool-changes-2026-07-01` sigue funcionando para los cambios que nombran una herramienta por referencia, en la Claude API, Amazon Bedrock y Google Cloud.

Tienes dos formas de usar estos bloques:

* **Declarar todas las herramientas desde el principio.** Pon en `tools`, en la primera solicitud, todas las herramientas que la sesión pueda necesitar, con `defer_loading: true` en las que el modelo todavía no deba ver. Después, activa y desactiva herramientas con bloques `tool_addition` y `tool_removal` que las nombren.
* **Empezar con una instantánea y agregar herramientas sobre la marcha.** Pon en `tools`, en la primera solicitud, las herramientas que conoces. Cuando aparezca una herramienta nueva, defínela dentro de un bloque `tool_addition` en lugar de editar `tools`.

De cualquier forma, `tools` nunca cambia, por lo que el pensamiento anterior sigue siendo válido y la caché de prompts sigue acertando, con la única excepción que se indica más adelante en esta sección.

Por ejemplo, para retirar una herramienta peligrosa después de un cambio de modo:

```json
{
  "role": "system",
  "content": [
    { "type": "tool_removal", "tool": { "type": "tool_reference", "name": "delete_branch" } },
    { "type": "text", "text": "Branch deletion is disabled for the rest of this session." }
  ]
}
```

Para activar una herramienta que declaraste con `defer_loading: true`, agrega un bloque `tool_addition` que la nombre:

```json
{
  "role": "system",
  "content": [
    { "type": "tool_addition", "tool": { "type": "tool_reference", "name": "deploy" } },
    { "type": "text", "text": "Authentication succeeded. Deployment is now available." }
  ]
}
```

A veces no puedes declarar una herramienta desde el principio porque todavía no conoces su esquema: una herramienta que tu aplicación descubre en tiempo de ejecución, o un servidor MCP que se conecta después del primer turno. Defínela dentro del bloque `tool_addition` en lugar de modificar `tools`. Con `inline-tools-2026-09-15`, el `tool` del bloque puede ser `{"type": "tool_definition", "definition": {...}}`, con la misma entrada que habrías puesto en `tools`:

```json
{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": {
          "name": "db_query",
          "description": "Run a read-only SQL query against the analytics database.",
          "input_schema": {
            "type": "object",
            "properties": { "sql": { "type": "string" } },
            "required": ["sql"]
          }
        }
      }
    }
  ]
}
```

La nueva herramienta llega en `messages`, `tools` nunca cambia y el pensamiento anterior sigue siendo válido. Mantén al menos una herramienta sin `defer_loading: true` en `tools`: si todas las herramientas allí están diferidas, la primera herramienta que definas de esta forma cuesta un fallo completo de la caché de prompts.

Si la API se conecta al servidor MCP por ti mediante el [conector MCP](https://platform.claude.com/docs/es/agents-and-tools/mcp-connector), envía también `mcp-client-2026-09-15`. Cubre todo lo que hace `mcp-client-2025-11-20`, así que envíalo en lugar de ese. El `definition` del bloque puede ser entonces un `mcp_toolset` para un servidor incluido en `mcp_servers`. Cuando la API tiene que obtener la lista de herramientas de un servidor, la respuesta comienza con un bloque `mcp_tool_listing` para ese servidor. Devuélvelo sin cambios junto con el resto del turno del asistente, y sigue enviando `mcp-client-2026-09-15` en cada solicitud posterior que lo incluya. El bloque fija el conjunto de herramientas a esa lista, así que la API no vuelve a contactar al servidor para obtenerla. Estas funciones del conector MCP están disponibles en la Claude API.

Con solo el encabezado más antiguo, aún puedes agregar a `tools` una herramienta que descubras a mitad de sesión con `defer_loading: true` y luego ofrecerla con un bloque `tool_addition`. Es seguro porque la verificación del prefijo ignora una herramienta diferida hasta que un bloque `tool_addition` hace referencia a ella. Agregar una herramienta sin `defer_loading: true` cambia el prefijo e invalida el pensamiento anterior.

Los mensajes `role: "system"` que contienen estos bloques pasan a formar parte del prefijo para el pensamiento posterior. Déjalos en su lugar en las solicitudes posteriores.

### Cambiar el esfuerzo con un `output_config` por mensaje

Cambiar `output_config.effort` de nivel superior entre solicitudes no invalida el pensamiento, porque el esfuerzo no forma parte del prefijo. Cambiar el esfuerzo de nivel superior sí reinicia la caché de prompts. Donde el modelo y la plataforma admitan [esfuerzo por mensaje](https://platform.claude.com/docs/es/build-with-claude/effort#change-effort-mid-conversation-beta), úsalo en su lugar: añade un mensaje `role: "system"` con `content` vacío y el nuevo nivel. Necesita el encabezado beta `mid-conversation-output-config-2026-07-01`. En Claude Haiku 5.5, el esfuerzo por mensaje está disponible en la Claude API y Google Cloud y necesita pensamiento adaptativo.

```json
{ "role": "system", "content": [], "output_config": { "effort": "low" } }
```

Cuándo entra en vigor el nuevo nivel depende de dónde coloques el mensaje. Directamente después de un mensaje `user` con nueva entrada, comienza con la respuesta de Claude a ese mensaje. En cualquier otro lugar, como después de un mensaje `assistant` o después de un mensaje `user` que contiene solo bloques `tool_result`, comienza con el siguiente mensaje `user` con nueva entrada, por lo que un bucle de herramientas ya en curso mantiene el nivel actual hasta entonces. Una vez enviado, el mensaje forma parte de `messages` y, por lo tanto, del prefijo para el pensamiento posterior: déjalo en su lugar en las solicitudes posteriores y añade otro para volver a cambiar el esfuerzo.

### Recortar el contexto en el servidor

Otra edición común del prefijo es el recorte del lado del cliente: descartar o resumir los turnos más antiguos y conservar los recientes textualmente. Los bloques de pensamiento de los turnos conservados se produjeron cuando el historial eliminado todavía estaba presente, así que no pasan la verificación. Los equivalentes del lado del servidor no cuentan como ediciones, porque la verificación compara la conversación tal como la enviaste:

* La [compactación bajo demanda](https://platform.claude.com/docs/es/build-with-claude/compaction-on-demand) (beta) devuelve el resumen desde una solicitud separada, que puede [ejecutarse en segundo plano](https://platform.claude.com/docs/es/build-with-claude/compaction-background). Luego envías el bloque devuelto en lugar de los mensajes que resume. La verificación acepta ese reemplazo, así que los turnos que conservas pueden mantener su pensamiento válido, bajo 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). [Solicitar un resumen](https://platform.claude.com/docs/es/build-with-claude/compaction-on-demand#request-a-summary) muestra la solicitud e indica el encabezado beta que necesita.
* La [compactación al alcanzar un umbral de tokens](https://platform.claude.com/docs/es/build-with-claude/compaction-threshold) resume los turnos más antiguos en un bloque de compactación cuando el contexto se acerca a un umbral que tú estableces. El prefijo verificado se reinicia desde ese bloque. Su [parámetro `instructions`](https://platform.claude.com/docs/es/build-with-claude/compaction-threshold#custom-summarization-instructions) acepta tu propio prompt de resumen, como "conserva cada ticker, tamaño de posición y supuesto declarado".
* La [edición de contexto](https://platform.claude.com/docs/es/build-with-claude/context-editing) borra resultados de herramientas antiguos o bloques de pensamiento antiguos según reglas, empezando por los más antiguos. Las estrategias son `clear_tool_uses_20250919` y `clear_thinking_20251015`.

### Compactar en el cliente

También puedes compactar en el cliente. Si escribes el resumen tú mismo, no devuelvas ningún bloque de pensamiento que se haya producido antes de la reescritura. Si la API escribe el resumen con compactación bajo demanda, consulta [Condiciones para que el pensamiento conservado siga siendo válido](https://platform.claude.com/docs/es/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) para saber cuándo el pensamiento conservado sigue siendo válido.

#### Compactación simple (recomendada)

Cuando la conversación se vuelva demasiado larga, resume toda la sesión en un solo mensaje del usuario y envía solo ese mensaje más la siguiente instrucción. No se reproduce nada anterior, por lo que no queda pensamiento que pueda fallar la verificación, y el modelo razona de nuevo a partir del resumen.

<Frame>
  ![Simple compaction (compactación simple): la solicitud 4 envía el historial completo con pensamiento en cada turno del asistente; la solicitud 5 envía un solo mensaje del usuario que contiene un resumen de los turnos 1 a 4 más la siguiente instrucción, por lo que no se envía pensamiento anterior y no se verifica nada](https://platform.claude.com/docs/images/preserved-thinking-simple-compaction.svg)
</Frame>

```json
[
  {
    "role": "user",
    "content": "<summary of the session so far>\n\n<the next instruction>"
  }
]
```

Los modelos Claude se entrenan en tareas de largo horizonte con este esquema y, para la mayoría de las cargas de trabajo, funciona bien.

#### Compactación con conservación de la cola

La "keep-tail compaction" (compactación con conservación de la cola) resume los turnos más antiguos y conserva textualmente los turnos más recientes, de modo que el modelo sigue viendo palabra por palabra los últimos intercambios. Si escribes el resumen tú mismo, rompe la regla: los turnos del asistente conservados aún llevan bloques de pensamiento que se produjeron cuando los turnos originales, no el resumen, los precedían. Esos bloques fallan.

Para conservar ese pensamiento, haz que la API escriba el resumen con compactación bajo demanda. [Compactación que conserva los turnos recientes](https://platform.claude.com/docs/es/build-with-claude/compaction-keep-recent-turns) muestra cómo hacerlo, y [Condiciones para que el pensamiento conservado siga siendo válido](https://platform.claude.com/docs/es/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) indica cuándo el pensamiento conservado sigue siendo válido.

El resto de esta sección trata sobre un resumen que escribes tú mismo.

<Frame>
  ![Keep-tail compaction (compactación con conservación de la cola): el historial se reemplaza por un resumen de los turnos 1 y 2 seguido de los turnos 3 a 5 textualmente; el pensamiento en los turnos 3 y 4 del asistente se produjo después de los turnos originales, no del resumen, por lo que falla; la misma solicitud enviada con prefix\_mismatch\_behavior drop\_block tiene éxito, la API descarta esos dos bloques y los lista en input\_transformations](https://platform.claude.com/docs/images/preserved-thinking-keep-tail-compaction.svg)
</Frame>

Solución: conserva los turnos exactamente como están y envía `prefix_mismatch_behavior: "drop_block"`. La API descarta los bloques de pensamiento obsoletos, el modelo lee los bloques `text` y `tool_use` de los turnos conservados, y la solicitud tiene éxito.

Pasa el historial compactado como `messages` y establece `block_binding` en la configuración de `thinking`. En el siguiente ejemplo, `compacted_messages` es el arreglo que produjo tu paso de compactación: el mensaje de resumen seguido de los turnos conservados exactamente como los devolvió la API, incluidos los bloques `thinking`:

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
    -d "{
      \"model\": \"claude-fable-5-1\",
      \"max_tokens\": 16000,
      \"thinking\": {
        \"type\": \"adaptive\",
        \"block_binding\": { \"prefix_mismatch_behavior\": \"drop_block\" }
      },
      \"messages\": $COMPACTED_MESSAGES
    }"
  ```

  ```bash CLI
  ant beta:messages create --beta thinking-binding-controls-2026-08-01 <<YAML
  model: claude-fable-5-1
  max_tokens: 16000
  thinking:
    type: adaptive
    block_binding:
      prefix_mismatch_behavior: drop_block
  messages: $COMPACTED_MESSAGES
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  # compacted_messages: el mensaje de resumen y luego los turnos conservados tal como se devuelven
  response = client.beta.messages.create(
      model="claude-fable-5-1",
      max_tokens=16000,
      thinking={
          "type": "adaptive",
          "block_binding": {"prefix_mismatch_behavior": "drop_block"},
      },
      messages=compacted_messages,
      betas=["thinking-binding-controls-2026-08-01"],
  )

  print(response.input_transformations)
  ```

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

  // compactedMessages: el mensaje de resumen y luego los turnos conservados tal como se devuelven
  const response = await client.beta.messages.create({
    model: "claude-fable-5-1",
    max_tokens: 16000,
    thinking: {
      type: "adaptive",
      block_binding: { prefix_mismatch_behavior: "drop_block" }
    },
    messages: compactedMessages,
    betas: ["thinking-binding-controls-2026-08-01"]
  });

  console.log(response.input_transformations);
  ```

  ```csharp C#
  AnthropicClient client = new();

  // compactedMessages: el mensaje de resumen y luego los turnos conservados tal como se devolvieron
  var response = await client.Beta.Messages.Create(
      new()
      {
          Model = Model.ClaudeFable5_1,
          MaxTokens = 16000,
          Thinking = new BetaThinkingConfigAdaptive
          {
              BlockBinding = new()
              {
                  PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.DropBlock,
              },
          },
          Messages = compactedMessages,
          Betas = [AnthropicBeta.ThinkingBindingControls2026_08_01],
      }
  );

  Console.WriteLine(response.InputTransformations?.Count ?? 0);
  ```

  ```go Go
  client := anthropic.NewClient()

  // compactedMessages: el mensaje de resumen y luego los turnos conservados tal como se devuelven
  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5_1,
  	MaxTokens: 16000,
  	Thinking: anthropic.BetaThinkingConfigParamUnion{
  		OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  			BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  				PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorDropBlock,
  			},
  		},
  	},
  	Messages: compactedMessages,
  	Betas:    []anthropic.AnthropicBeta{anthropic.AnthropicBetaThinkingBindingControls2026_08_01},
  })
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Println(len(response.InputTransformations))
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaMessage;
  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;
  import com.anthropic.models.messages.Model;

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

      // compactedMessages: el mensaje de resumen y luego los turnos conservados tal como se devuelven
      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5_1)
          .maxTokens(16000L)
          .thinking(BetaThinkingConfigAdaptive.builder()
              .blockBinding(BetaThinkingBlockBinding.builder()
                  .prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.DROP_BLOCK)
                  .build())
              .build())
          .messages(compactedMessages)
          .addBeta(AnthropicBeta.THINKING_BINDING_CONTROLS_2026_08_01)
          .build();

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

      IO.println(response.inputTransformations());
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaThinkingBlockBinding;
  use Anthropic\Beta\Messages\BetaThinkingConfigAdaptive;
  use Anthropic\Beta\Messages\BetaThinkingPrefixMismatchBehavior;
  use Anthropic\Client;

  $client = new Client();

  // $compactedMessages: el mensaje de resumen y luego los turnos conservados tal como se devolvieron
  $response = $client->beta->messages->create(
      model: 'claude-fable-5-1',
      maxTokens: 16000,
      thinking: BetaThinkingConfigAdaptive::with(
          blockBinding: BetaThinkingBlockBinding::with(
              prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::DROP_BLOCK,
          ),
      ),
      messages: $compactedMessages,
      betas: [AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01],
  );

  var_dump($response->inputTransformations);
  ```

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

  # compacted_messages: el mensaje de resumen y luego los turnos conservados tal como se devuelven
  response = client.beta.messages.create(
    model: "claude-fable-5-1",
    max_tokens: 16_000,
    thinking: {
      type: "adaptive",
      block_binding: {prefix_mismatch_behavior: "drop_block"}
    },
    messages: compacted_messages,
    betas: [Anthropic::AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01]
  )

  puts response.input_transformations
  ```
</CodeGroup>

La respuesta contiene el nuevo turno del asistente como de costumbre, más una entrada `input_transformations` por cada bloque descartado. Para el historial del diagrama, eso corresponde al pensamiento en los turnos 3 y 4 del asistente:

```json
{
  "input_transformations": [
    {
      "type": "thinking_dropped",
      "path": "messages.2.content.0",
      "reason": "prefix_binding_mismatch"
    },
    {
      "type": "thinking_dropped",
      "path": "messages.4.content.0",
      "reason": "prefix_binding_mismatch"
    }
  ]
}
```

Sigue enviando `"drop_block"` en las solicitudes posteriores mientras esos dos turnos permanezcan en el historial. El pensamiento que el modelo produce a partir de esta solicitud sigue al resumen y sigue siendo válido. Si prefieres no depender del encabezado beta, la alternativa es eliminar tú mismo los bloques `thinking` y `redacted_thinking` de los turnos del asistente conservados cuando construyas el historial compactado.

#### Compactación en segundo plano (asíncrona)

La compactación en segundo plano construye el resumen fuera de la ruta crítica mientras la conversación continúa, y lo sustituye unas cuantas solicitudes después. Para conservar el pensamiento producido mientras tanto, haz que la API escriba el resumen con compactación bajo demanda. [Compactación en segundo plano](https://platform.claude.com/docs/es/build-with-claude/compaction-background) describe los pasos. Ese pensamiento sigue siendo válido bajo las mismas [condiciones para el pensamiento conservado](https://platform.claude.com/docs/es/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) que los turnos recientes conservados.

Un resumen que construyes tú mismo rompe la regla de la misma manera que keep-tail, pero con un retraso: cada turno del asistente producido mientras se construía el resumen lleva pensamiento anterior al intercambio, y todo falla en el momento en que llega el resumen. Si usas uno, trata el intercambio como keep-tail y envía `"drop_block"` desde el intercambio en adelante, o compacta de forma síncrona.

#### Patrones que no funcionan con el pensamiento preservado

* **Recortar turnos del medio.** Eliminar turnos individuales invalida cada bloque de pensamiento posterior a ellos, y ningún esquema de compactación lo evita. Si estabas recortando un turno para cambiar una instrucción, añade en su lugar un [mensaje del sistema a mitad de conversación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#new-instructions). Para eliminar selectivamente resultados de herramientas antiguos o pensamiento antiguo, usa la [edición de contexto](https://platform.claude.com/docs/es/build-with-claude/context-editing) del lado del servidor.
* **Compactar en medio de una ronda de herramientas.** No compactes entre el `tool_use` de un turno del asistente y el `tool_result` que lo responde. Devuelve ese turno del asistente con su pensamiento intacto para que el modelo termine la ronda con su razonamiento. Consulta [Preservar bloques de pensamiento](https://platform.claude.com/docs/es/build-with-claude/thinking#preserving-thinking-blocks).

### Referencia archivos por ID, no por una URL cuyo contenido cambia

Para un bloque `image` o `document` con una fuente `url`, la verificación cubre los bytes obtenidos, no la cadena de la URL. Una URL cuyo contenido cambia invalida el pensamiento posterior: un endpoint de "última captura de pantalla", o un documento que alguien edita entre turnos. Una URL firmada rotativa para el mismo archivo no lo hace. Para el contenido que referencias a lo largo de varios turnos, súbelo una vez con la [Files API](https://platform.claude.com/docs/es/build-with-claude/files) y usa el `file_id`, o envía base64.

### Bibliotecas, proxies y gateways

Una biblioteca, proxy o gateway se sitúa entre el historial de otra persona y la API, por lo que sus propias reescrituras cuentan como ediciones, y sus usuarios no pueden verlas ni corregirlas.

* **Transmite lo que no reconozcas.** Reenvía sin cambios los valores `anthropic-beta` y `thinking.block_binding` del llamador, y devuélvele `input_transformations`. Un esquema de opciones que rechaza claves desconocidas impide que tus usuarios elijan `"drop_block"`.
* **Deja un mensaje `role: "system"` donde el llamador lo puso.** Moverlo al campo `system` de nivel superior cambia `system` en esa solicitud e invalida cada bloque de pensamiento de la conversación.
* **Para desactivar el uso de herramientas en una solicitud, envía `tool_choice: {"type": "none"}`.** No elimines `tools`.
* **No ocultes el 400.** Si tu código lo captura, elimina el pensamiento y reintenta en nombre del llamador, registra que lo hizo: su historial sigue editado, y el modelo pierde su razonamiento anterior en cada solicitud posterior.

## Preguntas frecuentes

<AccordionGroup>
  <Accordion title="¿Necesito una cuenta nueva para probar el pensamiento preservado?">
    No. Envía el encabezado beta `thinking-binding-controls-2026-08-01` y establece `thinking.block_binding.prefix_mismatch_behavior`. Establecer el campo hace que esa solicitud se someta a la verificación independientemente de la antigüedad de la cuenta. `"error"` rechaza un historial editado con el mismo 400 que recibe una cuenta nueva, y `"drop_block"` deja pasar la solicitud y lista lo que se descartó en `input_transformations`. Para encontrar ediciones del prefijo desde una cuenta más antigua sin aplicar la verificación, envía el encabezado y deja el campo sin establecer: los bloques que fallan siguen llegando al modelo, e `input_transformations` los lista como `thinking_mismatch_allowed`. Consulta [Verificar si tu código edita el prefijo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#how-to-tell-whether-your-integration-is-impacted).
  </Accordion>

  <Accordion title="Si algo antes de un bloque de pensamiento cambia, aunque sea la descripción de una herramienta, ¿la conversación queda inutilizable?">
    No. Lo que falla es el pensamiento que ya está en el historial después del punto que cambiaste, y tú eliges qué le sucede. Con `prefix_mismatch_behavior: "drop_block"`, la API descarta esos bloques y la solicitud tiene éxito: el modelo responde ese turno sin ese razonamiento, y la caché de prompts se reinicia en la edición. Con el valor predeterminado `"error"`, la API rechaza la solicitud con un 400 hasta que deshagas la edición o la reenvíes con `"drop_block"`. Consulta [Qué hace la API con un bloque no válido](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#mismatch-behavior). [Qué cuenta como una edición](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#what-counts-as-an-edit) indica qué cambios importan.
  </Accordion>

  <Accordion title="¿Cambiar el esfuerzo u otras configuraciones de pensamiento entre solicitudes invalida el pensamiento anterior?">
    No. `output_config.effort`, `max_tokens` y la configuración de `thinking` no forman parte del prefijo verificado, que cubre solo `system`, `tools` y `messages`. Un cambio de esfuerzo de nivel superior invalida la mayor parte de la caché de prompts. Donde el modelo y la plataforma admitan [esfuerzo por mensaje](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#effort-changes), un cambio de esfuerzo por mensaje conserva la caché de prompts y se usa como el nuevo nivel de esfuerzo hasta que se cambie de nuevo.
  </Accordion>

  <Accordion title="Mi lista de herramientas cambia a mitad de la sesión. ¿Cómo evito invalidar la conversación?">
    No edites `tools`. Declara el conjunto completo al inicio de la sesión, marca las herramientas que aún no están disponibles con `defer_loading: true`, y ofrécelas o retíralas con bloques `tool_addition` y `tool_removal`. Si conoces el esquema de una herramienta solo a mitad de la sesión, defínela dentro del bloque `tool_addition` (`inline-tools-2026-09-15`, más `mcp-client-2026-09-15` para un servidor al que llega el conector MCP de la API) y deja `tools` sin cambios. Los mensajes `role: "system"` que contienen estos bloques se unen al prefijo para el pensamiento posterior, así que no los muevas, reformules ni elimines después. Consulta [Agregar o eliminar herramientas con `tool_addition` y `tool_removal`](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#tool-changes).
  </Accordion>

  <Accordion title="Compacto resumiendo los turnos más antiguos y conservando textualmente los turnos recientes. ¿Eso sigue funcionando?">
    Sí, si la API escribe el resumen. La [compactación bajo demanda](https://platform.claude.com/docs/es/build-with-claude/compaction-on-demand) (encabezado beta `compact-2026-09-04`) resume los turnos más antiguos en un bloque firmado que envías en lugar de ellos. Los turnos recientes conservan su pensamiento bajo 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).

    Si escribes el resumen tú mismo, el pensamiento de los turnos conservados no pasa la verificación, porque esos bloques se produjeron con el historial que reemplazaste. Elimina los bloques `thinking` y `redacted_thinking` de los turnos que trasladas y conserva sus bloques `text` y `tool_use`, o envía `prefix_mismatch_behavior: "drop_block"` y deja que la API los descarte. La compactación simple no deja pensamiento que pueda fallar y es el enfoque recomendado: un mensaje de resumen más el siguiente turno del usuario, sin reproducir turnos anteriores. La [compactación](https://platform.claude.com/docs/es/build-with-claude/compaction) y la [edición de contexto](https://platform.claude.com/docs/es/build-with-claude/context-editing) del lado del servidor no cuentan como ediciones. Consulta [Compactar en el cliente](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#custom-compaction-on-the-client).
  </Accordion>

  <Accordion title="¿Cómo manejo archivos de instrucciones como AGENTS.md o CLAUDE.md que cambian a mitad de la sesión?">
    Cárgalos una vez al inicio de la sesión y mantén fijos la indicación del sistema `system` de nivel superior y `tools`. Cuando un archivo cambie, añade la nueva versión en ese punto de `messages` en lugar de editar el original. Usa un [mensaje del sistema a mitad de la conversación](https://platform.claude.com/docs/es/build-with-claude/mid-conversation-system-messages) para las instrucciones que provienen de ti como operador. Para el texto de archivos que tratas como no confiable, que no debería tener la autoridad de la indicación del sistema, coloca el contenido en el siguiente turno `user`. Consulta [Agregar instrucciones con un mensaje del sistema a mitad de conversación](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#new-instructions) y [Limitaciones](https://platform.claude.com/docs/es/build-with-claude/mid-conversation-system-messages#limitations).
  </Accordion>

  <Accordion title="¿Puedo reanudar una sesión guardada más tarde, después de un reinicio o al día siguiente?">
    Sí. Una sesión reanudada es una solicitud de seguimiento ordinaria: `system`, `tools` y los `messages` anteriores deben tener el mismo contenido que lo que enviaste por última vez. El formato JSON y el orden de las claves no importan; los valores sí. Guarda exactamente lo que enviaste y recibiste, y reprodúcelo: la indicación del sistema renderizada, las definiciones de herramientas y cada turno del asistente tal como se devolvió. No vuelvas a renderizar a partir de entradas que podrían haber cambiado desde entonces, como la fecha, un archivo de instrucciones actualizado o una nueva versión de una herramienta. Todo lo nuevo va en un mensaje añadido. Consulta [Enviar los turnos del asistente de vuelta exactamente como se devolvieron](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#append-assistant-turns-exactly-as-returned).
  </Accordion>

  <Accordion title="Una sesión guardada ahora falla en cada solicitud. ¿Cómo hago que vuelva a funcionar?">
    El historial almacenado contiene una edición, por lo que reproducirlo no puede tener éxito. Envía esa sesión con `prefix_mismatch_behavior: "drop_block"` de ahora en adelante, o elimina sus bloques `thinking` y `redacted_thinking` una vez y continúa. En Claude Sonnet 5.5 y Claude Haiku 5.5, `block_binding` funciona solo con `thinking: {"type": "adaptive"}`. Con `between_tools` en Claude Sonnet 5.5, o `thinking: {"type": "disabled"}` en Claude Haiku 5.5, mantén el historial de solo anexar, o elimina los bloques de pensamiento desde el turno editado en adelante. El pensamiento que el modelo produce a partir de ese punto sigue siendo válido mientras nada anterior vuelva a cambiar. Luego encuentra la edición para que las sesiones nuevas no la encuentren. Consulta [Manejar el error en el código](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#handle-the-error-in-code).
  </Accordion>

  <Accordion title="Mi harness puede dirigir un turno a un modelo que no es Claude. ¿Esos turnos invalidan el pensamiento anterior de Claude?">
    No, siempre que se añadan después del historial existente y nada anterior cambie: un mensaje del asistente sin bloques de pensamiento es un mensaje añadido como cualquier otro. Envía la salida del otro modelo como contenido `text` y `tool_use`.
  </Accordion>

  <Accordion title="¿Puedo trasladar el razonamiento de una conversación a una conversación nueva?">
    No a una conversación diferente. Un bloque de pensamiento solo se puede usar cuando sigue exactamente a los `system`, `tools` y `messages` a partir de los cuales se produjo. Una rama que reproduce ese historial sin cambios hasta el punto de bifurcación conserva su pensamiento. Una conversación que comienza a partir de cualquier otra cosa no puede usarlo, así que comienza esa conversación a partir de un resumen del estado de la tarea, como en la [compactación simple](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#custom-compaction-on-the-client): el objetivo, las decisiones tomadas, los archivos y resultados hasta el momento, y el siguiente paso. Los bloques de pensamiento de Claude Sonnet 5.5 y Claude Haiku 5.5 tampoco se pueden reutilizar desde otra cuenta (consulta [Los bloques de pensamiento permanecen con la cuenta que los produjo](https://platform.claude.com/docs/es/build-with-claude/preserved-thinking#account-bound-thinking)).
  </Accordion>
</AccordionGroup>

## Próximos pasos

<CardGroup cols={2}>
  <Card title="Solución de problemas del pensamiento" icon="hammer" href="https://platform.claude.com/docs/es/build-with-claude/thinking-troubleshooting">
    Diagnostica y corrige las fallas de pensamiento más comunes: errores 400 de configuración, bloques de pensamiento vacíos o faltantes, detenciones por max\_tokens y fallos de caché.
  </Card>

  <Card title="Mensajes de sistema y cambios de herramientas a mitad de conversación" icon="messages" href="https://platform.claude.com/docs/es/build-with-claude/mid-conversation-system-messages">
    Cambia las instrucciones del sistema o la disponibilidad de herramientas a mitad de una conversación sin invalidar el prefijo en caché que las precede.
  </Card>

  <Card title="Compactación" icon="stack" href="https://platform.claude.com/docs/es/build-with-claude/compaction">
    Compactación de contexto del lado del servidor para administrar conversaciones largas que se acercan a los límites de la ventana de contexto.
  </Card>

  <Card title="Almacenamiento en caché de prompts" icon="database" href="https://platform.claude.com/docs/es/build-with-claude/prompt-caching">
    Almacena en caché prefijos de prompts con `cache_control` para reducir costos y latencia, usando caché automática o puntos de interrupción explícitos con TTL de 5 minutos o 1 hora.
  </Card>
</CardGroup>
