feat: wire multi-agent config and routing

Co-authored-by: Mark Pors <1078320+pors@users.noreply.github.com>
This commit is contained in:
Peter Steinberger
2026-01-09 12:44:23 +00:00
parent 81beda0772
commit 7b81d97ec2
189 changed files with 4340 additions and 2903 deletions

View File

@@ -18,7 +18,7 @@ Youre putting an agent in a position to:
Start conservative:
- Always set `whatsapp.allowFrom` (never run open-to-the-world on your personal Mac).
- Use a dedicated WhatsApp number for the assistant.
- Heartbeats now default to every 30 minutes. Disable until you trust the setup by setting `agent.heartbeat.every: "0m"`.
- Heartbeats now default to every 30 minutes. Disable until you trust the setup by setting `agents.defaults.heartbeat.every: "0m"`.
## Prerequisites
@@ -103,7 +103,7 @@ clawdbot setup
Full workspace layout + backup guide: [`docs/agent-workspace.md`](/concepts/agent-workspace)
Optional: choose a different workspace with `agent.workspace` (supports `~`).
Optional: choose a different workspace with `agents.defaults.workspace` (supports `~`).
```json5
{
@@ -173,9 +173,9 @@ Example:
By default, CLAWDBOT runs a heartbeat every 30 minutes with the prompt:
`Read HEARTBEAT.md if exists. Consider outstanding tasks. Checkup sometimes on your human during (user local) day time.`
Set `agent.heartbeat.every: "0m"` to disable.
Set `agents.defaults.heartbeat.every: "0m"` to disable.
- If the agent replies with `HEARTBEAT_OK` (optionally with short padding; see `agent.heartbeat.ackMaxChars`), CLAWDBOT suppresses outbound delivery for that heartbeat.
- If the agent replies with `HEARTBEAT_OK` (optionally with short padding; see `agents.defaults.heartbeat.ackMaxChars`), CLAWDBOT suppresses outbound delivery for that heartbeat.
- Heartbeats run full agent turns — shorter intervals burn more tokens.
```json5

View File

@@ -115,14 +115,14 @@ Everything lives under `$CLAWDBOT_STATE_DIR` (default: `~/.clawdbot`):
Legacy singleagent path: `~/.clawdbot/agent/*` (migrated by `clawdbot doctor`).
Your **workspace** (AGENTS.md, memory files, skills, etc.) is separate and configured via `agent.workspace` (default: `~/clawd`).
Your **workspace** (AGENTS.md, memory files, skills, etc.) is separate and configured via `agents.defaults.workspace` (default: `~/clawd`).
### Can agents work outside the workspace?
Yes. The workspace is the **default cwd** and memory anchor, not a hard sandbox.
Relative paths resolve inside the workspace, but absolute paths can access other
host locations unless sandboxing is enabled. If you need isolation, use
[`agent.sandbox`](/gateway/sandboxing) or peragent sandbox settings. If you
[`agents.defaults.sandbox`](/gateway/sandboxing) or peragent sandbox settings. If you
want a repo to be the default working directory, point that agents
`workspace` to the repo root. The Clawdbot repo is just source code; keep the
workspace separate unless you intentionally want the agent to work inside it.
@@ -259,7 +259,7 @@ Direct chats collapse to the main session by default. Groups/channels have their
Clawdbots default model is whatever you set as:
```
agent.model.primary
agents.defaults.model.primary
```
Models are referenced as `provider/model` (example: `anthropic/claude-opus-4-5`). If you omit the provider, Clawdbot currently assumes `anthropic` as a temporary deprecation fallback — but you should still **explicitly** set `provider/model`.
@@ -282,7 +282,7 @@ You can list available models with `/model`, `/model list`, or `/model status`.
### Why do I see “Model … is not allowed” and then no reply?
If `agent.models` is set, it becomes the **allowlist** for `/model` and any
If `agents.defaults.models` is set, it becomes the **allowlist** for `/model` and any
session overrides. Choosing a model that isnt in that list returns:
```
@@ -290,11 +290,11 @@ Model "provider/model" is not allowed. Use /model to list available models.
```
That error is returned **instead of** a normal reply. Fix: add the model to
`agent.models`, remove the allowlist, or pick a model from `/model list`.
`agents.defaults.models`, remove the allowlist, or pick a model from `/model list`.
### Are opus / sonnet / gpt builtin shortcuts?
Yes. Clawdbot ships a few default shorthands (only applied when the model exists in `agent.models`):
Yes. Clawdbot ships a few default shorthands (only applied when the model exists in `agents.defaults.models`):
- `opus` → `anthropic/claude-opus-4-5`
- `sonnet` → `anthropic/claude-sonnet-4-5`
@@ -307,7 +307,7 @@ If you set your own alias with the same name, your value wins.
### How do I define/override model shortcuts (aliases)?
Aliases come from `agent.models.<modelId>.alias`. Example:
Aliases come from `agents.defaults.models.<modelId>.alias`. Example:
```json5
{
@@ -359,7 +359,7 @@ If you reference a provider/model but the required provider key is missing, you
Failover happens in two stages:
1) **Auth profile rotation** within the same provider.
2) **Model fallback** to the next model in `agent.model.fallbacks`.
2) **Model fallback** to the next model in `agents.defaults.model.fallbacks`.
Cooldowns apply to failing profiles (exponential backoff), so Clawdbot can keep responding even when a provider is ratelimited or temporarily failing.
@@ -387,7 +387,7 @@ It means the system attempted to use the auth profile ID `anthropic:default`, bu
If your model config includes Google Gemini as a fallback (or you switched to a Gemini shorthand), Clawdbot will try it during model fallback. If you havent configured Google credentials, youll see `No API key found for provider "google"`.
Fix: either provide Google auth, or remove/avoid Google models in `agent.model.fallbacks` / aliases so fallback doesnt route there.
Fix: either provide Google auth, or remove/avoid Google models in `agents.defaults.model.fallbacks` / aliases so fallback doesnt route there.
## Auth profiles: what they are and how to manage them
@@ -506,7 +506,7 @@ Yes, but you must isolate:
- `CLAWDBOT_CONFIG_PATH` (perinstance config)
- `CLAWDBOT_STATE_DIR` (perinstance state)
- `agent.workspace` (workspace isolation)
- `agents.defaults.workspace` (workspace isolation)
- `gateway.port` (unique ports)
There are convenience CLI flags like `--dev` and `--profile <name>` that shift state dirs and ports.
@@ -619,7 +619,7 @@ You can add options like `debounce:2s cap:25 drop:summarize` for followup modes.
### “All models failed” — what should I check first?
- **Credentials** present for the provider(s) being tried (auth profiles + env vars).
- **Model routing**: confirm `agent.model.primary` and fallbacks are models you can access.
- **Model routing**: confirm `agents.defaults.model.primary` and fallbacks are models you can access.
- **Gateway logs** in `/tmp/clawdbot/…` for the exact provider error.
- **`/model status`** to see current configured models + shorthands.
@@ -658,7 +658,7 @@ clawdbot providers login
**Q: “Whats the default model for Anthropic with an API key?”**
**A:** In Clawdbot, credentials and model selection are separate. Setting `ANTHROPIC_API_KEY` (or storing an Anthropic API key in auth profiles) enables authentication, but the actual default model is whatever you configure in `agent.model.primary` (for example, `anthropic/claude-sonnet-4-5` or `anthropic/claude-opus-4-5`). If you see `No credentials found for profile "anthropic:default"`, it means the Gateway couldnt find Anthropic credentials in the expected `auth-profiles.json` for the agent thats running.
**A:** In Clawdbot, credentials and model selection are separate. Setting `ANTHROPIC_API_KEY` (or storing an Anthropic API key in auth profiles) enables authentication, but the actual default model is whatever you configure in `agents.defaults.model.primary` (for example, `anthropic/claude-sonnet-4-5` or `anthropic/claude-opus-4-5`). If you see `No credentials found for profile "anthropic:default"`, it means the Gateway couldnt find Anthropic credentials in the expected `auth-profiles.json` for the agent thats running.
---

View File

@@ -19,7 +19,7 @@ Recommended path: use the **CLI onboarding wizard** (`clawdbot onboard`). It set
If you want the deeper reference pages, jump to: [Wizard](/start/wizard), [Setup](/start/setup), [Pairing](/start/pairing), [Security](/gateway/security).
Sandboxing note: `agent.sandbox.mode: "non-main"` uses `session.mainKey` (default `"main"`),
Sandboxing note: `agents.defaults.sandbox.mode: "non-main"` uses `session.mainKey` (default `"main"`),
so group/channel sessions are sandboxed. If you want the main agent to always
run on host, set an explicit per-agent override:

View File

@@ -71,12 +71,12 @@ Tip: `--json` does **not** imply non-interactive mode. Use `--non-interactive` (
2) **Model/Auth**
- **Anthropic OAuth (Claude CLI)**: on macOS the wizard checks Keychain item "Claude Code-credentials" (choose "Always Allow" so launchd starts don't block); on Linux/Windows it reuses `~/.claude/.credentials.json` if present.
- **Anthropic token (paste setup-token)**: run `claude setup-token` in your terminal, then paste the token (you can name it; blank = default).
- **OpenAI Codex OAuth (Codex CLI)**: if `~/.codex/auth.json` exists, the wizard can reuse it.
- **OpenAI Codex OAuth**: browser flow; paste the `code#state`.
- Sets `agent.model` to `openai-codex/gpt-5.2` when model is unset or `openai/*`.
- **OpenAI API key**: uses `OPENAI_API_KEY` if present or prompts for a key, then saves it to `~/.clawdbot/.env` so launchd can read it.
- **API key**: stores the key for you.
- **Anthropic token (paste setup-token)**: run `claude setup-token` in your terminal, then paste the token (you can name it; blank = default).
- **OpenAI Codex OAuth (Codex CLI)**: if `~/.codex/auth.json` exists, the wizard can reuse it.
- **OpenAI Codex OAuth**: browser flow; paste the `code#state`.
- Sets `agents.defaults.model` to `openai-codex/gpt-5.2` when model is unset or `openai/*`.
- **OpenAI API key**: uses `OPENAI_API_KEY` if present or prompts for a key, then saves it to `~/.clawdbot/.env` so launchd can read it.
- **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.
- Wizard runs a model check and warns if the configured model is unknown or missing auth.
@@ -144,14 +144,14 @@ Use `clawdbot agents add <name>` to create a separate agent with its own workspa
sessions, and auth profiles. Running without `--workspace` launches the wizard.
What it sets:
- `routing.agents.<agentId>.name`
- `routing.agents.<agentId>.workspace`
- `routing.agents.<agentId>.agentDir`
- `agents.list[].name`
- `agents.list[].workspace`
- `agents.list[].agentDir`
Notes:
- Default workspaces follow `~/clawd-<agentId>`.
- Add `routing.bindings` to route inbound messages (the wizard can do this).
- Non-interactive flags: `--model`, `--agent-dir`, `--bind`, `--non-interactive`.
- Add `bindings` to route inbound messages (the wizard can do this).
- Non-interactive flags: `--model`, `--agent-dir`, `--bind`, `--non-interactive`.
## Noninteractive mode
@@ -213,8 +213,8 @@ Notes:
## What the wizard writes
Typical fields in `~/.clawdbot/clawdbot.json`:
- `agent.workspace`
- `agent.model` / `models.providers` (if Minimax chosen)
- `agents.defaults.workspace`
- `agents.defaults.model` / `models.providers` (if Minimax chosen)
- `gateway.*` (mode, bind, auth, tailscale)
- `telegram.botToken`, `discord.token`, `signal.*`, `imessage.*`
- `skills.install.nodeManager`
@@ -224,7 +224,7 @@ Typical fields in `~/.clawdbot/clawdbot.json`:
- `wizard.lastRunCommand`
- `wizard.lastRunMode`
`clawdbot agents add` writes `routing.agents.<agentId>` and optional `routing.bindings`.
`clawdbot agents add` writes `agents.list[]` and optional `bindings`.
WhatsApp credentials go under `~/.clawdbot/credentials/whatsapp/<accountId>/`.
Sessions are stored under `~/.clawdbot/agents/<agentId>/sessions/`.