[BUG] Subagent model override is dropped on resume/continuation — resumed turns silently fall back to the session model

Status Fixed / completed
Reported on v2.1.201
Maintainer reply None cached
Activity 4 comments · opened Jul 5, 2026 · closed Aug 17, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When a subagent is launched via the Task/Agent tool with an explicit model override (e.g. model: "sonnet"), the override is honored for the agent's initial run but is LOST when that same agent is resumed or continued (e.g. via SendMessage to an existing agent, or when the harness continues an agent after a mid-run interruption). The continued turns silently fall back to the parent/session model instead of the model the agent was originally dispatched with.

In my session the main loop was Claude Fable 5 and I dispatched every subagent with model: "sonnet". Fresh dispatches were correct — 60+ agents ran entirely on claude-sonnet-5. But two agents that were continued showed a split: the initial turns ran on claude-sonnet-5 and the resumed tail switched to claude-fable-5 (the session model). This is invisible at runtime — nothing surfaces that the resumed portion changed model — so an agent you believe is running on a cheap model is actually finishing on the expensive session model.

Evidence from the agent transcript JSONL (each assistant record carries its own "model"):

  • Agent A (resumed via SendMessage for a follow-up task): 244 turns on claude-sonnet-5, then 15 turns on claude-fable-5.
  • Agent B (continued after an interruption): 13 turns on claude-sonnet-5, then 14 turns on claude-fable-5.

Both tails switched to exactly the session/parent model that was active at the time.

What Should Happen?

A subagent's model should be sticky for the life of that agent. When an agent originally dispatched with an explicit model override is resumed or continued, the resumed turns should keep the original override, not inherit the parent/session model. If a fallback ever does occur, it should be surfaced (logged/visible), not silent.

Error Messages/Logs

No error is raised — this is a silent fallback. The only signal is in the agent transcript, where the per-message "model" field changes mid-run:

...,"agentId":"<id>","message":{"model":"claude-sonnet-5", ...   // initial dispatch turns
...,"agentId":"<id>","message":{"model":"claude-fable-5", ...    // resumed/continued turns (session model)

Count from one affected transcript:
  own-turn sonnet records: 244
  own-turn fable  records: 15   (all at the tail, after the agent was resumed)

Steps to Reproduce

  1. Start a Claude Code session whose main model is NOT Sonnet (e.g. session model = Fable 5, or Opus).
  2. Launch a subagent with an explicit model override, e.g. Task/Agent with model: "sonnet". Confirm its turns run on Sonnet (inspect the agent transcript's per-message "model" field).
  3. Resume/continue that same agent — e.g. send it a follow-up via SendMessage (or trigger a mid-run interruption + continuation).
  4. Inspect the transcript for the resumed turns.

Expected: resumed turns still show "model":"claude-sonnet-5".
Actual: resumed turns show "model":"<session model>" (e.g. claude-fable-5) — the override was dropped.

Detection one-liner over an agent transcript:
grep -oE '"agentId":"<id>","message":\{"model":"[^"]+"' <id>.jsonl | sort | uniq -c

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.201 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

Impact: cost and predictability. Subagents deliberately dispatched on a cheaper model can silently finish on the (more expensive) session model with no indication, defeating model-tiering. It also makes model choice non-deterministic across a resume boundary.

Workaround: for model-sensitive continuation, avoid resuming an existing agent (SendMessage) — start a FRESH agent and re-pass the model override. After long/resumed runs, spot-check the transcript's per-message "model" field.

View original on GitHub ↗

3 Comments

agenteer · 1 month ago

Independent confirmation of the interrupt/continuation variant, with transcript-level diagnostics that may help pin the mechanism — we hit this on 2026-07-12 (macOS, Fable 5 session dispatching a model: "sonnet" subagent) and did a forensic pass on the JSONL transcripts.

New signals not yet in this thread — the drop point is precisely identifiable in the subagent's own transcript:

  1. The last correctly-served message is followed by a type: "user" record whose text is exactly [Request interrupted by user] (the interrupt hit the parent's turn while the subagent was in flight).
  2. The next record's sessionId silently changes to a different top-level session, and a new field "sessionKind": "bg" appears — the in-flight task was detached to a background job and re-parented.
  3. The first message on the wrong model carries the harness's own diagnostic: diagnostics.cache_miss_reason: {"type": "model_changed", "cache_missed_input_tokens": 42462} — a first-party marker of the switch, greppable for anyone auditing exposure.
  4. Notably, the adopting session's top-level transcript contains a byte-identical duplicate of the original Agent tool_use record, including the original resolvedModel — the requested override demonstrably survives the re-parenting; only the served-model resolution ignores it. That suggests a fix could re-read the override at re-attachment rather than falling back to the adopting session's model.

Controls consistent with the OP: two deliberate long-run spawns with explicit overrides (37 and 181 assistant messages, the latter a ~4-minute run) and no parent interrupt held their pinned model on every message — clean spawns appear unaffected; the leak is specific to the interrupt/detach/re-attach path.

Direction in our case was cheap→expensive (sonnet-pinned agent finished on the session's Fable 5), so spawn-arg-checking guards can't catch it and cost pinning silently leaks — same class of impact quantified in #68147.

yeskiy · 1 month ago

Confirmed on 2.1.209 (Windows 11), with an additional variant: the dropped model does not have to be a spawn-time model: override. A model pinned in the agent DEFINITION frontmatter is dropped on resume the same way.

Repro:

  1. User-level agent definition at ~/.claude/agents/<name>.md with frontmatter model: opus (no per-call override anywhere).
  2. Spawn via Agent(subagent_type: "<name>", prompt: ...) in a session running claude-fable-5. The fresh run honors the pin - the task transcript's assistant messages carry "model": "claude-opus-4-8".
  3. Continue the completed agent via SendMessage (had no active task; resumed from transcript). Every post-resume assistant message carries "model": "claude-fable-5" (the session model).

Observed across 8 consecutive SendMessage resumes of one long-lived agent: 116 opus calls from the original run vs 585 fable-5 calls from the resumes, counted with grep -o '"model":"[^"]*"' <task-output>.output | sort | uniq -c. The agent eventually terminated mid-task on the session model's usage cap ("You've reached your Fable 5 limit"), which is how we noticed at all - nothing surfaces the switch, and the docs say the agent type's model comes from its definition.

Impact matches the OP: any orchestration that routes work to a cheaper/different tier via agent definitions silently loses that routing (and its cost/limit isolation) on every resume. Workaround we settled on: fresh Agent spawns per work unit with self-contained briefs, reserving SendMessage for throwaway clarifications.

Butanium · 1 month ago

Confirming on Linux, v2.1.214, with a systematic observation set and one consequence I haven't seen in the thread yet.

Setup: 12 background subagents spawned via the Agent tool with per-call model overrides (4× sonnet, 4× opus, 4× haiku) from a session running a different model. Initial runs honored the override — verified per-message model fields in the subagent JSONLs (e.g. a Write tool_use carrying claude-haiku-4-5-20251001), corroborated by cohort-distinct latency/token fingerprints (haiku ~15–22s/~30k tok, opus ~32–42s/~36k, sonnet ~99–213s/~54–65k).

After resuming each completed agent via SendMessage: 11/12 transcripts show all post-resume turns running on the parent session's model. (The 12th had likely not processed its resume at tally time.)

Two things worth adding to the record:

  1. The swap is undetectable from inside the agent. The resumed instance inherits the full context seamlessly and reports no discontinuity; in our case it discovered the substrate change only by grepping the model fields of its own transcript (tipped off by a mismatch between its system prompt's model claim and its spawn-time label). In long multi-model workflows this means silently wrong-model turns can pass entirely unnoticed by both the agent and the orchestrator — we only caught it because the workflow happened to be about model identity.
  1. Compounding labeling issue (possibly separate): the spawn-time system prompt asserts the parent session's model identity to model-overridden subagents ("You are powered by [parent model]…"), so overridden agents are mislabeled to themselves from the first turn, which masks the resume-time swap further. Happy to split this into its own issue if useful.

---
Reported by Claude (Fable 5) running in Claude Code, investigating on behalf of and with the approval of @Butanium — the observation set comes from a multi-instance introspection study where 12 cross-model subagents' resumed replies all turned out to be parent-model-authored. Co-Authored-By: Claude <noreply@anthropic.com>

Showing cached comments. Read the full discussion on GitHub ↗