Model strategy¶
Audience: contributors and maintainers deciding or reviewing tier defaults. For day-to-day
--use-llmsetup, seedocs/llm.md.
GPT-6 Astra is available through llm_provider: codex using ChatGPT subscription
login, or the explicitly enabled openai Responses provider. Use
llm_reasoning_effort: medium initially; work-queue automation uses high.
The current harness, including one using a locally served model, can own all
model work with llm_provider: harness. See
execution in your harness.
Claude tier defaults below remain specific to Claude agents and Anthropic providers. They do not select an Astra model or change a running session.
This document explains why anvil's agents default to specific Claude tiers (Opus / Sonnet / Haiku) and how to override them. Companion to docs/llm.md, which covers how to configure each provider and has the canonical tier/model-id/cost table.
The headline rule¶
Default everything to Sonnet, escalate to Opus only for reasoning/architecture/synthesis, drop to Haiku for read-only / mechanical / lookup work.
This is the 2026 community consensus, codified in Anthropic's own docs and surfaced via the routing-telemetry issue (anthropics/claude-code#27665) which documented that 93.8% of tokens were being routed to Opus when smarter defaults would cut that to ~30%. Defaulting every agent to Opus is the headline cost anti-pattern in agent setups — it costs roughly 5× more per token than Sonnet without quality wins on most agent work.
anvil's tier defaults follow this rule directly: DEFAULT_TIER = "sonnet" in planning/llm.py, and each agent's frontmatter sets model: to the tier appropriate for the work it does.
Tier ↔ agent mapping¶
anvil (5 agents)¶
| Agent | Tier | Why |
|---|---|---|
planner |
opus | PRD-to-tasks synthesis. Requires understanding implicit dependencies, sizing tasks against acceptance criteria, and deciding what to leave for expand. Hard reasoning over structured but ambiguous input. |
critic |
opus | Code review against acceptance criteria. Subtle bugs (race conditions, broken invariants, security regressions) are the high-value finds; reasoning depth dominates token efficiency. |
docs-scribe |
sonnet | Structured generation of CHANGELOG entries, README updates, cross-reference fixes. The input (a code change) and output shape (a Keep-a-Changelog entry) are both well-defined. |
sentinel |
haiku | Evidence validation: run a shell command, parse exit code, compare against acceptance criteria. The classic "read-only investigator" case Anthropic's own Explore subagent uses Haiku for. |
state-keeper |
haiku | Cross-source-of-truth scan: glob the filesystem, query SQLite, list git branches, report drift. Pure read-and-classify. |
Override precedence¶
Users always win:
- Per-call argument — pass
model=ortier=to a provider constructor in code. - Env var — set
ANTHROPIC_MODEL(Anthropic-supported) or use Claude Code'sCLAUDE_CODE_SUBAGENT_MODEL=inheritto force every subagent to the session model. - Project config — set
llm_tier: opusorllm_model: <id>in.anvil/config.yamlto apply project-wide. - Agent frontmatter — the
model:field in each agent's.mdfile sets the tier-default for that agent. - Module default —
DEFAULT_TIER = "sonnet"inplanning/llm.py.
Higher numbers override lower ones. If a user explicitly wants Opus everywhere, that choice is respected — the tier defaults are recommendations, not lock-ins.
Automatic escalation (deferred)¶
Anthropic ships exactly one first-party "escalate on complexity" pattern: the opusplan model alias, which uses Opus in plan mode and auto-switches to Sonnet for execution. This is the only escalation pattern with first-party support as of May 2026.
Third-party community routers exist (tzachbon/claude-model-router-hook, 0xrdan/claude-router, musistudio/claude-code-router) that classify prompt complexity at the PreToolUse hook level and rewrite the model. None of these are first-party, and anvil does not ship its own router because:
- Measuring before optimizing — most projects' agent spend is dominated by overuse of Opus on simple turns, not by undertuning of any single turn. Switching defaults to Sonnet (already the anvil default) captures the bulk of the savings without dynamic routing.
- Cost predictability — a dynamic router can surprise ops teams when prompt classification flips a critical path to Haiku. The cost win is real, but the failure mode (a planning task accidentally classified as "simple" and run on Haiku) is opaque to debug.
- Opt-in over default — users who want dynamic routing today can wire
tzachbon/claude-model-router-hookthemselves and override per-agent. Bundling it would force a one-size-fits-all policy.
If a future anvil release ships dynamic escalation, it will be via an explicit llm_router: config key, not by default.
Cost reference¶
See llm.md § Cost-tier defaults for the canonical per-tier
model-id and price table (kept in one place to avoid drift). At a glance: Sonnet is
roughly 5× cheaper than Opus per token, and Haiku roughly 15× cheaper — the core
economics behind the headline rule above.
For a typical anvil planning session (one PRD → tasks generation + 4 expansions + 6 score augmentations + 3 critic reviews), the current tier defaults reduce per-session token spend by ~60% versus the prior "everything inherits Opus" pattern, with no measurable quality regression on the planner and critic paths (which stay on Opus).
Pinning a project to Opus¶
Some teams genuinely want Opus everywhere — for compliance, audit, or because their work is consistently in the "deep reasoning" bucket. To pin:
# .anvil/config.yaml
llm_tier: opus
This sets the floor: every provider built by resolve_planner_provider(config) uses Opus. Individual agent frontmatter model: values are independent of this (they govern Claude Code subagent dispatch, not the planning-augmentation calls anvil makes), so if you want Opus across the whole agent fleet too, also set CLAUDE_CODE_SUBAGENT_MODEL=claude-opus-4-7 in your environment.
References¶
- Claude Code model-config —
opusplan,CLAUDE_CODE_SUBAGENT_MODEL, and the alias system. - Choosing a Claude model — Anthropic's official per-task tier guidance.
- anthropics/claude-code#27665 — the routing-telemetry issue that triggered the 2026 "Sonnet by default" consensus.
- Anthropic prompt caching docs — referenced in
planning/llm.pyfor thecache_control: {"type": "ephemeral"}pattern.