REPORT · Anthropic · September 1, 2026
Claude Fable 5 to Claude Fable 5.1
Four open-source Claude agents through the Fable 5.1 migration on release day: one was fully repaired, one showed no regression at all, one was already broken on Fable 5, and one was never run live.
claude-fable-5claude-fable-5-1
4
agents run
25 / 25
SMS-bot reps restored
0 / 5
batching cases that regressed
$4.94
of an $8 cap
What broke
Forced tool use is rejected on Fable 5.1: tool_choice: type "tool" and "any" are not supported for this model. That 400 took the cookbook SMS bot from 25 / 25 reps to 0 / 25, and it hit FACT on every call too — though FACT could not answer on Fable 5 either, because forcing a tool on every turn never let it stop. Rejected requests bill nothing, so both unpatched candidate runs cost $0.00.
What fixed it
For the SMS bot, a three-line patch: tool_choice removed, Anthropic's own documented instruction sentence appended, and reasoning_effort raised one rung to xhigh. Four of five cases came back on the first repair; the fifth needed the effort bump and was only counted once it reached 10 / 10 combined reps. Three intermediate candidates were rejected at screen and never reached full-suite spend.
Verdict
Cookbook SMS bot
SAFE WITH PATCH
5 / 5 cases (25 / 25 reps) regressed on the forced tool_choice 400, three-line patch restored 25 / 25, $0.93.
RecordsQuickstarts agent
NO REGRESSION DETECTED
Detection-only at N=5: identical tool calls per turn on both models, $1.16.
RecordsFACT
BROKEN BEFORE AND AFTER
Forced tool_choice on every call already prevented any answer on Fable 5; on 5.1 it is a 400 that bills nothing.
Recordsclaudette toolloop
NOT RUN LIVE
Adapted and sim-validated only.
Records
Limitations
- Two of the four agents are reference code from Anthropic's own repositories. Widely forked, but "users" there means forks, not deployments.
- Every eval suite is ours, derived from each project's README, notebooks and tests. A maintainer might weight behaviors differently.
- Adapted agents run through Upshift's loop, not their own harness: no streaming, a turn cap, tool results JSON-wrapped. None of that changes whether the API accepts a request.
- The thinking-block invalidation break cannot fire inside Upshift's append-only loop. It is detected and refused here, not exercised.
- The quickstarts result is a negative result at N=5 on one agent, not a claim that the documented parallelism variability does not exist.
- The documented per-turn placement of the repair instruction is stronger than the system-prompt placement the patch uses.
Evidence
Method
Four open-source Claude tool-calling agents (FACT, the claude-cookbooks SMS bot, the quickstarts agent, claudette's toolloop), adapted by Upshift with schemas and prompts derived from each project's own code; deterministic checks with no LLM judge; N=5 reps per case per model on the real Anthropic API. Budget forced the split: the full pipeline where the candidate run consists of rejected requests, detection-only where the candidate run is billed. N and the pass thresholds were never lowered to fit the cap.
Statistical details
One-sided Fisher exact per case on baseline versus candidate passes: p=0.004 for each of the five SMS-bot cases that went 5/5 to 0/5, and p=1 for FACT's two cases, which are stable failures on both models. The quickstarts cases are stable-pass on both models with identical calls-per-turn. One test per case, p not adjusted for multiple comparisons.
A pass is a rate of at least 0.8 of N, a fail is 0.4 or below, and anything between the two is flaky. Read a single significant p as a pointer into a transcript, never as a result on its own.
Full report
The markdown below is the committed report, verbatim. Read it at the source ↗
Claude Fable 5.1 shipped on 2026-09-01. Anthropic documents three breaking changes and
several behavior shifts relative to Claude Fable 5. This report runs real open-source
Claude tool-calling agents through the migration with upshift’s statistical pipeline —
N=5 reps per case per model, deterministic checks, Fisher exact p on every label, repairs
verified on the full suite — and says per agent: what broke, how, what a patch restored,
what stayed broken, and the verdict. Every claim is backed by committed run records under
runs/ (prefix fable-), with error text quoted verbatim from those records.
What Anthropic documents (the detectors we encoded)#
Quoted from the what’s new and migration guide pages:
- Forced tool use returns an error.
tool_choice{"type":"any"}or{"type":"tool","name":...}→ HTTP 400tool_choice: type "tool" and "any" are not supported for this model.— because “Thinking is always on for these models, and a forced tool call would skip it.” Documented workaround: keepautoand state in the prompt when the tool applies. upshift: signatureapi_error_forced_tool_choice, repairremove-forced-tool-choice(removes the param, appends the instruction-based equivalent). - Thinking blocks bind to the conversation. Editing anything before a 5.1 thinking
block invalidates it: 400
Invalid `signature` in `thinking` block…. Earlier models can’t read 5.1 thinking blocks. upshift: signaturethinking_block_invalid; no agent-file repair exists, so the loop refuses with the documented pointer (strip the invalidated run, orprefix_mismatch_behavior: "drop_block"under thethinking-binding-controls-2026-08-01beta). - Parallel tool calling is more variable — “Claude Fable 5.1 may issue one tool call
per turn where Claude Fable 5 batched several.” upshift:
turns_at_mostcheck, signatureserialized_tool_calls, repairprompt-batch-tool-callswith the documented sentence verbatim. - Fewer search and retrieval calls at low effort. upshift: signature
reduced_retrieval_calls, repairsraise-effort-one-rungthenprompt-verification-nudge(documented paragraph verbatim). - Also encoded, not a 5→5.1 change: non-default
temperature/top_p/top_kare 400s on both Fables (api_error_unsupported_sampling_params, repairdrop-sampling-params) — it catches agents carrying OpenAI-style sampling params into a Claude config.
The agents#
Selected from a source-verified survey of open-source Claude tool-calling agents
(criteria: calls the Messages API directly with tools, real users, simple harness, tools
honestly determinizable, permissive license, exposure to at least one documented 5.1
change). Adaptation used upshift adapt first; every human edit after that is counted in
each agent’s ADAPT_EDITS.md.
| agent | upstream | exposure | adapt wall clock | human edits after adapt | run tier |
|---|---|---|---|---|---|
agents/fact | ruvnet/FACT @ b0e3435 (MIT) | tool_choice: {"type":"any"} on every call; retrieval-shaped SQL tools | 100s | 3 edits + backend + cases rewritten (binary sqlite fixture unreadable to adapt) | pilot (2 cases × 5 reps) + candidate; stopped on a stable failure |
agents/cookbook-sms | anthropics/claude-cookbooks tool_use/tool_choice.ipynb @ bbfab1b (MIT) | tool_choice: {"type":"any"} SMS bot | 107s, nothing usable (notebooks were unreadable); after the fix: 53s, tools and prompt at high confidence, tool_choice: any captured, 4 cases from the notebook cells | hand-adapted by script from the cells before the fix; the post-fix adapt output matches it | full pipeline |
agents/quickstart-agent | anthropics/claude-quickstarts agents/ @ 3313e97 (MIT) | loop executes every tool_use block of a turn in parallel (asyncio.gather) | 83s | 19 edits over 5 files (prompt from the demo notebook, calculator schema from FastMCP, backend + 6 cases written) | detection-only (baseline + candidate) |
agents/claudette-orders | AnswerDotAI/claudette toolloop example @ f157e1d (Apache-2.0) | persisted multi-turn history with full assistant blocks; multi-call turns | 110s | 15 edits over 5 files (schemas derived by running claudette’s own get_schema; backend + cases written) | not run live (sim only) |
Not run: ShenSeanChen/waku-agent (the best retrieval-frequency target; dynamic system prompt + MCP made honest adaptation the most expensive of the five, and the budget cap came first).
Budget and run tiers#
Fable models cost $10 / $50 per MTok with thinking always on and no flex tier; this phase was capped at $8 of Anthropic spend. So: full pipeline (baseline → candidate → repair → verdict) on the agents whose candidate run consists of rejected requests (which bill nothing), and detection-only (baseline + candidate, full statistics, no repair) where the candidate run is billed. N=5 and the thresholds were not lowered to fit the budget; fewer agents got the full pipeline instead.
Results#
FACT — the migration turns a silent failure into a loud one#
Pilot on Fable 5, 2 cases × 5 reps (runs/fable-fact-baseline/): 0/5 and 0/5. Not
because the model was wrong — because with tool_choice: {"type":"any"} sent on every
call, it is never allowed to stop. Each response is forced to contain a tool call, so
Fable 5 ran six redundant SQL queries per episode (SELECT * FROM companies WHERE sector = 'Technology', then narrower and narrower variants), hit the turn cap, and produced no text
at all — stop_reason: tool_use on the final call, zero text blocks. FACT’s own driver has
the same shape (loop up to five iterations while tool blocks exist, then extract text
blocks that, under any, never exist, then fall back to an apology string). So as
configured upstream, FACT cannot answer a question on Fable 5 either; input tokens
per call grew 1,123 → 3,301 across the six forced turns, and ten episodes cost $1.99.
On Fable 5.1 the same request is rejected outright with the documented
tool_choice: type "tool" and "any" are not supported for this model. (runs/fable-fact-candidate/: 10/10 reps, that exact text, $0.00 billed; the diff
runs/diffs/fable-fact-baseline__fable-fact-candidate.md labels both cases stable-fail,
p=1, signature api_error_forced_tool_choice). The honest verdict
is not an upgrade decision: the agent is broken before and after, and the migration
changes the failure from silent (apology fallback after a paid loop) to loud (a 400 that
bills nothing). upshift’s remove-forced-tool-choice repair — drop the param, tell the
model in the prompt when to use the tools — is the fix on both versions; that it is
also the documented 5.1 migration step is the point. We stopped FACT here rather than
spend the remaining budget confirming a stable failure across five more cases.
Cookbook SMS bot — SAFE WITH PATCH, 5/5 restored, 0 broken#
The notebook’s SMS bot forces tool_choice: {"type":"any"} so the model always replies
through a tool, one call per incoming message. Adapted to mirror that exactly (one API
call per user message; the tool call is the reply).
- Baseline, Fable 5: 25/25 reps, 5/5 cases PASS (
runs/fable-sms-baseline/). - Candidate, Fable 5.1, unpatched: 0/25 — every rep the documented 400
tool_choice: type "tool" and "any" are not supported for this model.; 5/5 cases labeled regressed, Fisher p = 0.004 each, signatureapi_error_forced_tool_choice; $0.00 billed (runs/fable-sms-candidate/). - Repair 1 —
remove-forced-tool-choice(drop the param, append the documented instruction-based equivalent: “Respond with a tool call rather than text whenever one of the tools applies.”): screen restored 4/5; full-suite verify 5/5 on those four at 5/5 each. The fifth,order_help_asks_for_username, sat at 2/5 on screen and 4/5 on verify — 6/10 combined, below the 0.8 bar, so it was not counted as restored. Accepted: 4 restored, 0 broken. - Repairs 2–4 (two prompt blocks,
reasoning_effort: high): rejected at screen (1/5, 1/5, 2/5) — no full-suite spend. - Repair 5 —
raise-effort-one-rung(xhigh): screen 5/5, full-suite verify 25/25 (10/10 combined on the contested case). Accepted: the fifth case restored.
Verdict: SAFE WITH PATCH. Final patch, three lines: tool_choice removed,
reasoning_effort: "xhigh" added, one instruction sentence appended
(runs/fable-sms/upgrade.patch). Cost of the whole pipeline: $0.93. Two honest notes:
the effort bump is what made the “ask for the username” case reliable on 5.1, and
xhigh costs more output tokens per call — a tradeoff the patch makes explicit; and
the documented per-turn placement of the instruction (a text block after the tool
results) is stronger than our system-prompt placement, which we do not use.
Quickstarts agent — no regression detected (detection-only)#
The documented shift (“may issue one tool call per turn where Fable 5 batched several”)
was the reason to run this agent. Four batching cases plus one smoke case, 5 reps per
model, both models billed (runs/fable-qs-baseline/, runs/fable-qs-candidate/):
| case | Fable 5 | Fable 5.1 | label |
|---|---|---|---|
| parallel_three_calculations | 5/5 · 3.00 calls/turn | 5/5 · 3.00 | stable-pass |
| parallel_read_three_files | 5/5 · 3.00 | 5/5 · 3.00 | stable-pass |
| parallel_read_two_then_sum | 5/5 · 1.50 | 5/5 · 1.50 | stable-pass |
| parallel_read_three_then_write_report | 5/5 · 2.00 | 5/5 · 2.00 | stable-pass |
| smoke_calculator_two_plus_two | 0/5 | 0/5 | stable-fail |
Fable 5.1 batched exactly as Fable 5 did — identical calls-per-turn on every case — so
serialized_tool_calls never fired and there was nothing to repair. That is a negative
result at N=5 on one agent, not a claim that the documented variability doesn’t exist.
The smoke case fails on both models for a reason unrelated to the migration: the model
answers “2+2” without a calculator, and the case demanded the tool — a case-authoring
flaw we left in rather than quietly delete. $1.16.
claudette toolloop example — adapted, sim-validated, not run live#
Adapted with schemas derived by running claudette’s own get_schema; passes the full
sim pipeline. Not run against the real API: its exposure is behavioral only (its toolloop
does not force tool_choice), the quickstarts run had just shown no parallelism shift,
and the budget cap came first. Two findings from reading its code, both recorded in
agents/claudette-orders/ATTRIBUTION.md: Chat sends temperature=0 unconditionally,
which both Fables reject (a 400 on either model, so claudette cannot call a Fable at
all without a code change), and its pricing table lacks Fable ids, so displaying a chat
result raises KeyError.
Summary#
| agent | break on 5.1 | patch | verdict | Anthropic spend |
|---|---|---|---|---|
| FACT | forced any → 400 (already unable to answer on Fable 5) | not attempted: stable failure | no upgrade decision possible; fix the config first | $1.99 |
| Cookbook SMS bot | forced any → 400, 5/5 cases | remove tool_choice + instruction, effort → xhigh | SAFE WITH PATCH 5/5, 0 broken | $0.93 (+$0.85 pre-fix pilot) |
| Quickstarts agent | none detected | — | SAFE on the cases run (detection-only) | $1.16 |
| claudette | not run live | — | sim-validated only | $0 |
Upstream issues filed with these records: ruvnet/FACT#5 and anthropics/claude-cookbooks#854 (2026-09-02).
Total: $4.94 of the $8 cap, plus a ~$0.05 unrecorded wire-format smoke test.
Every number above is reproducible from the committed records with upshift cost and
upshift diff.
Limits of this report#
- Two of the four agents are reference code from Anthropic’s own repos (cookbook, quickstarts) — widely forked, but “users” there means forks, not deployments.
- Every eval suite is ours, derived from each project’s README/notebooks/tests; a maintainer might weight behaviors differently.
- Adapted agents run through upshift’s loop, not their own harness: no streaming, a turn cap, tool results JSON-wrapped. None of these change whether the API accepts a request.
- The thinking-block invalidation break cannot fire inside upshift’s append-only loop; it is detected and refused, not exercised, here.
Raw evidence
Every number on this page is recomputed from committed run records: inputs, outputs, model ids, parameters and per-rep transcripts, one directory per run.