From d88c523ba487a1fd74835438a8b41b8a740baf34 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 5 Jan 2026 19:25:04 +0000 Subject: [PATCH] docs: add model config proposal --- docs/proposals/model-config.md | 153 +++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 docs/proposals/model-config.md diff --git a/docs/proposals/model-config.md b/docs/proposals/model-config.md new file mode 100644 index 000000000..3df6ba0d7 --- /dev/null +++ b/docs/proposals/model-config.md @@ -0,0 +1,153 @@ +--- +summary: "Proposal: model config, auth profiles, and fallback behavior" +read_when: + - Designing model selection, auth profiles, or fallback behavior + - Migrating model config schema +--- + +# Model config proposal + +Goals +- Multi OAuth + multi API key per provider +- Model selection via `/model` with sensible fallback +- Global (not per-session) fallback logic +- Keep last-known-good auth profile when switching models + +Non-goals (v1) +- Auto-discovery of provider capabilities beyond catalog input tags +- Per-model auth profile order (see open questions) + +## Proposed config shape + +```json +{ + "auth": { + "profiles": { + "anthropic:default": { + "provider": "anthropic", + "mode": "oauth" + }, + "anthropic:work": { + "provider": "anthropic", + "mode": "api_key" + }, + "openai:default": { + "provider": "openai", + "mode": "oauth" + } + }, + "order": { + "anthropic": ["anthropic:default", "anthropic:work"], + "openai": ["openai:default"] + } + }, + "agent": { + "models": { + "anthropic/claude-opus-4-5": { + "alias": "Opus" + }, + "openai/gpt-5.2": { + "alias": "gpt52" + } + }, + "model": { + "primary": "anthropic/claude-opus-4-5", + "fallbacks": ["openai/gpt-5.2"] + }, + "imageModel": { + "primary": "openai/gpt-5.2", + "fallbacks": ["anthropic/claude-opus-4-5"] + } + } +} +``` + +Notes +- Canonical model keys are full `provider/model`. +- `alias` optional; used by `/model` resolution. +- `auth.profiles` is keyed. Default CLI login creates `provider:default`. +- `auth.order[provider]` controls rotation order for that provider. + +## CLI / UX + +Login +- `clawdbot login anthropic` → create/replace `anthropic:default`. +- `clawdbot login anthropic --profile work` → create/replace `anthropic:work`. + +Model selection +- `/model Opus` → resolve alias to full id. +- `/model anthropic/claude-opus-4-5` → explicit. +- Optional: `/model Opus@anthropic:work` (pin auth profile for session override). + +Model listing +- `/model` list shows: + - model id + - alias + - provider + - auth order (from `auth.order`) + - auth source for the current provider (env/auth.json/models.json) + +## Fallback behavior (global) + +Fallback list +- Use `agent.model.fallbacks` globally. +- No per-session fallback list; last-known-good is per-session but uses global ordering. + +Auth profile rotation +- If provider auth error (401/403/invalid refresh): + - advance to next profile in `auth.order[provider]`. + - if all fail, fall back to next model. + +Rate limiting +- If rate limit / quota error: + - rotate auth profile first (same provider) + - if still failing, fall back to next model. + +Model not found / capability mismatch +- immediate model fallback. + +## Image routing + +Rule +- If current text model supports image input, use it. +- Else use `agent.imageModel` (primary then fallbacks). + +Support detection +- From model catalog `input` tags when available (e.g. `image` in models.json). +- If unknown: treat as text-only and use `agent.imageModel`. + +## Migration (doctor + gateway auto-run) + +Inputs +- `agent.model` (string) +- `agent.modelFallbacks` (string[]) +- `agent.imageModel` (string) +- `agent.imageModelFallbacks` (string[]) +- `agent.allowedModels` (string[]) +- `agent.modelAliases` (record) + +Outputs +- `agent.models` map with keys for all referenced models +- `agent.model.primary/fallbacks` +- `agent.imageModel.primary/fallbacks` +- `auth.profiles` seeded from current auth.json + env (as `provider:default`) +- `auth.order` seeded with `["provider:default"]` + +Auto-run +- Gateway start detects legacy keys and runs doctor migration. + +## Open questions + +1) Per-provider vs per-model auth order +- Proposed: per-provider only (`auth.order`). +- Alternative: allow `agent.models[...].authOrder` override. + +2) /model auth pinning +- Do we support `/model Opus@profile`? If not, keep purely automatic rotation. + +3) Image routing +- If model catalog lacks input tags, should we require explicit `agent.imageModel` or probe at runtime? + +4) Legacy compatibility +- Keep reading old keys if migration fails, or hard-break? +