Broadcast Groups: Fan Out WhatsApp Messages to Multiple Agents
Learn how to configure broadcast groups so multiple agents can respond to a single WhatsApp message, each in its own session. This guide is for developers setting up multi-agent group chats or DMs.
Read this when
- Configuring broadcast groups
- Debugging multi-agent replies in WhatsApp
Note
Status: Experimental. Introduced in 2026.1.9. WhatsApp (web channel) only.
Overview
With broadcast groups, multiple agents act on the same incoming message. Every agent handles the message within its own isolated session and sends back its own response, so a single WhatsApp number can support a set of specialized agents in one group chat or DM.
These groups are checked after channel allowlists and group activation rules. In WhatsApp groups, broadcasts trigger when OpenClaw would normally respond (such as on mention, depending on your group settings). They only affect which agents execute, never whether a message qualifies for processing.
The live WhatsApp QA lane contains whatsapp-broadcast-group-fanout, which confirms that a single mentioned group message can yield distinct visible replies from two configured agents.
Configuration
Basic setup
Place a top-level broadcast section alongside bindings. Keys correspond to WhatsApp peer ids, and values are arrays of agent ids:
- group chats: group JID (for example
120363403215116621@g.us) - DMs: sender E.164 phone number (for instance
+15551234567)
{
"broadcast": {
"120363403215116621@g.us": ["alfred", "baerbel", "assistant3"]
}
}
Outcome: whenever OpenClaw would respond in this chat, all three agents run.
Each agent id listed must be present in agents.entries: config validation flags unknown ids, and the runtime skips them with a Broadcast agent <id> not found in agents.entries; skipping warning.
Processing strategy
broadcast.strategy determines how agents handle the message:
| Strategy | Behavior |
|---|---|
parallel (default) | All agents run at the same time; replies come back in no fixed order. |
sequential | Agents run in the order given in the array; each one waits for the prior to complete. |
{
"broadcast": {
"strategy": "sequential",
"120363403215116621@g.us": ["alfred", "baerbel"]
}
}
Complete example
{
"agents": {
"entries": {
"code-reviewer": {
"default": true,
"name": "Code Reviewer",
"workspace": "/path/to/code-reviewer",
"sandbox": { "mode": "all" }
},
"security-auditor": {
"name": "Security Auditor",
"workspace": "/path/to/security-auditor",
"sandbox": { "mode": "all" }
},
"docs-generator": {
"name": "Documentation Generator",
"workspace": "/path/to/docs-generator",
"sandbox": { "mode": "all" }
}
}
},
"broadcast": {
"strategy": "parallel",
"120363403215116621@g.us": ["code-reviewer", "security-auditor", "docs-generator"],
"120363424282127706@g.us": ["support-en", "support-de"],
"+15555550123": ["assistant", "logger"]
}
}
How it works
Message flow
Incoming message arrives
A WhatsApp group or DM message comes in.
Route and admission
OpenClaw applies channel allowlists, group activation rules, and any configured ACP binding ownership.
Broadcast check
When no configured ACP binding owns the route, OpenClaw checks if the peer ID appears in broadcast.
If broadcast applies
- Every listed agent processes the message.
- Each agent gets its own session key and isolated context.
- Agents run in parallel (the default) or in sequence.
- Audio attachments get transcribed once before fan-out, so all agents share a single transcript instead of issuing separate STT calls.
If broadcast does not apply
OpenClaw sends the message along the ordinary route or the ACP session route chosen during routing.
Note
Broadcast groups do not override channel allowlists or group activation rules (mentions/commands/etc). They only change which agents execute when a message is eligible for processing.
Session isolation
Each agent within a broadcast group keeps fully separate:
- Session keys (
agent:alfred:whatsapp:group:120363...compared toagent:baerbel:whatsapp:group:120363...) - Conversation history (no agent sees another agent's replies)
- Workspace (separate sandboxes if those are set up)
- Tool access (distinct allow/deny lists)
- Memory/context (separate
IDENTITY.md,SOUL.md, and so on)
One deliberate exception exists: the group context buffer (recent group messages used for context) is shared per peer, so every broadcast agent sees the same context when triggered. It gets cleared once after the fan-out finishes.
This setup lets each agent carry different personalities, models, skills, and tool access (for example read-only versus read-write).
Example: isolated sessions
In group 120363403215116621@g.us with agents ["alfred", "baerbel"]:
Alfred's context
Session: agent:alfred:whatsapp:group:120363403215116621@g.us
History: [user message, alfred's previous responses]
Workspace: ~/openclaw-alfred/
Tools: read, write, exec
Baerbel's context
Session: agent:baerbel:whatsapp:group:120363403215116621@g.us
History: [user message, baerbel's previous responses]
Workspace: ~/openclaw-baerbel/
Tools: read only
Use cases
- Specialized agent teams: a dev group where
code-reviewer,security-auditor,test-generator, anddocs-checkereach address the same message from their own perspective. - Multi-language support: one support chat with
support-en,support-de,support-esreplying in their respective languages. - Quality assurance:
support-agentresponds whileqa-agentreviews and only chimes in when it spots problems. - Task automation:
task-tracker,time-logger, andreport-generatorall consume the same status update.
Best practices
1. Keep agents focused
Assign each agent one specific, clear duty (formatter, linter, tester) rather than a single generic "dev-helper" agent.
2. Use descriptive ids and names
{
"agents": {
"entries": {
"security-scanner": { "default": true, "name": "Security Scanner" },
"code-formatter": { "name": "Code Formatter" },
"test-generator": { "name": "Test Generator" }
}
}
}
3. Configure different tool access
{
"agents": {
"entries": {
"reviewer": {
"default": true,
"tools": { "allow": ["read", "exec"] }
},
"fixer": { "tools": { "allow": ["read", "write", "edit", "exec"] } }
}
}
}
reviewer is read-only. fixer has read and write access.
4. Monitor performance
When you have a large number of agents, stick with "strategy": "parallel" as the default, limit broadcast groups to only a few agents, and assign simpler models to the less complex agents for better speed.
5. Failures stay isolated
Each agent operates independently. If one fails, its error gets recorded in Broadcast agent <id> failed: ..., and the rest continue without being held up.
Compatibility
Providers
Right now, broadcast groups only function on the WhatsApp web channel. Any other channel will simply disregard the broadcast setting.
Routing
Broadcast groups work alongside existing routing:
{
"bindings": [
{
"match": { "channel": "whatsapp", "peer": { "kind": "group", "id": "GROUP_A" } },
"agentId": "alfred"
}
],
"broadcast": {
"GROUP_B": ["agent1", "agent2"]
}
}
GROUP_A: only alfred responds (normal routing).GROUP_B: agent1 AND agent2 respond (broadcast).
Note
Precedence:
broadcasttakes priority over ordinary route bindings. Configured ACP bindings (bindings[].type="acp") are exclusive: when one matches, OpenClaw dispatches to the configured ACP session instead of fan-out broadcast.
Troubleshooting
Agents not responding
Check:
- Agent IDs exist in
agents.entries(config validation rejects unknown ids). - Peer ID format is correct (group JID like
120363403215116621@g.us, or E.164 like+15551234567for DMs). - The message passed normal gating (mention/activation rules still apply).
Debug:
openclaw logs --follow | grep -i broadcast
A successful fan-out logs Broadcasting message to <n> agents (<strategy>).
Only one agent responding
Cause: the peer ID might be in ordinary route bindings but not broadcast, or it might match an exclusive configured ACP binding.
Fix: add ordinary route-bound peers to the broadcast config, or remove/change the configured ACP binding if fan-out broadcast is desired.
Performance issues
If slow with many agents: reduce the number of agents per group, use lighter models, and check sandbox startup time.
Examples
Example 1: Code review team
{
"broadcast": {
"strategy": "parallel",
"120363403215116621@g.us": [
"code-formatter",
"security-scanner",
"test-coverage",
"docs-checker"
]
},
"agents": {
"entries": {
"code-formatter": {
"default": true,
"workspace": "~/agents/formatter",
"tools": { "allow": ["read", "write"] }
},
"security-scanner": {
"workspace": "~/agents/security",
"tools": { "allow": ["read", "exec"] }
},
"test-coverage": {
"workspace": "~/agents/testing",
"tools": { "allow": ["read", "exec"] }
},
"docs-checker": { "workspace": "~/agents/docs", "tools": { "allow": ["read"] } }
}
}
}
One code snippet in the group produces four replies: formatting fixes, a security finding, a coverage gap, and a docs nit.
Example 2: Multi-language pipeline
{
"broadcast": {
"strategy": "sequential",
"+15555550123": ["detect-language", "translator-en", "translator-de"]
},
"agents": {
"entries": {
"detect-language": { "default": true, "workspace": "~/agents/lang-detect" },
"translator-en": { "workspace": "~/agents/translate-en" },
"translator-de": { "workspace": "~/agents/translate-de" }
}
}
}
API reference
Config schema
interface OpenClawConfig {
broadcast?: {
strategy?: "parallel" | "sequential";
[peerId: string]: string[];
};
}
Fields
-
strategy(parallel" | "sequential, default: parallel), How to process agents.parallelruns all agents simultaneously;sequentialruns them in array order. -
[peerId](string[]), WhatsApp group JID or E.164 phone number. Value is the array of agent IDs that should all process messages from that peer.
Limitations
- Max agents: no hard limit, but many agents (10+) can be slow.
- Shared context: agents do not see each other's responses (by design).
- Message ordering: parallel responses may arrive in any order.
- Rate limits: all replies come from one WhatsApp account, so every agent's reply counts toward the same WhatsApp rate limits.