---
title: Compaction et réflexion préservée
url: https://platform.claude.com/docs/fr/build-with-claude/compaction-thinking-blocks
description: Quand les blocs de réflexion des tours conservés après un compactage à la demande restent valides sur les modèles dotés de la réflexion préservée, et comment le vérifier.
featureMetadata:
  status: beta
  betaHeader: compact-2026-09-04
  supportedModels:
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-fable-5
    - claude-mythos-5
    - claude-mythos-preview
    - claude-opus-5-5
    - claude-opus-5
    - claude-opus-4-8
    - claude-opus-4-7
    - claude-opus-4-6
    - claude-sonnet-5-5
    - claude-sonnet-5
    - claude-sonnet-4-6
    - claude-haiku-5-5
  supportedPlatforms:
    Claude API: beta
    Claude Platform on AWS: beta
    Google Cloud: beta
    Microsoft Foundry: beta
---

Ignorez cette page, sauf si vous renvoyez des « thinking blocks » (blocs de réflexion) à un modèle doté de la [« preserved thinking » (réflexion préservée)](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking) et que vous conservez des tours après le bloc de compaction. Les « kept turns » (tours conservés) sont les tours qui suivent le bloc. Il peut s'agir de tours récents que vous avez exclus de la requête de compaction, comme dans [Compaction qui conserve les tours récents](https://platform.claude.com/docs/fr/build-with-claude/compaction-keep-recent-turns). Il peut aussi s'agir de tours arrivés pendant la rédaction du résumé, comme dans [Compaction en arrière-plan](https://platform.claude.com/docs/fr/build-with-claude/compaction-background).

Les modèles dotés de la réflexion préservée vérifient les blocs de réflexion antérieurs par rapport à la conversation qui les a produits. Un résumé remplace une partie de cette conversation. La vérification accepte toutefois cette substitution lorsque c'est l'API qui a rédigé le résumé, de sorte que la réflexion des tours conservés peut rester valide.

## Conditions pour que la réflexion conservée reste valide

Les blocs de réflexion des tours conservés restent valides tant que toutes ces conditions sont remplies :

* **La requête de compaction s'exécute sur un modèle doté de la réflexion préservée.** Cette condition couvre chaque requête de compaction effectuée depuis la production d'un bloc de réflexion, et pas seulement la plus récente. Pour la remplir, vous pouvez par exemple envoyer chaque requête de compaction au modèle qu'utilise la conversation.
* **Les tours conservés suivent directement les messages résumés, et vous les envoyez sans modification.** Envoyez chaque message conservé exactement tel qu'il figure dans votre historique. N'omettez et n'ajoutez aucun message entre le dernier message résumé et le premier message conservé. Le premier message conservé doit également avoir un rôle différent de celui du dernier message résumé. Il ne peut pas non plus s'agir d'un message `role: "system"` en cours de conversation. Sinon, l'API le fusionne avec le dernier message résumé. Pour obtenir un premier message conservé correct, vous pouvez par exemple compacter exactement les `messages` d'une requête que vous avez déjà envoyée. Les tours conservés commencent alors par la réponse de Claude à cette requête.
* **`system` et les `tools` non marqués `defer_loading: true` ne changent pas.** Ils sont identiques dans la requête de compaction et dans les requêtes qui ont produit la réflexion conservée, et ils restent identiques dans les requêtes suivantes. La section [Modifier l'invite système ou les outils](https://platform.claude.com/docs/fr/build-with-claude/compaction-thinking-blocks#change-the-system-prompt-or-tools) explique comment les modifier en toute sécurité.

Si une condition n'est pas remplie, rien n'échoue lors de la compaction, et l'API accepte le bloc dans les requêtes ultérieures dans tous les cas. L'échec survient lors de la première requête ultérieure qui envoie la réflexion conservée là où l'API applique la vérification. Par défaut, il s'agit d'une erreur 400. Si la requête définit `thinking.block_binding.prefix_mismatch_behavior` sur `"drop_block"`, les blocs de réflexion sont supprimés. Dans l'API Message Batches, un élément qui laisse ce champ non défini n'échoue pas : là où la vérification s'applique par défaut, l'API supprime plutôt les blocs. La section [Ce que fait l'API d'un bloc invalide](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#mismatch-behavior) décrit les deux résultats, et la section [Quand l'API applique la vérification](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#enforcement) indique quelles requêtes sont vérifiées.

## Compacter à nouveau sans invalider la réflexion antérieure

Vous pouvez [compacter à nouveau](https://platform.claude.com/docs/fr/build-with-claude/compaction-on-demand#compact-again) tout en conservant des tours. Le nouveau bloc couvre l'ancien résumé et chaque message qui le suit dans la requête de compaction. Tous les tours que vous excluez de cette requête deviennent des tours conservés du nouveau bloc.

La première des [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) prend en compte chaque compaction effectuée depuis la production d'un bloc de réflexion. Ainsi, pour un tour que vous conservez à travers deux compactions, les deux doivent s'être exécutées sur un modèle doté de la réflexion préservée.

Les compactions antérieures à la production d'un bloc de réflexion ne sont pas prises en compte pour ce bloc. La réflexion produite après la mise en place d'un bloc de compaction est liée à ce bloc. Elle reste valide à travers les compactions ultérieures qui remplissent les conditions.

## Modifier l'invite système ou les outils

Une requête ultérieure peut utiliser un `system`, des `tools` ou un modèle différents de ceux de la requête de compaction, et l'API accepte toujours le bloc. Un tel changement peut invalider la réflexion des tours conservés, mais il n'a aucun autre effet.

Pour modifier `system` ou `tools` sans invalider la réflexion conservée, compactez d'abord toute la conversation, afin qu'aucun tour ne soit conservé. Modifiez-les ensuite dans la requête suivante.

Pour ajouter une instruction ou modifier les outils disponibles sans toucher à `system` ni à `tools`, ajoutez la modification à la fin de `messages`, comme décrit dans [Effectuer des changements sans modifier le préfixe](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#replace-prefix-edits).

Les messages système en cours de conversation situés dans les tours résumés sont également résumés, de sorte que leurs instructions textuelles cessent de s'appliquer après la substitution. Un niveau d'[effort par message](https://platform.claude.com/docs/fr/build-with-claude/effort#change-effort-mid-conversation-beta) qu'ils définissent n'est pas non plus reporté : jusqu'à ce qu'un message ultérieur définisse un niveau, les tours s'exécutent avec le `output_config.effort` de premier niveau de la requête, ou avec la valeur par défaut du modèle si vous n'en définissez pas. Pour maintenir une instruction ou un niveau d'effort en vigueur, énoncez-le à nouveau dans un message `role: "system"` placé directement après le premier nouveau tour `user` qui suit les tours conservés. Les modifications d'outils au sein de ces tours sont reportées d'elles-mêmes lorsque la requête de compaction inclut également `inline-tools-2026-09-15` : le bloc renvoyé enregistre leur effet net dans son champ `tool_changes` ; renvoyez donc le bloc sans le modifier. Si le bloc n'a pas de champ `tool_changes`, énoncez à nouveau ces modifications d'outils de la même manière. Un message système placé entre le bloc et les tours conservés invalide leur réflexion.

## Vérifier que la réflexion conservée est restée valide

La réponse de compaction n'indique pas si la réflexion conservée reste valide. C'est la première requête après la substitution qui le révèle. Pour le vérifier dans vos tests :

1. Menez une courte conversation avec la réflexion activée. Utilisez un modèle sur lequel l'API exécute la vérification (voir [Quand l'API applique la vérification](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#enforcement)), et utilisez-le pour chaque étape. En effet, un modèle qui ne peut pas lire un bloc de réflexion le supprime sans renvoyer d'erreur.
2. Compactez les tours les plus anciens, et conservez au moins un tour qui contient un bloc de réflexion.
3. Envoyez la requête suivante en plaçant le bloc en premier, puis le tour conservé, puis un nouveau message `user`. Définissez `thinking.block_binding.prefix_mismatch_behavior` sur `"error"`.
4. Lisez le résultat. Une réponse 200 dont le tableau `input_transformations` est vide signifie qu'aucun bloc de réflexion n'a échoué à la vérification ni n'a été supprimé. Une erreur 400 indiquant que le bloc est lié à une conversation différente signifie qu'au moins un bloc a échoué. Le message commence par le chemin du premier bloc en échec, et la section [Ce que fait l'API d'un bloc invalide](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#mismatch-behavior) le présente en entier.

Le champ `prefix_mismatch_behavior` nécessite l'en-tête bêta `thinking-binding-controls-2026-08-01` en plus de [l'en-tête bêta `compact-2026-09-04`](https://platform.claude.com/docs/fr/build-with-claude/compaction-on-demand#request-a-summary). Sur les comptes où la vérification n'est pas activée par défaut, définir ce champ active également la vérification pour la requête.

Le programme suivant exécute les quatre étapes. Il affiche le nombre de blocs de réflexion que contient le tour conservé et le nombre d'entrées de `input_transformations`. Si ce tableau ne contient aucune entrée, la réflexion conservée est restée valide :

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

  client = anthropic.Anthropic()

  # Claude Fable 5.1 est le premier modèle qui vérifie la réflexion renvoyée par rapport à la conversation.
  MODEL = "claude-fable-5-1"
  BETAS = ["compact-2026-09-04", "thinking-binding-controls-2026-08-01"]
  SYSTEM = "You help plan a recipe app's release. Keep answers short."
  # Avec "error", un bloc de réflexion qui échoue à la vérification fait échouer la requête avec une erreur 400.
  THINKING: BetaThinkingConfigParam = {
      "type": "adaptive",
      "block_binding": {"prefix_mismatch_behavior": "error"},
  }

  # 1. Menez une courte conversation avec la réflexion activée.
  history: list[BetaMessageParam] = [
      {"role": "user", "content": "What are the main entities in the app's data model?"}
  ]
  first = client.beta.messages.create(
      model=MODEL,
      max_tokens=8192,
      system=SYSTEM,
      betas=BETAS,
      thinking=THINKING,
      messages=history,
  )
  history += [
      {"role": "assistant", "content": first.content},
      {
          "role": "user",
          "content": "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?",
      },
  ]
  second = client.beta.messages.create(
      model=MODEL,
      max_tokens=8192,
      system=SYSTEM,
      betas=BETAS,
      thinking=THINKING,
      messages=history,
  )
  history.append({"role": "assistant", "content": second.content})
  thinking_blocks = sum(block.type == "thinking" for block in second.content)
  print(f"Thinking blocks in the kept turn: {thinking_blocks}")

  # 2. Résumez le premier tour. Le deuxième tour reste hors de la requête.
  summary = client.beta.messages.create(
      model=MODEL,
      max_tokens=4096,
      system=SYSTEM,
      betas=BETAS,
      thinking=THINKING,
      messages=history[:2],
      compaction={"type": "summarize"},
  )
  if summary.stop_reason != "compaction":
      raise SystemExit(f"No summary: {summary.stop_reason}")

  # 3. Placez le bloc devant le tour conservé et posez la question suivante.
  history = [
      {"role": "assistant", "content": summary.content},
      *history[2:],
      {"role": "user", "content": "Which day should the release go out?"},
  ]
  third = client.beta.messages.create(
      model=MODEL,
      max_tokens=8192,
      system=SYSTEM,
      betas=BETAS,
      thinking=THINKING,
      messages=history,
  )

  # 4. Un code 200 sans bloc supprimé signifie que la réflexion conservée a été acceptée.
  print(f"Dropped thinking blocks: {len(third.input_transformations)}")
  ```

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

  // Claude Fable 5.1 est le premier modèle qui vérifie la réflexion renvoyée par rapport à la conversation.
  const model: Anthropic.Model = "claude-fable-5-1";
  const betas: Anthropic.Beta.AnthropicBeta[] = [
    "compact-2026-09-04",
    "thinking-binding-controls-2026-08-01"
  ];
  const systemPrompt = "You help plan a recipe app's release. Keep answers short.";
  // Avec "error", un bloc de réflexion qui échoue à la vérification fait échouer la requête avec une erreur 400.
  const thinking: Anthropic.Beta.Messages.BetaThinkingConfigParam = {
    type: "adaptive",
    block_binding: { prefix_mismatch_behavior: "error" }
  };

  // 1. Menez une courte conversation avec la réflexion activée.
  let history: Anthropic.Beta.Messages.BetaMessageParam[] = [
    { role: "user", content: "What are the main entities in the app's data model?" }
  ];
  const first = await client.beta.messages.create({
    model,
    max_tokens: 8192,
    system: systemPrompt,
    betas,
    thinking,
    messages: history
  });
  history.push(
    { role: "assistant", content: first.content },
    {
      role: "user",
      content:
        "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?"
    }
  );
  const second = await client.beta.messages.create({
    model,
    max_tokens: 8192,
    system: systemPrompt,
    betas,
    thinking,
    messages: history
  });
  history.push({ role: "assistant", content: second.content });
  const thinkingBlocks = second.content.filter((block) => block.type === "thinking").length;
  console.log(`Thinking blocks in the kept turn: ${thinkingBlocks}`);

  // 2. Résumez le premier tour. Le deuxième tour reste hors de la requête.
  const summary = await client.beta.messages.create({
    model,
    max_tokens: 4096,
    system: systemPrompt,
    betas,
    thinking,
    messages: history.slice(0, 2),
    compaction: { type: "summarize" }
  });
  if (summary.stop_reason !== "compaction") {
    throw new Error(`No summary: ${summary.stop_reason}`);
  }

  // 3. Placez le bloc devant le tour conservé et posez la question suivante.
  history = [
    { role: "assistant", content: summary.content },
    ...history.slice(2),
    { role: "user", content: "Which day should the release go out?" }
  ];
  const third = await client.beta.messages.create({
    model,
    max_tokens: 8192,
    system: systemPrompt,
    betas,
    thinking,
    messages: history
  });

  // 4. Un code 200 sans bloc supprimé signifie que la réflexion conservée a été acceptée.
  console.log(`Dropped thinking blocks: ${third.input_transformations?.length ?? 0}`);
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Model = Anthropic.Models.Messages.Model;

  AnthropicClient client = new();

  // Claude Fable 5.1 est le premier modèle qui vérifie la réflexion renvoyée par rapport à la conversation.
  const Model ModelId = Model.ClaudeFable5_1;
  AnthropicBeta[] betas = [AnthropicBeta.Compact2026_09_04, AnthropicBeta.ThinkingBindingControls2026_08_01];
  const string SystemPrompt = "You help plan a recipe app's release. Keep answers short.";
  // Avec "error", un bloc de réflexion qui échoue à la vérification fait échouer la requête avec une erreur 400.
  BetaThinkingConfigAdaptive thinking = new()
  {
      BlockBinding = new() { PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.Error },
  };

  // 1. Menez une courte conversation avec la réflexion activée.
  List<BetaMessageParam> history =
  [
      new() { Role = Role.User, Content = "What are the main entities in the app's data model?" },
  ];
  var first = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = ModelId,
      MaxTokens = 8192,
      System = SystemPrompt,
      Betas = [.. betas],
      Thinking = thinking,
      Messages = history,
  });
  history.AddRange(
  [
      new()
      {
          Role = Role.Assistant,
          Content = first.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
      },
      new()
      {
          Role = Role.User,
          Content = "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?",
      },
  ]);
  var second = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = ModelId,
      MaxTokens = 8192,
      System = SystemPrompt,
      Betas = [.. betas],
      Thinking = thinking,
      Messages = history,
  });
  history.Add(new()
  {
      Role = Role.Assistant,
      Content = second.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
  });
  var thinkingBlocks = second.Content.Count(block => block.TryPickThinking(out _));
  Console.WriteLine($"Thinking blocks in the kept turn: {thinkingBlocks}");

  // 2. Résumez le premier tour. Le deuxième tour reste en dehors de la requête.
  var summary = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = ModelId,
      MaxTokens = 4096,
      System = SystemPrompt,
      Betas = [.. betas],
      Thinking = thinking,
      Messages = history[..2],
      Compaction = new BetaCompactionConfig(), // type defaults to "summarize"
  });
  if (summary.StopReason != BetaStopReason.Compaction)
  {
      throw new InvalidOperationException($"No summary: {summary.StopReason?.Raw()}");
  }

  // 3. Placez le bloc devant le tour conservé et posez la question suivante.
  history =
  [
      new()
      {
          Role = Role.Assistant,
          Content = summary.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
      },
      .. history[2..],
      new() { Role = Role.User, Content = "Which day should the release go out?" },
  ];
  var third = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = ModelId,
      MaxTokens = 8192,
      System = SystemPrompt,
      Betas = [.. betas],
      Thinking = thinking,
      Messages = history,
  });

  // 4. Une réponse 200 sans bloc supprimé signifie que la réflexion conservée a été acceptée.
  Console.WriteLine($"Dropped thinking blocks: {third.InputTransformations?.Count ?? 0}");
  ```

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

  // Claude Fable 5.1 est le premier modèle qui vérifie la réflexion renvoyée par rapport à la conversation.
  const model = anthropic.ModelClaudeFable5_1
  betas := []anthropic.AnthropicBeta{
  	anthropic.AnthropicBetaCompact2026_09_04,
  	anthropic.AnthropicBetaThinkingBindingControls2026_08_01,
  }
  system := []anthropic.BetaTextBlockParam{{Text: "You help plan a recipe app's release. Keep answers short."}}
  // Avec "error", un bloc de réflexion qui échoue à la vérification fait échouer la requête avec une erreur 400.
  thinking := anthropic.BetaThinkingConfigParamUnion{
  	OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  		BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  			PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorError,
  		},
  	},
  }

  // 1. Menez une courte conversation avec la réflexion activée.
  history := []anthropic.BetaMessageParam{
  	anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What are the main entities in the app's data model?")),
  }
  first, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:     model,
  	MaxTokens: 8192,
  	System:    system,
  	Betas:     betas,
  	Thinking:  thinking,
  	Messages:  history,
  })
  if err != nil {
  	log.Fatal(err)
  }
  history = append(history,
  	first.ToParam(),
  	anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?")),
  )
  second, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:     model,
  	MaxTokens: 8192,
  	System:    system,
  	Betas:     betas,
  	Thinking:  thinking,
  	Messages:  history,
  })
  if err != nil {
  	log.Fatal(err)
  }
  history = append(history, second.ToParam())
  thinkingBlocks := 0
  for _, block := range second.Content {
  	if _, ok := block.AsAny().(anthropic.BetaThinkingBlock); ok {
  		thinkingBlocks++
  	}
  }
  fmt.Printf("Thinking blocks in the kept turn: %d\n", thinkingBlocks)

  // 2. Résumez le premier tour. Le deuxième tour reste hors de la requête.
  summary, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:     model,
  	MaxTokens: 4096,
  	System:    system,
  	Betas:     betas,
  	Thinking:  thinking,
  	Messages:  history[:2],
  	Compaction: anthropic.BetaCompactionConfigUnionParam{
  		OfSummarize: &anthropic.BetaSummarizeCompactionParam{},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  if summary.StopReason != anthropic.BetaStopReasonCompaction {
  	log.Fatalf("No summary: %s", summary.StopReason)
  }

  // 3. Placez le bloc devant le tour conservé et posez la question suivante.
  history = slices.Concat(
  	[]anthropic.BetaMessageParam{summary.ToParam()},
  	history[2:],
  	[]anthropic.BetaMessageParam{anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Which day should the release go out?"))},
  )
  third, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:     model,
  	MaxTokens: 8192,
  	System:    system,
  	Betas:     betas,
  	Thinking:  thinking,
  	Messages:  history,
  })
  if err != nil {
  	log.Fatal(err)
  }

  // 4. Une réponse 200 sans bloc supprimé signifie que la réflexion conservée a été acceptée.
  fmt.Printf("Dropped thinking blocks: %d\n", len(third.InputTransformations))
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaCompactionConfig;
  import com.anthropic.models.beta.messages.BetaContentBlock;
  import com.anthropic.models.beta.messages.BetaMessageParam;
  import com.anthropic.models.beta.messages.BetaStopReason;
  import com.anthropic.models.beta.messages.BetaThinkingBlockBinding;
  import com.anthropic.models.beta.messages.BetaThinkingConfigAdaptive;
  import com.anthropic.models.beta.messages.BetaThinkingPrefixMismatchBehavior;
  import com.anthropic.models.beta.messages.MessageCreateParams;

  // Claude Fable 5.1 est le premier modèle qui vérifie la réflexion renvoyée par rapport à la conversation.
  static final Model MODEL = Model.CLAUDE_FABLE_5_1;
  static final List<AnthropicBeta> BETAS = List.of(
      AnthropicBeta.COMPACT_2026_09_04,
      AnthropicBeta.THINKING_BINDING_CONTROLS_2026_08_01
  );
  static final String SYSTEM = "You help plan a recipe app's release. Keep answers short.";
  // Avec "error", un bloc de réflexion qui échoue à la vérification fait échouer la requête avec une erreur 400.
  static final BetaThinkingConfigAdaptive THINKING = BetaThinkingConfigAdaptive.builder()
      .blockBinding(BetaThinkingBlockBinding.builder()
          .prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.ERROR)
          .build())
      .build();

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

      // 1. Menez une courte conversation avec la réflexion activée.
      var history = new ArrayList<BetaMessageParam>();
      history.add(BetaMessageParam.builder()
          .role(BetaMessageParam.Role.USER)
          .content("What are the main entities in the app's data model?")
          .build());
      var firstParams = MessageCreateParams.builder()
          .model(MODEL)
          .maxTokens(8192)
          .system(SYSTEM)
          .betas(BETAS)
          .thinking(THINKING)
          .messages(history)
          .build();
      var first = client.beta().messages().create(firstParams);
      history.add(first.toParam());
      history.add(BetaMessageParam.builder()
          .role(BetaMessageParam.Role.USER)
          .content("Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?")
          .build());
      var secondParams = MessageCreateParams.builder()
          .model(MODEL)
          .maxTokens(8192)
          .system(SYSTEM)
          .betas(BETAS)
          .thinking(THINKING)
          .messages(history)
          .build();
      var second = client.beta().messages().create(secondParams);
      history.add(second.toParam());
      long thinkingBlocks = second.content().stream().filter(BetaContentBlock::isThinking).count();
      IO.println("Thinking blocks in the kept turn: " + thinkingBlocks);

      // 2. Résumez le premier tour. Le deuxième tour reste hors de la requête.
      var firstTurn = history.subList(0, 2);
      var summaryParams = MessageCreateParams.builder()
          .model(MODEL)
          .maxTokens(4096)
          .system(SYSTEM)
          .betas(BETAS)
          .thinking(THINKING)
          .messages(firstTurn)
          .compaction(BetaCompactionConfig.builder().build()) // type defaults to "summarize"
          .build();
      var summary = client.beta().messages().create(summaryParams);
      if (!summary.stopReason().map(BetaStopReason.COMPACTION::equals).orElse(false)) {
          throw new IllegalStateException("No summary: " + summary.stopReason().orElseThrow());
      }

      // 3. Placez le bloc devant le tour conservé et posez la question suivante.
      firstTurn.clear();
      history.addFirst(summary.toParam());
      history.add(BetaMessageParam.builder()
          .role(BetaMessageParam.Role.USER)
          .content("Which day should the release go out?")
          .build());
      var thirdParams = MessageCreateParams.builder()
          .model(MODEL)
          .maxTokens(8192)
          .system(SYSTEM)
          .betas(BETAS)
          .thinking(THINKING)
          .messages(history)
          .build();
      var third = client.beta().messages().create(thirdParams);

      // 4. Une réponse 200 sans bloc supprimé signifie que la réflexion conservée a été acceptée.
      IO.println("Dropped thinking blocks: " + third.inputTransformations().map(List::size).orElse(0));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaCompactionConfig;
  use Anthropic\Beta\Messages\BetaMessageParam;
  use Anthropic\Beta\Messages\BetaMessageParam\Role;
  use Anthropic\Beta\Messages\BetaStopReason;
  use Anthropic\Beta\Messages\BetaThinkingBlock;
  use Anthropic\Beta\Messages\BetaThinkingBlockBinding;
  use Anthropic\Beta\Messages\BetaThinkingConfigAdaptive;
  use Anthropic\Beta\Messages\BetaThinkingPrefixMismatchBehavior;

  $client = new Client();

  // Claude Fable 5.1 est le premier modèle qui vérifie la réflexion renvoyée par rapport à la conversation.
  const MODEL = Model::CLAUDE_FABLE_5_1;
  const BETAS = [AnthropicBeta::COMPACT_2026_09_04, AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01];
  const SYSTEM = "You help plan a recipe app's release. Keep answers short.";
  // Avec "error", un bloc de réflexion qui échoue à la vérification fait échouer la requête avec une erreur 400.
  $thinking = BetaThinkingConfigAdaptive::with(
      blockBinding: BetaThinkingBlockBinding::with(
          prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::ERROR,
      ),
  );

  // 1. Menez une courte conversation avec la réflexion activée.
  $history = [
      BetaMessageParam::with(role: Role::USER, content: "What are the main entities in the app's data model?"),
  ];
  $first = $client->beta->messages->create(
      model: MODEL,
      maxTokens: 8192,
      system: SYSTEM,
      betas: BETAS,
      thinking: $thinking,
      messages: $history,
  );
  $history[] = BetaMessageParam::with(role: Role::ASSISTANT, content: $first->content);
  $history[] = BetaMessageParam::with(
      role: Role::USER,
      content: 'Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?',
  );
  $second = $client->beta->messages->create(
      model: MODEL,
      maxTokens: 8192,
      system: SYSTEM,
      betas: BETAS,
      thinking: $thinking,
      messages: $history,
  );
  $history[] = BetaMessageParam::with(role: Role::ASSISTANT, content: $second->content);
  $thinkingBlocks = count(array_filter($second->content, fn ($block) => $block instanceof BetaThinkingBlock));
  printf("Thinking blocks in the kept turn: %d\n", $thinkingBlocks);

  // 2. Résumez le premier tour. Le second tour reste hors de la requête.
  $summary = $client->beta->messages->create(
      model: MODEL,
      maxTokens: 4096,
      system: SYSTEM,
      betas: BETAS,
      thinking: $thinking,
      messages: array_slice($history, 0, 2),
      compaction: new BetaCompactionConfig(), // type defaults to 'summarize'
  );
  if ($summary->stopReason !== BetaStopReason::COMPACTION->value) {
      throw new \RuntimeException("No summary: {$summary->stopReason}");
  }

  // 3. Placez le bloc devant le tour conservé et posez la question suivante.
  $history = [
      BetaMessageParam::with(role: Role::ASSISTANT, content: $summary->content),
      ...array_slice($history, 2),
      BetaMessageParam::with(role: Role::USER, content: 'Which day should the release go out?'),
  ];
  $third = $client->beta->messages->create(
      model: MODEL,
      maxTokens: 8192,
      system: SYSTEM,
      betas: BETAS,
      thinking: $thinking,
      messages: $history,
  );

  // 4. Un code 200 sans bloc supprimé signifie que la réflexion conservée a été acceptée.
  printf("Dropped thinking blocks: %d\n", count($third->inputTransformations));
  ```

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

  # Claude Fable 5.1 est le premier modèle qui vérifie la réflexion renvoyée par rapport à la conversation.
  MODEL = Anthropic::Model::CLAUDE_FABLE_5_1
  BETAS = [
    Anthropic::AnthropicBeta::COMPACT_2026_09_04,
    Anthropic::AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01
  ]
  SYSTEM = "You help plan a recipe app's release. Keep answers short."
  # Avec "error", un bloc de réflexion qui échoue à la vérification fait échouer la requête avec une erreur 400.
  THINKING = Anthropic::Beta::BetaThinkingConfigAdaptive.new(
    block_binding: Anthropic::Beta::BetaThinkingBlockBinding.new(
      prefix_mismatch_behavior: Anthropic::Beta::BetaThinkingPrefixMismatchBehavior::ERROR
    )
  )

  # 1. Menez une courte conversation avec la réflexion activée.
  history = [{ role: "user", content: "What are the main entities in the app's data model?" }]
  first = client.beta.messages.create(
    model: MODEL,
    max_tokens: 8192,
    system_: SYSTEM,
    betas: BETAS,
    thinking: THINKING,
    messages: history
  )
  history += [
    { role: "assistant", content: first.content },
    {
      role: "user",
      content: "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?"
    }
  ]
  second = client.beta.messages.create(
    model: MODEL,
    max_tokens: 8192,
    system_: SYSTEM,
    betas: BETAS,
    thinking: THINKING,
    messages: history
  )
  history << { role: "assistant", content: second.content }
  thinking_blocks = second.content.count { it.is_a?(Anthropic::Beta::BetaThinkingBlock) }
  puts "Thinking blocks in the kept turn: #{thinking_blocks}"

  # 2. Résumez le premier tour. Le deuxième tour reste hors de la requête.
  summary = client.beta.messages.create(
    model: MODEL,
    max_tokens: 4096,
    system_: SYSTEM,
    betas: BETAS,
    thinking: THINKING,
    messages: history.first(2),
    compaction: { type: "summarize" }
  )
  abort "No summary: #{summary.stop_reason}" unless summary.stop_reason == :compaction

  # 3. Placez le bloc devant le tour conservé et posez la question suivante.
  history = [
    { role: "assistant", content: summary.content },
    *history.drop(2),
    { role: "user", content: "Which day should the release go out?" }
  ]
  third = client.beta.messages.create(
    model: MODEL,
    max_tokens: 8192,
    system_: SYSTEM,
    betas: BETAS,
    thinking: THINKING,
    messages: history
  )

  # 4. Une réponse 200 sans bloc supprimé signifie que la réflexion conservée a été acceptée.
  puts "Dropped thinking blocks: #{third.input_transformations.length}"
  ```
</CodeGroup>

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

En production, `"drop_block"` permet aux requêtes de continuer à réussir lorsqu'une condition n'est pas remplie, et signale chaque bloc supprimé dans `input_transformations` avec `reason: "prefix_binding_mismatch"`. Une entrée dont le `path` se situe dans un tour conservé signifie que la réflexion de ce tour n'est pas restée valide. [Ce que fait l'API d'un bloc invalide](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#mismatch-behavior) décrit ce qui est supprimé et explique comment déclencher une alerte à ce sujet. Sur Claude Sonnet 5.5 et Claude Haiku 5.5, `block_binding` ne fonctionne qu'avec `thinking: {"type": "adaptive"}`. Une requête qui le définit avec `thinking: {"type": "between_tools"}` sur Claude Sonnet 5.5, ou avec `thinking: {"type": "disabled"}` sur Claude Haiku 5.5, renvoie une erreur 400. Pour ces requêtes, assurez-vous que chaque condition est remplie, ou supprimez les blocs `thinking` et `redacted_thinking` des tours conservés.
