OpenClaw

OpenClaw Discord Channel

Messaging
Easy

Connect OpenClaw to Discord using the discord.js Bot Gateway API. Create a Discord bot in the Developer Portal, enable the required intents, invite the bot to your server, and your AI assistant is live on Discord. Supports direct messages, guild channel conversations, reactions, threads, slash commands, and rich media. One of the easiest channels to set up.

Quick Info
DifficultyEasy
CategoryMessaging
Features Supported5 / 6

Discord Supported Features

Text Messages

Supported

Media & Files

Supported

Reactions

Supported

Threads

Supported

Voice Messages

Not Supported

Group Chat

Supported

Discord Prerequisites

  • A Discord account with access to the Discord Developer Portal
  • A Bot Token from Discord Developer Portal (Applications → New Application → Bot)
  • Message Content Intent enabled in Privileged Gateway Intents
  • OpenClaw Gateway running and configured

Discord Quick Setup

1

Create Discord bot and enable intents

Go to the Discord Developer Portal (discord.com/developers), create a New Application, add a Bot user, and copy the Bot Token. Under Privileged Gateway Intents, enable 'Message Content Intent' (required) and 'Server Members Intent' (recommended for member lookups).

2

Add Discord channel config

Add the Discord channel configuration to ~/.openclaw/openclaw.json. Set the token (or use DISCORD_BOT_TOKEN environment variable) and configure dm.policy to control who can DM the bot.

3

Invite bot to server and test

In the Developer Portal, go to OAuth2 → URL Generator. Select scopes 'bot' and 'applications.commands'. Choose permissions: View Channels, Send Messages, Read Message History, Embed Links, Attach Files, Add Reactions. Open the generated URL to invite the bot to your server. Send '@BotName hello' to test.

Discord Configuration Example

config.json
{
  "channels": {
    "discord": {
      "enabled": true,
      "token": "YOUR_DISCORD_BOT_TOKEN",
      "dm": {
        "policy": "pairing"
      }
    }
  }
}

Discord Deep Dive

Architecture Overview

OpenClaw connects to Discord through the discord.js library — a powerful Node.js module for interacting with the Discord Bot Gateway API. The bot connects via WebSocket to Discord's gateway, receiving real-time events for messages, reactions, and other interactions. Session routing differs by context: direct message conversations collapse into the agent's main session (agent:main:main), while guild channel conversations create isolated sessions per channel (agent:<agentId>:discord:channel:<channelId>). Slash commands get their own isolated sessions per user. Group DMs are disabled by default.
The bot token can be set via the DISCORD_BOT_TOKEN environment variable or in your config under channels.discord.token.
Enable Developer Mode in Discord (User Settings → Advanced) to easily copy Guild IDs, Channel IDs, and User IDs by right-clicking.

Creating Your Bot

Setting up a Discord bot requires creating an application in the Discord Developer Portal: 1. Go to discord.com/developers/applications 2. Click 'New Application' and name it 3. Navigate to the Bot section and click 'Add Bot' 4. Copy the Bot Token — save it securely 5. Under Privileged Gateway Intents, enable: • Message Content Intent (required — without this, the bot cannot read message content) • Server Members Intent (recommended for member/role lookups) 6. Go to OAuth2 → URL Generator 7. Select scopes: 'bot' and 'applications.commands' 8. Select permissions: View Channels, Send Messages, Read Message History, Embed Links, Attach Files, Add Reactions 9. Copy the generated URL and open it to invite the bot to your server
Avoid granting Administrator permission unless you're debugging. Use the minimum required permissions for better security.
Keep your bot token secret. Anyone with the token can control your bot. If compromised, regenerate it in the Developer Portal.
The Message Content Intent is required for the bot to read message text. Without it, the bot will connect but cannot see any message content.

DM Policies

DM (Direct Message) policies control who can interact with your AI assistant in private chats. OpenClaw supports four policies: • pairing (default) — Unknown senders receive a time-limited pairing code (expires after 1 hour). Approve via 'openclaw pairing approve discord <code>' in your terminal. Once approved, they can chat freely. • allowlist — Only user IDs explicitly listed in dm.allowFrom can message the bot. Everyone else is silently ignored. • open — Anyone who DMs the bot gets a response. Requires dm.allowFrom=["*"] to function. Use with caution. • disabled — DM handling is completely turned off. The bot will not respond to any direct messages.
openclaw.json
{
  "channels": {
    "discord": {
      "dm": {
        "policy": "pairing",
        "allowFrom": ["123456789012345678"]
      }
    }
  }
}

Guild Channel Configuration

Guild (server) channels are where most Discord interactions happen. OpenClaw provides fine-grained control over which servers and channels the bot operates in. Top-level settings: • groupPolicy — Controls guild channel handling. Options: open (respond in all channels), disabled (ignore all guild messages), allowlist (restrict to configured guilds) Per-guild configuration lets you customize behavior for each server: • slug — Friendly identifier for display • users — User allowlist (IDs or names) • requireMention — Whether the bot needs to be @mentioned • reactionNotifications — Control reaction event notifications (off, own, all, allowlist) Per-channel rules allow even finer control within a guild: • allow — Enable/disable the channel • requireMention — Channel-specific mention gating • users — Channel user allowlist • skills — Skill filter (omit for all) • systemPrompt — Extra context instructions for the AI
openclaw.json
{
  "channels": {
    "discord": {
      "groupPolicy": "open",
      "guilds": {
        "YOUR_GUILD_ID": {
          "slug": "my-server",
          "requireMention": true,
          "channels": {
            "CHANNEL_ID": {
              "allow": true,
              "requireMention": false,
              "systemPrompt": "You are a helpful assistant in this channel."
            }
          }
        }
      }
    }
  }
}
Enable Developer Mode in Discord (User Settings → Advanced) to right-click and copy Guild, Channel, and User IDs.
Per-channel systemPrompt lets you give the AI different personalities or instructions for different channels.

Reactions & Acknowledgments

OpenClaw supports Discord's reaction system for acknowledging messages and receiving reaction notifications. Acknowledgment reactions: The bot can react to incoming messages with an emoji to signal it's processing. Configure via messages.ackReaction. The reaction can be automatically removed after the AI responds using messages.removeAckAfterReply. Reaction notifications: Configure per-guild which reactions trigger agent notifications: • off — No reaction notifications • own — Only reactions to bot messages • all — All reactions in the channel • allowlist — Reactions from allowed users only
openclaw.json
{
  "channels": {
    "discord": {
      "messages": {
        "ackReaction": "👀",
        "removeAckAfterReply": true
      },
      "guilds": {
        "GUILD_ID": {
          "reactionNotifications": "own"
        }
      }
    }
  }
}

Message Formatting & Chunking

Discord has a 2,000-character message limit. OpenClaw automatically handles long AI responses by chunking them. Key settings: • textChunkLimit — Maximum characters per message chunk (default: 2000) • maxLinesPerMessage — Soft line limit per message (default: 17) • chunkMode — Split strategy: 'length' (default, hard character limit) or 'newline' (split at paragraph boundaries) The bot also injects context from recent guild messages (configurable via historyLimit, default 20 messages) so the AI can participate naturally in ongoing conversations.
openclaw.json
{
  "channels": {
    "discord": {
      "textChunkLimit": 2000,
      "chunkMode": "newline",
      "historyLimit": 20
    }
  }
}

Slash Commands & Tool Actions

OpenClaw registers native Discord slash commands automatically when the bot starts (default: auto, configurable via commands.native). Setting commands.native to false clears previously registered commands. Commands follow the same allowlist rules as messages — unauthorized users see commands in Discord UI but receive a 'not authorized' reply. Session isolation: Slash commands use separate session keys (agent:<agentId>:discord:slash:<userId>) rather than the shared main session, providing per-user isolation. The agent supports a rich set of tool actions for interacting with Discord: • Messaging — Send, edit, delete, pin/unpin messages, search messages • Threads — Create threads, list threads, reply in threads • Reactions — React to messages, list reactions • Moderation — Timeout, kick, ban members (disabled by default) • Server info — Member info, role info, channel info, emoji list • Presence — Set bot status (disabled by default) Reply tags allow models to control message threading: • [[reply_to_current]] — Thread reply to the triggering message • [[reply_to:<id>]] — Thread reply to a specific message ID
Make sure the 'applications.commands' scope is included in your OAuth2 invite URL for slash commands to appear.
Moderation tools (timeout, kick, ban) and role management are disabled by default. Enable them explicitly in your config if needed.

Media & File Handling

OpenClaw supports sending and receiving media files through Discord. The default maximum upload size is 8 MB (configurable via mediaMaxMb). Supported operations: • Receive image and file attachments from users • Send images, documents, and other files in responses • Embed links with rich previews The bot requires the 'Attach Files' permission to send media in guild channels.
Discord's file size limit depends on the server's boost level. The default is 8 MB for non-boosted servers, 50 MB for Level 2, and 100 MB for Level 3.

PluralKit Integration

OpenClaw optionally supports PluralKit proxy message resolution, allowing the bot to correctly identify messages from PluralKit systems. When enabled, the bot resolves proxied messages back to their original PluralKit member identity. This is useful for communities that use PluralKit for system/plural message routing. Key details: • Use pk:<memberId> prefix in allowlists to match PluralKit members • Member names are also matched by display name or slug • Lookups use the original Discord message ID within PluralKit's 30-minute window • If lookup fails, proxied messages are treated as bot messages (dropped unless allowBots=true)
openclaw.json
{
  "channels": {
    "discord": {
      "pluralkit": {
        "enabled": true,
        "token": "pk_live_..."
      }
    }
  }
}
Private PluralKit systems require a pluralkit.token to resolve members. Without it, proxied messages are treated as bot messages and dropped.
Use the pk:<memberId> prefix in allowlists for precise matching of PluralKit members.

Exec Approvals (Button UI)

Discord supports a button-based approval flow for exec operations. When enabled, the bot sends interactive buttons (Allow once, Always allow, Deny) to designated approvers in DMs. This replaces the command-based /approve flow with a more user-friendly interface. Requirements: • execApprovals.enabled must be true • Approver's Discord user ID must be listed in execApprovals.approvers • Optional agentFilter and sessionFilter arrays restrict which agents/sessions trigger approvals Note: The /approve <id> command is only used for forwarded approvals. Discord button UI supersedes command-based approvals for direct interactions.
openclaw.json
{
  "channels": {
    "discord": {
      "execApprovals": {
        "enabled": true,
        "approvers": ["USER_ID_1", "USER_ID_2"],
        "agentFilter": [],
        "sessionFilter": []
      }
    }
  }
}
If approval buttons don't appear or you see 'unknown approval id' errors, verify that the user ID is listed in execApprovals.approvers and that execApprovals.enabled is true.

Action Gates

OpenClaw provides fine-grained control over which Discord tool actions the agent can perform. Actions are gated via channels.discord.actions.<action> (true/false). Enabled by default: • reactions, stickers, emojiUploads, stickerUploads, polls, permissions, messages, threads, pins, search, memberInfo, roleInfo, channelInfo, voiceStatus, events, channels Disabled by default: • roles — Role management (assign/remove roles) • moderation — Timeout, kick, ban members • presence — Set bot status/activity Disable specific actions to reduce the bot's capabilities and limit risk. For example, set channels.discord.actions.moderation=false to ensure the agent can never kick or ban members.
Follow the principle of least privilege: only enable actions that your use case actually requires.
Per-guild and per-channel tool overrides are available via guilds.<id>.tools and guilds.<id>.channels.<id>.tools for more granular control.

Allowlist Resolution & Matching

OpenClaw supports multiple formats for specifying users and channels in allowlists: • Numeric IDs (preferred) — e.g., "123456789012345678" • Discord user/channel names — e.g., "username", "#channel-name" • Mentions — e.g., "<@userId>", "<#channelId>" • Prefixed formats — discord:, user:, channel:, pk: (for PluralKit members) • Wildcard — "*" for unrestricted access On startup, OpenClaw resolves names to IDs when the bot can search members (requires Server Members Intent). The mapping is logged; unresolved entries are retained as typed. Owner detection: When a per-guild or per-channel users allowlist matches the sender, OpenClaw treats the sender as owner in the system prompt. Global owner is configured via commands.ownerAllowFrom. Thread inheritance: Threads inherit parent channel config (allowlist, requireMention, skills, prompts) unless explicitly listed with the thread's channel ID.
Use numeric IDs whenever possible for reliable matching. Name-based resolution requires Server Members Intent and may fail for large servers.
Slug format is lowercase with spaces replaced by hyphens (e.g., #my-help → slug my-help).
Guild channel topics are injected as context but NOT as system prompt — treat them as untrusted input.

Discord Configuration Reference

enabled
Type: booleanDefault: true

Enable or disable the Discord channel

token
Type: stringDefault: ""

Discord Bot Token. Can also use DISCORD_BOT_TOKEN env var

dm.policy
Type: stringDefault: "pairing"

Controls who can DM the bot. Options: pairing, allowlist, open, disabled

dm.allowFrom
Type: string[]Default: []

Discord user IDs allowed to DM the bot (when dm.policy is allowlist)

groupPolicy
Type: stringDefault: "allowlist"

Guild channel handling policy. Options: open, disabled, allowlist

guilds
Type: objectDefault: {}

Per-guild configuration keyed by guild ID. Includes slug, users, channels, requireMention, etc.

requireMention
Type: booleanDefault: true

Whether the bot requires @mention to respond in guild channels

messages.ackReaction
Type: stringDefault: ""

Emoji to react with as message acknowledgment while processing

messages.removeAckAfterReply
Type: booleanDefault: false

Remove the acknowledgment reaction after the AI responds

textChunkLimit
Type: numberDefault: 2000

Maximum characters per message chunk (Discord limit is 2000)

chunkMode
Type: stringDefault: "length"

How to split long responses. Options: length (hard character limit), newline (paragraph boundaries)

historyLimit
Type: numberDefault: 20

Number of recent guild messages to include as AI context

mediaMaxMb
Type: numberDefault: 8

Maximum media file size in megabytes for uploads

replyToMode
Type: stringDefault: "off"

Reply threading mode. Options: off, first (thread first chunk only), all (thread every chunk)

configWrites
Type: booleanDefault: true

Allow Discord-initiated config updates via /config set|unset commands

allowBots
Type: booleanDefault: false

Whether to process messages from other bots. Use with caution to avoid loops

retry.attempts
Type: numberDefault: 3

Number of retry attempts for failed Discord API calls

retry.minDelayMs
Type: numberDefault: 500

Minimum delay in milliseconds between retry attempts

retry.maxDelayMs
Type: numberDefault: 30000

Maximum delay in milliseconds between retry attempts

retry.jitter
Type: numberDefault: 0.1

Jitter factor applied to retry delays for randomization

dm.enabled
Type: booleanDefault: true

Whether to accept direct messages

dm.groupEnabled
Type: booleanDefault: false

Enable group DM handling

dm.groupChannels
Type: string[]Default: []

Group DM channel allowlist

dmHistoryLimit
Type: numberDefault: -

Per-user DM history limit override

maxLinesPerMessage
Type: numberDefault: 17

Soft line count limit per message chunk

commands.native
Type: string | booleanDefault: "auto"

Native slash command registration. Options: auto (enabled for Discord), true, false

commands.text
Type: objectDefault: {}

Text command configuration requiring standalone /... messages

commands.useAccessGroups
Type: booleanDefault: false

Whether to enforce access-group checks for commands

actions.*
Type: booleanDefault: varies

Tool action gates. Most enabled by default; roles, moderation, and presence are disabled by default

pluralkit.enabled
Type: booleanDefault: false

Enable PluralKit proxy message resolution

Discord Frequently Asked Questions

Discord Troubleshooting

Bot connects but doesn't reply to messages

Message Content Intent is not enabled, the bot lacks channel permissions, or mention requirements are misconfigured.

Verify Message Content Intent is enabled in the Discord Developer Portal (Bot → Privileged Gateway Intents). Confirm the bot has View Channels, Send Messages, and Read Message History permissions. Check if requireMention is set to true and the bot isn't being @mentioned.
DMs are not working

DM handling may be disabled in config, or the pairing approval is pending.

Check that dm.policy is not set to 'disabled'. If using pairing mode, check pending pairings with 'openclaw pairing list' and approve via 'openclaw pairing approve discord <code>'. If using allowlist mode, ensure the user's Discord ID is in dm.allowFrom.
Slash commands are not visible in Discord

The 'applications.commands' scope was not included in the bot's OAuth2 invite URL.

Go to the Developer Portal → OAuth2 → URL Generator, ensure both 'bot' and 'applications.commands' scopes are selected, generate a new invite URL, and re-invite the bot to your server. Slash commands are gated by the same allowlists as regular messages.
Bot is rate-limited or stuck

Discord API rate limits have been hit, or the gateway connection is in a bad state.

Restart the gateway with 'openclaw gateway --force'. OpenClaw includes built-in retry logic with exponential backoff for rate limits (429 responses). If the issue persists, check the retry configuration under channels.discord.retry.
requireMention is false but the bot still doesn't reply

groupPolicy defaults to 'allowlist', so the bot only responds in explicitly configured guilds/channels.

Set groupPolicy to 'open' to respond in all channels, or add the specific guild and channel IDs to the guilds configuration. Ensure the guild entry includes the channel with allow: true.
Exec approval buttons don't appear in DMs

execApprovals is not enabled, or the user's Discord ID is not listed in the approvers array.

Set execApprovals.enabled to true in your Discord channel config. Add the user's numeric Discord ID to the execApprovals.approvers array. Use the button UI (not the /approve command) for direct Discord approvals.