---
title: Réflexion préservée
url: https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking
description: La réflexion préservée permet à un modèle d'utiliser un bloc de réflexion d'un tour précédent uniquement si ce modèle ou l'un des modèles d'un ensemble fixe d'autres modèles l'a produit et que rien avant le bloc n'a changé.
---

La « preserved thinking » (réflexion préservée) est une propriété des modèles Claude récents qui protège contre la distillation. Elle détermine si le modèle peut utiliser un « thinking block » (bloc de réflexion) que vous renvoyez depuis un tour précédent. À partir de Claude Fable 5.1, lorsqu'un bloc `thinking` ou `redacted_thinking` revient dans une requête, l'API vérifie deux choses dans la `signature` du bloc :

* **Le modèle peut lire le bloc.** Chaque modèle lit ses propres blocs de réflexion et ceux d'un ensemble fixe d'autres modèles. Claude Fable 5.1 lit les blocs de Claude Opus 5 et, sur l'API Claude, de Claude Opus 5.5 ; ni Claude Opus 5 ni Claude Opus 5.5 ne lisent les blocs de Claude Fable 5.1. Si le modèle actuel ne peut pas lire un bloc, l'API le supprime de cette requête sans erreur. Consultez [Changer de modèle en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#switching-models).
* **Rien avant le bloc de réflexion n'a changé.** L'invite `system` de niveau supérieur, les `tools` et les `messages` situés avant le bloc constituent son « prefix » (préfixe). Si le préfixe diffère de ce que vous avez envoyé lorsque le bloc a été produit, ce bloc et tous les blocs de réflexion ultérieurs sont invalides, et l'API rejette la requête avec une erreur 400 ou supprime les blocs invalides, selon votre choix. Consultez [Conserver le préfixe inchangé](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#prefix-check).

Les blocs de réflexion de Claude Sonnet 5.5 et Claude Haiku 5.5 sont également liés au compte qui les a produits. Consultez [Les blocs de réflexion restent liés au compte qui les a produits](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#account-bound-thinking) pour savoir où l'API applique cette règle.

La vérification du modèle s'applique à tous les comptes. L'API applique la vérification du préfixe par défaut pour les comptes créés le 31 août 2026 à 00:00 UTC ou après. Sur les comptes plus anciens, elle n'applique la vérification du préfixe qu'aux requêtes qui définissent `thinking.block_binding.prefix_mismatch_behavior`. **Rendez votre intégration « append-only » (ajout seul) quel que soit l'âge de votre compte**, afin que le même code fonctionne sur tous les comptes, y compris les comptes récents soumis à la vérification par défaut.

## Qui doit modifier quelque chose

Rien ne change pour vous si Claude Code, claude.ai, Claude Managed Agents ou le Claude Agent SDK construit vos requêtes, ou si votre code garde `system` et `tools` fixes pendant une session et ne fait qu'ajouter des éléments à `messages`. Claude Mythos 5.1 et les modèles antérieurs à Claude Fable 5.1 n'effectuent pas la vérification du préfixe. Si vous ne renvoyez jamais de blocs de réflexion, la vérification du préfixe n'a rien à rejeter, et le modèle ne reçoit aucun de ses raisonnements antérieurs.

Vérifiez votre intégration si, entre deux requêtes d'une même conversation, elle effectue l'une des opérations suivantes. Chaque élément renvoie vers ce qu'il faut faire à la place :

* [Reconstruit l'invite `system`](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#new-instructions) : la date, un indicateur de mode, des instructions de projet relues, ou un plugin ou serveur MCP qui se connecte après le premier tour
* [Régénère le contexte dans le premier message utilisateur](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#changing-context)
* [Efface ou raccourcit d'anciens résultats d'outils, ou réencode d'anciennes images](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#server-side-trimming)
* [Résume ou supprime d'anciens tours côté client](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#custom-compaction-on-the-client) et conserve les tours récents avec leur réflexion
* [Ajoute, supprime ou modifie des entrées dans `tools`](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#tool-changes)
* [Ajoute un rappel à un tour utilisateur](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#per-turn-reminders) puis le supprime ou le réécrit plus tard
* [Supprime certains blocs `thinking` et conserve les suivants](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#append-assistant-turns-exactly-as-returned), ou les supprime puis [les remet plus tard](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#prefix-check)
* [Reconstruit une session enregistrée à partir de modèles](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#faq) au lieu de rejouer ce qu'elle a envoyé

Sur un compte plus ancien, aucune de ces opérations ne produit d'erreur à moins que la requête ne définisse `prefix_mismatch_behavior`, de sorte qu'une exécution sans erreur avec votre propre clé ne montre pas si votre code est concerné. Si des personnes utilisent votre outil avec leurs propres clés API, celles qui ont des comptes récents obtiendront l'erreur 400 avant vous. Pour voir ce qu'elles voient sans modifier le comportement de vos requêtes, envoyez l'en-tête bêta `thinking-binding-controls-2026-08-01`. Sur un compte plus ancien, chaque réponse signale alors les blocs qui échouent à la vérification, et le modèle les lit quand même (consultez [Définir le comportement en cas de non-correspondance et lire `input_transformations`](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#preserved-thinking-controls)).

Vérifiez également votre intégration si elle envoie des blocs de réflexion de Claude Sonnet 5.5 ou Claude Haiku 5.5 provenant d'un compte dans une requête effectuée par un autre compte. Consultez [Les blocs de réflexion restent liés au compte qui les a produits](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#account-bound-thinking).

## Changer de modèle en cours de conversation

Claude Fable 5.1 et Claude Mythos 5.1 lisent les blocs de réflexion produits l'un par l'autre et par les modèles Claude antérieurs. Aucun autre modèle ne lit les blocs de réflexion de Claude Fable 5.1 ou Claude Mythos 5.1.

Claude Opus 5.5 lit les blocs de réflexion de Claude Opus 5, des modèles Opus, Sonnet et Haiku antérieurs et, sur l'API Claude et Google Cloud, de Claude Sonnet 5.5 et Claude Haiku 5.5, mais pas ceux des modèles Claude Fable ou Claude Mythos. Sur l'API Claude, Claude Fable 5.1 et Claude Mythos 5.1 lisent les blocs de réflexion de Claude Opus 5.5 ; aucun autre modèle ne le fait. Ainsi, une conversation qui passe de Claude Opus 5 à Claude Opus 5.5 conserve son raisonnement, tout comme une conversation qui passe de Claude Opus 5.5 à Claude Fable 5.1 ou Claude Mythos 5.1 sur l'API Claude. Une conversation qui passe de Claude Fable 5.1 ou Claude Mythos 5.1 à Claude Opus 5.5, ou de Claude Opus 5.5 à tout modèle autre que ces deux-là, exécute les tours suivant le changement sans le raisonnement du modèle précédent. Les blocs sont supprimés, et non rejetés, comme décrit plus loin dans cette section.

Claude Sonnet 5.5 lit les blocs de réflexion de Claude Sonnet 5, Claude Opus 4.8, Claude Haiku 4.5 et des modèles antérieurs, et, sur l'API Claude et Google Cloud, de Claude Haiku 5.5, mais pas ceux de Claude Opus 5, Claude Opus 5.5 ou de tout modèle Claude Fable ou Claude Mythos. Sur l'API Claude et Google Cloud, Claude Opus 5.5 lit les blocs de réflexion de Claude Sonnet 5.5 ; aucun autre modèle ne le fait. Ainsi, une conversation qui passe de Claude Sonnet 5 à Claude Sonnet 5.5 conserve son raisonnement, tout comme une conversation qui passe de Claude Sonnet 5.5 à Claude Opus 5.5 sur l'API Claude et Google Cloud. Une conversation qui passe à Claude Sonnet 5.5 depuis Claude Opus 5, Claude Opus 5.5 ou un modèle Claude Fable ou Claude Mythos exécute les tours suivant le changement sans le raisonnement du modèle précédent. Il en va de même pour tout autre passage depuis Claude Sonnet 5.5, par exemple un [repli côté serveur](https://platform.claude.com/docs/fr/build-with-claude/refusals-and-fallback#server-side-fallback) vers Claude Sonnet 5.

Claude Haiku 5.5 lit les blocs de réflexion de Claude Sonnet 5, Claude Opus 4.8, Claude Haiku 4.5 et des modèles antérieurs, mais pas de Claude Opus 5, Claude Opus 5.5, Claude Sonnet 5.5 ni d'aucun modèle Claude Fable ou Claude Mythos. Sur l'API Claude et Google Cloud, Claude Opus 5.5 et Claude Sonnet 5.5 lisent les blocs de réflexion de Claude Haiku 5.5 ; aucun autre modèle ne le fait. Ainsi, une conversation qui passe de Claude Haiku 4.5 à Claude Haiku 5.5 conserve son raisonnement, tout comme une conversation qui passe de Claude Haiku 5.5 à Claude Opus 5.5 ou Claude Sonnet 5.5 sur l'API Claude et Google Cloud. Une conversation qui passe à Claude Haiku 5.5 depuis Claude Opus 5, Claude Opus 5.5, Claude Sonnet 5.5 ou un modèle Claude Fable ou Claude Mythos exécute les tours suivant le changement sans le raisonnement du modèle précédent, et il en va de même pour tout autre passage depuis Claude Haiku 5.5.

* **Une conversation qui passe à Claude Fable 5.1 depuis un modèle antérieur, ou depuis Claude Opus 5.5 sur l'API Claude, conserve son raisonnement.** Les blocs de réflexion du modèle antérieur restent lisibles, de sorte que le modèle réfléchit normalement dès le premier tour suivant le changement.
* **Une conversation qui passe de Claude Fable 5.1 à tout modèle autre que Claude Mythos 5.1 perd le raisonnement de Claude Fable 5.1 pour cette requête.** Cela se produit lorsqu'un routeur envoie un tour à un modèle moins coûteux, après un [repli suite à un refus du classificateur](https://platform.claude.com/docs/fr/build-with-claude/refusals-and-fallback), ou lors d'un [repli côté serveur](https://platform.claude.com/docs/fr/build-with-claude/refusals-and-fallback#server-side-fallback). L'API supprime les blocs illisibles avant que le prompt n'atteigne le modèle. Ils ne sont pas facturés et ne comptent pas dans `input_tokens`.

Continuez à envoyer l'historique complet à chaque requête, blocs de réflexion compris, et laissez l'API supprimer ce que le modèle actuel ne peut pas lire. L'API ne modifie jamais votre tableau `messages`, de sorte que les blocs supprimés restent dans votre historique. Lorsque le même historique revient à Claude Fable 5.1, ses blocs sont à nouveau lisibles, ainsi que la réflexion du modèle antérieur. Le raisonnement n'est définitivement perdu que si votre client supprime lui-même les blocs, par exemple un harnais qui retire la réflexion lors d'un changement de modèle ou qui reconstruit l'historique à partir de ce que chaque modèle a utilisé.

<Frame>
  ![Animation : passer à Claude Opus ignore la réflexion de Claude Fable 5.1 pour ce tour ; en revenant, tout est à nouveau lu](https://platform.claude.com/docs/images/preserved-thinking-model-switch.svg)
</Frame>

Avec l'[en-tête bêta](https://platform.claude.com/docs/fr/api/beta-headers) `thinking-binding-controls-2026-08-01`, la réponse liste chaque bloc supprimé dans un tableau `input_transformations` de niveau supérieur avec `reason: "model_binding_mismatch"` :

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

Sans l'en-tête, la suppression est silencieuse. Cette entrée n'est pas un bogue de votre intégration, et `prefix_mismatch_behavior` n'a aucun effet sur elle : un bloc que le modèle actuel ne peut pas lire est toujours supprimé.

## Les blocs de réflexion restent liés au compte qui les a produits

Les blocs de réflexion que produit Claude Sonnet 5.5 ou Claude Haiku 5.5 ne fonctionnent que dans le compte qui les a produits, ou dans un compte qui lui est lié. Lorsqu'un autre compte envoie l'un de ces blocs, l'API supprime le bloc avant que le modèle ne le voie, et la requête réussit. Le modèle répond sans le raisonnement contenu dans les blocs supprimés. Les blocs des modèles antérieurs ne sont pas concernés.

Sur l'API Claude et Google Cloud, avec l'[en-tête bêta](https://platform.claude.com/docs/fr/api/beta-headers) `thinking-binding-controls-2026-08-01`, la réponse liste chaque bloc supprimé dans `input_transformations` sous forme d'entrée `thinking_dropped` avec `reason: "organization_binding_mismatch"`. Sans l'en-tête, la suppression est silencieuse.

## Conserver le préfixe inchangé

Sur Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 et Claude Haiku 5.5, un bloc de réflexion ne reste valide que tant que tout ce que vous avez envoyé avant lui reste inchangé dans les requêtes ultérieures. Le préfixe vérifié comporte trois parties :

* L'invite `system` de niveau supérieur
* L'ensemble des `tools`
* Chaque `message` situé avant le bloc

Remarque : avec la [compaction](https://platform.claude.com/docs/fr/build-with-claude/compaction) côté serveur, le préfixe vérifié commence au bloc de compaction le plus récent.

Les paramètres de requête en dehors de ces trois champs, tels que `effort`, `max_tokens`, `output_config`, `tool_choice` et `metadata`, ne font pas partie de la vérification du préfixe, pas plus que les marqueurs `cache_control`. [Ce qui compte comme une modification](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#what-counts-as-an-edit) en donne la liste complète.

Les blocs de réflexion antérieurs ne font pas partie du préfixe, mais chaque bloc de réflexion enregistre quel bloc de réflexion le précédait, d'un tour à l'autre. Vous pouvez supprimer des blocs de réflexion au début de l'historique (les plus anciens d'abord), à la fin, ou tous. Ce qui échoue, c'est un trou : les blocs de réflexion que vous conservez doivent former une suite ininterrompue de la séquence d'origine, de sorte que supprimer un bloc au milieu invalide les blocs de réflexion qui le suivent. Une fois un bloc supprimé, laissez-le de côté. Le remettre invalide les blocs de réflexion produits pendant son absence.

Gardez `system` et `tools` fixes pendant la session et traitez `messages` en ajout seul. La même discipline maintient le préfixe stable pour la [mise en cache des prompts](https://platform.claude.com/docs/fr/build-with-claude/prompt-caching) : les modifications qui invalident la réflexion sont celles qui redémarrent le cache.

### Ce que fait l'API d'un bloc invalide

Vous choisissez avec `thinking.block_binding.prefix_mismatch_behavior` :

* **`"error"` (par défaut) :** l'API rejette la requête avec une erreur 400 `invalid_request_error` qui nomme le premier bloc en échec.
* **`"drop_block"` :** l'API retire chaque bloc en échec et tous les blocs de réflexion qui le suivent, et la requête réussit. Les blocs retirés ne sont pas facturés. Le modèle répond à ce tour sans utiliser le raisonnement des blocs retirés, et le cache des prompts redémarre à la modification. La réponse liste chaque bloc retiré dans `input_transformations` (sur l'événement `message_start` en streaming) avec `reason: "prefix_binding_mismatch"`.

<Warning>
  `"drop_block"` permet aux requêtes de réussir, mais ne corrige pas la modification à l'origine de la non-correspondance, et a un coût. La suppression de blocs peut augmenter considérablement les tokens de sortie générés, en particulier à des niveaux d'effort plus élevés ou lorsque des blocs sont supprimés à chaque tour. Pour plus d'informations, consultez [Coût en tokens de sortie de `"drop_block"`](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#drop-block-cost). Les blocs supprimés ne sont pas facturés, mais Claude recrée le raisonnement qu'il ne peut plus lire, et génère donc davantage de tokens de sortie. La qualité des résultats peut également changer sur les tâches où les tours ultérieurs s'appuient sur un raisonnement antérieur. Utilisez `"drop_block"` comme solution provisoire pendant que vous corrigez la modification, mais pas comme paramètre à long terme.
</Warning>

Comptez les réponses de chaque session dont `input_transformations` contient une entrée `prefix_binding_mismatch`, déclenchez une alerte en conséquence et remplacez chaque modification par le schéma correspondant dans [Effectuer des changements sans modifier le préfixe](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#replace-prefix-edits). Dans l'API Message Batches, un élément qui laisse le champ non défini n'échoue pas. Là où l'API applique la vérification par défaut, elle supprime plutôt les blocs en échec. Définissez explicitement `"error"` dans ce cas si vous voulez que les éléments du lot échouent.

Le champ et le tableau `input_transformations` nécessitent tous deux l'[en-tête bêta](https://platform.claude.com/docs/fr/api/beta-headers) `thinking-binding-controls-2026-08-01`. [Définir le comportement en cas de non-correspondance et lire `input_transformations`](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#preserved-thinking-controls) montre la requête dans chaque SDK.

Le message 400 commence ainsi :

```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 requête n'a pas envoyé l'en-tête bêta, le message se poursuit ainsi :

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

Il se termine généralement par une phrase indiquant ce qui a changé, par exemple que l'invite `system` ou la liste `tools` diffère de celle du moment où le bloc a été créé. [Dépannage de la réflexion](https://platform.claude.com/docs/fr/build-with-claude/thinking-troubleshooting#error-thinking-block-signature) décrit ce que cette phrase peut indiquer.

Une signature altérée ou impossible à déchiffrer est un échec différent. Elle renvoie toujours une erreur 400 (``Invalid `signature` in `thinking` block`` sans phrase concernant la conversation), et `prefix_mismatch_behavior` ne s'y applique pas.

#### Coût en tokens de sortie de `"drop_block"`

Lors des tests d'Anthropic sur un benchmark de programmation multi-tours, la suppression des blocs de réflexion une fois par session a augmenté les tokens de sortie de 2,5 % à effort faible, 3,9 % à effort moyen, 4,5 % à effort élevé et 20,1 % à effort maximal. Leur suppression à chaque tour après le premier a augmenté les tokens de sortie de 4,6 % à effort faible, 9,7 % à effort moyen, 10,3 % à effort élevé et 67,1 % à effort maximal. Ces chiffres sont des estimations avec de larges marges d'erreur, et l'impact sur votre charge de travail dépend de votre harnais.

Lorsque Claude ne peut plus lire le raisonnement des tours précédents, il recrée ce raisonnement, de sorte que les requêtes qui suppriment des blocs de réflexion génèrent davantage de tokens de sortie et peuvent mettre plus de temps à répondre. Une suppression à chaque tour coûte plus cher qu'une suppression occasionnelle, et l'écart dépend de votre harnais : la fréquence à laquelle il modifie le préfixe et la mesure dans laquelle chaque tour s'appuie sur un raisonnement antérieur.

Avant de vous appuyer sur `"drop_block"`, exécutez des évaluations sur votre propre charge de travail pour mesurer l'augmentation. Si elle est faible, `"drop_block"` peut permettre aux requêtes de réussir pendant que vous corrigez la modification. Dans tous les cas, corriger la modification avec un schéma tiré de [Effectuer des changements sans modifier le préfixe](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#replace-prefix-edits) est une meilleure solution à long terme.

#### Gérer l'erreur dans le code

Il s'agit de l'erreur 400 `invalid_request_error` présentée plus haut dans cette section. Ne renvoyez pas le même corps : il échoue de la même manière à chaque fois. Réessayez une fois avec l'en-tête bêta et `prefix_mismatch_behavior: "drop_block"`, comme solution provisoire ([`"drop_block"` peut augmenter les tokens de sortie](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#drop-block-cost)), et enregistrez ce choix avec la session afin que chaque requête ultérieure l'envoie également, y compris après un redémarrage. Sur Claude Sonnet 5.5 et Claude Haiku 5.5, `block_binding` ne fonctionne qu'avec `thinking: {"type": "adaptive"}`. Avec `between_tools` sur Claude Sonnet 5.5, ou `thinking: {"type": "disabled"}` sur Claude Haiku 5.5, gardez l'historique en ajout seul, ou retirez les blocs de réflexion à partir du tour modifié. Si vous ne pouvez pas envoyer l'en-tête bêta, supprimez une fois pour toutes chaque bloc `thinking` et `redacted_thinking` de l'historique, laissez-les de côté et continuez. Corrigez ensuite la modification qui a provoqué la non-correspondance.

### Définir le comportement en cas de non-correspondance et lire `input_transformations`

L'[en-tête bêta](https://platform.claude.com/docs/fr/api/beta-headers) `thinking-binding-controls-2026-08-01` ajoute :

* Un tableau `input_transformations` de niveau supérieur dans chaque réponse
* Un objet `block_binding` dans la configuration `thinking`, dont l'unique champ est `prefix_mismatch_behavior`

`block_binding` est accepté avec `thinking.type: "adaptive"` et `thinking.type: "enabled"`. Sur Claude Sonnet 5.5 et Claude Haiku 5.5, `block_binding` ne fonctionne qu'avec `thinking: {"type": "adaptive"}`. L'envoyer avec `between_tools` sur Claude Sonnet 5.5, ou avec `thinking: {"type": "disabled"}` sur Claude Haiku 5.5, renvoie une erreur 400. L'envoyer sans l'en-tête bêta renvoie une erreur 400 dont le message se termine par `block_binding: Extra inputs are not permitted`. Les modèles qui n'effectuent pas la vérification du préfixe acceptent l'objet et ne signalent que les suppressions dues à la vérification du modèle, de sorte qu'un même corps de requête fonctionne avec tous les modèles. La référence de l'API appelle la vérification du préfixe la vérification de la conversation.

La requête suivante choisit la suppression plutôt que le rejet. Lors d'un premier tour, il n'y a rien à rejouer, donc `input_transformations` revient vide :

<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
```

Avec l'en-tête bêta, chaque réponse d'un modèle capable de réflexion contient `input_transformations`. Chaque entrée désigne un bloc de réflexion par son `path` (par exemple `messages.1.content.0`) et indique une `reason`. Il existe deux types d'entrées :

* **`thinking_dropped` :** l'API supprime le bloc avant que le modèle ne le lise, et le bloc n'est pas facturé. La `reason` est `prefix_binding_mismatch` ou `model_binding_mismatch` (consultez [Changer de modèle en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#switching-models)). La `reason` peut aussi être `organization_binding_mismatch`, ce qui signifie que le bloc provient d'un autre compte (consultez [Les blocs de réflexion restent liés au compte qui les a produits](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#account-bound-thinking)).
* **`thinking_mismatch_allowed` :** le bloc échoue à la vérification du préfixe, mais l'API n'applique pas cette vérification pour cette requête, de sorte que le bloc atteint le modèle sans modification et est facturé. La `reason` est toujours `prefix_binding_mismatch`. Cette entrée n'apparaît que sur les requêtes pour lesquelles l'API n'applique pas la vérification par défaut, comme celles provenant d'un compte plus ancien (consultez [Quand l'API applique la vérification](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#enforcement)). Définir `prefix_mismatch_behavior` sur l'une ou l'autre valeur soumet la requête à la vérification, de sorte qu'une requête qui le définit n'obtient jamais cette entrée.

Le tableau est vide lorsqu'aucun bloc n'a été supprimé et qu'aucun n'a échoué à la vérification du préfixe. Ignorez les entrées dont vous ne reconnaissez pas le `type` ou la `reason`, car des vérifications ultérieures ajoutent des valeurs.

En [streaming](https://platform.claude.com/docs/fr/build-with-claude/streaming), le tableau arrive sur l'objet `message` dans l'événement `message_start`. Après un repli côté serveur en cours de flux, l'événement `message_delta` final le transporte à nouveau avec les entrées du modèle qui répond. Dans un [lot de messages](https://platform.claude.com/docs/fr/build-with-claude/batch-processing), un élément dont un bloc échoue à la vérification du préfixe avec un `"error"` explicite se résout en `errored`. Un élément qui laisse le champ non défini n'échoue pas. Là où l'API applique la vérification par défaut, elle supprime plutôt les blocs en échec. Le point de terminaison de [comptage des tokens](https://platform.claude.com/docs/fr/build-with-claude/token-counting) effectue la même vérification du préfixe et renvoie la même erreur 400.

### Quand l'API applique la vérification

L'API applique la vérification du préfixe sur Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 et Claude Haiku 5.5 pour les nouveaux comptes.

* **Comptes créés le 31 août 2026 à 00:00 UTC ou après :** l'API vérifie les requêtes Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 et Claude Haiku 5.5 et applique `"error"` à moins que vous ne définissiez `"drop_block"`. La même définition d'un nouveau compte s'applique à l'API Claude et aux plateformes cloud.
* **Comptes plus anciens :** l'API n'applique la vérification qu'aux requêtes qui définissent `prefix_mismatch_behavior`. Définir ce champ soumet une requête à la vérification, ce qui vous permet de voir ce que voit un nouveau compte sans en créer un. Sur les requêtes qui le laissent non défini, l'API effectue tout de même la vérification mais laisse passer les blocs en échec jusqu'au modèle. Avec l'en-tête bêta, la réponse liste chacun d'eux dans `input_transformations` en tant que `thinking_mismatch_allowed`, ce qui vous permet de trouver les modifications du préfixe sans changer ce que reçoit le modèle.

Pour savoir à quel groupe appartient votre compte, prenez une conversation Claude Fable 5.1 qui contient un bloc de réflexion, modifiez quelque chose avant ce bloc, et envoyez-la à Claude Fable 5.1 sans l'en-tête bêta ni le champ `block_binding`. Une réponse 400 qui mentionne l'en-tête signifie que votre compte est soumis à la vérification par défaut. Une réponse 200 signifie qu'il ne l'est pas. Pour confirmer, renvoyez la même requête avec l'en-tête bêta, toujours sans `block_binding` : la réponse liste chaque bloc de réflexion situé après votre modification dans `input_transformations` en tant que `thinking_mismatch_allowed`.

### Ce qui compte comme une modification

Chaque ligne compare deux requêtes consécutives :

| Changement entre les requêtes                                                                                                                                                  | Blocs de réflexion ultérieurs                                                                                                                                                                                                                                                                                                                                                       |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ajouter des messages à la fin                                                                                                                                                  | Valides                                                                                                                                                                                                                                                                                                                                                                             |
| Ajouter un outil avec `defer_loading: true` que rien n'a encore référencé                                                                                                      | Valides                                                                                                                                                                                                                                                                                                                                                                             |
| Supprimer des blocs `thinking` au début de l'historique, à la fin, ou tous                                                                                                     | Valides (le modèle perd ce raisonnement)                                                                                                                                                                                                                                                                                                                                            |
| Modifier tout paramètre de requête en dehors de `system`, `tools` et `messages` (`effort`, `max_tokens`, `output_config`, `tool_choice`, `metadata`, `thinking.display`, etc.) | Valides                                                                                                                                                                                                                                                                                                                                                                             |
| Ajouter, déplacer ou supprimer des marqueurs `cache_control`                                                                                                                   | Valides                                                                                                                                                                                                                                                                                                                                                                             |
| Une URL signée tournante qui renvoie les mêmes octets                                                                                                                          | Valides                                                                                                                                                                                                                                                                                                                                                                             |
| La compaction ou l'édition de contexte côté serveur supprime ou remplace du contenu                                                                                            | Valides (la vérification compare ce que vous avez envoyé, et non la copie modifiée par le serveur)                                                                                                                                                                                                                                                                                  |
| Un [message système limité au tour](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#per-turn-reminders) effacé et laissé en place                     | Valides                                                                                                                                                                                                                                                                                                                                                                             |
| Modifier, réordonner ou supprimer tout message `user`, `assistant` ou `system` antérieur                                                                                       | Invalides, sauf lorsque le bloc signé issu de la [compaction à la demande](https://platform.claude.com/docs/fr/build-with-claude/compaction-on-demand) remplace les messages qu'il résume, dans les [conditions de validité de la réflexion conservée](https://platform.claude.com/docs/fr/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) |
| Régénérer le contexte placé dans le premier message utilisateur avec une valeur modifiée                                                                                       | Invalides pour tous les blocs de réflexion                                                                                                                                                                                                                                                                                                                                          |
| Effacer ou raccourcir un `tool_result` antérieur, réencoder une image antérieure, ou modifier l'entrée d'un `tool_use` antérieur                                               | Invalides pour tous les blocs de réflexion ultérieurs                                                                                                                                                                                                                                                                                                                               |
| Ajouter un bloc de texte à un tour utilisateur antérieur, ou supprimer celui que vous avez ajouté la fois précédente                                                           | Invalides                                                                                                                                                                                                                                                                                                                                                                           |
| Modifier la chaîne ou les blocs `system` de niveau supérieur                                                                                                                   | Invalides                                                                                                                                                                                                                                                                                                                                                                           |
| Ajouter, supprimer, renommer ou modifier un outil dans `tools`                                                                                                                 | Invalides                                                                                                                                                                                                                                                                                                                                                                           |
| Supprimer un bloc `thinking` au milieu de l'historique et conserver les suivants                                                                                               | Invalides pour tous les blocs de réflexion ultérieurs                                                                                                                                                                                                                                                                                                                               |
| Remettre un bloc `thinking` que vous aviez supprimé lors d'une requête antérieure                                                                                              | Invalides pour les blocs de réflexion produits pendant son absence                                                                                                                                                                                                                                                                                                                  |
| Une URL d'image ou de document qui renvoie des octets différents à la requête suivante                                                                                         | Invalides                                                                                                                                                                                                                                                                                                                                                                           |
| Le même message limité au tour supprimé ou reformulé lors d'une requête ultérieure                                                                                             | Invalides                                                                                                                                                                                                                                                                                                                                                                           |

### Vérifier si votre code modifie le préfixe

<Tip>
  **Automatisez cette vérification avec la skill Claude API.** Dans la dernière version de [Claude Code](https://code.claude.com/docs/fr/overview), ouvrez le dépôt qui construit vos requêtes et exécutez la [skill Claude API](https://platform.claude.com/docs/fr/agents-and-tools/agent-skills/claude-api-skill#checking-an-integration-for-preserved-thinking) fournie :

  Laissez Claude Code vérifier votre code pour vous

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

  La skill capture quelques-unes de vos propres sessions multi-tours et compare les requêtes consécutives pour trouver où votre code modifie le préfixe. Elle rejoue ensuite les sessions avec `"drop_block"` et compte les blocs de réflexion que l'API supprime. Après cela, elle corrige une cause à la fois et mesure à nouveau après chaque correction.
</Tip>

Commencez par comparer ce que vous envoyez. Capturez les corps de requête que votre intégration envoie sur quelques tours normaux, y compris une compaction ou un changement d'outil. Pour chaque paire de requêtes consécutives, comparez `system`, `tools` et les `messages` qu'elles ont en commun. Ils doivent être identiques jusqu'aux tours nouvellement ajoutés.

Confirmez ensuite auprès de l'API. Ajoutez l'en-tête bêta `thinking-binding-controls-2026-08-01`, définissez `prefix_mismatch_behavior` sur `"drop_block"`, et exécutez une session multi-tours normale via votre intégration sur claude-fable-5-1. L'exemple suivant exécute deux tours comme votre intégration devrait le faire : `messages` ne fait que croître, chaque tour assistant est renvoyé exactement tel que l'API l'a retourné, blocs `thinking` compris, et `block_binding` est défini sur chaque requête. Après chaque tour, il affiche le nombre de blocs `thinking` dans la réponse et le nombre de blocs supprimés :

<CodeGroup>
  ```bash cURL
  # Compte les blocs de réflexion d'une réponse et les blocs supprimés par l'API.
  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"

  # Tour 2 : le tour de l'assistant est renvoyé tel quel, puis le message utilisateur suivant.
  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
  # Compte les blocs de réflexion d'une réponse et les blocs supprimés par l'API.
  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"

  # Tour 2 : le tour de l'assistant est renvoyé tel quel, puis le message utilisateur suivant.
  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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé exactement tel que reçu.
  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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  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 liste de messages du builder s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
      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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  $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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  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
```

Aucun des deux tours ne supprime de bloc, car rien d'antérieur n'a changé. Vérifiez que la première réponse contient un bloc `thinking`. Avec la réflexion adaptative, certaines réponses n'en contiennent aucun. Si aucune réponse de la session n'en contient, il n'y a rien à vérifier et le nombre de blocs supprimés est 0 quoi que vous changiez ; exécutez donc à nouveau l'exemple.

Journalisez `input_transformations` à chaque tour de votre propre intégration. Lorsque l'API supprime un bloc, l'entrée ressemble à ceci :

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

* **Vide à chaque tour d'une session qui contient des blocs `thinking` :** votre intégration conserve le préfixe intact.
* **`reason: "prefix_binding_mismatch"` :** quelque chose avant le bloc situé à `path` a changé depuis la requête précédente. Comparez `system`, `tools` et `messages` jusqu'à ce tour pour le trouver, ou renvoyez la requête avec `"error"` : l'erreur 400 se termine généralement par une phrase indiquant ce qui a changé. Trouvez ensuite le remplacement correspondant dans [Effectuer des changements sans modifier le préfixe](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#replace-prefix-edits).
* **`reason: "model_binding_mismatch"` :** la conversation est passée à un modèle qui ne peut pas lire les blocs du modèle précédent. Il ne s'agit pas d'une modification du préfixe. Consultez [Changer de modèle en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#switching-models).
* **`reason: "organization_binding_mismatch"` :** le bloc provient d'un autre compte. Consultez [Les blocs de réflexion restent liés au compte qui les a produits](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#account-bound-thinking).

Pour provoquer volontairement un échec, envoyez un troisième tour à partir de l'exemple précédent et ajoutez une invite `system` à cette seule requête, de sorte qu'elle diffère des deux premières requêtes, qui n'en avaient pas. Avec `"drop_block"`, le nombre de blocs supprimés n'est plus 0 : la réponse contient une entrée pour chaque bloc de réflexion de l'historique, chacune avec `reason: "prefix_binding_mismatch"`. Avec `"error"`, la requête renvoie l'erreur 400 décrite dans [Ce que fait l'API d'un bloc invalide](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#mismatch-behavior), et sa dernière phrase mentionne l'invite `system`. Dans les onglets cURL et CLI, supprimez le filtre `jq` pour voir le corps de l'erreur. Si le nombre est toujours 0, il n'y avait rien à vérifier : confirmez que le modèle est claude-fable-5-1, que la requête définit `block_binding`, que l'historique envoyé contient des blocs `thinking`, et que les deux premières requêtes n'avaient pas d'invite `system`.

Deux tours simples révèlent rarement le problème. Exécutez une session couvrant chacun des cas suivants, avec `"error"` défini afin qu'une régression fasse échouer votre CI :

* La première compaction ou le premier élagage côté client
* Un outil, plugin ou serveur MCP qui se connecte après le premier tour
* Un changement de mode ou d'instructions
* Une longue boucle d'outils, si vous ajoutez des rappels ou raccourcissez d'anciens résultats d'outils
* Un passage à un autre modèle puis un retour
* Un enregistrement, un redémarrage et une reprise à une date ultérieure

Sur un compte plus ancien, vous pouvez également surveiller le trafic de production sans vous soumettre à la vérification : envoyez l'en-tête bêta, omettez `block_binding` et journalisez `input_transformations`. Envoyer l'en-tête seul ne change pas ce que reçoit le modèle. Chaque bloc de réflexion situé après le contenu que vous avez modifié échoue à la vérification et obtient sa propre entrée `thinking_mismatch_allowed`, avec les mêmes champs `path` et `reason` qu'une entrée `thinking_dropped`. Les blocs situés avant la modification passent toujours. Une modification de `system` ou de `tools` se situe avant tous les blocs, elle fait donc échouer tous les blocs de réflexion de la requête. Une entrée ressemble à ceci :

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

Exécutez l'exemple suivant depuis un [compte plus ancien](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#enforcement), car un compte récent rejette sa troisième requête avec l'erreur 400. Il envoie l'en-tête sans `block_binding` et prolonge la session précédente avec une troisième requête qui ajoute une invite système, ce qui modifie volontairement le préfixe. Après chaque tour, il affiche le nombre de blocs `thinking` et de blocs signalés :

<CodeGroup>
  ```bash cURL
  # Compte les blocs de réflexion d'une réponse et ceux ayant échoué à la vérification du préfixe.
  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"

  # Tour 2 : le tour de l'assistant est renvoyé tel quel, puis le message utilisateur suivant.
  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"

  # Tour 3 : seule cette requête ajoute une invite système, ce qui modifie volontairement le préfixe.
  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
  # Compte les blocs de réflexion d'une réponse et ceux qui ont échoué à la vérification du préfixe.
  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"

  # Tour 2 : le tour de l'assistant est renvoyé tel quel, puis le message utilisateur suivant.
  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"

  # Tour 3 : seule cette requête ajoute une invite système, ce qui modifie volontairement le préfixe.
  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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  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"},
          # Seule la dernière requête ajoute une invite système, ce qui modifie volontairement le préfixe.
          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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  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" },
      // Seule la dernière requête ajoute une invite système, ce qui modifie volontairement le préfixe.
      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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  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(),
              // Seule la dernière requête ajoute une invite système, ce qui modifie volontairement le préfixe.
              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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  messages := []anthropic.BetaMessageParam{}
  for i, userTurn := range userTurns {
  	messages = append(messages, anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(userTurn)))
  	// Seule la dernière requête ajoute une invite système, ce qui modifie volontairement le préfixe.
  	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 liste de messages du builder s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
      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) {
              // Seule la dernière requête ajoute une invite système, ce qui modifie volontairement le préfixe.
              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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  $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(),
          // Seule la dernière requête ajoute une invite système, ce qui modifie volontairement le préfixe.
          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 s'allonge au fil des tours : chaque tour de l'assistant est renvoyé tel quel.
  messages = []
  user_turns.each_with_index do |user_turn, turn_index|
    messages << {role: "user", content: user_turn}
    # Seule la dernière requête ajoute une invite système, ce qui modifie volontairement le préfixe.
    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 troisième réponse signale chaque bloc de réflexion des tours précédents, un par tour dans cette exécution, car la nouvelle invite système se situe avant tous ces blocs. Le modèle les a tout de même lus.

Traitez ces entrées comme vous traiteriez les suppressions `prefix_binding_mismatch`. La modification se situe avant le premier bloc listé : comparez `system`, `tools` et `messages` jusqu'au `path` de ce bloc avec la requête précédente pour la trouver, puis remplacez-la par le schéma correspondant dans [Effectuer des changements sans modifier le préfixe](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#replace-prefix-edits). Sur un nouveau compte, ou sur toute requête qui définit `prefix_mismatch_behavior`, l'API rejette plutôt la requête ou supprime les blocs en échec. Les entrées constituent une borne inférieure de ce que la vérification supprimerait : avec `"drop_block"`, un bloc en échec entraîne aussi avec lui le reste des blocs de réflexion de ce tour, et la suppression d'un bloc peut faire échouer le suivant également. Lorsque l'API se contente d'enregistrer la vérification, elle juge chaque bloc individuellement et ne liste un bloc que si ce bloc échoue.

## Effectuer des changements sans modifier le préfixe

Chaque modification courante du préfixe dispose d'un remplacement qui fournit au modèle les mêmes informations et laisse les octets antérieurs inchangés, de sorte que la réflexion ultérieure reste valide. Trouvez dans la première colonne la modification que votre code effectue aujourd'hui :

| Au lieu de                                                                                                                         | Utilisez                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | En-tête bêta                                                                                                                                                                                                                                                  |
| ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Reconstruire l'invite `system` de niveau supérieur                                                                                 | Un [message système en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#new-instructions)                                                                                                                                                                                                                                                                                                                                                                      | Aucun                                                                                                                                                                                                                                                         |
| Régénérer à chaque requête le contexte de votre premier message utilisateur (environnement, date, mémoire, instructions de projet) | Générez-le une fois et renvoyez-le sans modification. Lorsque quelque chose change, [placez la nouvelle version dans le tour le plus récent](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#changing-context)                                                                                                                                                                                                                                                                       | Aucun                                                                                                                                                                                                                                                         |
| Effacer ou raccourcir sur place d'anciens contenus `tool_result`, ou réencoder d'anciennes images                                  | Raccourcissez un résultat d'outil ou réduisez une image avant de l'envoyer pour la première fois, et non après. Pour effacer d'anciens résultats plus tard, [élaguez le contexte côté serveur](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#server-side-trimming) avec `clear_tool_uses_20250919`                                                                                                                                                                                 | `context-management-2025-06-27`                                                                                                                                                                                                                               |
| Injecter un rappel et le supprimer à la requête suivante                                                                           | Un [message système limité au tour](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#per-turn-reminders) (`clear_at: "next_user_message"`)                                                                                                                                                                                                                                                                                                                                            | `mid-conversation-system-clear-at-2026-08-21`                                                                                                                                                                                                                 |
| Ajouter ou supprimer des entrées dans `tools`                                                                                      | [Des blocs `tool_addition` et `tool_removal`](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#tool-changes)                                                                                                                                                                                                                                                                                                                                                                          | `inline-tools-2026-09-15` (ajoutez `mcp-client-2026-09-15` lorsque l'outil provient d'un serveur MCP connecté via le connecteur MCP), ou l'ancien `mid-conversation-tool-changes-2026-07-01`, qui fonctionne sur l'API Claude, Amazon Bedrock et Google Cloud |
| Modifier `output_config.effort` de niveau supérieur (redémarre le cache, n'affecte pas la réflexion)                               | Un [`output_config` par message](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#effort-changes)                                                                                                                                                                                                                                                                                                                                                                                     | `mid-conversation-output-config-2026-07-01`                                                                                                                                                                                                                   |
| Supprimer ou résumer d'anciens tours côté client                                                                                   | La [compaction à la demande](https://platform.claude.com/docs/fr/build-with-claude/compaction-on-demand) pour conserver les tours récents avec leur réflexion, une autre [compaction ou édition de contexte](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#server-side-trimming) côté serveur, ou une [compaction côté client](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#custom-compaction-on-the-client) qui ne conserve aucune réflexion obsolète | `compact-2026-09-04`                                                                                                                                                                                                                                          |
| Une URL d'image ou de document dont les octets changent entre les requêtes                                                         | Un [`file_id` de l'API Files](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#files-by-id), ou du base64                                                                                                                                                                                                                                                                                                                                                                             | Aucun                                                                                                                                                                                                                                                         |

Tous ces remplacements supposent que vous [renvoyez les tours assistant exactement tels qu'ils ont été retournés](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#append-assistant-turns-exactly-as-returned). Les messages système en cours de conversation, les messages système limités au tour et les changements d'outils ne sont pas disponibles sur tous les modèles : [Messages système et changements d'outils en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/mid-conversation-system-messages) liste les modèles qui les acceptent. Si votre code sert plusieurs modèles, continuez à modifier l'invite `system` de niveau supérieur pour les modèles qui ne les acceptent pas.

Pour utiliser plusieurs bêtas dans une même requête sur l'API Claude, combinez leurs noms dans un seul en-tête `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
```

Les autres plateformes qui proposent ces bêtas utilisent les mêmes noms. Pour les y envoyer, consultez [Fonctionnalités bêta sur d'autres plateformes](https://platform.claude.com/docs/fr/api/beta-headers#beta-features-on-other-platforms).

### Renvoyer les tours de l'assistant exactement tels qu'ils ont été retournés

Stockez le tableau `content` de chaque réponse et renvoyez-le sans modification comme tour assistant : chaque type de bloc, dans l'ordre de réception, y compris les blocs `thinking` dont le champ `thinking` est vide. Un sérialiseur qui supprime les types de blocs inconnus, supprime les champs vides ou réordonne les blocs modifie le préfixe pour tous les tours ultérieurs.

Sur Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 et Claude Haiku 5.5, le champ `thinking` est vide par défaut et la `signature` transporte le raisonnement, de sorte qu'un sérialiseur qui ignore les blocs vides supprime la réflexion. S'il les supprime tous, rien n'échoue et le modèle perd son raisonnement antérieur à chaque tour. Si vous analysez le flux vous-même, conservez le bloc même lorsqu'aucun texte de réflexion n'arrive : il s'ouvre, reçoit sa `signature` dans un événement `signature_delta`, puis se ferme. Un bloc renvoyé avec une `signature` vide échoue.

### Ajouter des instructions avec un message système en cours de conversation

Certains harnais reconstruisent l'invite `system` de niveau supérieur à chaque requête pour y inclure l'heure actuelle, un budget de tokens, un indicateur de mode ou un contexte de projet nouvellement découvert. Cela invalide tous les blocs de réflexion de la conversation. À la place, figez `system` au début de la session. Lorsque quelque chose change, ajoutez un [message `role: "system"`](https://platform.claude.com/docs/fr/build-with-claude/mid-conversation-system-messages) à l'endroit de `messages` où le changement devient effectif :

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

Le modèle traite ce message avec l'autorité d'une invite système, et tout ce qui le précède reste inchangé. Dans une boucle d'outils, placez le message après le message utilisateur `tool_result`, jamais entre un `tool_use` de l'assistant et son `tool_result` (consultez [Limitations](https://platform.claude.com/docs/fr/build-with-claude/mid-conversation-system-messages#limitations)). Une fois envoyé, le message fait partie du préfixe pour la réflexion ultérieure : laissez-le en place dans les requêtes ultérieures.

### Placer le contexte changeant dans le tour le plus récent

Certains harnais placent un bloc d'environnement dans le premier message utilisateur (répertoire de travail, branche, date, mémoire, instructions de projet) et le régénèrent à chaque requête. Lorsqu'une valeur change, `messages[0]` change, et tous les blocs de réflexion de la conversation deviennent invalides. Générez ce bloc une fois et renvoyez-le tel quel. Lorsqu'une valeur change, indiquez-le dans le tour le plus récent : ajoutez un bloc de texte au message utilisateur que vous êtes sur le point d'envoyer, ou ajoutez un [message système en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#new-instructions) si le changement vient de vous en tant qu'opérateur.

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

Une fois envoyé, ce bloc de texte fait partie du préfixe pour la réflexion ultérieure : laissez-le en place dans les requêtes ultérieures.

### Envoyer les rappels par tour sous forme de messages système limités au tour

Une modification courante du préfixe est le rappel par tour : une ligne telle que « regroupez les lectures indépendantes » ou « vous n'avez pas informé l'utilisateur depuis un moment » que votre code ajoute après chaque lot de résultats d'outils. Pour éviter que les rappels ne s'accumulent, envoyez chaque rappel sous forme de [message système en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/mid-conversation-system-messages) avec `clear_at: "next_user_message"`, placé après le message utilisateur `tool_result`. `clear_at` nécessite l'en-tête bêta `mid-conversation-system-clear-at-2026-08-21`. Le tableau `messages` suivant correspond à la requête après deux appels d'outils et leurs résultats. `messages[3]` est le rappel de la requête précédente, laissé en place, et `messages[6]` est la copie de cette requête :

```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 message utilisateur qui ne contient que des blocs `tool_result` compte comme le « message utilisateur suivant », donc `messages[3]` est déjà effacé. Il n'ajoute rien à ce que voit le modèle et ne coûte aucun token d'entrée, mais comme il est toujours dans le tableau, la réflexion de `messages[4]` reste valide. `messages[6]` est la copie que le modèle voit à ce tour. Dans les requêtes ultérieures, gardez les deux à leur place et ajoutez une nouvelle copie après le message `tool_result` suivant.

### Ajouter ou retirer des outils avec `tool_addition` et `tool_removal`

Modifier le tableau `tools` en cours de session invalide les blocs de réflexion préservés. Laissez le tableau tel que vous l'avez envoyé la première fois, et modifiez les outils que le modèle peut utiliser en ajoutant un message `role: "system"` qui contient des blocs `tool_addition` ou `tool_removal`. Il s'agit de [modifications d'outils en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes), qui nécessitent l'en-tête bêta `inline-tools-2026-09-15`, disponible sur l'API Claude. L'ancien en-tête `mid-conversation-tool-changes-2026-07-01` fonctionne toujours pour les modifications qui désignent un outil par référence, sur l'API Claude, Amazon Bedrock et Google Cloud.

Vous disposez de deux façons d'utiliser ces blocs :

* **Déclarer tous les outils dès le départ.** Placez dans `tools`, dès la première requête, tous les outils dont la session pourrait avoir besoin, avec `defer_loading: true` sur ceux que le modèle ne doit pas encore voir. Activez et désactivez ensuite les outils avec des blocs `tool_addition` et `tool_removal` qui les nomment.
* **Commencer avec un instantané et ajouter des outils au fur et à mesure.** Placez dans `tools`, dès la première requête, les outils que vous connaissez. Lorsqu'un nouvel outil apparaît, définissez-le dans un bloc `tool_addition` au lieu de modifier `tools`.

Dans les deux cas, `tools` ne change jamais, donc la réflexion antérieure reste valide et le cache des prompts continue de fonctionner, à une exception près, mentionnée plus loin dans cette section.

Par exemple, pour retirer un outil dangereux après un changement de mode :

```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." }
  ]
}
```

Pour activer un outil que vous avez déclaré avec `defer_loading: true`, ajoutez un bloc `tool_addition` qui le nomme :

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

Parfois, vous ne pouvez pas déclarer un outil dès le départ parce que vous ne connaissez pas encore son schéma : un outil que votre application découvre à l'exécution, ou un serveur MCP qui se connecte après le premier tour. Définissez-le dans le bloc `tool_addition` au lieu de toucher à `tools`. Avec `inline-tools-2026-09-15`, le `tool` du bloc peut être `{"type": "tool_definition", "definition": {...}}`, contenant la même entrée que celle que vous auriez placée dans `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"]
          }
        }
      }
    }
  ]
}
```

Le nouvel outil arrive dans `messages`, `tools` ne change jamais, et la réflexion antérieure reste valide. Gardez au moins un outil sans `defer_loading: true` dans `tools` : si tous les outils qui s'y trouvent sont différés, le premier outil que vous définissez de cette manière coûte un échec complet du cache des prompts.

Si l'API se connecte au serveur MCP pour vous via le [connecteur MCP](https://platform.claude.com/docs/fr/agents-and-tools/mcp-connector), envoyez également `mcp-client-2026-09-15`. Il couvre tout ce que fait `mcp-client-2025-11-20`, donc envoyez-le à la place de celui-ci. La `definition` du bloc peut alors être un `mcp_toolset` pour un serveur listé dans `mcp_servers`. Lorsque l'API doit récupérer la liste des outils d'un serveur, la réponse commence par un bloc `mcp_tool_listing` pour ce serveur. Renvoyez-le inchangé avec le reste du tour assistant, et continuez à envoyer `mcp-client-2026-09-15` dans chaque requête ultérieure qui le contient. Le bloc fige l'ensemble d'outils sur cette liste, de sorte que l'API ne contacte plus le serveur à ce sujet. Ces fonctionnalités du connecteur MCP sont disponibles sur la Claude API.

Avec uniquement l'ancien en-tête, vous pouvez toujours ajouter à `tools` un outil découvert en cours de session avec `defer_loading: true`, puis le proposer avec un bloc `tool_addition`. C'est sans risque, car la vérification du préfixe ignore un outil différé jusqu'à ce qu'un bloc `tool_addition` le référence. Ajouter un outil sans `defer_loading: true` modifie le préfixe et invalide la réflexion antérieure.

Les messages `role: "system"` qui contiennent ces blocs rejoignent le préfixe pour la réflexion ultérieure. Laissez-les en place dans les requêtes ultérieures.

### Modifier l'effort avec un `output_config` par message

Modifier `output_config.effort` au niveau supérieur entre les requêtes n'invalide pas la réflexion, car l'effort ne fait pas partie du préfixe. Modifier l'effort au niveau supérieur redémarre en revanche le cache de prompts. Lorsque le modèle et la plateforme prennent en charge l'[effort par message](https://platform.claude.com/docs/fr/build-with-claude/effort#change-effort-mid-conversation-beta), utilisez-le à la place : ajoutez un message `role: "system"` avec un `content` vide et le nouveau niveau. Cela nécessite l'en-tête bêta `mid-conversation-output-config-2026-07-01`. Sur Claude Haiku 5.5, l'effort par message est disponible sur l'API Claude et Google Cloud et nécessite la réflexion adaptative.

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

Le moment où le nouveau niveau prend effet dépend de l'endroit où vous placez le message. Directement après un message `user` contenant une nouvelle entrée, il commence avec la réponse de Claude à ce message. Partout ailleurs, par exemple après un message `assistant` ou après un message `user` qui ne contient que des blocs `tool_result`, il commence avec le message `user` suivant contenant une nouvelle entrée, de sorte qu'une boucle d'outils déjà en cours conserve le niveau actuel jusque-là. Une fois envoyé, le message fait partie de `messages` et donc du préfixe pour la réflexion ultérieure : laissez-le en place lors des requêtes suivantes, et ajoutez-en un autre pour modifier à nouveau l'effort.

### Élaguer le contexte côté serveur

Une autre modification courante du préfixe est l'élagage côté client : supprimer ou résumer les tours les plus anciens et conserver les tours récents tels quels. Les blocs de réflexion des tours conservés ont été produits alors que l'historique retiré était encore en place, donc ils échouent à la vérification. Les équivalents côté serveur ne comptent pas comme des modifications, car la vérification compare la conversation telle que vous l'avez envoyée :

* La [compaction à la demande](https://platform.claude.com/docs/fr/build-with-claude/compaction-on-demand) (bêta) renvoie le résumé à partir d'une requête distincte, qui peut [s'exécuter en arrière-plan](https://platform.claude.com/docs/fr/build-with-claude/compaction-background), et vous envoyez le bloc renvoyé à la place des messages qu'il résume. La vérification accepte cette substitution, de sorte que les tours que vous conservez peuvent rester valides avec leur réflexion, dans les [conditions applicables à la réflexion conservée](https://platform.claude.com/docs/fr/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid). [Demander un résumé](https://platform.claude.com/docs/fr/build-with-claude/compaction-on-demand#request-a-summary) présente la requête et indique l'en-tête bêta nécessaire.
* La [compaction à un seuil de tokens](https://platform.claude.com/docs/fr/build-with-claude/compaction-threshold) résume les tours plus anciens dans un bloc de compaction lorsque le contexte approche d'un seuil que vous définissez, et le préfixe vérifié redémarre à partir de ce bloc. Son [paramètre `instructions`](https://platform.claude.com/docs/fr/build-with-claude/compaction-threshold#custom-summarization-instructions) accepte votre propre prompt de résumé, par exemple « conserver chaque symbole boursier, chaque taille de position et chaque hypothèse énoncée ».
* L'[édition du contexte](https://platform.claude.com/docs/fr/build-with-claude/context-editing) efface les anciens résultats d'outils ou les anciens blocs de réflexion selon une règle, en commençant par les plus anciens. Les stratégies sont `clear_tool_uses_20250919` et `clear_thinking_20251015`.

### Compacter côté client

Vous pouvez toujours effectuer la compaction côté client. Si vous rédigez le résumé vous-même, ne renvoyez pas un bloc de réflexion produit avant la réécriture. Si l'API le rédige avec la compaction à la demande, [Conditions pour que la réflexion conservée reste valide](https://platform.claude.com/docs/fr/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) indique quand la réflexion conservée reste valide.

#### Compaction simple (recommandée)

Lorsque la conversation devient trop longue, résumez toute la session dans un seul message utilisateur et envoyez uniquement ce message ainsi que l'instruction suivante. Rien d'antérieur n'est rejoué, il ne reste donc aucune réflexion susceptible d'échouer à la vérification, et le modèle raisonne à nouveau à partir du résumé.

<Frame>
  ![« Simple compaction » (compaction simple) : la requête 4 envoie l'historique complet avec la réflexion sur chaque tour de l'assistant ; la requête 5 envoie un seul message utilisateur contenant un résumé des tours 1 à 4 ainsi que l'instruction suivante, de sorte qu'aucune réflexion antérieure n'est envoyée et que rien n'est vérifié](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>"
  }
]
```

Les modèles Claude sont entraînés sur des tâches à long horizon avec ce schéma, et pour la plupart des charges de travail, il donne de bons résultats.

#### Compaction avec conservation de la fin

La « keep-tail compaction » (compaction avec conservation de la fin) résume les tours plus anciens et conserve les tours les plus récents mot pour mot, de sorte que le modèle voit toujours les derniers échanges à l'identique. Si vous rédigez le résumé vous-même, cela enfreint la règle : les tours de l'assistant conservés contiennent toujours des blocs de réflexion produits lorsque les tours d'origine, et non le résumé, les précédaient. Ces blocs échouent.

Pour conserver cette réflexion, faites rédiger le résumé par l'API avec la compaction à la demande. [Compaction qui conserve les tours récents](https://platform.claude.com/docs/fr/build-with-claude/compaction-keep-recent-turns) montre comment procéder, et [Conditions pour que la réflexion conservée reste valide](https://platform.claude.com/docs/fr/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) indique quand la réflexion conservée reste valide.

Le reste de cette section concerne un résumé que vous rédigez vous-même.

<Frame>
  ![« Keep-tail compaction » (compaction avec conservation de la fin) : l'historique est remplacé par un résumé des tours 1 et 2 suivi des tours 3 à 5 mot pour mot ; la réflexion des tours 3 et 4 de l'assistant a été produite après les tours d'origine, et non après le résumé, elle échoue donc ; la même requête envoyée avec prefix\_mismatch\_behavior drop\_block réussit, l'API supprime ces deux blocs et les liste dans input\_transformations](https://platform.claude.com/docs/images/preserved-thinking-keep-tail-compaction.svg)
</Frame>

Solution : conservez les tours exactement tels qu'ils sont et envoyez `prefix_mismatch_behavior: "drop_block"`. L'API supprime les blocs de réflexion obsolètes, le modèle lit les blocs `text` et `tool_use` des tours conservés, et la requête réussit.

Transmettez l'historique compacté en tant que `messages` et définissez `block_binding` dans la configuration `thinking`. Dans l'exemple suivant, `compacted_messages` est le tableau produit par votre étape de compaction : le message de résumé suivi des tours conservés exactement tels que l'API les a renvoyés, blocs `thinking` inclus :

<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 : le message de résumé, puis les tours conservés tels que renvoyés.
  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 : le message de résumé, puis les tours conservés tels que renvoyés.
  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 : le message de résumé, puis les tours conservés tels que renvoyés.
  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 : le message de résumé, puis les tours conservés tels que renvoyés.
  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 : le message de résumé, puis les tours conservés tels que renvoyés.
      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 : le message de résumé, puis les tours conservés tels que renvoyés
  $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 : le message de résumé, puis les tours conservés tels que renvoyés.
  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 réponse contient le nouveau tour de l'assistant comme d'habitude, plus une entrée `input_transformations` par bloc supprimé. Pour l'historique du diagramme, il s'agit de la réflexion des tours 3 et 4 de l'assistant :

```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"
    }
  ]
}
```

Continuez à envoyer `"drop_block"` lors des requêtes suivantes tant que ces deux tours restent dans l'historique. La réflexion que le modèle produit à partir de cette requête suit le résumé et reste valide. Si vous préférez ne pas dépendre de l'en-tête bêta, l'alternative consiste à retirer vous-même les blocs `thinking` et `redacted_thinking` des tours de l'assistant conservés lorsque vous construisez l'historique compacté.

#### Compaction en arrière-plan (asynchrone)

La compaction en arrière-plan construit le résumé en dehors du chemin critique pendant que la conversation se poursuit, puis le substitue quelques requêtes plus tard. Pour conserver la réflexion produite entre-temps, faites rédiger le résumé par l'API avec la compaction à la demande : [Compactage en arrière-plan](https://platform.claude.com/docs/fr/build-with-claude/compaction-background) décrit les étapes, et cette réflexion reste valide dans les mêmes [conditions applicables à la réflexion conservée](https://platform.claude.com/docs/fr/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) que les tours récents conservés.

Un résumé que vous construisez vous-même enfreint la règle de la même manière que la compaction avec conservation de la fin, avec un décalage : chaque tour de l'assistant produit pendant la construction du résumé porte une réflexion antérieure au remplacement, et elle échoue entièrement dès que le résumé est inséré. Si vous en utilisez un, traitez le remplacement comme pour la compaction avec conservation de la fin et envoyez `"drop_block"` à partir du remplacement, ou compactez de manière synchrone.

#### Schémas qui ne fonctionnent pas avec la réflexion préservée

* **Supprimer des tours au milieu.** Retirer des tours individuels invalide chaque bloc de réflexion qui les suit, et aucun schéma de compaction ne l'évite. Si vous supprimiez un tour pour modifier une instruction, ajoutez plutôt un [message système en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#new-instructions). Pour retirer sélectivement d'anciens résultats d'outils ou d'anciennes réflexions, utilisez l'[édition du contexte](https://platform.claude.com/docs/fr/build-with-claude/context-editing) côté serveur.
* **Compacter au milieu d'un cycle d'outils.** Ne compactez pas entre le `tool_use` d'un tour de l'assistant et le `tool_result` qui y répond. Renvoyez ce tour de l'assistant avec sa réflexion intacte afin que le modèle termine le cycle avec son raisonnement. Consultez [Préserver les blocs de réflexion](https://platform.claude.com/docs/fr/build-with-claude/thinking#preserving-thinking-blocks).

### Référencer les fichiers par ID, et non par une URL dont le contenu change

Pour un bloc `image` ou `document` avec une source `url`, la vérification porte sur les octets récupérés, et non sur la chaîne de l'URL. Une URL dont le contenu change invalide la réflexion ultérieure : un point de terminaison « dernière capture d'écran », ou un document que quelqu'un modifie entre les tours. Une URL signée renouvelée pour le même fichier ne l'invalide pas. Pour le contenu que vous référencez sur plusieurs tours, téléversez-le une fois avec l'[API Files](https://platform.claude.com/docs/fr/build-with-claude/files) et utilisez le `file_id`, ou envoyez-le en base64.

### Bibliothèques, proxys et passerelles

Une bibliothèque, un proxy ou une passerelle se situe entre l'historique de quelqu'un d'autre et l'API ; ses propres réécritures comptent donc comme des modifications, et ses utilisateurs ne peuvent ni les voir ni les corriger.

* **Transmettez ce que vous ne reconnaissez pas.** Transférez sans modification les valeurs `anthropic-beta` et `thinking.block_binding` de l'appelant, et renvoyez-lui `input_transformations`. Un schéma d'options qui rejette les clés inconnues empêche vos utilisateurs de choisir `"drop_block"`.
* **Laissez un message `role: "system"` là où l'appelant l'a placé.** Le déplacer dans le champ `system` de niveau supérieur modifie `system` pour cette requête et invalide chaque bloc de réflexion de la conversation.
* **Pour désactiver le « tool use » (utilisation d'outils) pour une requête, envoyez `tool_choice: {"type": "none"}`.** Ne retirez pas `tools`.
* **Ne masquez pas l'erreur 400.** Si votre code l'intercepte, retire la réflexion et réessaie au nom de l'appelant, consignez-le : son historique reste modifié, et le modèle perd son raisonnement antérieur à chaque requête ultérieure.

## FAQ

<AccordionGroup>
  <Accordion title="Ai-je besoin d'un nouveau compte pour tester la réflexion préservée ?">
    Non. Envoyez l'en-tête bêta `thinking-binding-controls-2026-08-01` et définissez `thinking.block_binding.prefix_mismatch_behavior`. Définir ce champ soumet cette requête à l'application de la vérification, quelle que soit l'ancienneté du compte. `"error"` rejette un historique modifié avec la même erreur 400 qu'un nouveau compte reçoit, et `"drop_block"` laisse passer la requête et liste ce qui a été supprimé dans `input_transformations`. Pour détecter les modifications du préfixe depuis un compte plus ancien sans appliquer la vérification, envoyez l'en-tête et laissez le champ non défini : les blocs en échec atteignent toujours le modèle, et `input_transformations` les liste comme `thinking_mismatch_allowed`. Consultez [Vérifier si votre code modifie le préfixe](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#how-to-tell-whether-your-integration-is-impacted).
  </Accordion>

  <Accordion title="Si quoi que ce soit change avant un bloc de réflexion, même la description d'un seul outil, la conversation est-elle inutilisable ?">
    Non. Ce qui échoue, c'est la réflexion déjà présente dans l'historique après le point que vous avez modifié, et vous choisissez ce qu'il en advient. Avec `prefix_mismatch_behavior: "drop_block"`, l'API supprime ces blocs et la requête réussit : le modèle répond à ce tour sans ce raisonnement, et le cache de prompts redémarre à la modification. Avec la valeur par défaut `"error"`, l'API rejette la requête avec une erreur 400 jusqu'à ce que vous annuliez la modification ou renvoyiez la requête avec `"drop_block"`. Consultez [Ce que fait l'API d'un bloc invalide](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#mismatch-behavior). [Ce qui compte comme une modification](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#what-counts-as-an-edit) liste les changements qui comptent.
  </Accordion>

  <Accordion title="Modifier l'effort ou d'autres paramètres de réflexion entre les requêtes invalide-t-il la réflexion antérieure ?">
    Non. `output_config.effort`, `max_tokens` et la configuration `thinking` ne font pas partie du préfixe vérifié, qui ne couvre que `system`, `tools` et `messages`. Une modification de l'effort au niveau supérieur invalide la majeure partie du cache de prompts. Lorsque le modèle et la plateforme prennent en charge l'[effort par message](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#effort-changes), une modification de l'effort par message conserve le cache de prompts et est utilisée comme nouveau niveau d'effort jusqu'à une nouvelle modification.
  </Accordion>

  <Accordion title="Ma liste d'outils change en cours de session. Comment éviter d'invalider la conversation ?">
    Ne modifiez pas `tools`. Déclarez l'ensemble complet au début de la session, marquez les outils qui ne sont pas encore disponibles avec `defer_loading: true`, et proposez-les ou retirez-les avec des blocs `tool_addition` et `tool_removal`. Si vous ne découvrez le schéma d'un outil qu'en cours de session, définissez-le dans le bloc `tool_addition` (`inline-tools-2026-09-15`, plus `mcp-client-2026-09-15` pour un serveur atteint par le connecteur MCP de l'API) et laissez `tools` inchangé. Les messages `role: "system"` qui contiennent ces blocs rejoignent le préfixe pour la réflexion ultérieure, ne les déplacez donc pas, ne les reformulez pas et ne les supprimez pas par la suite. Consultez [Ajouter ou retirer des outils avec `tool_addition` et `tool_removal`](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#tool-changes).
  </Accordion>

  <Accordion title="Je compacte en résumant les tours plus anciens et en conservant les tours récents mot pour mot. Cela fonctionne-t-il toujours ?">
    Oui, si l'API rédige le résumé. La [compaction à la demande](https://platform.claude.com/docs/fr/build-with-claude/compaction-on-demand) (en-tête bêta `compact-2026-09-04`) résume les tours plus anciens dans un bloc signé que vous envoyez à leur place. Les tours récents conservent leur réflexion dans les [conditions pour que la réflexion conservée reste valide](https://platform.claude.com/docs/fr/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid).

    Si vous rédigez le résumé vous-même, la réflexion des tours conservés échoue à la vérification, car ces blocs ont été produits à partir de l'historique que vous avez remplacé. Retirez les blocs `thinking` et `redacted_thinking` des tours que vous reportez et conservez leurs blocs `text` et `tool_use`, ou envoyez `prefix_mismatch_behavior: "drop_block"` et laissez l'API les supprimer. La compaction simple ne laisse aucune réflexion susceptible d'échouer et constitue l'approche recommandée : un message de résumé plus le prochain tour utilisateur, sans rejouer aucun tour antérieur. La [compaction](https://platform.claude.com/docs/fr/build-with-claude/compaction) et l'[édition du contexte](https://platform.claude.com/docs/fr/build-with-claude/context-editing) côté serveur ne comptent pas comme des modifications. Consultez [Compacter côté client](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#custom-compaction-on-the-client).
  </Accordion>

  <Accordion title="Comment gérer les fichiers d'instructions tels que AGENTS.md ou CLAUDE.md qui changent en cours de session ?">
    Chargez-les une fois au début de la session et gardez fixes l'invite `system` de niveau supérieur et `tools`. Lorsqu'un fichier change, ajoutez la nouvelle version à ce point dans `messages` au lieu de modifier l'original. Utilisez un [message système en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/mid-conversation-system-messages) pour les instructions qui viennent de vous en tant qu'opérateur. Pour le texte de fichier que vous considérez comme non fiable, qui ne doit pas avoir l'autorité d'une invite système, placez plutôt le contenu dans le prochain tour `user`. Consultez [Ajouter des instructions avec un message système en cours de conversation](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#new-instructions) et [Limitations](https://platform.claude.com/docs/fr/build-with-claude/mid-conversation-system-messages#limitations).
  </Accordion>

  <Accordion title="Puis-je reprendre une session enregistrée plus tard, après un redémarrage ou le lendemain ?">
    Oui. Une session reprise est une requête de suivi ordinaire : `system`, `tools` et les `messages` antérieurs doivent avoir le même contenu que ce que vous avez envoyé en dernier. Le formatage JSON et l'ordre des clés n'ont pas d'importance ; les valeurs, si. Conservez exactement ce que vous avez envoyé et reçu, et rejouez-le : l'invite système générée, les définitions d'outils et chaque tour de l'assistant tel que renvoyé. Ne régénérez pas à partir d'entrées qui ont pu changer depuis, comme la date, un fichier d'instructions mis à jour ou une nouvelle version d'outil. Tout élément nouveau va dans un message ajouté. Consultez [Renvoyer les tours de l'assistant exactement tels qu'ils ont été retournés](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#append-assistant-turns-exactly-as-returned).
  </Accordion>

  <Accordion title="Une session enregistrée échoue désormais à chaque requête. Comment la faire fonctionner à nouveau ?">
    L'historique stocké contient une modification, donc le rejouer ne peut pas réussir. Envoyez désormais cette session avec `prefix_mismatch_behavior: "drop_block"`, ou retirez une fois ses blocs `thinking` et `redacted_thinking` et continuez. Sur Claude Sonnet 5.5 et Claude Haiku 5.5, `block_binding` ne fonctionne qu'avec `thinking: {"type": "adaptive"}`. Avec `between_tools` sur Claude Sonnet 5.5, ou `thinking: {"type": "disabled"}` sur Claude Haiku 5.5, gardez l'historique en ajout seul, ou retirez les blocs de réflexion à partir du tour modifié. La réflexion que le modèle produit à partir de ce point reste valide tant que rien de ce qui la précède ne change à nouveau. Trouvez ensuite la modification afin que les nouvelles sessions ne la rencontrent pas. Consultez [Gérer l'erreur dans le code](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#handle-the-error-in-code).
  </Accordion>

  <Accordion title="Mon harnais peut acheminer un tour vers un modèle autre que Claude. Ces tours invalident-ils la réflexion antérieure de Claude ?">
    Non, à condition qu'ils soient ajoutés après l'historique existant et que rien d'antérieur ne change : un message de l'assistant sans blocs de réflexion est un message ajouté comme un autre. Envoyez la sortie de l'autre modèle sous forme de contenu `text` et `tool_use`.
  </Accordion>

  <Accordion title="Puis-je reporter le raisonnement d'une conversation dans une nouvelle conversation ?">
    Pas dans une conversation différente. Un bloc de réflexion n'est utilisable que lorsqu'il suit exactement les `system`, `tools` et `messages` à partir desquels il a été produit. Une branche qui rejoue cet historique sans modification jusqu'au point de bifurcation conserve sa réflexion. Une conversation qui part de quoi que ce soit d'autre ne peut pas l'utiliser, commencez donc cette conversation à partir d'un résumé de l'état de la tâche, comme dans la [compaction simple](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#custom-compaction-on-the-client) : l'objectif, les décisions prises, les fichiers et résultats obtenus jusqu'ici, et l'étape suivante. Les blocs de réflexion de Claude Sonnet 5.5 et Claude Haiku 5.5 ne peuvent pas non plus être réutilisés depuis un autre compte (consultez [Les blocs de réflexion restent liés au compte qui les a produits](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#account-bound-thinking)).
  </Accordion>
</AccordionGroup>

## Étapes suivantes

<CardGroup cols={2}>
  <Card title="Dépannage de la réflexion" icon="hammer" href="https://platform.claude.com/docs/fr/build-with-claude/thinking-troubleshooting">
    Diagnostiquez et corrigez les échecs de réflexion les plus courants : erreurs 400 de configuration, blocs de réflexion vides ou manquants, arrêts max\_tokens et échecs de cache.
  </Card>

  <Card title="Messages système et changements d'outils en cours de conversation" icon="messages" href="https://platform.claude.com/docs/fr/build-with-claude/mid-conversation-system-messages">
    Modifiez les instructions système ou la disponibilité des outils au cours d'une conversation sans invalider le préfixe mis en cache qui les précède.
  </Card>

  <Card title="Compaction" icon="stack" href="https://platform.claude.com/docs/fr/build-with-claude/compaction">
    Compaction de contexte côté serveur pour gérer les longues conversations qui approchent des limites de la fenêtre de contexte.
  </Card>

  <Card title="Mise en cache des prompts" icon="database" href="https://platform.claude.com/docs/fr/build-with-claude/prompt-caching">
    Mettez en cache les préfixes de prompts avec `cache_control` pour réduire les coûts et la latence, en utilisant la mise en cache automatique ou des points de rupture explicites avec des TTL de 5 minutes ou 1 heure.
  </Card>
</CardGroup>
