Multi-Channel Setup
How to enable multiple messaging channels simultaneously, link user identities across channels, use cross-channel approvals, and understand message normalization.
Multi-Channel Setup
CodeSpar agents can operate on multiple messaging channels simultaneously. The same agent responds on WhatsApp, Slack, Discord, and Telegram with a unified experience. Users can start a conversation on one channel and continue on another.
Overview
All channels connect to the same agent instance. Commands, permissions, and context are shared.
How to Enable Multiple Channels Simultaneously
Enabling multiple channels is simply a matter of setting the environment variables for each channel. All enabled channels run in parallel within the same CodeSpar process.
Step 1: Set Environment Variables
Add the configuration for each channel you want to enable in your .env file:
Step 2: Start CodeSpar
On startup, CodeSpar initializes each enabled channel and reports its status:
Step 3: Verify Channel Status
Check that all channels are connected:
Or via the API:
Common Configurations
Slack + WhatsApp (most common for mixed teams):
Slack only (engineering-focused teams):
Discord + Telegram (open-source communities):
Message Normalization
Every incoming message from any channel is normalized to a common NormalizedMessage format before being processed by the agent. This is the foundation of cross-channel consistency.
NormalizedMessage Type
How Each Channel Normalizes
| Platform | User ID Source | Display Name Source | @mention Handling |
|---|---|---|---|
| Slack | event.user (e.g., U1234ABCD) | Slack user profile | <@UBOTID> prefix stripped |
Phone number (e.g., 5511999990000) | WhatsApp profile name | Text matching against WHATSAPP_BOT_MENTION | |
| Discord | Discord user ID (e.g., 123456789012345678) | Discord username | <@BOTID> prefix stripped |
| Telegram | Telegram user ID (e.g., 987654321) | Telegram first + last name | /command or @botname prefix stripped |
After normalization, the agent processes every message identically regardless of its source channel. This means the same command syntax works everywhere:
Identity Linking
By default, CodeSpar treats each channel user as a separate identity. To enable cross-channel features, users need to link their identities by registering with the same display name from each channel.
How Identity Linking Works
Step 1: Register from First Channel
From Slack:
CodeSpar creates an identity:
Step 2: Register from Second Channel
From WhatsApp (same person, same name):
CodeSpar finds the existing identity with display name "John Silva" and links the WhatsApp channel:
Step 3: Register from Additional Channels
From Discord:
The Discord channel is added to the same identity. All three channels are now linked.
Verify Identity Linking
Check your identity from any channel:
Important Notes
- Name matching is case-sensitive.
John Silvaandjohn silvaare treated as different identities. - One identity per display name. If two different people register with the same name, their channels will be incorrectly linked. Use unique display names.
- Registration is per-organization in multi-tenant mode. The same person must register separately in each organization.
Cross-Channel Features
Once identities are linked, several powerful cross-channel capabilities become available.
Cross-Channel Approval
Approve an action from a different channel than where it was requested:
This works because:
- The approval token (
dp-a1b2c3) is global — not scoped to any channel - Bob's identity is resolved from his WhatsApp channel ID
- Bob's RBAC role is checked against the required permission
- Status updates are broadcast to all connected channels
Unified Notifications
When an event occurs (build failure, PR opened, deploy completed), the notification is sent to all connected channels. Users with linked identities are not notified twice — they receive the notification on their primary channel.
Consistent Permissions
RBAC roles apply across all channels. If John is a maintainer on Slack, he has maintainer permissions on WhatsApp, Discord, and Telegram too. Role changes apply instantly across all channels.
Unified Audit Trail
All actions are attributed to the resolved identity, regardless of which channel was used:
Example Scenario: Cross-Channel Development Flow
Here is a realistic scenario showing how multi-channel works in practice.
Setup
- Slack: Used by the engineering team for day-to-day development
- WhatsApp: Used by the team lead and CTO for approvals on the go
- Both channels are connected to the same CodeSpar agent
The Flow
1. Developer posts a task in Slack:
2. CI runs and passes. CodeSpar notifies both channels:
3. Developer requests deploy from Slack:
4. Team lead approves from WhatsApp (on mobile):
5. Both channels receive the deployment result:
Same @mention Syntax
The same @codespar mention syntax works on every channel:
| Channel | Syntax | Notes |
|---|---|---|
| Slack | @codespar deploy staging | Standard Slack mention |
@codespar deploy staging | Configurable via WHATSAPP_BOT_MENTION | |
| Discord | @codespar deploy staging | Uses Discord bot mention |
| Telegram | @codespar deploy staging | Uses Telegram bot username |
In direct messages (DMs), the @codespar prefix is optional on all channels.
Channel-Specific Behavior
While the core experience is identical, some channels have minor differences:
| Feature | Slack | Discord | Telegram | |
|---|---|---|---|---|
| Code blocks | Rendered with syntax highlighting | Monospace text | Rendered with syntax highlighting | Monospace text |
| Thread support | Messages in threads | Flat messages | Messages in threads | Flat messages |
| File attachments | Supported | Supported | Supported | Supported |
| Max message length | 40,000 chars | 4,096 chars | 2,000 chars | 4,096 chars |
| Emoji reactions | Supported | Not supported | Supported | Not supported |
For channels with shorter message limits (Discord at 2,000 chars), long outputs are automatically split into multiple messages. CodeSpar uses the channel's capabilities.maxMessageLength to determine where to split.
Reconnecting a Channel
If a channel disconnects, you can reconnect it without restarting CodeSpar:
Or check status and reconnect all disconnected channels:
Troubleshooting
Channel shows "disconnected"
- Check channel-specific environment variables are correctly set
- Verify the external service is running (Evolution API for WhatsApp, etc.)
- Try reconnecting via the API:
POST /api/channels/:name/reconnect - Check CodeSpar logs for connection errors
Identity not linking across channels
- Ensure the exact same display name is used on all channels (case-sensitive)
- Check identity resolution:
@codespar whoamifrom each channel - Verify via API:
GET /api/identity?channelType=slack&channelUserId=U1234 - In multi-tenant mode, ensure you are registering in the same organization
Notifications received on wrong channel
- Check that the user's identity is properly linked
- Notifications are sent to all connected channels by default
- Channel preferences are not yet configurable (coming soon)
Approval token not recognized on another channel
- Approval tokens are global — they work on any channel
- Verify the token has not expired (30-minute default)
- Verify the approving user has the required RBAC role
- Check that self-approval is not the issue (same identity requesting and approving)
Next Steps
- Command Reference — Commands work the same on all channels
- Security — RBAC roles and cross-channel identity
- Channel API — Programmatic channel management
- Deploy Pipeline — Cross-channel approval for deploys