Setting Up the Discord Gateway
I have spent plenty of nights fighting with bot integrations where everything seems right, but the bot just stays offline. It usually comes down to a missed checkbox in a developer portal or a token that isn’t being read correctly. I want to help you avoid that loop and get your Discord connection running quickly.
What You’ll Need
Section titled “What You’ll Need”- A Discord Developer Portal application.
- A Bot token.
- Message Content Intent enabled.
- Server Members Intent enabled.
Quick Start
Section titled “Quick Start”I recommend following these four steps to get your gateway online.
1. Create a Discord bot and enable intents
Section titled “1. Create a Discord bot and enable intents”Go to the Discord Developer Portal and create your application. Add a bot to the project and make sure you toggle these specific switches:
- Message Content Intent
- Server Members Intent (I suggest this for name-to-ID lookups and allowlist matching)
2. Configure your token
Section titled “2. Configure your token”You can set your token in your configuration file. If you are using the default account, you can use an environment variable instead.
{ channels: { discord: { enabled: true, token: "YOUR_BOT_TOKEN", }, },}Or use the environment fallback:
DISCORD_BOT_TOKEN=...I should mention that configuration values take priority. If you have a token in your config file, it will override the DISCORD_BOT_TOKEN environment variable.
3. Invite the bot and start the gateway
Section titled “3. Invite the bot and start the gateway”Invite the bot to your server. Make sure it has message permissions. Once invited, run the gateway command:
openclaw gateway4. Approve the first DM pairing
Section titled “4. Approve the first DM pairing”Discord DMs use pairing mode by default. You need to list the active pairing requests and approve them using the provided code.
openclaw pairing list discordopenclaw pairing approve discord <CODE>Troubleshooting
Section titled “Troubleshooting”If things aren’t working as expected, check these two areas:
- Expired Pairing Codes: Pairing codes only last for 1 hour. If you wait too long, you will need to generate a new one.
- Group DMs: By default, group DMs are ignored because
channels.discord.dm.groupEnabledis set tofalse.
What’s Next
Section titled “What’s Next”If you run into a specific error not covered here, ask the AI Setup Assistant.
I’ve been in that spot where you deploy a bot and it immediately starts responding to every random message in a server, or worse, strangers start messaging it directly. It is a headache to clean up. I want to show you how to set up routing and access control properly so your bot only talks to the people and channels you actually want.
What You’ll Need
Section titled “What You’ll Need”- A Discord bot token from the Developer Portal.
- Privileged Gateway Intents enabled (Message Content and Server Members).
- Numeric IDs for your server, channels, and user account.
- OAuth scopes:
botandapplications.commands.
Quick Start
Section titled “Quick Start”I find the fastest way to get running is to set up a strict allowlist from the start. This prevents the bot from leaking into places it doesn’t belong.
- Create your App: Head to the Discord Developer Portal, hit New Application, go to Bot, and click Add Bot. Copy your token.
- Enable Intents: In the Bot tab, scroll to Privileged Gateway Intents and toggle on Message Content Intent and Server Members Intent.
- Get your IDs: Enable Developer Mode in your Discord client settings. Right-click your server, your channel, and your own profile to copy their numeric IDs.
- Configure the Allowlist: Drop this into your config to lock the bot to specific channels.
{ channels: { discord: { groupPolicy: "allowlist", guilds: { "123456789012345678": { requireMention: true, users: ["987654321098765432"], channels: { general: { allow: true }, help: { allow: true, requireMention: true }, }, }, }, }, },}Managing DMs and Guilds
Section titled “Managing DMs and Guilds”I usually recommend being very specific about who can DM the bot. You can control this via channels.discord.dm.policy.
DM Policies
Section titled “DM Policies”pairing: This is the default. It prompts unknown users for pairing.allowlist: Only specific users you’ve listed can talk to the bot.open: Anyone can message it (requireschannels.discord.dm.allowFromto include"*").disabled: DMs are completely off.
When you are targeting a user for delivery, I suggest using the format user:<id> or the <@id> mention. I’ve noticed that bare numeric IDs are often ambiguous and will be rejected unless you explicitly provide the target kind.
Guild Routing
Section titled “Guild Routing”If you have channels.discord in your config, the bot defaults to a secure allowlist policy for guilds. If you don’t create a specific block but provide a DISCORD_BOT_TOKEN, it falls back to open but will throw a warning in your logs.
For the allowlist behavior:
- The guild must match an ID or slug in
channels.discord.guilds. - If you list a guild but don’t define a
channelsblock inside it, the bot allows all channels in that guild. - If you do define a
channelsblock, any channel not explicitly listed is denied.
Mentions and Native Commands
Section titled “Mentions and Native Commands”By default, guild messages are mention-gated. This means the bot won’t respond unless it is explicitly called out. I’ve found this is the best way to keep noise down in busy servers. The bot looks for:
- An explicit @bot mention.
- Configured mention patterns in
agents.list[].groupChat.mentionPatterns. - Implicit replies to the bot’s own messages.
You can toggle this per channel using requireMention.
Regarding commands, commands.native is set to "auto" by default. If you want to turn off Discord native commands, set commands.native=false, which clears any previously registered commands. Even if a user isn’t authorized, they might still see the commands in the Discord UI. However, if they try to run one, the bot enforces the auth policy and returns “not authorized.”
Troubleshooting
Section titled “Troubleshooting”- IDs being rejected: Make sure you aren’t using bare numbers. Use the
user:<id>format for DMs to avoid ambiguity. - Bot ignoring messages: Check if
requireMentionis enabled for that guild or channel. If it is, the bot won’t respond to plain text without a mention.
If you hit a wall while setting this up, I recommend checking the AI Setup Assistant for help.
What’s Next
Section titled “What’s Next”- Slash commands - See the full command catalog and how they behave.
I’ve spent a lot of time trying to make bots feel like they actually belong in a conversation. It is a common headache when an agent just shouts into a channel instead of replying to a specific person or remembering what was said a few minutes ago. If you want your Discord integration to feel less like a script and more like a participant, you need to get these settings right.
I will show you how to handle replies, manage message history, and set up advanced tools like PluralKit and execution approvals.
What You’ll Need
Section titled “What You’ll Need”- An active Discord bot integration.
- Access to your configuration file (JSON5).
- A PluralKit token (if you use private systems).
- Specific User IDs for DM-based history or approvals.
Quick Start
Section titled “Quick Start”You can get the basics running in about five minutes by focusing on history and replies.
- Set History Limits: Define how many messages the agent sees.
channels.discord.historyLimit: Set this to20(the default).
- Enable Replies: Decide how the agent responds.
- Set
channels.discord.replyToModetofirstorall.
- Set
- Test Threads: Send a message in a thread to see the agent inherit parent channel settings.
Feature Details
Section titled “Feature Details”Reply Tags and Native Replies
Section titled “Reply Tags and Native Replies”Discord allows agents to target specific messages. I recommend using native replies to keep conversations organized. You can control this with channels.discord.replyToMode.
Available modes:
off(default)firstall
The agent can use these specific tags in its output:
[[reply_to_current]][[reply_to:<id>]]
Message IDs are included in the context and history, so agents know exactly which message to target.
History, Context, and Threads
Section titled “History, Context, and Threads”Managing how much an agent remembers is vital for performance. You can set limits for both guilds and DMs.
- Guild History: Use
channels.discord.historyLimit. It defaults to20. If this is missing, it usesmessages.groupChat.historyLimit. Setting it to0disables history. - DM History: Use
channels.discord.dmHistoryLimitfor general DMs. For specific users, usechannels.discord.dms["<user_id>"].historyLimit.
For threads, the system routes them as channel sessions. The agent can use parent thread metadata to link sessions. Thread configurations will inherit settings from the parent channel unless you create a specific entry for that thread. Note that channel topics are injected as untrusted context, not as system prompts.
Reaction Notifications
Section titled “Reaction Notifications”You can decide how the agent reacts to emoji interactions. This is set per-guild using these modes:
offown(default)allallowlist(usesguilds.<id>.users)
When a reaction occurs, the system turns it into a system event and attaches it to the Discord session.
Config Writes
Section titled “Config Writes”By default, the system allows channel-initiated config writes. This is what makes /config set|unset commands work. If you want to stop this, use the following configuration:
{ channels: { discord: { configWrites: false, }, },}PluralKit Support
Section titled “PluralKit Support”If your community uses PluralKit, you can map proxied messages to system member identities. This helps the agent recognize who is actually speaking.
{ channels: { discord: { pluralkit: { enabled: true, token: "pk_live_...", // optional; needed for private systems }, }, },}Key points for PluralKit:
- You can use
pk:<memberId>in allowlists. - The system matches member display names by name or slug.
- Lookups are constrained by a time window.
- If a lookup fails, proxied messages are dropped as bot messages unless
allowBots=trueis set.
Exec Approvals in Discord
Section titled “Exec Approvals in Discord”You can handle execution approvals directly in Discord DMs using buttons. This is great for maintaining security without leaving the app.
Configuration paths:
channels.discord.execApprovals.enabledchannels.discord.execApprovals.approvers- Other options include
agentFilter,sessionFilter, andcleanupAfterResolve.
Troubleshooting
Section titled “Troubleshooting”Approvals are failing with “unknown approval IDs”
If you run into this, you should verify your approvers list. Also, double-check that the execApprovals.enabled flag is actually set to true in your config.
Proxied messages are being ignored
If you are using PluralKit and messages aren’t showing up, the lookup might be failing. The system drops these as bot messages by default. You can fix this by setting allowBots=true.
Agent is ignoring channel topics Remember that channel topics are treated as untrusted context. They are not system prompts, so the agent might not follow them as strictly as you expect.
Need more help with your specific configuration? Check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”Dealing with bot permissions often feels like a guessing game. You want your integration to perform specific tasks, but figuring out which actions are allowed and where to toggle them can be a headache when you are just trying to get your code running. I find it much easier to have a clear map of what is available and what is locked by default.
What You’ll Need
Section titled “What You’ll Need”- Access to the
channels.discord.actions.*configuration path. - Knowledge of your required action groups (like messaging or moderation).
Quick Start
Section titled “Quick Start”I recommend starting with the core actions. Discord message actions cover everything from basic chatting to server administration and metadata.
Here are the core examples of what you can do:
- messaging:
sendMessage,readMessages,editMessage,deleteMessage,threadReply - reactions:
react,reactions,emojiList - moderation:
timeout,kick,ban - presence:
setPresence
You control these through action gates located under channels.discord.actions.*. While many features are ready to use immediately, some sensitive groups are turned off by default to keep things secure.
Refer to this table to see the default behavior for each action group:
| Action group | Default |
|---|---|
| reactions, messages, threads, pins, polls, search, memberInfo, roleInfo, channelInfo, channels, voiceStatus, events, stickers, emojiUploads, stickerUploads, permissions | enabled |
| roles | disabled |
| moderation | disabled |
| presence | disabled |
Troubleshooting
Section titled “Troubleshooting”If you try to use a moderation tool like kick or ban and it fails, check your action gates. Since moderation, roles, and presence are set to disabled by default, your integration will not have permission to execute those specific functions until you change the configuration.
If you have questions about a specific gate, ask the AI Setup Assistant.
What’s Next
Section titled “What’s Next”I know the feeling when you’ve spent time configuring your Discord gateway only to find the bot won’t respond to a single command. It is frustrating when the logs stay silent or messages seem to vanish without any clear error. I have spent many nights staring at a terminal window wondering why my configuration isn’t picking up events that are clearly happening in the server.
Usually, the fix is hidden in a small intent setting or a specific allowlist rule. I have put together this guide to help you debug these common friction points so you can get back to building.
What You’ll Need
Section titled “What You’ll Need”- An active Discord Bot Token (stored as
DISCORD_BOT_TOKEN). - The
openclawCLI tool. - Access to your gateway configuration file.
- Discord Developer Portal access to toggle intents.
Quick Start
Section titled “Quick Start”If things aren’t working, I recommend this 5-minute check to find the root cause:
- Run
openclaw doctorto verify your environment and connection. - Check your intents in the Discord Developer Portal; ensure Message Content Intent is on.
- Use
openclaw channels status --probeto see if the bot can actually “see” your target channels. - Restart the gateway service after any configuration change to ensure the new settings take effect.
Troubleshooting
Section titled “Troubleshooting”Disallowed intents or missing messages
Section titled “Disallowed intents or missing messages”If your bot is online but sees no guild messages, it is almost always an intent issue. You need to:
- Enable Message Content Intent in the Discord Developer Portal.
- Enable Server Members Intent if your logic depends on user or member resolution.
- Restart the gateway after changing these intents on the Discord website.
Guild messages blocked unexpectedly
Section titled “Guild messages blocked unexpectedly”When messages are being sent but the bot ignores them, I check these four areas:
- Verify the
groupPolicysetting. - Check the guild allowlist under
channels.discord.guilds. - If a guild
channelsmap exists, remember that only listed channels are allowed. - Verify
requireMentionbehavior and your mention patterns.
I find these commands are the fastest way to verify what is happening:
openclaw doctoropenclaw channels status --probeopenclaw logs --followRequire mention is false but still blocked
Section titled “Require mention is false but still blocked”If you set requireMention to false and messages are still blocked, it is likely one of these causes:
- You have
groupPolicy="allowlist"set without a matching guild or channel allowlist. - The
requireMentiontoggle is in the wrong place. It must be underchannels.discord.guildsor a specific channel entry. - The sender is blocked by a guild or channel
usersallowlist.
Permissions audit mismatches
Section titled “Permissions audit mismatches”The channels status --probe command is great, but it has a limitation. Permission checks only work for numeric channel IDs. If you use slug keys, the runtime matching still works, but the probe cannot fully verify permissions for you.
DM and pairing issues
Section titled “DM and pairing issues”If your DMs aren’t working, check these two settings:
channels.discord.dm.enabled=false(this should be true).channels.discord.dm.policy="disabled".
If you are using pairing mode, the bot will stay silent while it is awaiting pairing approval.
Bot to bot loops
Section titled “Bot to bot loops”By default, the gateway ignores messages authored by other bots. If you set channels.discord.allowBots=true, I recommend using strict mention and allowlist rules. This prevents the bot from getting stuck in an infinite loop with another automated user.
Configuration Reference Pointers
Section titled “Configuration Reference Pointers”When you are deep in the config file, these are the high-signal fields I look at first:
- Startup and Auth:
enabled,token,accounts.*,allowBots. - Policy:
groupPolicy,dm.*,guilds.*,guilds.*.channels.*. - Commands:
commands.native,commands.useAccessGroups,configWrites. - Delivery:
textChunkLimit,chunkMode,maxLinesPerMessage.
For a full list, check the Configuration reference - Discord.
Safety and Operations
Section titled “Safety and Operations”I always treat bot tokens as secrets. I prefer using DISCORD_BOT_TOKEN in supervised environments rather than hardcoding it. You should also grant the least-privilege Discord permissions necessary for your bot to function. If your command deployment or state seems stale, restart the gateway and re-check the status with openclaw channels status --probe.
If you are still stuck, try the AI Setup Assistant.
What’s Next
Section titled “What’s Next”OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.