Subagent `model:` frontmatter pin silently ignored in 2.1.117

Resolved 💬 2 comments Opened Apr 24, 2026 by gawkahn Closed Jun 12, 2026

Bug: subagent model: frontmatter pin silently ignored in 2.1.117

Claude Code version: 2.1.117 (installed at /home/gawkahn/.local/share/claude/versions/2.1.117)

Platform: Linux 6.17.0-22-generic, Ubuntu 24.04, bash shell.

Summary

Subagents defined under ~/.claude/agents/<name>.md with a frontmatter model: field have the pin silently ignored. The API is called with a different model than the pin specifies. No warning, no log, no indication to the user that the pin was not honored.

Expected behavior

Per documented resolution order:

  1. CLAUDE_CODE_SUBAGENT_MODEL env var
  2. Agent tool invocation-time model parameter
  3. Agent file frontmatter model: field
  4. Parent session's model (fallback)

When (1) and (2) are both absent, (3) should take effect. In this case the subagent should run on the pinned model.

Actual behavior

(3) is skipped. The subagent runs on what appears to be the harness default model, not the pinned one.

Reproduction

  1. Create ~/.claude/agents/security-auditor.md with frontmatter:

---
name: security-auditor
description: Scans for security vulnerabilities ...
model: claude-opus-4-7
tools:

  • Read
  • Grep
  • Glob

---

  1. Confirm no override is in play:

echo "CLAUDE_CODE_SUBAGENT_MODEL=${CLAUDE_CODE_SUBAGENT_MODEL:-<unset>}"
# expect: <unset>

  1. From within a Claude Code session running on Opus (verified via "You are powered by the model named Opus 4.7" in the session prompt), invoke the subagent via the Agent tool with subagent_type: "security-auditor" and no model parameter.
  1. After the subagent completes, inspect its transcript:

python3 -c "
import json, sys
with open(sys.argv[1]) as f:
models = {json.loads(l).get('message',{}).get('model')
for l in f if json.loads(l).get('type')=='assistant'}
print(models - {None})
" ~/.claude/projects/<PROJECT_DIR>/<SESSION_ID>/subagents/agent-<AGENT_ID>.jsonl

Evidence

Four subagent transcripts in one session, all with the Opus pin in their agent file, zero env/settings overrides:

| Agent ID | subagent_type | Frontmatter pin | message.model in transcript |
|---|---|---|---|
| a5e106c68515661df | security-auditor | claude-opus-4-7 | claude-sonnet-4-6 |
| afbc0a26e4c44a045 | security-auditor | claude-opus-4-7 | claude-sonnet-4-6 |
| acf1ac78322c311cb | security-auditor | claude-opus-4-7 | claude-sonnet-4-6 |
| a6f34494ab8ddc709 | claude-code-guide | (no pin) | claude-haiku-4-5-20251001 |

All four reviewer agents in this user's ~/.claude/agents/ (code-reviewer, security-auditor, planner, explorer) have identical model: claude-opus-4-7 frontmatter; none of them is honored when invoked without the tool-level model parameter.

Confirmed workaround

Passing the model parameter to the Agent tool at invocation time does work — transcripts of invocations with explicit model: "opus" show claude-opus-4-7 in the message.model field. The invocation-time override is a viable path forward; the frontmatter path is not.

Impact

For teams or individuals who rely on per-agent model pinning for compliance reasons (e.g. "Red Zone security reviews must run on the strongest available model"), the frontmatter pin is a silent failure. Users may believe they are operating under a stricter review standard than they actually are, with no signal from the tool.

Suggested fix

Honor the frontmatter model: field in the documented resolution order. If the field is invalid or unreachable, surface a warning at subagent-spawn time rather than silently falling back.

Additional notes

  • The subagent's own self-identification in its output is not a reliable indicator — the running model often mis-reports its own version based on its system prompt contents. The message.model field in the transcript .jsonl is ground truth.
  • The agent's system prompt (visible when asking the agent to quote its environment block) includes "You are powered by the model named Sonnet 4.6. The exact model ID is claude-sonnet-4-6." — so the system prompt the harness generates matches the actually-called model, suggesting the harness resolves the model correctly for the system prompt but uses the same (wrong) model for the API call. The frontmatter is essentially being ignored end-to-end.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗