Broadcast Groups: Multi-Agent Responses for Team-Based Workflows
Summary
Enable multiple agents to process and respond to the same message simultaneously, allowing teams of specialized agents with atomic tasks to work together in a single WhatsApp group using one phone number.
Problem
Currently, ClawdBot's routing uses first-match logic. When multiple bindings target the same peer (group/DM), only the first agent in the bindings array responds.
Example:
{
"routing": {
"bindings": [
{ "agentId": "alfred", "match": { "peer": { "id": "GROUP_A" } } },
{ "agentId": "baerbel", "match": { "peer": { "id": "GROUP_A" } } }
]
}
}
Current behavior: Only alfred responds ❌
Desired behavior: Both alfred AND baerbel respond ✅
This limits the ability to:
- Deploy specialized agents with different roles in the same group
- Scale to hundreds of micro-agents on a single phone number
- Create agent ensembles that collaborate on responses with atomic responsibilities
Proposed Solution
Add a new routing.broadcast config field that maps peer IDs to arrays of agent IDs:
{
"routing": {
"broadcast": {
"strategy": "parallel",
"120363403215116621@g.us": ["alfred", "baerbel", "assistant3"]
}
}
}
Result: All three agents process every message in this group, each with isolated sessions and contexts.
Use Cases
1. Specialized Agent Teams (Atomic Responsibilities)
Group: "Development Team"
Message: "Review this code: [snippet]"
Agents:
- CodeFormatter → "Fixed indentation and added type hints"
- SecurityScanner → "⚠️ SQL injection vulnerability in line 12"
- TestCoverage → "Missing tests for error cases"
- DocsChecker → "Missing docstring for function process_data"
Each agent has one atomic task and responds independently.
2. Multi-Language Support
Group: "International Support"
Message: "How do I reset my password?"
Agents:
- Agent_EN → Responds in English
- Agent_DE → Responds in German
- Agent_ES → Responds in Spanish
3. Quality Assurance Workflows
Group: "Customer Support"
Agents:
- SupportAgent → Provides answer to customer
- QAAgent → Reviews answer quality, only responds if issues found
4. Task Automation
Group: "Project Management"
Message: "Meeting from 2-3pm about Q1 planning"
Agents:
- TaskTracker → Creates task in database
- TimeLogger → Logs meeting time
- CalendarBot → Adds to calendar
- ReportGenerator → Updates weekly report
Key Benefits
✅ Minimal code changes - Only ~60 lines in core routing
✅ Backward compatible - Existing configs work unchanged
✅ Session isolation - Each agent has separate history, workspace, tools
✅ Flexible processing - Parallel (default) or sequential strategies
✅ Scalable - Enables 100s of specialized agents on one number
✅ Atomic tasks - Each agent focuses on one specific responsibility
✅ One phone number - All agents share the same WhatsApp account
Example Configuration
{
"routing": {
"defaultAgentId": "main",
"broadcast": {
"strategy": "parallel",
"120363403215116621@g.us": ["code-formatter", "security-scanner", "docs-checker"],
"+15555550123": ["support-en", "support-de", "support-es"]
},
"agents": {
"code-formatter": {
"name": "Code Formatter",
"workspace": "/path/to/formatter",
"sandbox": { "mode": "all" },
"tools": { "allow": ["read", "write"] }
},
"security-scanner": {
"name": "Security Scanner",
"workspace": "/path/to/security",
"sandbox": { "mode": "all" },
"tools": { "allow": ["read", "bash"] }
},
"docs-checker": {
"name": "Documentation Checker",
"workspace": "/path/to/docs",
"sandbox": { "mode": "all" },
"tools": { "allow": ["read"] }
}
}
}
}
Processing Strategies
Parallel (Default)
All agents process simultaneously:
{
"routing": {
"broadcast": {
"strategy": "parallel",
"GROUP_ID": ["agent1", "agent2", "agent3"]
}
}
}
Uses Promise.allSettled() - fastest, all agents work at once.
Sequential
Agents process one after another:
{
"routing": {
"broadcast": {
"strategy": "sequential",
"GROUP_ID": ["agent1", "agent2", "agent3"]
}
}
}
Agent2 waits for Agent1 to finish, etc.
Session Isolation
Each agent in a broadcast group maintains completely separate:
- Session keys:
agent:alfred:whatsapp:group:... vs agent:baerbel:whatsapp:group:...
- Conversation history: Doesn't see other agents' messages
- Workspace: Separate sandboxes if configured
- Tool access: Different allow/deny lists
- Memory: Separate IDENTITY.md, SOUL.md, etc.
- Models: Can use different Claude versions (Opus vs Sonnet)
This allows each agent to have different personalities, tool access, and responsibilities.
Implementation Approach
Minimal Code Changes (~60 lines)
File: src/web/auto-reply.ts
After routing resolution, check for broadcast groups:
const route = resolveAgentRoute({ cfg, provider, accountId, peer });
// NEW: Check for broadcast group
const broadcastAgents = cfg.routing?.broadcast?.[peerId];
if (broadcastAgents && Array.isArray(broadcastAgents) && broadcastAgents.length > 0) {
const strategy = cfg.routing?.broadcast?.strategy || "parallel";
const processForAgent = (agentId: string) => {
const agentRoute = {
...route,
agentId: normalizeAgentId(agentId),
sessionKey: buildAgentPeerSessionKey({ agentId, provider, peer }),
mainSessionKey: buildAgentMainSessionKey({ agentId }),
};
return processMessage(msg, agentRoute).catch(err => {
log.error(`Broadcast agent ${agentId} failed: ${err}`);
});
};
if (strategy === "sequential") {
for (const agentId of broadcastAgents) await processForAgent(agentId);
} else {
await Promise.allSettled(broadcastAgents.map(processForAgent));
}
return;
}
// Existing single-agent logic
return processMessage(msg, route);
Config Types: src/config/types.ts
export type RoutingConfig = {
// ... existing fields ...
broadcast?: {
strategy?: "parallel" | "sequential";
[peerId: string]: string[] | "parallel" | "sequential";
};
};
Similar changes needed for:
- Telegram (
src/telegram/bot.ts)
- Discord (
src/discord/monitor.ts)
- Slack (
src/slack/monitor.ts)
Real-World Impact
This enables scaling to hundreds of specialized micro-agents on a single phone number:
Instead of: 1 general-purpose agent that does everything
Deploy:
- 10 agents for code review (formatter, linter, security, docs, tests, performance, accessibility, i18n, best-practices, deprecations)
- 5 agents for customer support (EN, DE, ES, FR, IT)
- 8 agents for project management (tasks, time, calendar, reports, notifications, reminders, standup, retro)
Each agent:
- Has one atomic responsibility
- Can be developed independently
- Can be tested in isolation
- Can be enabled/disabled individually
- Can use different models (cheap Haiku for simple tasks, Opus for complex)
- Runs in its own sandbox
All on one WhatsApp number. 📱
Alternatives Considered
1. Multi-Agent Bindings
{
"bindings": [{
"agentId": "alfred",
"multiAgent": ["baerbel"],
"match": { ... }
}]
}
Rejected: More invasive, requires changing routing core logic.
2. Virtual Account IDs
Create fake accountIds like cyberheld-alfred, cyberheld-baerbel.
Rejected: Doesn't work - incoming message has only ONE accountId from WhatsApp.
3. Agent-to-Agent via sessions_send
First agent manually triggers others using tool calls.
Rejected:
- Not transparent (agent must know about others)
- Extra latency (sequential tool calls)
- Complex orchestration logic
- Agent must decide who to call
Breaking Changes
None. This is purely additive:
- New optional
routing.broadcast config field
- Existing configs continue to work unchanged
- If
broadcast is not configured, behavior is identical to current
- Broadcast takes precedence over bindings (explicit configuration wins)
Testing Plan
Unit tests:
Integration tests:
Manual testing:
Documentation
Would include:
docs/broadcast-groups.md - Complete feature guide
- Configuration examples
- Use cases with real-world examples
- Best practices (keep agents focused, max 10 agents per group, etc.)
- Troubleshooting guide
- API reference
Future Enhancements
Potential follow-ups:
Questions
- Should there be a hard limit on max agents per broadcast group? (e.g., 10)
- Should agents see each other's responses in the context? (Currently no - isolated sessions)
- Who sends the ACK reaction (👀) in groups? (Proposal: first agent in array)
- Should we add metrics/logging for broadcast performance?
Related
- Multi-agent routing:
docs/multi-agent-sandbox-tools.md
- Session management:
docs/sessions.md
- Current routing code:
src/routing/resolve-route.ts
Labels: enhancement, routing, multi-agent
Priority: Medium-High
Effort: ~2-3 days
Broadcast Groups: Multi-Agent Responses for Team-Based Workflows
Summary
Enable multiple agents to process and respond to the same message simultaneously, allowing teams of specialized agents with atomic tasks to work together in a single WhatsApp group using one phone number.
Problem
Currently, ClawdBot's routing uses first-match logic. When multiple bindings target the same peer (group/DM), only the first agent in the bindings array responds.
Example:
{ "routing": { "bindings": [ { "agentId": "alfred", "match": { "peer": { "id": "GROUP_A" } } }, { "agentId": "baerbel", "match": { "peer": { "id": "GROUP_A" } } } ] } }Current behavior: Only
alfredresponds ❌Desired behavior: Both
alfredANDbaerbelrespond ✅This limits the ability to:
Proposed Solution
Add a new
routing.broadcastconfig field that maps peer IDs to arrays of agent IDs:{ "routing": { "broadcast": { "strategy": "parallel", "120363403215116621@g.us": ["alfred", "baerbel", "assistant3"] } } }Result: All three agents process every message in this group, each with isolated sessions and contexts.
Use Cases
1. Specialized Agent Teams (Atomic Responsibilities)
Each agent has one atomic task and responds independently.
2. Multi-Language Support
3. Quality Assurance Workflows
4. Task Automation
Key Benefits
✅ Minimal code changes - Only ~60 lines in core routing
✅ Backward compatible - Existing configs work unchanged
✅ Session isolation - Each agent has separate history, workspace, tools
✅ Flexible processing - Parallel (default) or sequential strategies
✅ Scalable - Enables 100s of specialized agents on one number
✅ Atomic tasks - Each agent focuses on one specific responsibility
✅ One phone number - All agents share the same WhatsApp account
Example Configuration
{ "routing": { "defaultAgentId": "main", "broadcast": { "strategy": "parallel", "120363403215116621@g.us": ["code-formatter", "security-scanner", "docs-checker"], "+15555550123": ["support-en", "support-de", "support-es"] }, "agents": { "code-formatter": { "name": "Code Formatter", "workspace": "/path/to/formatter", "sandbox": { "mode": "all" }, "tools": { "allow": ["read", "write"] } }, "security-scanner": { "name": "Security Scanner", "workspace": "/path/to/security", "sandbox": { "mode": "all" }, "tools": { "allow": ["read", "bash"] } }, "docs-checker": { "name": "Documentation Checker", "workspace": "/path/to/docs", "sandbox": { "mode": "all" }, "tools": { "allow": ["read"] } } } } }Processing Strategies
Parallel (Default)
All agents process simultaneously:
{ "routing": { "broadcast": { "strategy": "parallel", "GROUP_ID": ["agent1", "agent2", "agent3"] } } }Uses
Promise.allSettled()- fastest, all agents work at once.Sequential
Agents process one after another:
{ "routing": { "broadcast": { "strategy": "sequential", "GROUP_ID": ["agent1", "agent2", "agent3"] } } }Agent2 waits for Agent1 to finish, etc.
Session Isolation
Each agent in a broadcast group maintains completely separate:
agent:alfred:whatsapp:group:...vsagent:baerbel:whatsapp:group:...This allows each agent to have different personalities, tool access, and responsibilities.
Implementation Approach
Minimal Code Changes (~60 lines)
File:
src/web/auto-reply.tsAfter routing resolution, check for broadcast groups:
Config Types:
src/config/types.tsSimilar changes needed for:
src/telegram/bot.ts)src/discord/monitor.ts)src/slack/monitor.ts)Real-World Impact
This enables scaling to hundreds of specialized micro-agents on a single phone number:
Instead of: 1 general-purpose agent that does everything
Deploy:
Each agent:
All on one WhatsApp number. 📱
Alternatives Considered
1. Multi-Agent Bindings
{ "bindings": [{ "agentId": "alfred", "multiAgent": ["baerbel"], "match": { ... } }] }Rejected: More invasive, requires changing routing core logic.
2. Virtual Account IDs
Create fake accountIds like
cyberheld-alfred,cyberheld-baerbel.Rejected: Doesn't work - incoming message has only ONE accountId from WhatsApp.
3. Agent-to-Agent via
sessions_sendFirst agent manually triggers others using tool calls.
Rejected:
Breaking Changes
None. This is purely additive:
routing.broadcastconfig fieldbroadcastis not configured, behavior is identical to currentTesting Plan
Unit tests:
routing.broadcastIntegration tests:
Manual testing:
Documentation
Would include:
docs/broadcast-groups.md- Complete feature guideFuture Enhancements
Potential follow-ups:
Questions
Related
docs/multi-agent-sandbox-tools.mddocs/sessions.mdsrc/routing/resolve-route.tsLabels: enhancement, routing, multi-agent
Priority: Medium-High
Effort: ~2-3 days