Claude Code Model Config: Aliases, Fallbacks, Effort

No. On the Anthropic API and Claude Platform on AWS it resolves to Opus 5, on Amazon Bedrock and Google Cloud's Agent Platform to Opus 5, and on Microsoft Foundry to Opus 4.6. The sonnet alias varies more widely still. If you need a specific version, pin the full model name rather than relying on an alias.
They solve different problems. A fallbackModel chain handles availability — the primary model is overloaded or returns a non-retryable server error, so Claude Code tries the next entry. Automatic model fallback is content-based: Fable 5 and Opus 5 run safety classifiers, and a flagged request is re-run on a different model.
Because it may be silently degrading. If you set a level the active model does not support, Claude Code falls back to the highest supported level at or below it — xhigh runs as high on Opus 4.6, with no notice. Opus 4.6 and Sonnet 4.6 support low, medium, high and max but not xhigh.
Each entry into and exit from plan mode is a model switch, and every model has its own prompt cache. So a session that toggles plan mode four times has paid for four full uncached re-reads of the conversation so far. On short sessions this is negligible; on long ones it is noticeable.
No. Claude Code does not confirm the chain at startup and the status command does not display it. The notice shown when a switch actually happens is the first visible sign that a fallback is configured at all, which is why it is worth documenting the chain somewhere you will read it.

Key Takeaway
Claude Code model aliases resolve to different versions depending on your provider, so the same setting can mean Opus 5 on the Anthropic API and Opus 4.6 on Microsoft Foundry. Fallback chains cap at three models, last only for the current turn, and are not shown in status output. Effort levels silently degrade to the highest one the active model supports.
A colleague and I compared notes on the same alias configuration and got different answers to the same question. Same settings file, same prompt, visibly different reasoning. He was on Bedrock, I was on the Anthropic API, and the word opus in both our configs was resolving to different models. Nothing in either session said so.
Model configuration in Claude Code is one of those areas where the defaults are good enough that most people never look, and then one day the abstraction matters. This post covers what aliases actually resolve to, the two completely different fallback mechanisms and why one of them is invisible, how effort levels degrade, and the organisation-level controls that decide what anyone on a team can select.
Aliases exist so you do not have to remember version numbers, and they update over time as new versions ship. The cost of that convenience is that the same alias is not the same model everywhere. This is the table worth having open when comparing behaviour with someone on a different provider.
Where the two common aliases land, by provider:
| Provider | opus resolves to | sonnet resolves to |
|---|---|---|
| Anthropic API | Opus 5 | Sonnet 5 |
| Claude Platform on AWS | Opus 5 | Sonnet 4.6 |
| Amazon Bedrock, Google Cloud Agent Platform | Opus 5 | Sonnet 4.5 |
| Microsoft Foundry | Opus 4.6 | Sonnet 4.5 |
Where an alias lands on an older model, the newer one is still reachable by naming it in full or by setting the default-opus or default-sonnet environment variable. If you need a specific version and not the recommended one, pin the full model name — an alias is a moving target by design, and that is usually what you want right up until it is not.
The opusplan alias is a hybrid: Opus while you are in plan mode for the reasoning, Sonnet for the execution that follows. It pairs the model that is better at architecture with the one that is cheaper at typing, and for a lot of workflows it is the right default without any further thought.
The subtlety is what it does to caching. Every entry into and exit from plan mode is a model switch, and each model has its own cache — so a session where you toggle plan mode four times has paid for four full uncached re-reads of the conversation so far. On a short session that is nothing. On a long one it is the reason the fifth toggle feels slow.
When the organisation allowlist excludes the newest Opus but permits an older version, opusplan uses the newest permitted Opus for planning rather than giving up and staying on Sonnet. A Haiku session that would normally upgrade to Sonnet in plan mode behaves the same way. That substitution applies on the Anthropic API and Claude Platform on AWS only — on Bedrock, Agent Platform, Foundry and Mantle, whose deployments use provider-specific IDs, plan mode simply stays on the session's model.
This mechanism handles availability: the primary model is overloaded, unavailable, or returns another non-retryable server error, and Claude Code moves down a chain rather than failing the request. It is worth configuring and easy to forget you configured.
# Availability-based fallback: the primary model is overloaded
# or returns a non-retryable server error, so Claude Code moves
# down the chain instead of failing the request.
claude --fallback-model sonnet,haiku # one session
# Or persist it. Capped at three models after deduplication;
# extra entries are ignored.
{
"fallbackModel": ["claude-sonnet-5", "claude-haiku-4-5"]
}
# Two things worth knowing:
# - the switch lasts for the CURRENT TURN only. Your next
# message tries the primary again.
# - /status does not display the chain and Claude Code does
# not confirm it at startup. The notice shown when a switch
# happens is the first visible sign it is configured at all.
#
# Auth, billing, rate-limit, request-size and transport errors
# never trigger a switch — those follow normal retry handling.Two entries are dropped before the walk even starts. Anything outside the organisation allowlist is removed when Claude Code reads the chain. And because the chain also covers compaction, Claude Code refuses to fall back to a model with a smaller context window than the primary's — summarising there would cut off part of the conversation before summarising it. If every fallback is smaller, compaction shows the original error and you retry.
Fable 5 and Opus 5 run safety classifiers for cybersecurity and biology content, and a flagged request can be re-run on a different model. This is a completely separate mechanism from the chain above, and it surprises people because it can fire on the very first request of a session:
Fallback can trigger before you have sent anything unusual, because the first request carries workspace context — your CLAUDE.md content and git status. A repository containing security or biology material can trip the classifier on that alone. To check whether your customisations are the trigger, start with the safe-mode flag, which disables CLAUDE.md, skills, MCP servers and hooks. Git status and directory names are not customisations and are still included, which is itself a useful clue.
Effort controls adaptive reasoning: how much the model thinks per step based on task complexity. The levels available depend on the model, and the failure mode is quiet rather than loud.
# Effort levels are per model, and the default is high
# everywhere that supports them.
Fable 5, Opus 5, Sonnet 5, Opus 4.8, Opus 4.7
low medium high xhigh max
Opus 4.6, Sonnet 4.6
low medium high max (no xhigh)
# Set a level the active model does not support and Claude Code
# falls back to the highest supported level at or below it —
# xhigh runs as high on Opus 4.6, silently.
/effort xhigh
/effort ultracode # xhigh + automatic workflow orchestration
claude --effort ultracodeIf you set a level the active model does not support, Claude Code falls back to the highest supported level at or below it. So a config that says xhigh runs as high on Opus 4.6 and nothing tells you. Combine that with an alias resolving to a different model on your provider, and two people with identical settings files can be running at genuinely different reasoning depths while both believing they are on xhigh.
Three settings shape what anyone on a team can select, and they solve different problems. The allowlist restricts which models are permitted at all. The picker curates what the model command actually offers, in an order and with labels you choose. And the pricing setting makes cost output reflect your organisation's contracted rates rather than list price, which matters the moment someone uses that output to make a decision.
// Restrict which models a session may run on, then curate
// what the picker actually shows.
{
"availableModels": ["sonnet", "claude-opus-4-6"],
// Ordered, labelled list for the /model picker. Accepts any
// ID spelling, including Vertex and Bedrock IDs.
"modelPicker": [
{ "id": "claude-sonnet-5", "label": "Sonnet 5 — daily driver" },
{ "id": "claude-opus-5", "label": "Opus 5 — hard problems" }
],
// Price /cost, the statusline and telemetry at your
// organisation's contracted rates instead of list price.
"modelPricing": { }
}
# Substitution when the allowlist blocks a request: a family
# alias such as "opus" runs on the newest permitted version of
# that family on the Anthropic API and Claude Platform on AWS.
# On providers with provider-specific IDs there is no such
# substitution, and a blocked value falls back to the lead's model.For subagents specifically, the subagent-model environment variable overrides both the session model and anything a workflow script requests, so it is the single lever for keeping a fan-out on a cheaper model without editing scripts. Set it before a large run rather than trying to route each stage individually — and remember that in a workflow, an agent whose requested model is blocked by the allowlist runs on a substituted model and the progress view names both.
Most of this you will never touch. These three earn their keep immediately:
The useful mental model is that almost every model setting in Claude Code is a request rather than an instruction: an alias is resolved per provider, an effort level is clamped to what the model supports, a chain entry is dropped if the allowlist forbids it, and a flagged request is re-routed by a classifier you never see. None of that is wrong, but it does mean the answer to what model am I actually running is a command you run, not a line you read in a settings file.
Sources & further reading