Files
openclaw/docs/channels/broadcast-groups.md
Andy Ye 8549a203d4 Honor WhatsApp configured ACP bindings (#92513)
Merged via squash.

Prepared head SHA: 665080f482
Co-authored-by: TurboTheTurtle <35905412+TurboTheTurtle@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr
2026-06-13 18:09:22 -03:00

13 KiB

summary, read_when, status, title, sidebarTitle
summary read_when status title sidebarTitle
Broadcast a WhatsApp message to multiple agents
Configuring broadcast groups
Debugging multi-agent replies in WhatsApp
experimental Broadcast groups Broadcast groups
**Status:** Experimental. Added in 2026.1.9.

Overview

Broadcast Groups enable multiple agents to process and respond to the same message simultaneously. This allows you to create specialized agent teams that work together in a single WhatsApp group or DM — all using one phone number.

Current scope: WhatsApp only (web channel).

Broadcast groups are evaluated after channel allowlists and group activation rules. In WhatsApp groups, this means broadcasts happen when OpenClaw would normally reply (for example: on mention, depending on your group settings).

Use cases

Deploy multiple agents with atomic, focused responsibilities:
```
Group: "Development Team"
Agents:
  - CodeReviewer (reviews code snippets)
  - DocumentationBot (generates docs)
  - SecurityAuditor (checks for vulnerabilities)
  - TestGenerator (suggests test cases)
```

Each agent processes the same message and provides its specialized perspective.
``` Group: "International Support" Agents: - Agent_EN (responds in English) - Agent_DE (responds in German) - Agent_ES (responds in Spanish) ``` ``` Group: "Customer Support" Agents: - SupportAgent (provides answer) - QAAgent (reviews quality, only responds if issues found) ``` ``` Group: "Project Management" Agents: - TaskTracker (updates task database) - TimeLogger (logs time spent) - ReportGenerator (creates summaries) ```

Configuration

Basic setup

Add a top-level broadcast section (next to bindings). Keys are WhatsApp peer ids:

  • group chats: group JID (e.g. 120363403215116621@g.us)
  • DMs: E.164 phone number (e.g. +15551234567)
{
  "broadcast": {
    "120363403215116621@g.us": ["alfred", "baerbel", "assistant3"]
  }
}

Result: When OpenClaw would reply in this chat, it will run all three agents.

Processing strategy

Control how agents process messages:

All agents process simultaneously:
```json
{
  "broadcast": {
    "strategy": "parallel",
    "120363403215116621@g.us": ["alfred", "baerbel"]
  }
}
```
Agents process in order (one waits for previous to finish):
```json
{
  "broadcast": {
    "strategy": "sequential",
    "120363403215116621@g.us": ["alfred", "baerbel"]
  }
}
```

Complete example

{
  "agents": {
    "list": [
      {
        "id": "code-reviewer",
        "name": "Code Reviewer",
        "workspace": "/path/to/code-reviewer",
        "sandbox": { "mode": "all" }
      },
      {
        "id": "security-auditor",
        "name": "Security Auditor",
        "workspace": "/path/to/security-auditor",
        "sandbox": { "mode": "all" }
      },
      {
        "id": "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

A WhatsApp group or DM message arrives. OpenClaw applies channel allowlists, group activation rules, and configured ACP binding ownership. If no configured ACP binding owns the route, OpenClaw checks whether the peer ID is in `broadcast`. - All listed agents process the message. - Each agent has its own session key and isolated context. - Agents process in parallel (default) or sequentially. OpenClaw dispatches the ordinary route or the configured ACP session route selected during routing. Broadcast groups do not bypass channel allowlists or group activation rules (mentions/commands/etc). They only change _which agents run_ when a message is eligible for processing.

Session isolation

Each agent in a broadcast group maintains completely separate:

  • Session keys (agent:alfred:whatsapp:group:120363... vs agent:baerbel:whatsapp:group:120363...)
  • Conversation history (agent doesn't see other agents' messages)
  • Workspace (separate sandboxes if configured)
  • Tool access (different allow/deny lists)
  • Memory/context (separate IDENTITY.md, SOUL.md, etc.)
  • Group context buffer (recent group messages used for context) is shared per peer, so all broadcast agents see the same context when triggered

This allows each agent to have:

  • Different personalities
  • Different tool access (e.g., read-only vs. read-write)
  • Different models (e.g., opus vs. sonnet)
  • Different skills installed

Example: isolated sessions

In group 120363403215116621@g.us with agents ["alfred", "baerbel"]:

``` Session: agent:alfred:whatsapp:group:120363403215116621@g.us History: [user message, alfred's previous responses] Workspace: /Users/user/openclaw-alfred/ Tools: read, write, exec ``` ``` Session: agent:baerbel:whatsapp:group:120363403215116621@g.us History: [user message, baerbel's previous responses] Workspace: /Users/user/openclaw-baerbel/ Tools: read only ```

Best practices

Design each agent with a single, clear responsibility:
```json
{
  "broadcast": {
    "DEV_GROUP": ["formatter", "linter", "tester"]
  }
}
```

✅ **Good:** Each agent has one job. ❌ **Bad:** One generic "dev-helper" agent.
Make it clear what each agent does:
```json
{
  "agents": {
    "security-scanner": { "name": "Security Scanner" },
    "code-formatter": { "name": "Code Formatter" },
    "test-generator": { "name": "Test Generator" }
  }
}
```
Give agents only the tools they need:
```json
{
  "agents": {
    "reviewer": {
      "tools": { "allow": ["read", "exec"] }
    },
    "fixer": {
      "tools": { "allow": ["read", "write", "edit", "exec"] }
    }
  }
}
```

`reviewer` is read-only. `fixer` can read and write.
With many agents, consider:
- Using `"strategy": "parallel"` (default) for speed
- Limiting broadcast groups to 5-10 agents
- Using faster models for simpler agents
Agents fail independently. One agent's error doesn't block others:
```
Message → [Agent A ✓, Agent B ✗ error, Agent C ✓]
Result: Agent A and C respond, Agent B logs error
```

Compatibility

Providers

Broadcast groups currently work with:

  • WhatsApp (implemented)
  • 🚧 Telegram (planned)
  • 🚧 Discord (planned)
  • 🚧 Slack (planned)

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).
**Precedence:** `broadcast` takes 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

**Check:**
1. Agent IDs exist in `agents.list`.
2. Peer ID format is correct (e.g., `120363403215116621@g.us`).
3. Agents are not in deny lists.

**Debug:**

```bash
tail -f ~/.openclaw/logs/gateway.log | grep broadcast
```
**Cause:** 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 broadcast config, or remove/change the configured ACP binding if fan-out broadcast is desired.
If slow with many agents:
- Reduce number of agents per group.
- Use lighter models (sonnet instead of opus).
- Check sandbox startup time.

Examples

```json { "broadcast": { "strategy": "parallel", "120363403215116621@g.us": [ "code-formatter", "security-scanner", "test-coverage", "docs-checker" ] }, "agents": { "list": [ { "id": "code-formatter", "workspace": "~/agents/formatter", "tools": { "allow": ["read", "write"] } }, { "id": "security-scanner", "workspace": "~/agents/security", "tools": { "allow": ["read", "exec"] } }, { "id": "test-coverage", "workspace": "~/agents/testing", "tools": { "allow": ["read", "exec"] } }, { "id": "docs-checker", "workspace": "~/agents/docs", "tools": { "allow": ["read"] } } ] } } ```
**User sends:** Code snippet.

**Responses:**

- code-formatter: "Fixed indentation and added type hints"
- security-scanner: "⚠️ SQL injection vulnerability in line 12"
- test-coverage: "Coverage is 45%, missing tests for error cases"
- docs-checker: "Missing docstring for function `process_data`"
```json { "broadcast": { "strategy": "sequential", "+15555550123": ["detect-language", "translator-en", "translator-de"] }, "agents": { "list": [ { "id": "detect-language", "workspace": "~/agents/lang-detect" }, { "id": "translator-en", "workspace": "~/agents/translate-en" }, { "id": "translator-de", "workspace": "~/agents/translate-de" } ] } } ```

API reference

Config schema

interface OpenClawConfig {
  broadcast?: {
    strategy?: "parallel" | "sequential";
    [peerId: string]: string[];
  };
}

Fields

How to process agents. `parallel` runs all agents simultaneously; `sequential` runs them in array order. WhatsApp group JID, E.164 number, or other peer ID. Value is the array of agent IDs that should process messages.

Limitations

  1. Max agents: No hard limit, but 10+ agents may be slow.
  2. Shared context: Agents don't see each other's responses (by design).
  3. Message ordering: Parallel responses may arrive in any order.
  4. Rate limits: All agents count toward WhatsApp rate limits.

Future enhancements

Planned features:

  • Shared context mode (agents see each other's responses)
  • Agent coordination (agents can signal each other)
  • Dynamic agent selection (choose agents based on message content)
  • Agent priorities (some agents respond before others)