[FEATURE] Native multi-provider model routing in settings.json (per-subagent / per-model-alias provider selection)
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Claude Code's model configuration assumes a single upstream: ANTHROPIC_BASE_URL (and the auth token that goes with it) applies to the entire session, including every subagent. There's no way to point different models at different endpoints from within Claude Code itself.
This breaks down for anyone running a mixed setup: real Claude models for planning/orchestration, plus one or more self-hosted OpenAI-compatible inference servers for cheaper bulk/mechanical work (e.g. two separate local LLM servers on a LAN, each serving several model sizes). Today the only way to mix providers in one session is to stand up an external translating proxy (e.g. LiteLLM) in front of Claude Code that fakes a single Anthropic-compatible endpoint and internally re-routes by model name. That works, but it means:
- running and maintaining an extra service just to do request translation Claude Code could reasonably do natively
- an extra network hop and failure point
- no visibility into provider routing from Claude Code's own config,
/modelpicker, or docs — it's all hidden in a shim
Proposed Solution
Let settings.json define multiple named model providers (base URL + auth + protocol), and let any model reference (main session model, subagent frontmatter model:, ANTHROPIC_DEFAULT_*_MODEL) specify which provider it targets. Rough shape:
{
"modelProviders": {
"anthropic": {
"baseUrl": "https://api.anthropic.com",
"authToken": "env:ANTHROPIC_API_KEY"
},
"providerA": {
"baseUrl": "http://192.168.1.1:8000/v1",
"protocol": "openai",
"authToken": "sk-local-a"
},
"providerB": {
"baseUrl": "http://192.168.1.2:8000/v1",
"protocol": "openai",
"authToken": "sk-local-b"
}
},
"model": "anthropic/claude-opus-4-8"
}
And in subagent frontmatter:
model: providerA/70b-instruct
Claude Code would handle the OpenAI-format translation for protocol: openai providers internally (same translation logic a proxy like LiteLLM does today), so no external shim is needed. The /model picker would list models grouped by provider.
Alternative Solutions
Currently workable, but external and imperfect:
- Run a local translating proxy (e.g. LiteLLM proxy) that exposes a single Anthropic-format
/v1/messagesendpoint and fans requests out to multiple upstream providers based on model name, then pointANTHROPIC_BASE_URLat it. Works, but requires maintaining a separate service, adds a hop, and provider routing lives outside Claude Code's own config entirely.
Priority
High - Significant impact on productivity
Feature Category
Configuration and settings
Use Case Example
I run two self-hosted Claude or even OpenAI-compatible inference servers on my LAN (192.168.1.1 and 192.168.1.2), each serving 4-5 model sizes. I want Claude Code's main session to plan using a real Claude model, then delegate mechanical/bulk work to whichever local subagent model fits the task — different sizes for different jobs, across both servers — all from one settings.json, without running a separate translation proxy just to make that possible.
Additional Context
- Related prior art: LiteLLM's proxy config (
model_listwith per-entryapi_base) does roughly this shape of multi-provider routing already; something similar natively in Claude Code would remove the need for that extra layer. - Would also need: a per-provider protocol field (Anthropic Messages vs. OpenAI chat completions) since local servers are typically OpenAI-compatible, not Anthropic-format.
- This feature request is real, but this issue writing is assisted by claude chat
5 Comments
What, Anybody?
?
Also hitting this, on the subscription path, where the failure differs from the API-key setups above.
Claude Code v2.1.220, claude.ai subscription, no API key set.
ANTHROPIC_CUSTOM_MODEL_OPTIONputs a third-party model into the/modelpicker, but selecting it fails:ANTHROPIC_BASE_URLapplies to the whole session, so the model ID reaches Anthropic and gets rejected. Gateway discovery does not solve it either, since a gateway credential replaces the subscription login for that session.The mechanism already ships for one provider: with the Bedrock Mantle endpoint enabled,
availableModelsentries prefixedanthropic.are added to the picker as custom options and routed to Mantle.Would a per-entry override be considered, something like
ANTHROPIC_CUSTOM_MODEL_OPTION_BASE_URL, scoped to that one picker entry while the rest of the session keeps the subscription? If a session-wide base URL is a deliberate constraint, saying so would close this out.@bcherny @ThariqS worth a maintainer call on this one: would a per-entry endpoint override on
ANTHROPIC_CUSTOM_MODEL_OPTIONbe accepted, givenavailableModelsalready does per-entry routing to Mantle foranthropic.-prefixed IDs? A "session-wide base URL is intentional" would settle it too, and this thread plus #38698 have both been open with no maintainer read.For API/provider-credential setups, the external-gateway workaround can route
the main session and local subagents to different providers today. It does not
add the requested native
settings.jsonsupport, and it does not work for thesubscription-only setup described later in this thread.
In Swobu, create a
claude-codeworkspace with twoexplicit routes:
| Route | Backend | Backend model | Protocol |
|---|---|---|---|
|
orchestrator| Anthropic or another hosted target | your main model | Messages ||
local-subagent| your local OpenAI-compatible server | your local model | Chat Completions |Then point Claude Code at the workspace and map its Opus and Haiku aliases to
those route names:
Set
model: haikuin the local subagent definition. Claude Code sendsorchestratorfor the main request andlocal-subagentfor that subagent;Swobu selects the matching backend and translates Messages to Chat Completions
for the local route.
I tested both paths with Claude Code 2.1.204: the main request reached the
Messages backend with its configured model, and the subagent request reached a
different Chat Completions backend with its configured local model.
The client-side API key above is only a placeholder. Configure real credentials
on the hosted Swobu target. Each backend must support the Claude Code semantics
used by its workload. This remains an external service and does not preserve a
claude.ai subscription while diverting one model to another provider.
Disclosure: I maintain Swobu. If you try this, please share the result. For a
Swobu-specific failure, include the Claude Code version, route name, and backend
setup at github.com/swobuforge/swobu, and
I will help investigate.