* feat(discord): restore gateway channel flow in wasm * chore(discord): bump channel version to 0.2.1 * fix(discord): address review feedback on gateway channel PR - Add #[serde(default)] to DiscordMessageMetadata for backward compat with old Option<String> serialized metadata - Restore mention polling alongside Gateway (on_poll processes gateway events first, then runs poll_for_mentions if configured) - Update on_respond to handle source_message_id with message_reference for mention-poll reply threading - Implement Gateway presence status: dnd before pairing, online after - Implement Gateway resume (OP 6) with session_id tracking, falling back to fresh identify on Invalid Session (OP 9) - Extract WebsocketSessionState and spawn_websocket_poll to reduce nesting in start_websocket_runtime - Simplify should_apply_dm_pairing tautology - Remove completed plan docs - Fix clippy items_after_test_module in extensions handler Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix(discord): address review findings in gateway channel PR - Fix gateway presence always showing "online" by filtering empty owner_id strings from workspace store reads - Fix interaction followup using POST instead of PATCH to /messages/@original, which left deferred "thinking" state unresolved - Restore mention-poll pagination (up to 5 pages of 100 messages) - Remove dead ed25519-dalek and hex dependencies from WASM crate - Remove unused _channel_id parameter from remember_processed_id - Clean up redundant let binding in send_pairing_reply Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix(discord): address second-round review findings - Log warning when gateway event queue JSON fails to deserialize instead of silently returning empty (zmanian review item 1) - Defer presence update from OP 10 Hello to after OP 0 READY, per Discord gateway protocol which requires READY before non-Identify commands (zmanian review item 2) - Add 0-25% random jitter to websocket reconnect backoff per Discord's reconnection recommendations (zmanian suggestion) - Extract WebsocketPollContext struct to replace 19-parameter spawn_websocket_poll function (zmanian suggestion) - Document intent bitmask 4609 = GUILDS + GUILD_MESSAGES + DIRECT_MESSAGES in capabilities JSON (zmanian suggestion) Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: zhyaoyu <[email protected]> Co-authored-by: [email protected] <[email protected]> Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Discord Channel for IronClaw
WASM channel for Discord integration - handle slash commands and button interactions via webhooks.
Features
- Slash Commands - Process Discord slash commands
- Button Interactions - Handle button clicks
- Thread Support - Respond in threads
- DM Support - Handle direct messages
Setup
-
Create a Discord Application at https://discord.com/developers/applications
-
Create a Bot and get the token
-
Set up Interactions URL to point to your IronClaw instance
-
Copy the Application ID and Public Key
-
Store in IronClaw secrets:
ironclaw secret set discord_bot_token YOUR_BOT_TOKENNote: The
discord_bot_tokensecret is used for Discord REST API calls. Interaction signature verification is performed inside the Discord channel module and uses the channel config fieldwebhook_secret(set this to your Discord app public key hex).
Discord Configuration
Register Slash Commands
curl -X POST \
-H "Authorization: Bot YOUR_BOT_TOKEN" \
-H "Content-Type: application/json" \
https://discord.com/api/v10/applications/YOUR_APP_ID/commands \
-d '{
"name": "ask",
"description": "Ask the AI agent",
"options": [{
"name": "question",
"description": "Your question",
"type": 3,
"required": true
}]
}'
Set Interactions Endpoint
In your Discord app settings, set:
- Interactions Endpoint URL:
https://your-ironclaw.com/webhook/discord
Usage Examples
Slash Command
User types: /ask question: What is the weather?
The agent receives:
User: @username
Content: /ask question: What is the weather?
Button Click
When a user clicks a button in a message, the agent receives:
User: @username
Content: [Button clicked] Original message content
Error Handling
If an internal error occurs (e.g., metadata serialization failure), the tool attempts to send an ephemeral message to the user:
❌ Internal Error: Failed to process command metadata.
Check the host logs for detailed error information.
Advanced Usage
Gateway Mode
The Discord channel now defaults to Discord Gateway transport for inbound message intake.
The bundled identify payload requests intents 4609, which expands to:
GUILDS(1)GUILD_MESSAGES(512)DIRECT_MESSAGES(4096)
Gateway DMs now follow the same pairing policy as webhook DMs. Unpaired users receive a pairing
instruction reply in the DM channel before the message is allowed through to the agent. If you
want stricter access control than pairing, set owner_id; that lock still applies to both
webhook and Gateway traffic.
Gateway presence simply reflects a successful authenticated Gateway connection and advertises
online. Pairing still controls whether DMs are allowed through to the agent, but it no longer
changes the visible Discord status.
Mention Polling
The Discord channel can also poll configured channels for @bot mentions.
Example channel config:
{
"require_signature_verification": true,
"webhook_secret": "YOUR_DISCORD_PUBLIC_KEY_HEX",
"polling_enabled": true,
"poll_interval_ms": 30000,
"mention_channel_ids": ["123456789012345678"],
"owner_id": null,
"dm_policy": "pairing",
"allow_from": []
}
Access Control
owner_id: when set, only that Discord user can interact with the bot.dm_policy:openallows all DMs;pairingrequires approval.allow_from: allowlist entries for DM pairing checks (*, user id, or username).- Gateway DMs respect
dm_policyand pairing just like webhook DMs.
Embeds
To send embeds, include an embeds array in the metadata_json field of the agent's response. The structure should match the Discord API embed object.
Troubleshooting
"Invalid Signature"
- Check that
webhook_secretis set to your Discord app public key hex in the Discord channel config. - Validation happens inside the Discord WASM channel.
- If
require_signature_verificationistrueandwebhook_secretis empty, the channel returns HTTP500with a configuration error.
"401 Unauthorized"
- Check that
discord_bot_tokenis set correctly in IronClaw secrets. - Ensure the bot is added to the server.
"Interaction Failed"
- The interaction might have timed out (Discord requires a response within 3 seconds).
- The
interactions_endpoint_urlmight be unreachable.
Building
cd channels-src/discord
cargo build --target wasm32-wasi --release
License
MIT/Apache-2.0