Discord relay.
Discord serves as a unified inbox for Concierge. Messages from any channel (email, WhatsApp, Instagram) can be forwarded to Discord, where you can read, reply, approve AI drafts, or drop messages, all without leaving Discord.
Bot Setup
- Go to the Discord Developer Portal
- Create a new application
- Under General Information, copy the Application ID and Public Key
- Under Bot, create a bot user and copy the Token
- Set these as Worker secrets:
wrangler secret put DISCORD_APPLICATION_ID wrangler secret put DISCORD_PUBLIC_KEY wrangler secret put DISCORD_BOT_TOKEN
Interaction Endpoint
In the Discord Developer Portal, under General Information, set the Interactions Endpoint URL to:
https://your-domain/discord/interactions
Discord will send a PING request to verify the endpoint. Concierge verifies all interactions using Ed25519 signature verification with the DISCORD_PUBLIC_KEY.
Inviting the Bot
Generate an invite URL with these permissions:
- Send Messages: for posting forwarded messages and embeds
- Use Slash Commands: for admin commands
- Embed Links: for rich message formatting
The invite URL format:
https://discord.com/api/oauth2/authorize?client_id=YOUR_APP_ID&permissions=2048&scope=bot%20applications.commands
Guild-to-Tenant Mapping
Each Discord server (guild) is linked to a tenant via a DiscordConfig stored in KV. This maps guild IDs to tenant IDs so slash commands and relay actions know which tenant's data to access.
Slash Commands
Concierge supports three slash commands:
/status
Shows an overview of the tenant's configuration:
- Number of WhatsApp accounts
- Number of Instagram accounts
- Configured email domains
- Email metrics for the last 7 days (action counts by type)
/domains
Manage email domains:
/domains list: list all configured domains/domains add <domain>: register a new domain/domains remove <domain>: remove a domain and its rules
/rules
View email routing rules:
/rules list <domain>: list all rules for a domain with status, priority, and action
For complex rule management (creating, editing, deleting rules), use the web admin panel.
Cross-Channel Relay
When a message from another channel is forwarded to Discord (e.g., via the Forward Discord email action), it arrives as a rich embed with action buttons:
- Reply: opens a modal for composing a response. The reply is sent back through the originating channel.
- Approve: sends an AI-generated draft (for AI Reply actions). Only shown when there is a draft.
- Drop: dismisses the message and cleans up the conversation context.
ConversationContext
When a message is forwarded to Discord, a ConversationContext is saved in KV. It stores:
- The Discord message and channel IDs
- The originating channel (email, WhatsApp, Instagram)
- The original sender and recipient
- Tenant and account identifiers
- Reply metadata needed to route the response back
- An optional AI draft (for AI Reply actions)
When you click Reply and submit text, Concierge looks up the ConversationContext, calls the appropriate channel adapter (email forward, WhatsApp API, Instagram API), and sends the reply to the original sender.
Relay Flow Example
- Email from
alice@external.comarrives atsupport@example.com - A routing rule with action Forward Discord matches
- The email content is posted to Discord channel
#inboxas an embed - A
ConversationContextis saved with the email details - You click Reply, type your response in the modal
- Concierge sends an email reply to
alice@external.comvia the email channel adapter - The relay is logged to the unified
messagestable
Interaction Types
Concierge handles four Discord interaction types:
| Type | Code | Handler |
|---|---|---|
| PING | 1 | Returns {"type": 1} for endpoint verification |
| APPLICATION_COMMAND | 2 | Dispatches to slash command handlers |
| MESSAGE_COMPONENT | 3 | Handles button clicks (Reply, Approve, Drop) |
| MODAL_SUBMIT | 5 | Handles reply text submitted from modals |