feat!: redesign model config + auth profiles

This commit is contained in:
Peter Steinberger
2026-01-06 00:56:29 +00:00
parent bd2e003171
commit b04c838c15
60 changed files with 2037 additions and 790 deletions

View File

@@ -91,18 +91,40 @@ Env var equivalent:
### Auth storage (OAuth + API keys)
Clawdbot stores **OAuth credentials** in:
Clawdbot stores **auth profiles** (OAuth + API keys) in:
- `~/.clawdbot/agent/auth-profiles.json`
Legacy OAuth imports:
- `~/.clawdbot/credentials/oauth.json` (or `$CLAWDBOT_STATE_DIR/credentials/oauth.json`)
Clawdbot stores **API keys** in the agent auth store:
- `~/.clawdbot/agent/auth.json`
The embedded Pi agent maintains a runtime cache at:
- `~/.clawdbot/agent/auth.json` (managed automatically; dont edit manually)
Overrides:
- OAuth dir: `CLAWDBOT_OAUTH_DIR`
- OAuth dir (legacy import only): `CLAWDBOT_OAUTH_DIR`
- Agent dir: `CLAWDBOT_AGENT_DIR` (preferred), `PI_CODING_AGENT_DIR` (legacy)
On first use, Clawdbot imports `oauth.json` entries into `auth.json` so the embedded
agent can use them. `oauth.json` remains the source of truth for OAuth refresh.
On first use, Clawdbot imports `oauth.json` entries into `auth-profiles.json`.
### `auth`
Optional metadata for auth profiles. This does **not** store secrets; it maps
profile IDs to a provider + mode (and optional email) and defines the provider
rotation order used for failover.
```json5
{
auth: {
profiles: {
"anthropic:default": { provider: "anthropic", mode: "oauth", email: "me@example.com" },
"anthropic:work": { provider: "anthropic", mode: "api_key" }
},
order: {
anthropic: ["anthropic:default", "anthropic:work"]
}
}
}
```
### `identity`
@@ -494,14 +516,12 @@ Defaults for Talk mode (macOS/iOS/Android). Voice IDs fall back to `ELEVENLABS_V
### `agent`
Controls the embedded agent runtime (model/thinking/verbose/timeouts).
`allowedModels` lets `/model` list/filter and enforce a per-session allowlist
(omit to show the full catalog).
`modelAliases` adds short names for `/model` (alias -> provider/model).
`modelFallbacks` lists ordered fallback models to try when the default fails.
`imageModel` selects an image-capable model for the `image` tool.
`imageModelFallbacks` lists ordered fallback image models for the `image` tool.
`agent.models` defines the configured model catalog (and acts as the allowlist for `/model`).
`agent.model.primary` sets the default model; `agent.model.fallbacks` are global failovers.
`agent.imageModel` is optional and is **only used if the primary model lacks image input**.
Clawdbot also ships a few built-in `modelAliases` shorthands (when an `agent` section exists):
Clawdbot also ships a few built-in alias shorthands. Defaults only apply when the model
is already present in `agent.models`:
- `opus` -> `anthropic/claude-opus-4-5`
- `sonnet` -> `anthropic/claude-sonnet-4-5`
@@ -515,23 +535,24 @@ If you configure the same alias name (case-insensitive) yourself, your value win
```json5
{
agent: {
model: "anthropic/claude-opus-4-5",
allowedModels: [
"anthropic/claude-opus-4-5",
"anthropic/claude-sonnet-4-1"
],
modelAliases: {
Opus: "anthropic/claude-opus-4-5",
Sonnet: "anthropic/claude-sonnet-4-1"
models: {
"anthropic/claude-opus-4-5": { alias: "Opus" },
"anthropic/claude-sonnet-4-1": { alias: "Sonnet" },
"openrouter/deepseek/deepseek-r1:free": {}
},
model: {
primary: "anthropic/claude-opus-4-5",
fallbacks: [
"openrouter/deepseek/deepseek-r1:free",
"openrouter/meta-llama/llama-3.3-70b-instruct:free"
]
},
imageModel: {
primary: "openrouter/qwen/qwen-2.5-vl-72b-instruct:free",
fallbacks: [
"openrouter/google/gemini-2.0-flash-vision:free"
]
},
modelFallbacks: [
"openrouter/deepseek/deepseek-r1:free",
"openrouter/meta-llama/llama-3.3-70b-instruct:free"
],
imageModel: "openrouter/qwen/qwen-2.5-vl-72b-instruct:free",
imageModelFallbacks: [
"openrouter/google/gemini-2.0-flash-vision:free"
],
thinkingDefault: "low",
verboseDefault: "off",
elevatedDefault: "on",
@@ -566,8 +587,8 @@ Block streaming:
}
```
`agent.model` should be set as `provider/model` (e.g. `anthropic/claude-opus-4-5`).
If `modelAliases` is configured, you may also use the alias key (e.g. `Opus`).
`agent.model.primary` should be set as `provider/model` (e.g. `anthropic/claude-opus-4-5`).
Aliases come from `agent.models.*.alias` (e.g. `Opus`).
If you omit the provider, CLAWDBOT currently assumes `anthropic` as a temporary
deprecation fallback.
Z.AI models are available as `zai/<model>` (e.g. `zai/glm-4.7`) and require
@@ -729,11 +750,16 @@ When `models.providers` is present, Clawdbot writes/merges a `models.json` into
- default behavior: **merge** (keeps existing providers, overrides on name)
- set `models.mode: "replace"` to overwrite the file contents
Select the model via `agent.model` (provider/model).
Select the model via `agent.model.primary` (provider/model).
```json5
{
agent: { model: "custom-proxy/llama-3.1-8b" },
agent: {
model: { primary: "custom-proxy/llama-3.1-8b" },
models: {
"custom-proxy/llama-3.1-8b": {}
}
},
models: {
mode: "merge",
providers: {
@@ -766,14 +792,10 @@ via **LM Studio** using the **Responses API**.
```json5
{
agent: {
model: "Minimax",
allowedModels: [
"anthropic/claude-opus-4-5",
"lmstudio/minimax-m2.1-gs32"
],
modelAliases: {
Opus: "anthropic/claude-opus-4-5",
Minimax: "lmstudio/minimax-m2.1-gs32"
model: { primary: "lmstudio/minimax-m2.1-gs32" },
models: {
"anthropic/claude-opus-4-5": { alias: "Opus" },
"lmstudio/minimax-m2.1-gs32": { alias: "Minimax" }
}
},
models: {

View File

@@ -27,8 +27,13 @@ Doctor will:
- Show the migration it applied.
- Rewrite `~/.clawdbot/clawdbot.json` with the updated schema.
The Gateway also auto-runs doctor migrations on startup when it detects a legacy
config format, so stale configs are repaired without manual intervention.
Current migrations:
- `routing.allowFrom``whatsapp.allowFrom`
- `agent.model`/`allowedModels`/`modelAliases`/`modelFallbacks`/`imageModelFallbacks`
`agent.models` + `agent.model.primary/fallbacks` + `agent.imageModel.primary/fallbacks`
## Usage

View File

@@ -15,7 +15,8 @@ Everything lives under `~/.clawdbot/`:
|------|---------|
| `~/.clawdbot/clawdbot.json` | Main config (JSON5) |
| `~/.clawdbot/credentials/oauth.json` | OAuth credentials (Anthropic/OpenAI, etc.) |
| `~/.clawdbot/agent/auth.json` | API key store |
| `~/.clawdbot/agent/auth-profiles.json` | Auth profiles (OAuth + API keys) |
| `~/.clawdbot/agent/auth.json` | Runtime API key cache (managed automatically) |
| `~/.clawdbot/credentials/` | WhatsApp/Telegram auth tokens |
| `~/.clawdbot/sessions/` | Conversation history & state |
| `~/.clawdbot/sessions/sessions.json` | Session metadata |
@@ -576,21 +577,16 @@ List available models with `/model`, `/model list`, or `/model status`.
Clawdbot ships a few default model shorthands (you can override them in config):
`opus`, `sonnet`, `gpt`, `gpt-mini`, `gemini`, `gemini-flash`.
**Setup:** Configure allowed models and aliases in `clawdbot.json`:
**Setup:** Configure models and aliases in `clawdbot.json`:
```json
{
"agent": {
"model": "anthropic/claude-opus-4-5",
"allowedModels": [
"anthropic/claude-opus-4-5",
"anthropic/claude-sonnet-4-5",
"anthropic/claude-haiku-4-5"
],
"modelAliases": {
"opus": "anthropic/claude-opus-4-5",
"sonnet": "anthropic/claude-sonnet-4-5",
"haiku": "anthropic/claude-haiku-4-5"
"model": { "primary": "anthropic/claude-opus-4-5" },
"models": {
"anthropic/claude-opus-4-5": { "alias": "opus" },
"anthropic/claude-sonnet-4-5": { "alias": "sonnet" },
"anthropic/claude-haiku-4-5": { "alias": "haiku" }
}
}
}
@@ -606,7 +602,8 @@ If you don't want to use Anthropic directly, you can use alternative providers:
```json5
{
agent: {
model: "openrouter/anthropic/claude-sonnet-4",
model: { primary: "openrouter/anthropic/claude-sonnet-4" },
models: { "openrouter/anthropic/claude-sonnet-4": {} },
env: { OPENROUTER_API_KEY: "sk-or-..." }
}
}
@@ -616,7 +613,8 @@ If you don't want to use Anthropic directly, you can use alternative providers:
```json5
{
agent: {
model: "zai/glm-4.7",
model: { primary: "zai/glm-4.7" },
models: { "zai/glm-4.7": {} },
env: { ZAI_API_KEY: "..." }
}
}

View File

@@ -16,35 +16,32 @@ that prefers tool-call + image-capable models and maintains ordered fallbacks.
- default: configured models only
- flags: `--all` (full catalog), `--local`, `--provider <name>`, `--json`, `--plain`
- `clawdbot models status`
- show default model + aliases + fallbacks + allowlist
- show default model + aliases + fallbacks + configured models
- `clawdbot models set <modelOrAlias>`
- writes `agent.model` in config
- writes `agent.model.primary` and ensures `agent.models` entry
- `clawdbot models set-image <modelOrAlias>`
- writes `agent.imageModel` in config
- writes `agent.imageModel.primary` and ensures `agent.models` entry
- `clawdbot models aliases list|add|remove`
- writes `agent.modelAliases`
- writes `agent.models.*.alias`
- `clawdbot models fallbacks list|add|remove|clear`
- writes `agent.modelFallbacks`
- writes `agent.model.fallbacks`
- `clawdbot models image-fallbacks list|add|remove|clear`
- writes `agent.imageModelFallbacks`
- writes `agent.imageModel.fallbacks`
- `clawdbot models scan`
- OpenRouter :free scan; probe tool-call + image; interactive selection
## Config changes
- Add `agent.modelFallbacks: string[]` (ordered list of provider/model IDs).
- Add `agent.imageModel?: string` (optional image-capable model for image tool).
- Add `agent.imageModelFallbacks?: string[]` (ordered list for image tool).
- Keep existing:
- `agent.model` (default)
- `agent.allowedModels` (list filter)
- `agent.modelAliases` (shortcut names)
- `agent.models` (configured model catalog + aliases).
- `agent.model.primary` + `agent.model.fallbacks`.
- `agent.imageModel.primary` + `agent.imageModel.fallbacks` (optional).
- `auth.profiles` + `auth.order` for per-provider auth failover.
## Scan behavior (models scan)
Input
- OpenRouter `/models` list (filter `:free`)
- Requires `OPENROUTER_API_KEY` (or stored OpenRouter key in auth storage)
- Requires OpenRouter API key from auth profiles or `OPENROUTER_API_KEY`
- Optional filters: `--max-age-days`, `--min-params`, `--provider`, `--max-candidates`
- Probe controls: `--timeout`, `--concurrency`
@@ -66,17 +63,20 @@ Interactive selection (TTY)
- Non-TTY: auto-select; require `--yes`/`--no-input` to apply.
Output
- Writes `agent.modelFallbacks` ordered.
- Writes `agent.imageModelFallbacks` ordered (image-capable models).
- Optional `--set-default` to set `agent.model`.
- Optional `--set-image` to set `agent.imageModel`.
- Writes `agent.model.fallbacks` ordered.
- Writes `agent.imageModel.fallbacks` ordered (image-capable models).
- Ensures `agent.models` entries exist for selected models.
- Optional `--set-default` to set `agent.model.primary`.
- Optional `--set-image` to set `agent.imageModel.primary`.
## Runtime fallback
- On model failure: try `agent.modelFallbacks` in order.
- Ignore fallback entries not in `agent.allowedModels` (if allowlist set).
- Persist last successful provider/model to session entry.
- `/status` shows last used model (not just default).
- On model failure: try `agent.model.fallbacks` in order.
- Per-provider auth failover uses `auth.order` (or stored profile order) **before**
moving to the next model.
- Image routing uses `agent.imageModel` **only when configured** and the primary
model lacks image input.
- Persist last successful provider/model to session entry; auth profile success is global.
## Tests
@@ -86,5 +86,5 @@ Output
## Docs
- Update `docs/configuration.md` with `agent.modelFallbacks`.
- Update `docs/configuration.md` with `agent.models` + `agent.model` + `agent.imageModel`.
- Keep this doc current when CLI surface or scan logic changes.

View File

@@ -41,7 +41,7 @@ The macOS app should:
- `~/.clawdbot/credentials/oauth.json` (file mode `0600`, directory mode `0700`)
Why this location matters: its the Clawdbot-owned OAuth store.
Clawdbot also imports `oauth.json` into the agent auth store (`~/.clawdbot/agent/auth.json`) on first use.
Clawdbot also imports `oauth.json` into the agent auth profile store (`~/.clawdbot/agent/auth-profiles.json`) on first use.
### Recommended: OAuth (OpenAI Codex)
@@ -148,7 +148,7 @@ If the Gateway runs on another machine, OAuth credentials must be created/stored
For now, remote onboarding should:
- explain why OAuth isn't shown
- point the user at the credential location (`~/.clawdbot/credentials/oauth.json`) and the workspace location on the gateway host
- point the user at the credential location (`~/.clawdbot/credentials/oauth.json`) and the auth profile store (`~/.clawdbot/agent/auth-profiles.json`) on the gateway host
- mention that the **bootstrap ritual happens on the gateway host** (same BOOTSTRAP/IDENTITY/USER files)
### Manual credential setup

View File

@@ -87,7 +87,7 @@ Model listing
- alias
- provider
- auth order (from `auth.order`)
- auth source for the current provider (env/auth.json/models.json)
- auth source for the current provider (auth-profiles.json/env/shell env/models.json)
## Fallback behavior (global)
@@ -121,19 +121,20 @@ Support detection
## Migration (doctor + gateway auto-run)
Inputs
- `agent.model` (string)
- `agent.modelFallbacks` (string[])
- `agent.imageModel` (string)
- `agent.imageModelFallbacks` (string[])
- `agent.allowedModels` (string[])
- `agent.modelAliases` (record)
- Legacy keys (pre-migration):
- `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"]`
- Auth profile store seeded from current auth-profiles.json/auth.json + oauth.json + env (as `provider:default`)
- `auth.order` seeded with `["provider:default"]` when config is updated
Auto-run
- Gateway start detects legacy keys and runs doctor migration.

View File

@@ -126,7 +126,7 @@ Core parameters:
- `maxBytesMb` (optional size cap)
Notes:
- Only available when `agent.imageModel` or `agent.imageModelFallbacks` is set.
- Only available when `agent.imageModel` is configured (primary or fallbacks).
- Uses the image model directly (independent of the main chat model).
### `cron`

View File

@@ -48,7 +48,7 @@ Use SSH tunneling or Tailscale to reach the Gateway WS.
- `/help`
- `/status`
- `/session <key>` (or `/sessions`)
- `/model <provider/model>` (or `/models`)
- `/model <provider/model>` (or `/model list`, `/models`)
- `/think <off|minimal|low|medium|high>`
- `/verbose <on|off>`
- `/elevated <on|off>`

View File

@@ -52,7 +52,7 @@ It does **not** install or change anything on the remote host.
- **API key**: stores the key for you.
- **Minimax M2.1 (LM Studio)**: config is autowritten for the LM Studio endpoint.
- **Skip**: no auth configured yet.
- OAuth credentials live in `~/.clawdbot/credentials/oauth.json`; API keys live in `~/.clawdbot/agent/auth.json`.
- OAuth credentials live in `~/.clawdbot/credentials/oauth.json`; auth profiles live in `~/.clawdbot/agent/auth-profiles.json` (API keys + OAuth).
3) **Workspace**
- Default `~/clawd` (configurable).