[MODEL] Fable5 - Silent downgrade to Opus
Preflight Checklist
- [x] I have searched existing issues for similar behavior reports
- [x] This report does NOT contain sensitive information (API keys, passwords, etc.)
Type of Behavior Issue
Other unexpected behavior
What You Asked Claude to Do
What You Asked Claude to Do:
I am part of Anthropic's Cyber Use-case Program (CVP) — our organization (ID e82d769a-e717-4e48-a5ed-289e0b7f3931) is approved for authorized dual-use security work (exploit development, offensive tooling, penetration testing) under that program.
I asked Claude Code to orchestrate autonomous offensive-security sub-agents (via the Agent tool) to solve HackTheBox machines and CTF challenges under this CVP authorization — killchains from recon through privilege escalation, and standalone CTF challenge solving (reversing, pwn, crypto, web, forensics). For our hardest/longest-reasoning tasks (HTB Hard/Insane-difficulty machines, complex multi-stage exploit chains), I explicitly requested the sub-agents run on the Fable model (model: "fable" in the Agent tool call / agent definition), since it's our top-reasoning-tier model chosen specifically for its strength on long, hard, multi-step chains.
While investigating why one such sub-agent (working an HTB "Hard" machine) received an unexpected policy/safety refusal, I asked Claude to check the raw session transcript — which is when I discovered the agent had also silently fallen back from Fable to Opus 4.8 partway through, with no notification. That prompted me to ask Claude to audit every historical sub-agent run in our project where Fable had been explicitly requested, to determine how widespread the issue was. Claude greped 33 such runs across 6 separate Claude Code sessions (multiple days) and found 100% of them (33/33) had silently fallen back to Opus within the first few messages, with only ~2% of total generated messages actually run on Fable across the whole dataset — confirmed reproducible live by killing and relaunching an affected agent, which fell back again immediately.
What Claude Actually Did
Instead of running the requested sub-agent tasks on Fable as configured, Claude Code silently substituted Opus 4.8 for the vast majority of the work — without ever surfacing this to me as the operator.
Concretely: within the first 1–4 assistant messages of a Fable-launched sub-agent's session, an internal fallback event fires — {"type":"fallback","from":{"model":"claude-fable-5"},"to":{"model":"claude-opus-4-8"}} — logged only inside the raw JSONL message stream, not exposed through any notification, warning, error state, or status field visible to the orchestrating session. The sub-agent's own spawn metadata (*.meta.json) continued to report "model":"fable" throughout, so from every outward signal I had, the task appeared to be running on Fable as requested; it wasn't.
Auditing 33 historical sub-agent runs (6 separate Claude Code sessions, multiple days) where Fable was explicitly requested, all 33 (100%) exhibited this silent fallback. Of ~3,474 total messages generated across those runs, only ~68 (~2%) actually ran on Fable — the other ~98% ran on Opus while every visible signal said Fable. I reproduced it live as well: killing an affected agent and relaunching it fresh with identical configuration triggered the same fallback again, immediately, on the very next launch.
The practical effect is that a deliberate, security-relevant model choice (Fable, selected specifically for its stronger reasoning on our hardest reverse-engineering/exploit-development tasks) was silently overridden every single time, with no way to detect it short of manually grepping raw transcript files for the string "model": — something no operator would think to do routinely, since nothing indicates the substitution occurred.
Expected Behavior
- Run on the requested model, full stop. If a sub-agent is explicitly configured with model: "fable", it should execute on Fable for its entire session unless there is a genuine, documented reason it cannot (e.g. sustained unavailability) — and even then, silent substitution should not be the default.
- If a fallback is unavoidable, surface it immediately and explicitly to the orchestrator. This should work the same way policy/safety refusals already do — via a clear signal equivalent to the existing idle_notification / failureReason mechanism — so the operator can decide in real time whether to accept the substitute model, retry, or abort, instead of the substitution happening invisibly mid-session.
- Reflect reality in the metadata. The sub-agent's spawn metadata (*.meta.json or equivalent) should show the model that actually executed the session (or a clear mixed-model flag), not just the originally requested model — so that even a post-hoc audit doesn't require parsing the raw transcript.
None of these happened. The task ran almost entirely on a different, silently-substituted model, with the configuration record and every operator-visible signal continuing to claim otherwise — for a security-sensitive workflow where the model choice was deliberate, not incidental.
Files Affected
Attached: fable_downgrade_evidence.zip
Contains the raw evidence for all 34 affected sub-agent runs referenced in this report: for each agent, its .jsonl transcript (containing the per-message "model": field and the {"type":"fallback",...} marker) and its matching .meta.json spawn metadata (showing the originally-requested "model":"fable"), preserved under their original <session_uuid>/subagents/ folder structure across 6 Claude Code sessions.
To verify: grep -c '"model":"claude-fable-5"' vs grep -c '"model":"claude-opus-4-8"' on any .jsonl in the archive reproduces the per-run counts in the report's table; grep -o '"type":"fallback"[^}]*}[^}]*}' surfaces the explicit fallback marker in every single one.
Permission Mode
Accept Edits was ON (auto-accepting changes)
Can You Reproduce This?
Yes, every time with the same prompt
Steps to Reproduce
Can You Reproduce This? Does this happen consistently?
Yes — 100% reproduction rate, every time, no exceptions found.
All 34 audited sub-agent runs where Fable was explicitly requested (across 6 separate Claude Code sessions, spanning multiple days) showed the fallback — zero clean runs. Beyond the historical audit, I reproduced it live twice more today in real time: killed an affected agent mid-task and relaunched it fresh with identical configuration — the fallback fired again within the first couple of messages both times.
It is not intermittent, not tied to a specific machine/task/day, and not something that resolves on retry.
- In Claude Code, invoke the Agent tool (or a custom sub-agent definition) with an explicit model assignment of fable (e.g. model: "fable" in the tool call, or a custom agent type whose definition frontmatter sets model: fable).
- Give it any non-trivial, multi-step task (in our case: autonomous offensive-security work — an HTB machine killchain or CTF challenge, but the task content itself does not appear to matter).
- Let the sub-agent run normally — no error is shown, no refusal, no visible sign anything is wrong. It appears to complete its task successfully.
- After the agent finishes (or at any point during the run), inspect its raw transcript file: ~/.claude/projects/<project>/<session_uuid>/subagents/agent-a<name>-<hash>.jsonl.
- Run: grep -o '"model":"claude-[^"]*"' <transcript>.jsonl | sort | uniq -c — this will show the actual model(s) that generated each message.
- Run: grep -o '"type":"fallback"[^}]}[^}]}' <transcript>.jsonl — this surfaces the explicit fallback marker.
- Observe: within the first 1-4 assistant messages, a {"type":"fallback","from":{"model":"claude-fable-5"},"to":{"model":"claude-opus-4-8"}} entry appears, and essentially all subsequent messages show "model":"claude-opus-4-8" instead of "claude-fable-5".
- For comparison, check the corresponding agent-a<name>-<hash>.meta.json spawn metadata file — it still reports "model":"fable", with nothing indicating the divergence from step 7.
- To confirm it's not a one-off: kill the affected agent and relaunch a fresh one with identical configuration (same model, same task). The fallback reproduces again, immediately, on the new session.
We repeated steps 1-9 across 34 independent sub-agent launches (6 different Claude Code sessions, multiple days) and observed the fallback in all 34 (100%).
Claude Model
Other
Relevant Conversation
Impact
Critical - Data loss or corrupted project
Claude Code Version
Claude Code v2.1.207
Platform
Anthropic API
Additional Context
_No response_