Default Claude model — design
Status: Implemented. Makes the router's default Claude model
runtime-tunable from the UI admin page (no redeploy), seeded to
claude-sonnet-4-6.
What "default model" means
The router picks the model sent to Anthropic per request:
- Anthropic ingress (
/v1/messages) — the client's ownclaude-*model id is honored (Claude Code names a model per task; flattening them all to one would degrade it). SeeClaudeBackend._effective_model. - Otherwise — the OpenAI ingress (
/v1/chat/completions, wheremodelis a router alias) and any request that doesn't name a realclaude-*model fall back to the default model.
This setting controls that fallback. It does not override a client that pins its own Claude model.
Where the value lives
A single JSON file on the shared PVC, written by the UI and read by the router
— the same pattern as limits.json (see token-limits):
/var/split-brain/settings/settings.json
-> { "default_claude_model": "claude-sonnet-4-6" }
- UI (
ui/settings.py) is the single writer (replicaCount 1). The admin page (/admin,@smasint.comonly) POSTs/admin/model; the value is validated (claude-*) and written atomically. - Router (
router/settings.pySettingsStore) reads it, cached ~5s, and resolves the Claude backend'smodel_idper request via a provider callable — so a change takes effect within seconds, no restart. - Seed / fallback: when
settings.jsonis absent or holds a bad value, both sides fall back to the configured seed (anthropic_model/ui_default_claude_model, bothclaude-sonnet-4-6; the router seed is also set via the chart'sconfig.anthropicModel).
Safety
is_valid_model_id requires a non-empty claude-* string on both the write
side (rejected with 400) and the read side (a malformed file silently falls
back to the seed) — a bad value can never break every Claude call.