Réflexion préservée
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.
- Rien avant le bloc de réflexion n'a changé. L'invite
systemde niveau supérieur, lestoolset lesmessagessitué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é.
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 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: 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
- Efface ou raccourcit d'anciens résultats d'outils, ou réencode d'anciennes images
- Résume ou supprime d'anciens tours côté client et conserve les tours récents avec leur réflexion
- Ajoute, supprime ou modifie des entrées dans
tools - Ajoute un rappel à un tour utilisateur puis le supprime ou le réécrit plus tard
- Supprime certains blocs
thinkinget conserve les suivants, ou les supprime puis les remet plus tard - Reconstruit une session enregistrée à partir de modèles 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).
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.
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 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, ou lors d'un repli côté serveur. 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é.
Avec l'en-tête bêta 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" :
{
"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 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
systemde niveau supérieur - L'ensemble des
tools - Chaque
messagesitué avant le bloc
Remarque : avec la 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 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 : 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 400invalid_request_errorqui 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é dansinput_transformations(sur l'événementmessage_starten streaming) avecreason: "prefix_binding_mismatch".
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. 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 thinking-binding-controls-2026-08-01. Définir le comportement en cas de non-correspondance et lire input_transformations montre la requête dans chaque SDK.
Le message 400 commence ainsi :
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 :
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 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 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), 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 thinking-binding-controls-2026-08-01 ajoute :
- Un tableau
input_transformationsde niveau supérieur dans chaque réponse - Un objet
block_bindingdans la configurationthinking, dont l'unique champ estprefix_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 :
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 [])}")The greatest common divisor of 1071 and 462 is 21.
Input transformations: 0Avec 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é. Lareasonestprefix_binding_mismatchoumodel_binding_mismatch(consultez Changer de modèle en cours de conversation). Lareasonpeut aussi êtreorganization_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).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é. Lareasonest toujoursprefix_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). Définirprefix_mismatch_behaviorsur 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, 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, 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 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 dansinput_transformationsen tant quethinking_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 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 remplace les messages qu'il résume, dans les conditions de validité de la réflexion conservée |
| 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
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 . 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 :
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}")thinking blocks: 1, dropped: 0
thinking blocks: 1, dropped: 0Aucun 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 :
{
"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é àpatha changé depuis la requête précédente. Comparezsystem,toolsetmessagesjusqu'à 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.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.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.
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, 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 , 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 :
{
"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, 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 :
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}")thinking blocks: 1, flagged: 0
thinking blocks: 1, flagged: 0
thinking blocks: 1, flagged: 2La 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. 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 | 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 | 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 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 (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 | 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 | mid-conversation-output-config-2026-07-01 |
| Supprimer ou résumer d'anciens tours côté client | La compaction à la demande pour conserver les tours récents avec leur réflexion, une autre compaction ou édition de contexte côté serveur, ou une compaction côté 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, ou du base64 | Aucun |
Tous ces remplacements supposent que vous renvoyez les tours assistant exactement tels qu'ils ont été retournés. 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 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 :
anthropic-beta: thinking-binding-controls-2026-08-01,mid-conversation-system-clear-at-2026-08-21,inline-tools-2026-09-15Les 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.
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" à l'endroit de messages où le changement devient effectif :
{
"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). 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 si le changement vient de vous en tant qu'opérateur.
{
"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 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 :
[
{ "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, 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, avecdefer_loading: truesur ceux que le modèle ne doit pas encore voir. Activez et désactivez ensuite les outils avec des blocstool_additionettool_removalqui 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 bloctool_additionau lieu de modifiertools.
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 :
{
"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 :
{
"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 :
{
"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, 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, 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.
{ "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 (bêta) renvoie le résumé à partir d'une requête distincte, qui peut s'exécuter en arrière-plan, 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. Demander un résumé présente la requête et indique l'en-tête bêta nécessaire.
- La compaction à un seuil de tokens 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
instructionsaccepte 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 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_20250919etclear_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 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é.
[
{
"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 montre comment procéder, et Conditions pour que la réflexion conservée reste valide 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.
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 :
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)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 :
{
"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 décrit les étapes, et cette réflexion reste valide dans les mêmes conditions applicables à la réflexion conservée 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. Pour retirer sélectivement d'anciens résultats d'outils ou d'anciennes réflexions, utilisez l'édition du contexte côté serveur.
- Compacter au milieu d'un cycle d'outils. Ne compactez pas entre le
tool_used'un tour de l'assistant et letool_resultqui 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.
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 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-betaetthinking.block_bindingde l'appelant, et renvoyez-luiinput_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 champsystemde niveau supérieur modifiesystempour 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 pastools. - 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
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.
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. Ce qui compte comme une modification liste les changements qui comptent.
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, 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.
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.
Oui, si l'API rédige le résumé. La compaction à la demande (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.
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 et l'édition du contexte côté serveur ne comptent pas comme des modifications. Consultez Compacter côté client.
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 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 et Limitations.
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.
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.
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.
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 : 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).
Étapes suivantes
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.
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.
Compaction de contexte côté serveur pour gérer les longues conversations qui approchent des limites de la fenêtre de contexte.
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.
Was this page helpful?