Files
Moltbot/docs/channels/discord.md

13 KiB

summary, read_when, title
summary read_when title
Discord bot support status, capabilities, and configuration
Working on Discord channel features
Discord

Discord (Bot API)

Status: ready for DMs and guild channels via the official Discord gateway.

Discord DMs default to pairing mode. Native command behavior and command catalog. Cross-channel diagnostics and repair flow.

Quick setup

Create an application in the Discord Developer Portal, add a bot, then enable:
- **Message Content Intent**
- **Server Members Intent** (recommended for name-to-ID lookups and allowlist matching)
{
  channels: {
    discord: {
      enabled: true,
      token: "YOUR_BOT_TOKEN",
    },
  },
}
Env fallback for the default account:
DISCORD_BOT_TOKEN=...
Invite the bot to your server with message permissions.
openclaw gateway
openclaw pairing list discord
openclaw pairing approve discord <CODE>
Pairing codes expire after 1 hour.
Token resolution is account-aware. Config token values win over env fallback. `DISCORD_BOT_TOKEN` is only used for the default account.

Runtime model

  • Gateway owns the Discord connection.
  • Reply routing is deterministic: Discord inbound replies back to Discord.
  • By default (session.dmScope=main), direct chats share the agent main session (agent:main:main).
  • Guild channels are isolated session keys (agent:<agentId>:discord:channel:<channelId>).
  • Group DMs are ignored by default (channels.discord.dm.groupEnabled=false).
  • Native slash commands run in isolated command sessions (agent:<agentId>:discord:slash:<userId>), while still carrying CommandTargetSessionKey to the routed conversation session.

Access control and routing

`channels.discord.dm.policy` controls DM access:
- `pairing` (default)
- `allowlist`
- `open` (requires `channels.discord.dm.allowFrom` to include `"*"`)
- `disabled`

If DM policy is not open, unknown users are blocked (or prompted for pairing in `pairing` mode).

DM target format for delivery:

- `user:<id>`
- `<@id>` mention

Bare numeric IDs are ambiguous and rejected unless an explicit user/channel target kind is provided.
Guild handling is controlled by `channels.discord.groupPolicy`:
- `open`
- `allowlist`
- `disabled`

Secure baseline when `channels.discord` exists is `allowlist`.

`allowlist` behavior:

- guild must match `channels.discord.guilds` (`id` preferred, slug accepted)
- if a guild has `channels` configured, non-listed channels are denied
- if a guild has no `channels` block, all channels in that allowlisted guild are allowed

Example:
{
  channels: {
    discord: {
      groupPolicy: "allowlist",
      guilds: {
        "123456789012345678": {
          requireMention: true,
          users: ["987654321098765432"],
          channels: {
            general: { allow: true },
            help: { allow: true, requireMention: true },
          },
        },
      },
    },
  },
}
If you only set `DISCORD_BOT_TOKEN` and do not create a `channels.discord` block, runtime fallback is `groupPolicy="open"` (with a warning in logs).
Guild messages are mention-gated by default.
Mention detection includes:

- explicit bot mention
- configured mention patterns (`agents.list[].groupChat.mentionPatterns`, fallback `messages.groupChat.mentionPatterns`)
- implicit reply-to-bot behavior in supported cases

`requireMention` is configured per guild/channel (`channels.discord.guilds...`).

Group DMs:

- default: ignored (`dm.groupEnabled=false`)
- optional allowlist via `dm.groupChannels` (channel IDs or slugs)

Developer Portal setup

1. Discord Developer Portal -> **Applications** -> **New Application**
2. **Bot** -> **Add Bot**
3. Copy bot token
In **Bot -> Privileged Gateway Intents**, enable:
- Message Content Intent
- Server Members Intent (recommended)

Presence intent is optional and only required if you want to receive presence updates. Setting bot presence (`setPresence`) does not require enabling presence updates for members.
OAuth URL generator:
- scopes: `bot`, `applications.commands`

Typical baseline permissions:

- View Channels
- Send Messages
- Read Message History
- Embed Links
- Attach Files
- Add Reactions (optional)

Avoid `Administrator` unless explicitly needed.
Enable Discord Developer Mode, then copy:
- server ID
- channel ID
- user ID

Prefer numeric IDs in OpenClaw config for reliable audits and probes.

Native commands and command auth

  • commands.native defaults to "auto" and is enabled for Discord.
  • Per-channel override: channels.discord.commands.native.
  • commands.native=false explicitly clears previously registered Discord native commands.
  • Native command auth uses the same Discord allowlists/policies as normal message handling.
  • Commands may still be visible in Discord UI for users who are not authorized; execution still enforces OpenClaw auth and returns "not authorized".

See Slash commands for command catalog and behavior.

Feature details

Discord supports reply tags in agent output:
- `[[reply_to_current]]`
- `[[reply_to:<id>]]`

Controlled by `channels.discord.replyToMode`:

- `off` (default)
- `first`
- `all`

Message IDs are surfaced in context/history so agents can target specific messages.
Guild history context:
- `channels.discord.historyLimit` default `20`
- fallback: `messages.groupChat.historyLimit`
- `0` disables

DM history controls:

- `channels.discord.dmHistoryLimit`
- `channels.discord.dms["<user_id>"].historyLimit`

Thread behavior:

- Discord threads are routed as channel sessions
- parent thread metadata can be used for parent-session linkage
- thread config inherits parent channel config unless a thread-specific entry exists

Channel topics are injected as **untrusted** context (not as system prompt).
Per-guild reaction notification mode:
- `off`
- `own` (default)
- `all`
- `allowlist` (uses `guilds.<id>.users`)

Reaction events are turned into system events and attached to the routed Discord session.
Channel-initiated config writes are enabled by default.
This affects `/config set|unset` flows (when command features are enabled).

Disable:
{
  channels: {
    discord: {
      configWrites: false,
    },
  },
}
Enable PluralKit resolution to map proxied messages to system member identity:
{
  channels: {
    discord: {
      pluralkit: {
        enabled: true,
        token: "pk_live_...", // optional; needed for private systems
      },
    },
  },
}
Notes:

- allowlists can use `pk:<memberId>`
- member display names are matched by name/slug
- lookups use original message ID and are time-window constrained
- if lookup fails, proxied messages are treated as bot messages and dropped unless `allowBots=true`
Discord supports button-based exec approvals in DMs.
Config path:

- `channels.discord.execApprovals.enabled`
- `channels.discord.execApprovals.approvers`
- `agentFilter`, `sessionFilter`, `cleanupAfterResolve`

If approvals fail with unknown approval IDs, verify approver list and feature enablement.

Related docs: [Exec approvals](/tools/exec-approvals)

Tools and action gates

Discord message actions include messaging, channel admin, moderation, presence, and metadata actions.

Core examples:

  • messaging: sendMessage, readMessages, editMessage, deleteMessage, threadReply
  • reactions: react, reactions, emojiList
  • moderation: timeout, kick, ban
  • presence: setPresence

Action gates live under channels.discord.actions.*.

Default gate behavior:

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

- enable Message Content Intent
- enable Server Members Intent when you depend on user/member resolution
- restart gateway after changing intents
- verify `groupPolicy`
- verify guild allowlist under `channels.discord.guilds`
- if guild `channels` map exists, only listed channels are allowed
- verify `requireMention` behavior and mention patterns

Useful checks:
openclaw doctor
openclaw channels status --probe
openclaw logs --follow
Common causes:
- `groupPolicy="allowlist"` without matching guild/channel allowlist
- `requireMention` configured in the wrong place (must be under `channels.discord.guilds` or channel entry)
- sender blocked by guild/channel `users` allowlist
`channels status --probe` permission checks only work for numeric channel IDs.
If you use slug keys, runtime matching can still work, but probe cannot fully verify permissions.
- DM disabled: `channels.discord.dm.enabled=false`
- DM policy disabled: `channels.discord.dm.policy="disabled"`
- awaiting pairing approval in `pairing` mode
By default bot-authored messages are ignored.
If you set `channels.discord.allowBots=true`, use strict mention and allowlist rules to avoid loop behavior.

Configuration reference pointers

Primary reference:

High-signal Discord fields:

  • startup/auth: enabled, token, accounts.*, allowBots
  • policy: groupPolicy, dm.*, guilds.*, guilds.*.channels.*
  • command: commands.native, commands.useAccessGroups, configWrites
  • reply/history: replyToMode, historyLimit, dmHistoryLimit, dms.*.historyLimit
  • delivery: textChunkLimit, chunkMode, maxLinesPerMessage
  • media/retry: mediaMaxMb, retry
  • actions: actions.*
  • features: pluralkit, execApprovals, intents, agentComponents, heartbeat, responsePrefix

Safety and operations

  • Treat bot tokens as secrets (DISCORD_BOT_TOKEN preferred in supervised environments).
  • Grant least-privilege Discord permissions.
  • If command deploy/state is stale, restart gateway and re-check with openclaw channels status --probe.