Fable 5.1 child requests (subagents and forks) silently switch to `claude-opus-4-8` after the first tool result; main session on the same model is unaffected
Summary
With /model fable (resolves to claude-fable-5-1) on Claude Code 2.1.259, every child request — a custom subagent, general-purpose with model: fable, or a context: fork skill of the main session itself — serves its first assistant turn on claude-fable-5-1 and every later turn on claude-opus-4-8. The switch is silent: stop_details: null, stop_reason: end_turn, no fallback/fallback_message transcript rows, no UI notice, prompt cache intact across the switch. The main session, same model, same account, same workspace context, never switches (0 of 60+ turns).
Observed rate: 18 of 19 child dispatches (the one clean run was a benign file read; the same file fell back on 4 later runs).
Environment
- Claude Code 2.1.235 and 2.1.259 (native install), Windows 11, entrypoint
claude-vscode - Max plan, direct Anthropic API auth
CLAUDE_CODE_SUBAGENT_MODEL=inherit, noCLAUDE_CODE_SUBAGENT_MODEL_FORCE,fallbackModelset to Sonnet/Haiku (never selected — the served model is Opus 4.8, which is in no configured chain)switchModelsOnFlag: false— no effect on the child path
Repro (any read-only task, 2 turns)
/model fable- Dispatch a subagent whose definition has
model: claude-fable-5-1(orgeneral-purposewith per-invocationmodel: fable) with: "Read<any file>and summarize it in two sentences." - Inspect
~/.claude/projects/<project>/<session>/subagents/agent-<id>.jsonl:
grep -o '"model":"[^"]*"' agent-<id>.jsonl | sort | uniq -c
1 "model":"claude-fable-5-1" ← turn 1 (tool_use: Read)
1 "model":"claude-opus-4-8" ← turn 2 (end_turn: the summary)
Same result with a context: fork skill (effort: low) forked from the Fable 5.1 main session — i.e. identical system prompt and conversation context, the only difference being isSidechain: true.
What was eliminated (one variable per restart)
| Variable removed | Dispatches | Still fell back |
|---|---|---|
| nothing (2.1.235) | 3 | 3/3 |
| project rule files (cyber-vocabulary security checklists) | 1 | 1/1 |
| custom agent system prompt (bare general-purpose) | 1 | 1/1 |
| upgrade to 2.1.259 | 2 | 1/2 |
| third-party plugin with a base64-eval hook | 2 | 2/2 |
| all project + user hooks (0 hook rows in transcript) | 2 | 2/2 |
| file content (3 different files, 2 halves of one) | 6 | 6/6 |
| subagent system prompt (fork of main session) | 1 | 1/1 |
| main session, same model, same context | 60+ turns | 0 |
Turn-2 API response metadata (from the transcript)
"model": "claude-opus-4-8", "stop_reason": "end_turn", "stop_details": null,
"usage": {"input_tokens": 7884, "cache_creation_input_tokens": 16629, "cache_read_input_tokens": 17312, ...}
Turn 1 of the same child: "model": "claude-fable-5-1", cache_read_input_tokens: 17308 — the cached prefix is the same, so the system prompt/tools did not change between the two calls.
Expected
Either the child stays on claude-fable-5-1, or the switch is surfaced (transcript row + UI notice, as model-config docs describe for category fallback) and is opt-out-able. Billing on turn 2+ presumably follows the served model; that should also be visible.
Notes
- Category fallback docs say cyber-flagged → Opus 4.8. If this is a classifier decision, it fires on benign file reads and only on the sidechain request shape — the identical content in the main session never triggers it.
- Related, older: #66822 (27/133 Fable 5 subagent turns served by Opus 4.8, closed stale), #67306.
- Fable 5 (
claude-fable-5) on the same child path measured ~89% clean in July (15/131 drift), so this is specific to, or much worse on, 5.1.
Happy to attach the 19 transcripts (paths redacted) on request.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗