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

Status Open
Reported on v2.1.259
Maintainer reply None cached
Activity 1 comment · opened Sep 3, 2026

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, no CLAUDE_CODE_SUBAGENT_MODEL_FORCE, fallbackModel set 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)

  1. /model fable
  2. Dispatch a subagent whose definition has model: claude-fable-5-1 (or general-purpose with per-invocation model: fable) with: "Read <any file> and summarize it in two sentences."
  3. 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.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗