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

@@ -32,7 +32,7 @@ reach other host locations unless sandboxing is enabled. See
- Config: `~/.clawdbot/clawdbot.json` (or `CLAWDBOT_CONFIG_PATH`)
- State dir: `~/.clawdbot` (or `CLAWDBOT_STATE_DIR`)
- Workspace: `~/clawd` (or `~/clawd-<agentId>`)
- Agent dir: `~/.clawdbot/agents/<agentId>/agent` (or `routing.agents.<agentId>.agentDir`)
- Agent dir: `~/.clawdbot/agents/<agentId>/agent` (or `agents.list[].agentDir`)
- Sessions: `~/.clawdbot/agents/<agentId>/sessions`
### Single-agent mode (default)
@@ -52,7 +52,7 @@ Use the agent wizard to add a new isolated agent:
clawdbot agents add work
```
Then add `routing.bindings` (or let the wizard do it) to route inbound messages.
Then add `bindings` (or let the wizard do it) to route inbound messages.
Verify with:
@@ -79,7 +79,7 @@ Bindings are **deterministic** and **most-specific wins**:
3. `teamId` (Slack)
4. `accountId` match for a provider
5. provider-level match (`accountId: "*"`)
6. fallback to `routing.defaultAgentId` (default: `main`)
6. fallback to default agent (`agents.list[].default`, else first list entry, default: `main`)
## Multiple accounts / phone numbers
@@ -100,39 +100,42 @@ multiple phone numbers without mixing sessions.
```js
{
routing: {
defaultAgentId: "home",
agents: {
home: {
agents: {
list: [
{
id: "home",
default: true,
name: "Home",
workspace: "~/clawd-home",
agentDir: "~/.clawdbot/agents/home/agent",
},
work: {
{
id: "work",
name: "Work",
workspace: "~/clawd-work",
agentDir: "~/.clawdbot/agents/work/agent",
},
},
// Deterministic routing: first match wins (most-specific first).
bindings: [
{ agentId: "home", match: { provider: "whatsapp", accountId: "personal" } },
{ agentId: "work", match: { provider: "whatsapp", accountId: "biz" } },
// Optional per-peer override (example: send a specific group to work agent).
{
agentId: "work",
match: {
provider: "whatsapp",
accountId: "personal",
peer: { kind: "group", id: "1203630...@g.us" },
},
},
],
},
// Off by default: agent-to-agent messaging must be explicitly enabled + allowlisted.
// Deterministic routing: first match wins (most-specific first).
bindings: [
{ agentId: "home", match: { provider: "whatsapp", accountId: "personal" } },
{ agentId: "work", match: { provider: "whatsapp", accountId: "biz" } },
// Optional per-peer override (example: send a specific group to work agent).
{
agentId: "work",
match: {
provider: "whatsapp",
accountId: "personal",
peer: { kind: "group", id: "1203630...@g.us" },
},
},
],
// Off by default: agent-to-agent messaging must be explicitly enabled + allowlisted.
tools: {
agentToAgent: {
enabled: false,
allow: ["home", "work"],
@@ -160,16 +163,18 @@ Starting with v2026.1.6, each agent can have its own sandbox and tool restrictio
```js
{
routing: {
agents: {
personal: {
agents: {
list: [
{
id: "personal",
workspace: "~/clawd-personal",
sandbox: {
mode: "off", // No sandbox for personal agent
},
// No tool restrictions - all tools available
},
family: {
{
id: "family",
workspace: "~/clawd-family",
sandbox: {
mode: "all", // Always sandboxed
@@ -184,7 +189,7 @@ Starting with v2026.1.6, each agent can have its own sandbox and tool restrictio
deny: ["bash", "write", "edit"], // Deny others
},
},
},
],
},
}
```
@@ -194,8 +199,8 @@ Starting with v2026.1.6, each agent can have its own sandbox and tool restrictio
- **Resource control**: Sandbox specific agents while keeping others on host
- **Flexible policies**: Different permissions per agent
Note: `agent.elevated` is **global** and sender-based; it is not configurable per agent.
If you need per-agent boundaries, use `routing.agents[id].tools` to deny `bash`.
For group targeting, you can set `routing.agents[id].mentionPatterns` so @mentions map cleanly to the intended agent.
Note: `tools.elevated` is **global** and sender-based; it is not configurable per agent.
If you need per-agent boundaries, use `agents.list[].tools` to deny `bash`.
For group targeting, use `agents.list[].groupChat.mentionPatterns` so @mentions map cleanly to the intended agent.
See [Multi-Agent Sandbox & Tools](/multi-agent-sandbox-tools) for detailed examples.