openclaw.connect('discord')
/** Turn your Discord server into an AI-powered community hub */
## Step 1: Create a Discord Bot
## Step 2: Configure OpenClaw
π¬ Live Example
What to check when the bot says nothing
Almost every Discord report is the same complaint: the bot is in the server, it shows as online, and it ignores everything. There is no error to read because none of these failures raise one. Work down the table β the order reflects how often each turns out to be the cause.
| Symptom | Most likely cause | Where to fix it |
|---|---|---|
| Bot replies to DMs but ignores the server | Message Content Intent is off | Developer Portal β Bot β Privileged Gateway Intents |
| It worked, then stopped in every channel but one | Naming one channel turned the rest into a deny list | Add a "*" wildcard entry under channels.discord.guilds |
| requireMention: false and still nothing | groupPolicy is "allowlist" with no matching entry | channels.discord.guilds and the sender users rules |
| DMs go nowhere | Pairing code was never approved | openclaw pairing approve discord <CODE> |
| Roles in the allowlist never match | Server Members Intent is off | Developer Portal, same panel as above |
The allowlist behaviour catches people repeatedly and deserves stating plainly: while you have configured no channels, every channel is allowed. The moment you add one entry, everything you did not list is denied. That is a reasonable default for a security-sensitive agent, but it turns a small config addition into a silent outage across the rest of the server.
Registering the bot and handing it a token
The token goes in an environment variable and the config only holds a reference to it. That keeps the secret out of openclaw.json, which matters because that file gets pasted into issue reports.
# Developer Portal β your app β Bot β Privileged Gateway Intents # # Message Content Intent REQUIRED for normal guild messages # Server Members Intent needed for role allowlists and nameβID matching # Presence Intent optional; only for presence updates
Message Content is the one that matters. Without it Discord still delivers events, but the content field is empty, so the agent sees messages arrive with nothing in them and stays quiet. Turning it on later requires a gateway restart to take effect.
export DISCORD_BOT_TOKEN="YOUR_BOT_TOKEN"
Never inline the token. Anyone who can read openclaw.json can otherwise take over the bot, and that file ends up in screenshots more often than you would expect.
{
channels: {
discord: {
enabled: true,
token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" },
},
},
}The `source: "env"` form is a SecretRef: OpenClaw resolves it at load time and keeps the literal value out of your config and out of any diff you share.
openclaw config patch --file ./discord.patch.json5 openclaw gateway restart
`config patch` merges into the existing file rather than replacing it, so this is safe to run against a config you have already customised.
Pairing, and keeping the rest of the server reachable
DMs are gated behind an explicit pairing approval by default. This is deliberate: a DM channel to an agent with shell access is not something you want open to anyone who finds the bot.
openclaw pairing list discord
A user who DMs the bot generates a code here. Until you approve it, their messages are dropped rather than queued, so there is nothing to catch up on afterwards.
openclaw pairing approve discord <CODE>
Approve per person, not blanket. If you find codes here you cannot account for, someone has found your bot β check who can add it to servers.
# Keep other channels reachable after you name even one:
{
channels: {
discord: {
guilds: {
"123456789012345678": {
channels: { "*": {} },
},
},
},
},
}This is the wildcard that undoes the deny-by-default behaviour described above. Add it at the same time as your first specific channel entry, not after you have spent an evening debugging.
Things worth knowing before you wire this into a real server
- βAn agent in a shared server can read every message in every channel it can see. Decide that is acceptable before you invite it, not afterwards.
- βDiscord rate-limits aggressively. An agent that replies to everything in a busy server will get throttled, and the throttling looks like the bot going quiet.
- βGuild and channel keys are IDs, not names. Names change; IDs do not, and a renamed channel silently falls out of an allowlist keyed by name.
- βIf the bot needs to act only when addressed, set that explicitly. "It only answers when spoken to" is a configuration, not a default you can assume.