From e13225c9d1caac816ed1d736a51a8d7d94344490 Mon Sep 17 00:00:00 2001 From: sheeek Date: Wed, 7 Jan 2026 11:59:16 +0100 Subject: [PATCH] docs: add comprehensive guide for multi-agent sandbox and tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add docs/multi-agent-sandbox-tools.md covering: - Configuration examples (personal + restricted, work agents) - Different sandbox modes per agent - Tool restriction patterns (read-only, safe execution, communication-only) - Configuration precedence rules - Migration guide from single-agent setups - Troubleshooting tips Add PR_SUMMARY.md for upstream submission with: - Feature overview and use cases - Implementation details (49 LoC across 5 files) - Test coverage (18 new tests, all existing tests pass) - Backward compatibility confirmation - Migration examples --- Kudos to Eula, the beautiful and selfless family owl 🦉 This feature was developed to enable safe, restricted access for family group chats while maintaining full access for the personal assistant. Schuhu! --- PR_SUMMARY.md | 203 ++++++++++++++++++++++ docs/multi-agent-sandbox-tools.md | 278 ++++++++++++++++++++++++++++++ 2 files changed, 481 insertions(+) create mode 100644 PR_SUMMARY.md create mode 100644 docs/multi-agent-sandbox-tools.md diff --git a/PR_SUMMARY.md b/PR_SUMMARY.md new file mode 100644 index 000000000..f21887543 --- /dev/null +++ b/PR_SUMMARY.md @@ -0,0 +1,203 @@ +# PR: Agent-specific Sandbox and Tool Configuration + +## Summary + +Adds support for per-agent sandbox and tool configurations in multi-agent setups. This allows running multiple agents with different security profiles (e.g., personal assistant with full access, family bot with read-only restrictions). + +## Changes + +### Core Implementation (5 files, +49 LoC) + +1. **`src/config/types.ts`** (+4 lines) + - Added `sandbox` and `tools` fields to `routing.agents[agentId]` type + +2. **`src/config/zod-schema.ts`** (+6 lines) + - Added Zod validation for `routing.agents[].sandbox` and `routing.agents[].tools` + +3. **`src/agents/agent-scope.ts`** (+12 lines) + - Extended `resolveAgentConfig()` to return `sandbox` and `tools` fields + +4. **`src/agents/sandbox.ts`** (+12 lines) + - Modified `defaultSandboxConfig()` to accept `agentId` parameter + - Added logic to prefer agent-specific sandbox config over global config + - Updated `resolveSandboxContext()` and `ensureSandboxWorkspaceForSession()` to extract and pass `agentId` + +5. **`src/agents/pi-tools.ts`** (+15 lines) + - Added agent-specific tool filtering before sandbox tool filtering + - Imports `resolveAgentConfig` and `resolveAgentIdFromSessionKey` + +### Tests (3 new test files, 18 tests) + +1. **`src/agents/agent-scope.test.ts`** (7 tests) + - Tests for `resolveAgentConfig()` with sandbox and tools fields + +2. **`src/agents/sandbox-agent-config.test.ts`** (6 tests) + - Tests for agent-specific sandbox mode, scope, and workspaceRoot overrides + - Tests for multiple agents with different sandbox configs + +3. **`src/agents/pi-tools-agent-config.test.ts`** (5 tests) + - Tests for agent-specific tool filtering + - Tests for combined global + agent + sandbox tool policies + +### Documentation (3 files) + +1. **`docs/multi-agent-sandbox-tools.md`** (new) + - Comprehensive guide for per-agent sandbox and tool configuration + - Examples for common use cases + - Migration guide from single-agent configs + +2. **`docs/concepts/multi-agent.md`** (updated) + - Added section on per-agent sandbox and tool configuration + - Link to detailed guide + +3. **`docs/gateway/configuration.md`** (updated) + - Added documentation for `routing.agents[].sandbox` and `routing.agents[].tools` fields + +## Features + +### Agent-specific Sandbox Config + +```json +{ + "routing": { + "agents": { + "main": { + "workspace": "~/clawd", + "sandbox": { "mode": "off" } + }, + "family": { + "workspace": "~/clawd-family", + "sandbox": { + "mode": "all", + "scope": "agent" + } + } + } + } +} +``` + +**Result:** +- `main` agent runs on host (no Docker) +- `family` agent runs in Docker with one container per agent + +### Agent-specific Tool Restrictions + +```json +{ + "routing": { + "agents": { + "family": { + "workspace": "~/clawd-family", + "tools": { + "allow": ["read"], + "deny": ["bash", "write", "edit", "process"] + } + } + } + } +} +``` + +**Result:** +- `family` agent can only use the `read` tool +- All other tools are denied + +## Configuration Precedence + +### Sandbox Config +Agent-specific settings override global: +- `routing.agents[id].sandbox.mode` > `agent.sandbox.mode` +- `routing.agents[id].sandbox.scope` > `agent.sandbox.scope` +- `routing.agents[id].sandbox.workspaceRoot` > `agent.sandbox.workspaceRoot` + +Note: `docker`, `browser`, `tools`, and `prune` settings from `agent.sandbox` remain global. + +### Tool Filtering +Filtering order (each level can only further restrict): +1. Global tool policy (`agent.tools`) +2. **Agent-specific tool policy** (`routing.agents[id].tools`) ← NEW +3. Sandbox tool policy (`agent.sandbox.tools`) +4. Subagent tool policy (if applicable) + +## Backward Compatibility + +✅ **100% backward compatible** +- All existing configs work unchanged +- New fields (`routing.agents[].sandbox`, `routing.agents[].tools`) are optional +- Default behavior: if no agent-specific config exists, use global config +- All 1325 existing tests pass + +## Testing + +### New Tests: 18 tests, all passing +``` +✓ src/agents/agent-scope.test.ts (7 tests) +✓ src/agents/sandbox-agent-config.test.ts (6 tests) +✓ src/agents/pi-tools-agent-config.test.ts (5 tests) +``` + +### Existing Tests: All passing +``` +Test Files 227 passed | 2 skipped (229) +Tests 1325 passed | 2 skipped (1327) +``` + +Specifically verified: +- Discord provider tests: ✓ 23 tests +- Telegram provider tests: ✓ 42 tests +- Routing tests: ✓ 7 tests +- Gateway tests: ✓ All passed + +## Use Cases + +### Use Case 1: Personal Assistant + Restricted Family Bot +- Personal agent: Host, all tools +- Family agent: Docker, read-only + +### Use Case 2: Work Agent with Limited Access +- Personal agent: Full access +- Work agent: Docker, no browser/gateway tools + +### Use Case 3: Public-facing Bot +- Main agent: Trusted, full access +- Public agent: Always sandboxed, minimal tools + +## Migration Path + +**Before (global config):** +```json +{ + "agent": { + "sandbox": { "mode": "non-main" } + } +} +``` + +**After (per-agent config):** +```json +{ + "routing": { + "agents": { + "main": { "sandbox": { "mode": "off" } }, + "family": { "sandbox": { "mode": "all", "scope": "agent" } } + } + } +} +``` + +## Related Issues + +- Addresses need for per-agent security policies in multi-agent setups +- Complements existing multi-agent routing feature (introduced in 7360abad) +- Prepares for upcoming `clawdbot agents` CLI (announced 2026-01-07) + +## Checklist + +- [x] Code changes implemented +- [x] Tests written and passing +- [x] Documentation updated +- [x] Backward compatibility verified +- [x] No breaking changes +- [x] TypeScript types updated +- [x] Zod schema validation added diff --git a/docs/multi-agent-sandbox-tools.md b/docs/multi-agent-sandbox-tools.md new file mode 100644 index 000000000..102c68c5c --- /dev/null +++ b/docs/multi-agent-sandbox-tools.md @@ -0,0 +1,278 @@ +# Multi-Agent Sandbox & Tools Configuration + +## Overview + +Each agent in a multi-agent setup can now have its own: +- **Sandbox configuration** (`mode`, `scope`, `workspaceRoot`) +- **Tool restrictions** (`allow`, `deny`) + +This allows you to run multiple agents with different security profiles: +- Personal assistant with full access +- Family/work agents with restricted tools +- Public-facing agents in sandboxes + +--- + +## Configuration Examples + +### Example 1: Personal + Restricted Family Agent + +```json +{ + "routing": { + "defaultAgentId": "main", + "agents": { + "main": { + "name": "Personal Assistant", + "workspace": "~/clawd", + "sandbox": { + "mode": "off" + } + // No tool restrictions - all tools available + }, + "family": { + "name": "Family Bot", + "workspace": "~/clawd-family", + "sandbox": { + "mode": "all", + "scope": "agent" + }, + "tools": { + "allow": ["read"], + "deny": ["bash", "write", "edit", "process", "browser"] + } + } + }, + "bindings": [ + { + "agentId": "family", + "match": { + "provider": "whatsapp", + "accountId": "*", + "peer": { + "kind": "group", + "id": "120363424282127706@g.us" + } + } + } + ] + } +} +``` + +**Result:** +- `main` agent: Runs on host, full tool access +- `family` agent: Runs in Docker (one container per agent), only `read` tool + +--- + +### Example 2: Work Agent with Shared Sandbox + +```json +{ + "routing": { + "agents": { + "personal": { + "workspace": "~/clawd-personal", + "sandbox": { "mode": "off" } + }, + "work": { + "workspace": "~/clawd-work", + "sandbox": { + "mode": "all", + "scope": "shared", + "workspaceRoot": "/tmp/work-sandboxes" + }, + "tools": { + "allow": ["read", "write", "bash"], + "deny": ["browser", "gateway", "discord"] + } + } + } + } +} +``` + +--- + +### Example 3: Different Sandbox Modes per Agent + +```json +{ + "agent": { + "sandbox": { + "mode": "non-main", // Global default + "scope": "session" + } + }, + "routing": { + "agents": { + "main": { + "workspace": "~/clawd", + "sandbox": { + "mode": "off" // Override: main never sandboxed + } + }, + "public": { + "workspace": "~/clawd-public", + "sandbox": { + "mode": "all", // Override: public always sandboxed + "scope": "agent" + }, + "tools": { + "allow": ["read"], + "deny": ["bash", "write", "edit"] + } + } + } + } +} +``` + +--- + +## Configuration Precedence + +When both global (`agent.*`) and agent-specific (`routing.agents[id].*`) configs exist: + +### Sandbox Config +Agent-specific settings override global: +``` +routing.agents[id].sandbox.mode > agent.sandbox.mode +routing.agents[id].sandbox.scope > agent.sandbox.scope +routing.agents[id].sandbox.workspaceRoot > agent.sandbox.workspaceRoot +``` + +**Note:** `docker`, `browser`, `tools`, and `prune` settings from `agent.sandbox` are still **global** and apply to all sandboxed agents. + +### Tool Restrictions +The filtering order is: +1. **Global tool policy** (`agent.tools`) +2. **Agent-specific tool policy** (`routing.agents[id].tools`) +3. **Sandbox tool policy** (`agent.sandbox.tools` or `routing.agents[id].sandbox.tools`) +4. **Subagent tool policy** (if applicable) + +Each level can further restrict tools, but cannot grant back denied tools from earlier levels. + +--- + +## Migration from Single Agent + +**Before (single agent):** +```json +{ + "agent": { + "workspace": "~/clawd", + "sandbox": { + "mode": "non-main", + "tools": { + "allow": ["read", "write", "bash"], + "deny": [] + } + } + } +} +``` + +**After (multi-agent with different profiles):** +```json +{ + "routing": { + "defaultAgentId": "main", + "agents": { + "main": { + "workspace": "~/clawd", + "sandbox": { + "mode": "off" + } + } + } + } +} +``` + +The global `agent.workspace` and `agent.sandbox` are still supported for backward compatibility, but we recommend using `routing.agents` for clarity in multi-agent setups. + +--- + +## Tool Restriction Examples + +### Read-only Agent +```json +{ + "tools": { + "allow": ["read"], + "deny": ["bash", "write", "edit", "process"] + } +} +``` + +### Safe Execution Agent (no file modifications) +```json +{ + "tools": { + "allow": ["read", "bash", "process"], + "deny": ["write", "edit", "browser", "gateway"] + } +} +``` + +### Communication-only Agent +```json +{ + "tools": { + "allow": ["sessions_list", "sessions_send", "sessions_history"], + "deny": ["bash", "write", "edit", "read", "browser"] + } +} +``` + +--- + +## Testing + +After configuring multi-agent sandbox and tools: + +1. **Check agent resolution:** + ```bash + clawdbot agents list + ``` + +2. **Verify sandbox containers:** + ```bash + docker ps --filter "label=clawdbot.sandbox=1" + ``` + +3. **Test tool restrictions:** + - Send a message requiring restricted tools + - Verify the agent cannot use denied tools + +4. **Monitor logs:** + ```bash + tail -f ~/.clawdbot/logs/gateway.log | grep -E "routing|sandbox|tools" + ``` + +--- + +## Troubleshooting + +### Agent not sandboxed despite `mode: "all"` +- Check if there's a global `agent.sandbox.mode` that overrides it +- Agent-specific config takes precedence, so set `routing.agents[id].sandbox.mode: "all"` + +### Tools still available despite deny list +- Check tool filtering order: global → agent → sandbox → subagent +- Each level can only further restrict, not grant back +- Verify with logs: `[tools] filtering tools for agent:${agentId}` + +### Container not isolated per agent +- Set `scope: "agent"` in agent-specific sandbox config +- Default is `"session"` which creates one container per session + +--- + +## See Also + +- [Multi-Agent Routing](/concepts/multi-agent) +- [Sandbox Configuration](/gateway/configuration#agent-sandbox) +- [Session Management](/concepts/session)