2026-01-02 01:19:22 +01:00
---
2026-02-24 23:30:05 +00:00
summary: "Group chat behavior across surfaces (WhatsApp/Telegram/Discord/Slack/Signal/iMessage/Microsoft Teams/Zalo)"
2026-01-02 01:19:22 +01:00
read_when:
- Changing group chat behavior or mention gating
2026-01-31 16:04:03 -05:00
title: "Groups"
2026-01-02 01:19:22 +01:00
---
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
# Groups
2026-02-24 23:30:05 +00:00
OpenClaw treats group chats consistently across surfaces: WhatsApp, Telegram, Discord, Slack, Signal, iMessage, Microsoft Teams, Zalo.
2026-01-02 01:19:22 +01:00
2026-01-10 19:56:43 +01:00
## Beginner intro (2 minutes)
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
OpenClaw “lives” on your own messaging accounts. There is no separate WhatsApp bot user.
If **you ** are in a group, OpenClaw can see that group and respond there.
2026-01-10 19:56:43 +01:00
Default behavior:
2026-01-31 21:13:13 +09:00
2026-01-12 08:21:50 +00:00
- Groups are restricted (`groupPolicy: "allowlist"` ).
2026-01-10 19:56:43 +01:00
- Replies require a mention unless you explicitly disable mention gating.
2026-01-30 03:15:10 +01:00
Translation: allowlisted senders can trigger OpenClaw by mentioning it.
2026-01-10 19:56:43 +01:00
> TL;DR
2026-01-31 21:13:13 +09:00
>
2026-01-10 19:56:43 +01:00
> - **DM access** is controlled by `*.allowFrom`.
> - **Group access** is controlled by `*.groupPolicy` + allowlists (`*.groups`, `*.groupAllowFrom`).
> - **Reply triggering** is controlled by mention gating (`requireMention`, `/activation`).
Quick flow (what happens to a group message):
2026-01-31 21:13:13 +09:00
2026-01-10 19:56:43 +01:00
```
groupPolicy? disabled -> drop
groupPolicy? allowlist -> group allowed? no -> drop
requireMention? yes -> mentioned? no -> store for context only
otherwise -> reply
```
2026-01-10 20:05:18 +01:00

2026-01-10 19:56:43 +01:00
If you want...
2026-02-06 09:35:57 -05:00
| Goal | What to set |
| -------------------------------------------- | ---------------------------------------------------------- |
| Allow all groups but only reply on @mentions | `groups: { "*": { requireMention: true } }` |
| Disable all group replies | `groupPolicy: "disabled"` |
| Only specific groups | `groups: { "<group-id>": { ... } }` (no `"*"` key) |
| Only you can trigger in groups | `groupPolicy: "allowlist"` , `groupAllowFrom: ["+1555..."]` |
2026-01-10 19:56:43 +01:00
2026-01-02 01:19:22 +01:00
## Session keys
2026-01-31 21:13:13 +09:00
2026-01-13 07:15:57 +00:00
- Group sessions use `agent:<agentId>:<channel>:group:<id>` session keys (rooms/channels use `agent:<agentId>:<channel>:channel:<id>` ).
2026-01-07 02:10:56 +00:00
- Telegram forum topics add `:topic:<threadId>` to the group id so each topic has its own session.
2026-01-02 01:19:22 +01:00
- Direct chats use the main session (or per-sender if configured).
- Heartbeats are skipped for group sessions.
2026-01-15 03:48:06 +00:00
## 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:<channel>:group:<id>` ). 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:
2026-01-31 21:13:13 +09:00
2026-01-15 03:48:06 +00:00
- **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)
2026-01-31 21:13:13 +09:00
workspaceAccess: "none",
},
},
2026-01-15 03:48:06 +00:00
},
tools: {
sandbox: {
tools: {
// If allow is non-empty, everything else is blocked (deny still wins).
allow: ["group:messaging", "group:sessions"],
2026-01-31 21:13:13 +09:00
deny: ["group:runtime", "group:fs", "group:ui", "nodes", "cron", "gateway"],
},
},
},
2026-01-15 03:48:06 +00:00
}
```
2026-01-15 03:52:52 +00:00
Want “groups can only see folder X” instead of “no host access”? Keep `workspaceAccess: "none"` and mount only allowlisted paths into the sandbox:
``` json5
{
agents: {
defaults: {
sandbox: {
mode: "non-main",
scope: "session",
workspaceAccess: "none",
docker: {
binds: [
// hostPath:containerPath:mode
2026-02-16 03:05:16 +01:00
"/home/user/FriendsShared:/data:ro",
2026-01-31 21:13:13 +09:00
],
},
},
},
},
2026-01-15 03:52:52 +00:00
}
```
2026-01-15 03:48:06 +00:00
Related:
2026-01-31 21:13:13 +09:00
2026-01-15 03:48:06 +00:00
- 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 )
2026-01-15 03:52:52 +00:00
- Bind mounts details: [Sandboxing ](/gateway/sandboxing#custom-bind-mounts )
2026-01-15 03:48:06 +00:00
2026-01-02 10:14:58 +01:00
## Display labels
2026-01-31 21:13:13 +09:00
2026-01-13 07:15:57 +00:00
- UI labels use `displayName` when available, formatted as `<channel>:<token>` .
2026-01-02 10:14:58 +01:00
- `#room` is reserved for rooms/channels; group chats use `g-<slug>` (lowercase, spaces -> `-` , keep `#@+._-` ).
2026-01-06 06:40:42 +00:00
## Group policy
2026-01-31 21:13:13 +09:00
2026-01-13 07:15:57 +00:00
Control how group/room messages are handled per channel:
2026-01-06 01:41:19 -03:00
``` json5
{
2026-01-13 06:16:43 +00:00
channels: {
whatsapp: {
groupPolicy: "disabled", // "open" | "disabled" | "allowlist"
2026-01-31 21:13:13 +09:00
groupAllowFrom: ["+15551234567"],
2026-01-13 06:16:43 +00:00
},
telegram: {
groupPolicy: "disabled",
2026-02-14 16:08:41 +01:00
groupAllowFrom: ["123456789"], // numeric Telegram user id (wizard can resolve @username)
2026-01-13 06:16:43 +00:00
},
signal: {
groupPolicy: "disabled",
2026-01-31 21:13:13 +09:00
groupAllowFrom: ["+15551234567"],
2026-01-13 06:16:43 +00:00
},
imessage: {
groupPolicy: "disabled",
2026-01-31 21:13:13 +09:00
groupAllowFrom: ["chat_id:123"],
2026-01-13 06:16:43 +00:00
},
msteams: {
groupPolicy: "disabled",
2026-01-31 21:13:13 +09:00
groupAllowFrom: ["user@org.com"],
2026-01-13 06:16:43 +00:00
},
discord: {
groupPolicy: "allowlist",
guilds: {
2026-01-31 21:13:13 +09:00
GUILD_ID: { channels: { help: { allow: true } } },
},
2026-01-13 06:16:43 +00:00
},
slack: {
groupPolicy: "allowlist",
2026-01-31 21:13:13 +09:00
channels: { "#general": { allow: true } },
2026-01-20 09:37:27 +01:00
},
matrix: {
groupPolicy: "allowlist",
groupAllowFrom: ["@owner:example.org"],
groups: {
"!roomId:example.org": { allow: true },
2026-01-31 21:13:13 +09:00
"#alias:example.org": { allow: true },
},
},
},
2026-01-06 01:41:19 -03:00
}
```
2026-01-31 21:13:13 +09:00
| Policy | Behavior |
| ------------- | ------------------------------------------------------------ |
| `"open"` | Groups bypass allowlists; mention-gating still applies. |
| `"disabled"` | Block all group messages entirely. |
2026-01-06 06:40:42 +00:00
| `"allowlist"` | Only allow groups/rooms that match the configured allowlist. |
2026-01-06 01:41:19 -03:00
Notes:
2026-01-31 21:13:13 +09:00
2026-01-06 01:41:19 -03:00
- `groupPolicy` is separate from mention-gating (which requires @mentions ).
2026-02-24 23:30:05 +00:00
- WhatsApp/Telegram/Signal/iMessage/Microsoft Teams/Zalo: use `groupAllowFrom` (fallback: explicit `allowFrom` ).
2026-01-13 06:16:43 +00:00
- Discord: allowlist uses `channels.discord.guilds.<id>.channels` .
- Slack: allowlist uses `channels.slack.channels` .
2026-01-20 09:37:27 +01:00
- Matrix: allowlist uses `channels.matrix.groups` (room IDs, aliases, or names). Use `channels.matrix.groupAllowFrom` to restrict senders; per-room `users` allowlists are also supported.
2026-01-13 06:16:43 +00:00
- Group DMs are controlled separately (`channels.discord.dm.*` , `channels.slack.dm.*` ).
2026-01-06 06:40:42 +00:00
- Telegram allowlist can match user IDs (`"123456789"` , `"telegram:123456789"` , `"tg:123456789"` ) or usernames (`"@alice"` or `"alice"` ); prefixes are case-insensitive.
2026-01-12 08:21:50 +00:00
- Default is `groupPolicy: "allowlist"` ; if your group allowlist is empty, group messages are blocked.
2026-02-22 12:17:44 +01:00
- Runtime safety: when a provider block is completely missing (`channels.<provider>` absent), group policy falls back to a fail-closed mode (typically `allowlist` ) instead of inheriting `channels.defaults.groupPolicy` .
2026-01-06 01:41:19 -03:00
2026-01-10 19:56:43 +01:00
Quick mental model (evaluation order for group messages):
2026-01-31 21:13:13 +09:00
1. `groupPolicy` (open/disabled/allowlist)
2. group allowlists (`*.groups` , `*.groupAllowFrom` , channel-specific allowlist)
3. mention gating (`requireMention` , `/activation` )
2026-01-10 19:56:43 +01:00
2026-01-02 01:19:22 +01:00
## Mention gating (default)
2026-01-31 21:13:13 +09:00
2026-01-02 22:23:00 +01:00
Group messages require a mention unless overridden per group. Defaults live per subsystem under `*.groups."*"` .
2026-01-02 01:19:22 +01:00
2026-01-16 21:50:44 +00:00
Replying to a bot message counts as an implicit mention (when the channel supports reply metadata). This applies to Telegram, WhatsApp, Slack, Discord, and Microsoft Teams.
2026-01-02 01:19:22 +01:00
``` json5
{
2026-01-13 06:16:43 +00:00
channels: {
whatsapp: {
groups: {
"*": { requireMention: true },
2026-01-31 21:13:13 +09:00
"123@g.us": { requireMention: false },
},
2026-01-13 06:16:43 +00:00
},
telegram: {
groups: {
"*": { requireMention: true },
2026-01-31 21:13:13 +09:00
"123456789": { requireMention: false },
},
2026-01-13 06:16:43 +00:00
},
imessage: {
groups: {
"*": { requireMention: true },
2026-01-31 21:13:13 +09:00
"123": { requireMention: false },
},
},
2026-01-02 22:23:00 +01:00
},
2026-01-09 12:44:23 +00:00
agents: {
list: [
{
id: "main",
groupChat: {
2026-01-30 03:15:10 +01:00
mentionPatterns: ["@openclaw", "openclaw", "\\+15555550123"],
2026-01-31 21:13:13 +09:00
historyLimit: 50,
},
},
],
},
2026-01-02 01:19:22 +01:00
}
```
Notes:
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
- `mentionPatterns` are case-insensitive regexes.
- Surfaces that provide explicit mentions still pass; patterns are a fallback.
2026-01-09 12:44:23 +00:00
- Per-agent override: `agents.list[].groupChat.mentionPatterns` (useful when multiple agents share a group).
2026-01-06 01:38:36 +01:00
- Mention gating is only enforced when mention detection is possible (native mentions or `mentionPatterns` are configured).
2026-01-13 06:16:43 +00:00
- Discord defaults live in `channels.discord.guilds."*"` (overridable per guild/channel).
2026-01-16 23:52:14 +00:00
- Group history context is wrapped uniformly across channels and is **pending-only ** (messages skipped due to mention gating); use `messages.groupChat.historyLimit` for the global default and `channels.<channel>.historyLimit` (or `channels.<channel>.accounts.*.historyLimit` ) for overrides. Set `0` to disable.
2026-01-02 01:19:22 +01:00
2026-01-27 18:12:33 +13:00
## Group/channel tool restrictions (optional)
2026-01-31 21:13:13 +09:00
2026-01-27 18:12:33 +13:00
Some channel configs support restricting which tools are available **inside a specific group/room/channel ** .
- `tools` : allow/deny tools for the whole group.
2026-02-22 21:03:09 +01:00
- `toolsBySender` : per-sender overrides within the group.
Use explicit key prefixes:
`id:<senderId>` , `e164:<phone>` , `username:<handle>` , `name:<displayName>` , and `"*"` wildcard.
Legacy unprefixed keys are still accepted and matched as `id:` only.
2026-01-27 18:12:33 +13:00
Resolution order (most specific wins):
2026-01-31 21:13:13 +09:00
1. group/channel `toolsBySender` match
2. group/channel `tools`
3. default (`"*"` ) `toolsBySender` match
4. default (`"*"` ) `tools`
2026-01-27 18:12:33 +13:00
Example (Telegram):
``` json5
{
channels: {
telegram: {
groups: {
"*": { tools: { deny: ["exec"] } },
"-1001234567890": {
tools: { deny: ["exec", "read", "write"] },
toolsBySender: {
2026-02-22 21:03:09 +01:00
"id:123456789": { alsoAllow: ["exec"] },
2026-01-31 21:13:13 +09:00
},
},
},
},
},
2026-01-27 18:12:33 +13:00
}
```
Notes:
2026-01-31 21:13:13 +09:00
2026-01-27 18:12:33 +13:00
- Group/channel tool restrictions are applied in addition to global/agent tool policy (deny still wins).
- Some channels use different nesting for rooms/channels (e.g., Discord `guilds.*.channels.*` , Slack `channels.*` , MS Teams `teams.*.channels.*` ).
2026-01-06 04:27:21 +01:00
## Group allowlists
2026-01-31 21:13:13 +09:00
2026-01-13 06:16:43 +00:00
When `channels.whatsapp.groups` , `channels.telegram.groups` , or `channels.imessage.groups` is configured, the keys act as a group allowlist. Use `"*"` to allow all groups while still setting default mention behavior.
2026-01-06 04:27:21 +01:00
2026-01-10 19:56:43 +01:00
Common intents (copy/paste):
2026-01-31 21:13:13 +09:00
1. Disable all group replies
2026-01-10 19:56:43 +01:00
``` json5
{
2026-01-31 21:13:13 +09:00
channels: { whatsapp: { groupPolicy: "disabled" } },
2026-01-10 19:56:43 +01:00
}
```
2026-02-06 10:00:08 -05:00
2. Allow only specific groups (WhatsApp)
2026-01-31 21:13:13 +09:00
2026-01-10 19:56:43 +01:00
``` json5
{
2026-01-13 06:16:43 +00:00
channels: {
whatsapp: {
groups: {
"123@g.us": { requireMention: true },
2026-01-31 21:13:13 +09:00
"456@g.us": { requireMention: false },
},
},
},
2026-01-10 19:56:43 +01:00
}
```
2026-02-06 10:00:08 -05:00
3. Allow all groups but require mention (explicit)
2026-01-31 21:13:13 +09:00
2026-01-10 19:56:43 +01:00
``` json5
{
2026-01-13 06:16:43 +00:00
channels: {
whatsapp: {
2026-01-31 21:13:13 +09:00
groups: { "*": { requireMention: true } },
},
},
2026-01-10 19:56:43 +01:00
}
```
2026-02-06 10:00:08 -05:00
4. Only the owner can trigger in groups (WhatsApp)
2026-01-31 21:13:13 +09:00
2026-01-10 19:56:43 +01:00
``` json5
{
2026-01-13 06:16:43 +00:00
channels: {
whatsapp: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15551234567"],
2026-01-31 21:13:13 +09:00
groups: { "*": { requireMention: true } },
},
},
2026-01-10 19:56:43 +01:00
}
```
2026-01-02 01:19:22 +01:00
## Activation (owner-only)
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
Group owners can toggle per-group activation:
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
- `/activation mention`
- `/activation always`
2026-01-13 06:16:43 +00:00
Owner is determined by `channels.whatsapp.allowFrom` (or the bot’ s self E.164 when unset). Send the command as a standalone message. Other surfaces currently ignore `/activation` .
2026-01-02 01:19:22 +01:00
## Context fields
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
Group inbound payloads set:
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
- `ChatType=group`
- `GroupSubject` (if known)
- `GroupMembers` (if known)
- `WasMentioned` (mention gating result)
2026-01-07 02:10:56 +00:00
- Telegram forum topics also include `MessageThreadId` and `IsForum` .
2026-01-02 01:19:22 +01:00
2026-01-13 03:40:22 +00:00
The agent system prompt includes a group intro on the first turn of a new group session. It reminds the model to respond like a human, avoid Markdown tables, and avoid typing literal `\n` sequences.
2026-01-02 01:19:22 +01:00
## iMessage specifics
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
- Prefer `chat_id:<id>` when routing or allowlisting.
- List chats: `imsg chats --limit 20` .
- Group replies always go back to the same `chat_id` .
## WhatsApp specifics
2026-01-31 21:13:13 +09:00
2026-02-07 15:40:35 -05:00
See [Group messages ](/channels/group-messages ) for WhatsApp-only behavior (history injection, mention handling details).