Skip to main content

Discord

WednesdayAI connects to Discord via the Discord Bot API. Setup requires creating a Discord application, adding a bot to your server, and configuring the bot token.

Quick setup

1. Create a Discord application and bot:
  1. Go to the Discord Developer Portal
  2. Click New Application → give it a name
  3. In the sidebar, click BotAdd Bot
  4. Copy the bot token (click Reset Token to reveal it)
2. Enable required intents: In the Bot page, scroll to Privileged Gateway Intents and enable:
  • Message Content Intent (MESSAGE_CONTENT) — required for reading message content
  • Server Members Intent — recommended for user lookup
The Server Members intent also requires opting in via config: channels.discord.intents.guildMembers: true. Without this, the gateway does not request the GuildMembers intent even when enabled in the Portal.
Also ensure these standard (non-privileged) intents are active:
  • GUILD_MESSAGE_REACTIONS — required for reaction-based interactions
MESSAGE_CONTENT is a privileged intent. It must be enabled in the Discord Developer Portal for bots in 100+ servers.
3. Generate an invite URL and add the bot to your server:
  1. Go to OAuth2 → URL Generator
  2. Scopes: bot, applications.commands
  3. Bot Permissions: View Channels, Send Messages, Read Message History, Embed Links, Attach Files, Add Reactions
  4. Copy the URL and open it in your browser to add the bot
4. Configure the bot token:
# Set token securely via CLI (avoids putting it in the config file in plaintext)
openclaw config set channels.discord.token '"YOUR_BOT_TOKEN"' --json
openclaw config set channels.discord.enabled true --json
Or in ~/.openclaw/openclaw.json:
{
  channels: {
    discord: {
      enabled: true,
      token: "YOUR_BOT_TOKEN",   // or DISCORD_BOT_TOKEN env var
      dmPolicy: "pairing",
    },
  },
}
5. Configure server allowlist and start gateway:
{
  channels: {
    discord: {
      groupPolicy: "allowlist",
      guilds: {
        "YOUR_SERVER_ID": {
          requireMention: true,
          users: ["YOUR_USER_ID"],
        },
      },
    },
  },
}
Get your server ID: Server Settings → right-click server icon → Copy Server ID (requires Developer Mode: User Settings → Advanced → Developer Mode).
openclaw gateway run
openclaw pairing list discord
openclaw pairing approve discord <CODE>

Access control

DM policy

{
  channels: {
    discord: {
      dmPolicy: "pairing",     // pairing | allowlist | open | disabled
      allowFrom: ["user:987654321098765432"],  // Discord user IDs with user: prefix
    },
  },
}
Use user:<id> or <@id> format. Unquoted numeric literals are rejected by schema validation — IDs must be JSON strings. Bare quoted strings ("987654321098765432") are accepted, but the user: prefix is preferred for clarity.

Server (guild) policy

{
  channels: {
    discord: {
      groupPolicy: "allowlist",
      guilds: {
        "123456789012345678": {
          requireMention: true,                          // bot must be @mentioned
          users: ["987654321098765432"],                 // allowed user IDs
          roles: ["111222333444555666"],                 // allowed role IDs
          channels: {                                   // optional channel allowlist
            "555666777888999000": { allow: true },
            "111222333444000999": { allow: true, requireMention: false },
          },
        },
      },
    },
  },
}
requireMention: false lets the bot respond to all messages in allowed channels without needing an @mention.

Native slash commands

{
  commands: {
    native: "auto",   // enables native commands for Discord and Telegram
  },
}
Discord slash commands register at startup. If you change native: false, the gateway clears previously registered commands on next startup. Default slash command behavior: responses are ephemeral (only visible to the invoking user). Configure per command if needed.

Live streaming

{
  channels: {
    discord: {
      streaming: "partial",   // off | partial | block | progress
    },
  },
}
partial edits a single message in-place as tokens arrive. off disables streaming — bot shows typing then sends the complete response.

Thread support

channels:
  discord:
    threadBindings:
      enabled: true
      idleHours: 24
      maxAgeHours: 0
      spawnSubagentSessions: false
      spawnAcpSessions: false
KeyTypeDefaultDescription
threadBindings.enabledbooleantrueParticipate in threads
threadBindings.idleHoursinteger24Hours of inactivity before a thread is considered idle
threadBindings.maxAgeHoursinteger0Maximum thread age in hours (0 = disabled by default)
threadBindings.spawnSubagentSessionsbooleanfalseSpawn a subagent session per thread
threadBindings.spawnAcpSessionsbooleanfalseSpawn an ACP session per thread

Delivery settings

KeyTypeDefaultDescription
textChunkLimitinteger2000Maximum characters per outbound chunk (Discord’s per-message limit is 2000)
chunkModestring"length"length splits at character count; newline splits at paragraph boundaries
{ channels: { discord: { textChunkLimit: 2000, chunkMode: "length" } } }

Voice channels

Requires:
  • Native commands enabled (commands.native: "auto")
  • Bot permissions: Connect, Speak in voice channels
{
  channels: {
    discord: {
      voice: {
        enabled: true,
        autoJoin: [{ guildId: "123...", channelId: "456..." }],
        tts: { enabled: true },
        daveEncryption: true,              // enable DAVE E2E voice encryption (default: true)
        decryptionFailureTolerance: 24,    // hours before treating decryption failures as an error (default: 24)
      },
    },
  },
}
If you see DecryptionFailed(UnencryptedWhenPassthroughDisabled) errors in logs, this is a known upstream Discord/DAVE bug triggered when clients that don’t support DAVE encryption join the channel. If voice becomes unusable, set daveEncryption: false as a workaround. decryptionFailureTolerance (default 24 hours) controls how long transient failures are tolerated before being treated as a hard error.
Users join voice channels via /vc join (Discord native command only).

Forum channels

The bot can post to Discord forum channels. Send a message to the forum parent channel ID — the bot automatically creates a thread:
openclaw message send --channel discord --target "channel:<forumId>" --message "Title\n\nBody"
Or via the message thread create tool action in an agent.

Troubleshooting

  1. Verify Message Content Intent is enabled in the Developer Portal
  2. Verify the bot has “View Channels” and “Read Message History” permissions in the server
  3. Restart the gateway after enabling intents
Check the groupPolicy — if it is "allowlist", the guild must be in guilds map AND the sender must be in users or have an allowed roles entry. requireMention: false only removes the mention requirement; allowlist enforcement is separate.
Commands can take up to 1 hour to propagate globally. For testing, use guild-specific command registration (contact maintainer for config). Check openclaw logs --follow | grep "discord.*command" for registration errors.
Discord has a 3-second timeout on interaction acknowledgment. For slow tools, increase the event queue timeout:
{ channels: { discord: { accounts: { default: { eventQueue: { listenerTimeout: 300000 } } } } } }
The default is already 120 000 ms — use a value higher than that, e.g., 300 000 ms (5 min).