CLAUDE LABJP
MODEL — Claude Fable 5.1 and Claude Mythos 5.1 landed on September 1. They are the same underlying model; only the strength of the safeguards differsPRICING — Per-token rates hold at $10/$50 per MTok. What changed is cache reads, cut 75% to $0.25 per MTokCOST — How much that saves depends on your workload: roughly 25% for typical use, up to about 45% for context-heavy agentic work. Worth measuring your own split before quoting a numberBENCH — Terminal-Bench-Science 0.1 climbs from 24.7% on Fable 5 to 52.6%. Anthropic also states a standard error of 3.5-4.5 points, which is worth remembering before reading small gaps as realSAFEGUARDS — Sharper cyber safeguards cut interventions in Claude Code sessions by roughly 60% on average. Finding vulnerabilities is now allowed; developing exploits still is notAPI — New API accounts created from today can no longer edit prior context while preserving Claude's thinking transcript. It is an anti-distillation measure, and existing accounts are unaffected for nowMODEL — Claude Fable 5.1 and Claude Mythos 5.1 landed on September 1. They are the same underlying model; only the strength of the safeguards differsPRICING — Per-token rates hold at $10/$50 per MTok. What changed is cache reads, cut 75% to $0.25 per MTokCOST — How much that saves depends on your workload: roughly 25% for typical use, up to about 45% for context-heavy agentic work. Worth measuring your own split before quoting a numberBENCH — Terminal-Bench-Science 0.1 climbs from 24.7% on Fable 5 to 52.6%. Anthropic also states a standard error of 3.5-4.5 points, which is worth remembering before reading small gaps as realSAFEGUARDS — Sharper cyber safeguards cut interventions in Claude Code sessions by roughly 60% on average. Finding vulnerabilities is now allowed; developing exploits still is notAPI — New API accounts created from today can no longer edit prior context while preserving Claude's thinking transcript. It is an anti-distillation measure, and existing accounts are unaffected for now
Articles/API & SDK
API & SDK/2026-09-02Intermediate

The 400 that rejects a thinking block, and finding the edit that caused it

On Claude Fable 5.1, editing the system prompt, tools, or earlier messages before a thinking block makes the request fail with a 400. Here is how to check whether your own agent loop does that in a single request, and how to move a rebuilt system prompt and client-side trimming to patterns that leave the prefix untouched.

Claude API120extended thinking2agents8troubleshooting90Fable 5.1

I keep a small loop that drafts App Store review replies, written directly against the Messages API. It works through years of reviews, so the conversation gets long, and my system prompt rebuilt a line like "Today is 2026-09-02" on every request. Tone shifts with the date, so putting it there felt obvious at the time.

That "rebuild it every request" habit started to matter on September 1. On Claude Fable 5.1, a request that changes anything before a thinking block now fails a check. My loop was firmly on the failing side.

Before you go rewrite everything: the check applies to Fable 5.1 only, and only to accounts created on or after August 31, 2026, 00:00 UTC. Claude Code, Claude Cowork, claude.ai, and Claude reached through a third-party product are all unaffected. Anthropic has said it will apply to every account on future models, though, so auditing your loop now is not wasted work.

The rejection happens when something before the thinking block changed

Claude produces reasoning before its answer, and the API returns it as a thinking block. In a multi-turn conversation you send those blocks back, signature included. The API now uses that signature to verify that the same system prompt, tools, and messages that produced the block are the ones arriving with it. If they differ, you get a 400.

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".

Three things get checked: the model is the same or newer, nothing before the block has changed in system, tools, or messages, and the chain of earlier thinking blocks is unbroken. That third one is easy to miss. Dropping thinking blocks from the front of the history is fine. Pulling one out of the middle invalidates every thinking block after it.

Anthropic publishes the full table of what counts as an edit. These are the rows I found myself checking against real code.

Change between two consecutive requestsLater thinking blocks
Append messages at the endValid
Change a parameter outside system, tools, and messages (max_tokens, tool_choice, and so on)Valid
Add, move, or remove a cache_control markerValid
Server-side compaction or context editing removes contentValid — the check compares what you sent
Edit, reorder, or delete an earlier user / assistant / system messageInvalid
Change the top-level system string or blocksInvalid
Add, remove, rename, or edit a tool in toolsInvalid
Remove a thinking block from the middle of the historyInvalid for every later block
An image or document URL that returns different bytes next requestInvalid

The last row caught me off guard. If you reference a "latest screenshot" endpoint every turn, the URL string stays the same while the bytes change, and the thinking after it stops verifying. For anything you carry across turns, upload it once and reference the file_id, or send base64.

One request tells you whether your loop is affected

Rather than guess, run the check. Send the beta header thinking-binding-controls-2026-08-01 and set prefix_mismatch_behavior to "drop_block", and enforcement turns on regardless of how old your account is. From an older key, you get to see what a user on a new account would see.

curl https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
  -d '{
    "model": "claude-fable-5-1",
    "max_tokens": 16000,
    "thinking": {
      "type": "adaptive",
      "block_binding": { "prefix_mismatch_behavior": "drop_block" }
    },
    "system": "You are a review-reply assistant.",
    "messages": [
      { "role": "user", "content": "Draft a reply to this one-star review." },
      {
        "role": "assistant",
        "content": [
          { "type": "thinking", "thinking": "", "signature": "EqQBCkYIBxgCKkD..." },
          { "type": "text", "text": "Could you paste the review text?" }
        ]
      },
      { "role": "user", "content": "\"I paid and the ads are still there.\"" }
    ]
  }'

Run a few normal turns that way and every response carries a top-level input_transformations array. Logging it each turn is enough to tell you whether your loop is append-only.

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

There are two readings. prefix_binding_mismatch means something before the block at path changed since the last request — keep the previous request body around, diff system, tools, and the shared part of messages, and the culprit surfaces immediately. model_binding_mismatch means the conversation moved to a model that cannot read the earlier blocks, usually through a router or a fallback. That one is not a bug in your code; keep sending the blocks and let the API drop what the current model cannot read.

What I ended up with is small: I hold one previous request body in memory and compare system and tools right before sending the next one. In CI I set "error" instead, so a history edit turns the build red.

What I had to change was the rebuilt system prompt

Injecting the date on every request turned out to be a clean swap for a mid-conversation system message. Freeze the top-level system at session start, and when something new becomes true, append a role: "system" message inside messages. Nothing before it moves by a single byte.

# Before: system rebuilt on every request, invalidating every later thinking block
system = f"You are a review-reply assistant. Today is {date.today()}."
 
# After: system is fixed for the session, and changes are appended to messages
system = "You are a review-reply assistant."
 
messages.append({
    "role": "system",
    "content": "The date has changed. Today is 2026-09-02. Use this for any dates you mention.",
})
messages.append({"role": "user", "content": next_review_text})

On Fable 5.1 this is stable and needs no beta header, and the model treats it with system-prompt authority. Inside a tool loop, place it after the user message carrying the tool_result, never between an assistant tool_use and its tool_result.

Tool changes follow the same shape. Instead of editing the tools array, declare the full set at session start and use tool_addition and tool_removal to offer or withdraw a tool from that point on. I wrote about how a one-line tool edit throws away the cached prefix in designing a tool registry for mid-conversation swaps; with this check in place, the consequence is no longer just a cold cache.

Trimming history is allowed — the shape decides whether it passes

The other common edit is trimming a conversation that grew too long. This is not banned outright. The rule is narrower: never leave a thinking block behind a prefix you rewrote.

Compaction shapePasses the check?What it needs
Server-side compaction / context editingYesNothing — the check compares what you sent
Simple compaction (one summary, start the next request fresh)YesNothing. No earlier thinking is carried across
Keep-tail compaction (summarize old turns, keep recent ones verbatim)NoStrip thinking and redacted_thinking from carried-over assistant turns, keeping text and tool_use
Background compaction (build the summary off the critical path, swap it in)NoSend "drop_block" on requests still carrying pre-swap thinking, or compact synchronously
Snipping individual turns out of the middleNoNo client-side shape avoids this. Use a mid-conversation system message or server-side context editing

What surprised me is that simple compaction is the recommended shape. Rebuild messages from one summary plus the next instruction, replay no earlier turns and no thinking, and the model reasons afresh over the compacted conversation — Anthropic says it performs comparably to more elaborate schemes for most workloads. I have built the layered kind before, described in hierarchical summarization of chat history, and weighed against the upkeep, moving to the simple shape is a defensible trade.

One ordering rule holds regardless: never compact in the middle of a tool round. An assistant turn whose tool_use is still waiting on its tool_result should go back with its thinking intact, so the model can finish the round with the reasoning it started.

Choosing between error and drop_block in production

"error" is the default, and once your loop is append-only, a mismatch can only mean a bug on your side. Failing loudly is the healthier choice there, and it is what I run in CI.

"drop_block" earns its place when degrading beats failing: a routed or fallback setup, or several clients touching the same conversation. Operations get quieter. The cost is silence, so pair it with logging input_transformations every time. Without that log, a later drop in output quality has no explanation attached.

Decide the recovery path too. Retrying the same request after a 400 will not clear it. Resend with the beta header and "drop_block", and keep sending "drop_block" for the rest of that session. If the beta is not an option, strip every thinking and redacted_thinking block from the history, leave each turn's text and tool_use in place, and retry once. Then go fix the edit itself.

There is a side benefit worth naming. A conversation whose prefix never moves keeps the prompt cache warm, which shows up directly in what extended thinking costs to run. I put my numbers on that in what extended thinking actually cost in production.

I have come to read this less as a restriction than as a design hint. Conversation history is a place to append, not a place to revise. A date change, a mode switch, a tool appearing or disappearing — each can be expressed by adding "from here onward, this is true" rather than reaching backward. Obvious in hindsight, and it took me years of rebuilding system on every request to see it.

Run one session of your own loop under "drop_block" and watch whether input_transformations stays empty. If it does not, path hands you the first line to look at. That is where I started.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

API & SDK2026-06-23
When Thinking Is Always On, Prefill Quietly Stops Working — Fixing Streaming and Token Budgets for Fable 5
Fable 5 thinks by default. Prefill no longer applies, the first streamed block isn't text, and max_tokens has to leave room for reasoning. Here is how I fixed those three broken assumptions in my own automated publishing pipeline.
API & SDK2026-06-16
Taming Token Bloat in Long-Running Agents with Context Editing and the Memory Tool
For long-running agents whose input tokens balloon as tool results pile up, here is how to pair context editing with the memory tool and measure the savings with count_tokens, including a working backend implementation.
API & SDK2026-05-28
Why JSON.parse Fails on Claude API Streaming tool_use Arguments — and How to Fix It
When you stream a Claude API response with tool_use, calling JSON.parse on each input_json_delta throws SyntaxError. Here is the correct way to assemble partial_json fragments, plus disconnect handling.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →