#18434: feat(discord): add broadcast group support for multi-agent fan-out
channel: discord
agents
size: L
Cluster:
Signal and Discord Fixes
## Summary
Port the existing WhatsApp broadcast pattern to Discord guild channels, enabling multiple agents to independently process the same message in a Discord channel.
## Motivation
Broadcast groups are a powerful feature for multi-agent setups where specialized agents (coder, reviewer, researcher, etc.) collaborate in the same channel. This is currently supported for WhatsApp but not Discord, despite Discord being a natural fit for project-based multi-agent workflows.
## Changes
### New: `src/discord/monitor/broadcast.ts`
- `maybeBroadcastDiscordMessage()` — checks `config.broadcast[channelId]` and fans out to all listed agents
- Only applies to guild/channel messages (never DMs)
- Rebuilds route per agent with correct `agentId`, `sessionKey`, and `mainSessionKey`
- Supports `parallel` (default) and `sequential` strategies
- Per-agent error handling — one agent failure doesn't block others
- Snapshots guild history before fan-out, clears once after all agents finish
### Modified: `src/discord/monitor/message-handler.ts`
- Imports and calls `maybeBroadcastDiscordMessage()` in both flush paths (single-message and debounced-batch)
- If broadcast returns `true`, skips normal single-agent processing
### Modified: `src/discord/monitor/message-handler.process.ts`
- Extended `processDiscordMessage()` signature with optional `opts` parameter:
- `guildHistory?: HistoryEntry[]` — use snapshotted history instead of live map
- `suppressGuildHistoryClear?: boolean` — prevent per-agent history clearing during broadcast
- Imported `HistoryEntry` type
## Config example
Uses the same `BroadcastConfig` type — no schema changes needed. Discord channel IDs work as peer IDs:
```json5
{
broadcast: {
strategy: "parallel",
"123456789012345678": ["coder", "reviewer", "researcher"],
"987654321098765432": ["pm", "coder", "qa"],
}
}
```
## Testing
- All 96 existing Discord monitor tests pass
- Zero TypeScript errors
- No changes to WhatsApp broadcast, config types, or zod schema
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Ports WhatsApp broadcast pattern to Discord, enabling multi-agent fan-out in guild channels. Each broadcast agent receives the same message with independent processing, snapshotted history, and per-agent identity via Discord webhooks.
**Key changes:**
- New `maybeBroadcastDiscordMessage()` function in `src/discord/monitor/broadcast.ts` checks `config.broadcast[channelId]` and fans out to configured agents
- Modified `processDiscordMessage()` to accept optional `guildHistory`, `suppressGuildHistoryClear`, and `agentIdentity` parameters for broadcast support
- Webhook delivery (`send.webhook.ts` + `webhook-cache.ts`) enables per-agent identity (username/avatar/emoji) for broadcast agents
- Guild history is snapshotted before broadcast and cleared once after all agents complete, preventing race conditions
- Supports both `parallel` (default) and `sequential` broadcast strategies with per-agent error isolation
**Implementation follows WhatsApp broadcast pattern** (`src/web/auto-reply/monitor/broadcast.ts`) with Discord-specific adaptations for webhook delivery and guild channel handling.
<h3>Confidence Score: 5/5</h3>
- Safe to merge - clean port of existing WhatsApp pattern with comprehensive test coverage and no breaking changes
- Implementation faithfully follows the proven WhatsApp broadcast pattern with proper error isolation, history snapshotting, and TypeScript type safety. The webhook delivery feature is well-encapsulated with fallback to standard delivery. All 96 existing Discord tests pass, and the PR includes dedicated webhook delivery tests. No schema changes required since `BroadcastConfig` already supports the pattern.
- No files require special attention - implementation is clean and follows established patterns
<sub>Last reviewed commit: 8741759</sub>
<!-- greptile_other_comments_section -->
<sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#14318: feat(discord): enforce outbound allowlist on send functions
by builtbyrobben · 2026-02-11
72.8%
#20186: fix(discord): thread mediaLocalRoots through reply delivery path
by pvoo · 2026-02-18
72.0%
#20078: feat(session): Add channelGroups config(optional config) for shared...
by demarlik01 · 2026-02-18
71.6%
#17254: fix(discord): intercept text-based slash commands instead of forwar...
by robbyczgw-cla · 2026-02-15
71.0%
#20594: feat(whatsapp): batch multi-image messages via debouncer
by arniesaha · 2026-02-19
71.0%
#23464: feat(synology-chat): add group/channel support
by druide67 · 2026-02-22
70.9%
#23158: discord: harden preflight/reply path against slow lookup latency
by danielstarman · 2026-02-22
70.8%
#17513: fix(discord): respect groupPolicy in channel config fallback (#4555)
by aronchick · 2026-02-15
70.8%
#15467: feat(messages): add debounceMedia option for inbound debouncing
by tangcruz · 2026-02-13
70.8%
#16736: fix: stagger multi-account channel startup to avoid Discord rate li...
by rm289 · 2026-02-15
70.6%