The whole hunk
from line 26, old and new numbered
/
lines
The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.
from line 26
2626* [Drops some `thinking` blocks and keeps later ones](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#append-assistant-turns-exactly-as-returned), or removes them and [later puts them back](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check)
2727* [Rebuilds a saved session from templates](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#faq) instead of replaying what it sent
2828
29On an older account, none of these produces an error unless the request sets `prefix_mismatch_behavior`, so a run with no errors on your own key doesn't show whether your code is affected. If people run your tool with their own API keys, those on newer accounts get the 400 error before you do. [Set `prefix_mismatch_behavior` in your tests](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#how-to-tell-whether-your-integration-is-impacted) to see what they see.
29On an older account, none of these produces an error unless the request sets `prefix_mismatch_behavior`, so a run with no errors on your own key doesn't show whether your code is affected. If people run your tool with their own API keys, those on newer accounts get the 400 error before you do. To see what they see without changing how your requests behave, send the `thinking-binding-controls-2026-08-01` beta header. On an older account, each response then flags blocks that fail the check, and the model still reads them (see [Set the mismatch behavior and read `input_transformations`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#preserved-thinking-controls)).
3030
3131## Switching models mid-conversation
3232
from line 78
7878* **`"error"` (the default):** the API rejects the request with a 400 `invalid_request_error` that names the first failing block.
7979* **`"drop_block"`:** the API drops each failing block and every thinking block after it, and the request succeeds. Dropped blocks aren't billed. The model answers that turn without using reasoning from dropped blocks, and the prompt cache restarts at the edit. The response lists each dropped block in `input_transformations` (on the `message_start` event when streaming) with `reason: "prefix_binding_mismatch"`.
8080
81`"drop_block"` keeps requests succeeding but doesn't fix the edit. Count the responses in each session whose `input_transformations` has a `prefix_binding_mismatch` entry, and alert on them. In the Message Batches API, an item that leaves the field unset drops failing blocks instead of erroring, so set `"error"` explicitly there if you want batch items to fail.
81`"drop_block"` keeps requests succeeding but doesn't fix the edit. Count the responses in each session whose `input_transformations` has a `prefix_binding_mismatch` entry, and alert on them. In the Message Batches API, an item that leaves the field unset doesn't fail. Where the API enforces the check by default, it drops the failing blocks instead. Set `"error"` explicitly there if you want batch items to fail.
8282
8383Both the field and the `input_transformations` array require the `thinking-binding-controls-2026-08-01` [beta header](https://platform.claude.com/docs/en/api/beta-headers). [Set the mismatch behavior and read `input_transformations`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#preserved-thinking-controls) shows the request in each SDK.
8484
from line 365
365365Input transformations: 0
366366```
367367
368Under the beta header, every response from a thinking-capable model carries `input_transformations`. It's empty when nothing was dropped. Each entry has `type: "thinking_dropped"`, the `path` of the dropped block (for example `messages.1.content.0`), and a `reason` of `prefix_binding_mismatch` or `model_binding_mismatch` (see [Switching models mid-conversation](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#switching-models)). Ignore entries whose `type` or `reason` you don't recognize, because later checks add values.
369
370When [streaming](https://platform.claude.com/docs/en/build-with-claude/streaming), the array arrives on the `message` object in the `message_start` event. After a mid-stream server-side fallback, the final `message_delta` event carries it again with the serving model's entries. In a [message batch](https://platform.claude.com/docs/en/build-with-claude/batch-processing), an item whose block fails the prefix check under an explicit `"error"` resolves as `errored`, and an item that leaves the field unset drops the failing blocks instead. The [token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting) endpoint runs the same prefix check and returns the same 400.
368Under the beta header, every response from a thinking-capable model carries `input_transformations`. Each entry names one thinking block by its `path` (for example `messages.1.content.0`) and gives a `reason`. There are two entry types:
369
370* **`thinking_dropped`:** the API drops the block before the model reads it, and the block isn't billed. The `reason` is `prefix_binding_mismatch` or `model_binding_mismatch` (see [Switching models mid-conversation](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#switching-models)).
371* **`thinking_mismatch_allowed`:** the block fails the prefix check, but the API doesn't enforce that check for this request, so the block reaches the model unchanged and is billed. The `reason` is always `prefix_binding_mismatch`. This entry appears only on requests where the API doesn't enforce the check by default, such as those from an older account (see [When the API enforces the check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement)). Setting `prefix_mismatch_behavior` to either value opts the request into enforcement, so a request that sets it never gets this entry.
372
373The array is empty when no block was dropped and none failed the prefix check. Ignore entries whose `type` or `reason` you don't recognize, because later checks add values.
374
375When [streaming](https://platform.claude.com/docs/en/build-with-claude/streaming), the array arrives on the `message` object in the `message_start` event. After a mid-stream server-side fallback, the final `message_delta` event carries it again with the serving model's entries. In a [message batch](https://platform.claude.com/docs/en/build-with-claude/batch-processing), an item whose block fails the prefix check under an explicit `"error"` resolves as `errored`. An item that leaves the field unset doesn't fail. Where the API enforces the check by default, it drops the failing blocks instead. The [token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting) endpoint runs the same prefix check and returns the same 400.
371376
372377### When the API enforces the check
373378
374The prefix check runs on Claude Fable 5.1 for new accounts.
379The API enforces the prefix check on Claude Fable 5.1 for new accounts.
375380
376381* **Accounts created on or after August 31, 2026, 00:00 UTC:** the API checks Claude Fable 5.1 requests and applies `"error"` unless you set `"drop_block"`. The same definition of a new account applies to the Claude API and to cloud platforms.
377* **Older accounts:** the API checks requests that set `prefix_mismatch_behavior`. This parameter opts a request in, so you can see what a new account sees without creating one.
382* **Older accounts:** the API enforces the check only on requests that set `prefix_mismatch_behavior`. Setting the field opts a request in, so you can see what a new account sees without creating one. On requests that leave it unset, the API still runs the check but lets failing blocks through to the model. With the beta header, the response lists each one in `input_transformations` as `thinking_mismatch_allowed`, so you can find prefix edits without changing what the model receives.
378383* **Later models:** every account, on every request.
379384
380To find out which group your account is in, take a Claude Fable 5.1 conversation that contains a thinking block, change something before that block, and send it to Claude Fable 5.1 without the beta header or the `block_binding` field. A 400 response that names the header means your account is enforced by default.
385To find out which group your account is in, take a Claude Fable 5.1 conversation that contains a thinking block, change something before that block, and send it to Claude Fable 5.1 without the beta header or the `block_binding` field. A 400 response that names the header means your account is enforced by default. A 200 response means it isn't. To confirm, send the same request again with the beta header, still without `block_binding`: the response lists every thinking block after your edit in `input_transformations` as `thinking_mismatch_allowed`.
381386
382387### What counts as an edit
383388
from line 785
780785* A long tool loop, if you add reminders or shorten old tool results
781786* A switch to another model and back
782787* A save, a restart, and a resume on a later date
788
789On an older account, you can also watch production traffic without opting into enforcement: send the beta header, leave `block_binding` out, and log `input_transformations`. Sending the header alone doesn't change what the model receives. Every thinking block that comes after the content you edited fails the check and gets its own `thinking_mismatch_allowed` entry, with the same `path` and `reason` fields as a `thinking_dropped` entry. Blocks before the edit still pass. An edit to `system` or `tools` comes before every block, so it fails every thinking block in the request. One entry looks like this:
790
791```json
792{
793 "input_transformations": [
794 {
795 "type": "thinking_mismatch_allowed",
796 "path": "messages.1.content.0",
797 "reason": "prefix_binding_mismatch"
798 }
799 ]
800}
801```
802
803Run the following example from an [older account](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement), because a newer account rejects its third request with the 400. It sends the header without `block_binding` and extends the earlier session with a third request that adds a system prompt, which changes the prefix on purpose. After each turn it prints the number of `thinking` blocks and flagged blocks:
804
805<CodeGroup>
806 ```bash cURL
807 # Counts the thinking blocks in a response and the blocks that failed the prefix check
808 COUNTS='"thinking blocks: \([.content[] | select(.type == "thinking")] | length), " +
809 "flagged: \([.input_transformations[] |
810 select(.type == "thinking_mismatch_allowed")] | length)"'
811
812 FIRST=$(curl -s https://api.anthropic.com/v1/messages \
813 -H "content-type: application/json" \
814 -H "x-api-key: $ANTHROPIC_API_KEY" \
815 -H "anthropic-version: 2023-06-01" \
816 -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
817 -d '{
818 "model": "claude-fable-5-1",
819 "max_tokens": 16000,
820 "thinking": { "type": "adaptive" },
821 "messages": [
822 {
823 "role": "user",
824 "content": "How many positive integers below 500 have exactly 6 positive divisors?"
825 }
826 ]
827 }')
828 echo "$FIRST" | jq -r "$COUNTS"
829
830 # Turn 2: the assistant turn goes back exactly as returned, then the next user message
831 MESSAGES=$(jq -n --argjson first "$FIRST" '[
832 {
833 role: "user",
834 content: "How many positive integers below 500 have exactly 6 positive divisors?"
835 },
836 { role: "assistant", content: $first.content },
837 { role: "user", content: "How many of those are odd?" }
838 ]')
839
840 SECOND=$(jq -n --argjson messages "$MESSAGES" '{
841 model: "claude-fable-5-1",
842 max_tokens: 16000,
843 thinking: { type: "adaptive" },
844 messages: $messages
845 }' | curl -s https://api.anthropic.com/v1/messages \
846 -H "content-type: application/json" \
847 -H "x-api-key: $ANTHROPIC_API_KEY" \
848 -H "anthropic-version: 2023-06-01" \
849 -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
850 -d @-)
851 echo "$SECOND" | jq -r "$COUNTS"
852
853 # Turn 3: only this request adds a system prompt, which changes the prefix on purpose
854 jq -n --argjson messages "$MESSAGES" --argjson second "$SECOND" '{
855 model: "claude-fable-5-1",
856 max_tokens: 16000,
857 thinking: { type: "adaptive" },
858 system: "Answer briefly.",
859 messages: ($messages + [
860 { role: "assistant", content: $second.content },
861 { role: "user", content: "And how many of the odd ones are below 100?" }
862 ])
863 }' | curl -s https://api.anthropic.com/v1/messages \
864 -H "content-type: application/json" \
865 -H "x-api-key: $ANTHROPIC_API_KEY" \
866 -H "anthropic-version: 2023-06-01" \
867 -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
868 -d @- | jq -r "$COUNTS"
869 ```
870
871 ```bash CLI
872 # Counts the thinking blocks in a response and the blocks that failed the prefix check
873 COUNTS='"thinking blocks: \([.content[] | select(.type == "thinking")] | length), " +
874 "flagged: \([.input_transformations[] |
875 select(.type == "thinking_mismatch_allowed")] | length)"'
876
877 FIRST=$(ant beta:messages create --beta thinking-binding-controls-2026-08-01 \
878 --format json <<'YAML'
879 model: claude-fable-5-1
880 max_tokens: 16000
881 thinking:
882 type: adaptive
883 messages:
884 - role: user
885 content: How many positive integers below 500 have exactly 6 positive divisors?
886 YAML
887 )
888 echo "$FIRST" | jq -r "$COUNTS"
889
890 # Turn 2: the assistant turn goes back exactly as returned, then the next user message
891 SECOND=$(ant beta:messages create --beta thinking-binding-controls-2026-08-01 \
892 --format json <<YAML
893 model: claude-fable-5-1
894 max_tokens: 16000
895 thinking:
896 type: adaptive
897 messages:
898 - role: user
899 content: How many positive integers below 500 have exactly 6 positive divisors?
900 - role: assistant
901 content: $(echo "$FIRST" | jq -c .content)
902 - role: user
903 content: How many of those are odd?
904 YAML
905 )
906 echo "$SECOND" | jq -r "$COUNTS"
907
908 # Turn 3: only this request adds a system prompt, which changes the prefix on purpose
909 ant beta:messages create --beta thinking-binding-controls-2026-08-01 \
910 --format json <<YAML | jq -r "$COUNTS"
911 model: claude-fable-5-1
912 max_tokens: 16000
913 thinking:
914 type: adaptive
915 system: Answer briefly.
916 messages:
917 - role: user
918 content: How many positive integers below 500 have exactly 6 positive divisors?
919 - role: assistant
920 content: $(echo "$FIRST" | jq -c .content)
921 - role: user
922 content: How many of those are odd?
923 - role: assistant
924 content: $(echo "$SECOND" | jq -c .content)
925 - role: user
926 content: And how many of the odd ones are below 100?
927 YAML
928 ```
929
930 ```python Python
931 client = anthropic.Anthropic()
932
933 user_turns = [
934 "How many positive integers below 500 have exactly 6 positive divisors?",
935 "How many of those are odd?",
936 "And how many of the odd ones are below 100?",
937 ]
938
939 # messages grows across turns: each assistant turn goes back exactly as returned
940 messages = []
941 for turn, user_turn in enumerate(user_turns, start=1):
942 messages.append({"role": "user", "content": user_turn})
943 response = client.beta.messages.create(
944 model="claude-fable-5-1",
945 max_tokens=16000,
946 thinking={"type": "adaptive"},
947 # Only the last request adds a system prompt, which changes the prefix on purpose
948 system="Answer briefly." if turn == len(user_turns) else anthropic.omit,
949 messages=messages,
950 betas=["thinking-binding-controls-2026-08-01"],
951 )
952 messages.append({"role": "assistant", "content": response.content})
953 thinking_blocks = sum(block.type == "thinking" for block in response.content)
954 flagged = sum(
955 transformation.type == "thinking_mismatch_allowed"
956 for transformation in response.input_transformations or []
957 )
958 print(f"thinking blocks: {thinking_blocks}, flagged: {flagged}")
959 ```
960
961 ```typescript TypeScript
962 const client = new Anthropic();
963
964 const userTurns = [
965 "How many positive integers below 500 have exactly 6 positive divisors?",
966 "How many of those are odd?",
967 "And how many of the odd ones are below 100?"
968 ];
969
970 // messages grows across turns: each assistant turn goes back exactly as returned
971 const messages: Anthropic.Beta.BetaMessageParam[] = [];
972 for (const [turnIndex, userTurn] of userTurns.entries()) {
973 messages.push({ role: "user", content: userTurn });
974 const response = await client.beta.messages.create({
975 model: "claude-fable-5-1",
976 max_tokens: 16000,
977 thinking: { type: "adaptive" },
978 // Only the last request adds a system prompt, which changes the prefix on purpose
979 system: turnIndex === userTurns.length - 1 ? "Answer briefly." : undefined,
980 messages,
981 betas: ["thinking-binding-controls-2026-08-01"]
982 });
983 messages.push({ role: "assistant", content: response.content });
984 const thinkingBlocks = response.content.filter((block) => block.type === "thinking");
985 const flagged = (response.input_transformations ?? []).filter(
986 (transformation) => transformation.type === "thinking_mismatch_allowed"
987 );
988 console.log(`thinking blocks: ${thinkingBlocks.length}, flagged: ${flagged.length}`);
989 }
990 ```
991
992 ```csharp C#
993 AnthropicClient client = new();
994
995 string[] userTurns =
996 [
997 "How many positive integers below 500 have exactly 6 positive divisors?",
998 "How many of those are odd?",
999 "And how many of the odd ones are below 100?",
1000 ];
1001
1002 // messages grows across turns: each assistant turn goes back exactly as returned
1003 List<BetaMessageParam> messages = [];
1004 for (var turnIndex = 0; turnIndex < userTurns.Length; turnIndex++)
1005 {
1006 messages.Add(new() { Role = Role.User, Content = userTurns[turnIndex] });
1007 var response = await client.Beta.Messages.Create(
1008 new()
1009 {
1010 Model = "claude-fable-5-1",
1011 MaxTokens = 16000,
1012 Thinking = new BetaThinkingConfigAdaptive(),
1013 // Only the last request adds a system prompt, which changes the prefix on purpose
1014 System = turnIndex == userTurns.Length - 1 ? new("Answer briefly.") : null,
1015 Messages = messages,
1016 Betas = [AnthropicBeta.ThinkingBindingControls2026_08_01],
1017 }
1018 );
1019 messages.Add(new()
1020 {
1021 Role = Role.Assistant,
1022 Content = response.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
1023 });
1024 var thinkingBlocks = response.Content.Count(block => block.TryPickThinking(out _));
1025 var flagged = response.InputTransformations?.Count(transformation =>
1026 transformation.TryPickThinkingMismatchAllowed(out _)
1027 ) ?? 0;
1028 Console.WriteLine($"thinking blocks: {thinkingBlocks}, flagged: {flagged}");
1029 }
1030 ```
1031
1032 ```go Go
1033 client := anthropic.NewClient()
1034
1035 userTurns := []string{
1036 "How many positive integers below 500 have exactly 6 positive divisors?",
1037 "How many of those are odd?",
1038 "And how many of the odd ones are below 100?",
1039 }
1040
1041 // messages grows across turns: each assistant turn goes back exactly as returned
1042 messages := []anthropic.BetaMessageParam{}
1043 for i, userTurn := range userTurns {
1044 messages = append(messages, anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(userTurn)))
1045 // Only the last request adds a system prompt, which changes the prefix on purpose
1046 var system []anthropic.BetaTextBlockParam
1047 if i == len(userTurns)-1 {
1048 system = []anthropic.BetaTextBlockParam{{Text: "Answer briefly."}}
1049 }
1050 response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
1051 Model: "claude-fable-5-1",
1052 MaxTokens: 16000,
1053 Thinking: anthropic.BetaThinkingConfigParamUnion{
1054 OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{},
1055 },
1056 System: system,
1057 Messages: messages,
1058 Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaThinkingBindingControls2026_08_01},
1059 })
1060 if err != nil {
1061 log.Fatal(err)
1062 }
1063 messages = append(messages, response.ToParam())
1064 thinkingBlocks := 0
1065 for _, block := range response.Content {
1066 if block.Type == "thinking" {
1067 thinkingBlocks++
1068 }
1069 }
1070 flagged := 0
1071 for _, transformation := range response.InputTransformations {
1072 if transformation.Type == "thinking_mismatch_allowed" {
1073 flagged++
1074 }
1075 }
1076 fmt.Printf("thinking blocks: %d, flagged: %d\n", thinkingBlocks, flagged)
1077 }
1078 ```
1079
1080 ```java Java
1081 import com.anthropic.models.beta.AnthropicBeta;
1082 import com.anthropic.models.beta.messages.BetaContentBlock;
1083 import com.anthropic.models.beta.messages.BetaInputTransformation;
1084 import com.anthropic.models.beta.messages.BetaMessage;
1085 import com.anthropic.models.beta.messages.BetaThinkingConfigAdaptive;
1086 import com.anthropic.models.beta.messages.MessageCreateParams;
1087
1088 void main() {
1089 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
1090
1091 List<String> userTurns = List.of(
1092 "How many positive integers below 500 have exactly 6 positive divisors?",
1093 "How many of those are odd?",
1094 "And how many of the odd ones are below 100?");
1095
1096 // The builder's message list grows across turns: each assistant turn goes back exactly as returned
1097 MessageCreateParams.Builder conversation = MessageCreateParams.builder()
1098 .model("claude-fable-5-1")
1099 .maxTokens(16000L)
1100 .thinking(BetaThinkingConfigAdaptive.builder().build())
1101 .addBeta(AnthropicBeta.THINKING_BINDING_CONTROLS_2026_08_01);
1102
1103 for (int turnIndex = 0; turnIndex < userTurns.size(); turnIndex++) {
1104 if (turnIndex == userTurns.size() - 1) {
1105 // Only the last request adds a system prompt, which changes the prefix on purpose
1106 conversation.system("Answer briefly.");
1107 }
1108 conversation.addUserMessage(userTurns.get(turnIndex));
1109 BetaMessage response = client.beta().messages().create(conversation.build());
1110 conversation.addMessage(response);
1111 long thinkingBlocks = response.content().stream()
1112 .filter(BetaContentBlock::isThinking)
1113 .count();
1114 long flagged = response.inputTransformations().stream()
1115 .flatMap(List::stream)
1116 .filter(BetaInputTransformation::isThinkingMismatchAllowed)
1117 .count();
1118 IO.println("thinking blocks: " + thinkingBlocks + ", flagged: " + flagged);
1119 }
1120 }
1121 ```
1122
1123 ```php PHP
1124 use Anthropic\Beta\AnthropicBeta;
1125 use Anthropic\Beta\Messages\BetaThinkingConfigAdaptive;
1126 use Anthropic\Beta\Messages\BetaThinkingMismatchAllowedInputTransformation;
1127 use Anthropic\Client;
1128
1129 $client = new Client();
1130
1131 $userTurns = [
1132 'How many positive integers below 500 have exactly 6 positive divisors?',
1133 'How many of those are odd?',
1134 'And how many of the odd ones are below 100?',
1135 ];
1136
1137 // $messages grows across turns: each assistant turn goes back exactly as returned
1138 $messages = [];
1139 foreach ($userTurns as $turnIndex => $userTurn) {
1140 $messages[] = ['role' => 'user', 'content' => $userTurn];
1141 $response = $client->beta->messages->create(
1142 model: 'claude-fable-5-1',
1143 maxTokens: 16000,
1144 thinking: BetaThinkingConfigAdaptive::with(),
1145 // Only the last request adds a system prompt, which changes the prefix on purpose
1146 system: $turnIndex === array_key_last($userTurns) ? 'Answer briefly.' : null,
1147 messages: $messages,
1148 betas: [AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01],
1149 );
1150 $messages[] = ['role' => 'assistant', 'content' => $response->content];
1151 $thinkingBlocks = array_filter($response->content, fn ($block) => $block->type === 'thinking');
1152 $flagged = array_filter(
1153 $response->inputTransformations ?? [],
1154 fn ($transformation) => $transformation instanceof BetaThinkingMismatchAllowedInputTransformation,
1155 );
1156 echo 'thinking blocks: ', count($thinkingBlocks), ', flagged: ', count($flagged), PHP_EOL;
1157 }
1158 ```
1159
1160 ```ruby Ruby
1161 client = Anthropic::Client.new
1162
1163 user_turns = [
1164 "How many positive integers below 500 have exactly 6 positive divisors?",
1165 "How many of those are odd?",
1166 "And how many of the odd ones are below 100?"
1167 ]
1168
1169 # messages grows across turns: each assistant turn goes back exactly as returned
1170 messages = []
1171 user_turns.each_with_index do |user_turn, turn_index|
1172 messages << {role: "user", content: user_turn}
1173 # Only the last request adds a system prompt, which changes the prefix on purpose
1174 system_param = (turn_index == user_turns.length - 1) ? {system_: "Answer briefly."} : {}
1175 response = client.beta.messages.create(
1176 model: "claude-fable-5-1",
1177 max_tokens: 16_000,
1178 thinking: {type: "adaptive"},
1179 messages: messages,
1180 betas: [Anthropic::AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01],
1181 **system_param
1182 )
1183 messages << {role: "assistant", content: response.content}
1184 thinking_blocks = response.content.count { |block| block.type == :thinking }
1185 flagged = (response.input_transformations || []).count do |transformation|
1186 transformation.type == :thinking_mismatch_allowed
1187 end
1188 puts "thinking blocks: #{thinking_blocks}, flagged: #{flagged}"
1189 end
1190 ```
1191</CodeGroup>
1192
1193```text Output wrap
1194thinking blocks: 1, flagged: 0
1195thinking blocks: 1, flagged: 0
1196thinking blocks: 1, flagged: 2
1197```
1198
1199The third response flags every thinking block from the earlier turns, one per turn in this run, because the new system prompt comes before all of them. The model still read them.
1200
1201Handle these entries as you would `prefix_binding_mismatch` drops. The edit is before the first block listed: diff `system`, `tools`, and `messages` up to that block's `path` against the previous request to find it, then replace it with the matching pattern in [Make changes without editing the prefix](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#replace-prefix-edits). On a new account, or on any request that sets `prefix_mismatch_behavior`, the API instead rejects the request or drops the failing blocks. The entries are a lower bound on what enforcement would remove: with `"drop_block"`, a failing block also takes the rest of that turn's thinking blocks with it, and removing one block can make the next one fail too. When the API only records the check, it judges each block on its own and lists a block only if that block fails.
7831202
7841203## Make changes without editing the prefix
7851204
from line 1635
12161635
12171636<AccordionGroup>
12181637 <Accordion title="Do I need a new account to test preserved thinking?">
1219 No. Send the `thinking-binding-controls-2026-08-01` beta header and set `thinking.block_binding.prefix_mismatch_behavior`. Setting the field opts that request into enforcement regardless of account age. `"error"` rejects an edited history with the same 400 a new account gets, and `"drop_block"` lets the request through and lists what was dropped in `input_transformations`. See [Check whether your code edits the prefix](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#how-to-tell-whether-your-integration-is-impacted).
1638 No. Send the `thinking-binding-controls-2026-08-01` beta header and set `thinking.block_binding.prefix_mismatch_behavior`. Setting the field opts that request into enforcement regardless of account age. `"error"` rejects an edited history with the same 400 a new account gets, and `"drop_block"` lets the request through and lists what was dropped in `input_transformations`. To find prefix edits from an older account without enforcing the check, send the header and leave the field unset: failing blocks still reach the model, and `input_transformations` lists them as `thinking_mismatch_allowed`. See [Check whether your code edits the prefix](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#how-to-tell-whether-your-integration-is-impacted).
12201639 </Accordion>
12211640
12221641 <Accordion title="If anything before a thinking block changes, even one tool description, is the conversation unusable?">
12231642