From 4e48d0a4319b5d8a04a8066c3572a237793f7449 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 15 Jan 2026 03:48:06 +0000 Subject: [PATCH] docs: document personal DMs vs public groups --- docs/concepts/groups.md | 41 +++++++++++++++++++++++++++++++++++++++++ docs/start/faq.md | 10 ++++++++++ 2 files changed, 51 insertions(+) diff --git a/docs/concepts/groups.md b/docs/concepts/groups.md index cc6e82797..e11408699 100644 --- a/docs/concepts/groups.md +++ b/docs/concepts/groups.md @@ -46,6 +46,47 @@ If you want... - Direct chats use the main session (or per-sender if configured). - Heartbeats are skipped for group sessions. +## Pattern: personal DMs + public groups (single agent) + +Yes — this works well if your “personal” traffic is **DMs** and your “public” traffic is **groups**. + +Why: in single-agent mode, DMs typically land in the **main** session key (`agent:main:main`), while groups always use **non-main** session keys (`agent:main::group:`). If you enable sandboxing with `mode: "non-main"`, those group sessions run in Docker while your main DM session stays on-host. + +This gives you one agent “brain” (shared workspace + memory), but two execution postures: +- **DMs**: full tools (host) +- **Groups**: sandbox + restricted tools (Docker) + +> If you need truly separate workspaces/personas (“personal” and “public” must never mix), use a second agent + bindings. See [Multi-Agent Routing](/concepts/multi-agent). + +Example (DMs on host, groups sandboxed + messaging-only tools): + +```json5 +{ + agents: { + defaults: { + sandbox: { + mode: "non-main", // groups/channels are non-main -> sandboxed + scope: "session", // strongest isolation (one container per group/channel) + workspaceAccess: "none" + } + } + }, + tools: { + sandbox: { + tools: { + // If allow is non-empty, everything else is blocked (deny still wins). + allow: ["group:messaging", "group:sessions"], + deny: ["group:runtime", "group:fs", "group:ui", "nodes", "cron", "gateway"] + } + } + } +} +``` + +Related: +- Configuration keys and defaults: [Gateway configuration](/gateway/configuration#agentsdefaultssandbox) +- Debugging why a tool is blocked: [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated) + ## Display labels - UI labels use `displayName` when available, formatted as `:`. - `#room` is reserved for rooms/channels; group chats use `g-` (lowercase, spaces -> `-`, keep `#@+._-`). diff --git a/docs/start/faq.md b/docs/start/faq.md index 13b0b0ff6..b284514b3 100644 --- a/docs/start/faq.md +++ b/docs/start/faq.md @@ -404,6 +404,16 @@ ClawdHub installs into `./skills` under your current directory (or falls back to Yes. See [Sandboxing](/gateway/sandboxing). For Docker-specific setup (full gateway in Docker or sandbox images), see [Docker](/install/docker). +### Can I keep DMs “personal” but make groups “public/sandboxed” with one agent? + +Yes — if your private traffic is **DMs** and your public traffic is **groups**. + +Use `agents.defaults.sandbox.mode: "non-main"` so group/channel sessions (non-main keys) run in Docker, while the main DM session stays on-host. Then restrict what tools are available in sandboxed sessions via `tools.sandbox.tools`. + +Setup walkthrough + example config: [Groups: personal DMs + public groups](/concepts/groups#pattern-personal-dms-public-groups-single-agent) + +Key config reference: [Gateway configuration](/gateway/configuration#agentsdefaultssandbox) + ### How do I bind a host folder into the sandbox? Set `agents.defaults.sandbox.docker.binds` to `["host:path:mode"]` (e.g., `"/home/user/src:/src:ro"`). Global + per-agent binds merge; per-agent binds are ignored when `scope: "shared"`. Use `:ro` for anything sensitive and remember binds bypass the sandbox filesystem walls. See [Sandboxing](/gateway/sandboxing#custom-bind-mounts) and [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated#bind-mounts-security-quick-check) for examples and safety notes.