Skip to main content
Who may reach the bot, which guild channels it answers in, and which Discord actions it is allowed to take.

Access control and routing

channels.discord.dmPolicy controls DM access. channels.discord.allowFrom is the canonical DM allowlist.
  • pairing (default)
  • allowlist (requires at least one allowFrom sender)
  • open (requires channels.discord.allowFrom to include "*")
  • disabled
If DM policy is not open, unknown users are blocked (or prompted for pairing in pairing mode).Multi-account precedence:
  • Omitted account dmPolicy and groupPolicy inherit the channel root. Explicit account policies win; with neither scope set, defaults remain pairing and allowlist respectively.
  • channels.discord.accounts.default.allowFrom applies only to the default account.
  • For one account, allowFrom takes precedence over legacy dm.allowFrom.
  • Named accounts inherit channels.discord.allowFrom when their own allowFrom and legacy dm.allowFrom are unset.
  • Named accounts do not inherit channels.discord.accounts.default.allowFrom.
Legacy channels.discord.dm.policy and channels.discord.dm.allowFrom are still read for compatibility. openclaw doctor --fix migrates them to dmPolicy and allowFrom when it can do so without changing access.DM target format for delivery:
  • user:<id>
  • <@id> mention
Bare numeric IDs normally resolve as channel IDs when a channel default is active, but IDs listed in the account’s effective DM allowFrom are treated as user DM targets for compatibility.

Guild channel maps are allowlists

A guild entry with no channels map lets the bot work in every channel it can see, subject to the guild’s requireMention and users rules. Adding even one channel entry turns the map into an allowlist: any channel not matched by an entry is denied, not merely left at guild defaults. This surprises people who add one channel to give it special settings and find the bot has gone silent everywhere else. Use the "*" wildcard key to keep the rest of the guild reachable:
Channel entries override guild-level values, so a channel entry with users: ["*"] opens that one room to any sender even when the guild users list is narrow. Entries match by channel ID, name, or slug, and a thread falls back to its parent channel’s entry.

Applying access-policy changes

For running Discord accounts, policy-only changes saved in the Control UI apply through the Gateway’s validated runtime config publication without restarting the Discord connection or waiting for active Control UI turns to finish. This covers groupPolicy, dmPolicy, allowFrom, dm, guilds, allowBots, and dangerouslyAllowNameMatching, both at channels.discord and under channels.discord.accounts.<accountId>. New messages and interactions use the published policy, including guild/channel membership, user and role allowlists, and mention requirements. Name-based entries are resolved and cached for the policy revision before admission; already admitted work retains its existing context. If a name-policy lookup cannot finish within an interaction’s response budget, components show an ephemeral policy-updating message and autocomplete returns no choices. A later interaction uses the resolved policy; the expired interaction is never resumed. Token, application ID, proxy, intents, command registration, voice configuration, and account enablement still use the channel’s restart path and drain deferral. A write that mixes policy and restart-required settings stays one deferred transaction. Manual channel stop/start reads the committed config; it does not publish a pending transport change from disk.

Role-based agent routing

Use bindings[].match.roles to route Discord guild members to different agents by role ID. Role-based bindings accept role IDs only and are evaluated after peer or parent-peer bindings and before guild-only bindings. If a binding also sets other match fields (for example peer + guildId + roles), all configured fields must match.

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 skips Discord slash-command registration and cleanup during startup. Previously registered commands may remain visible in Discord until you remove them from the Discord app.
  • Native command auth uses the same Discord allowlists/policies as normal message handling.
  • Commands may still be visible in the Discord UI for unauthorized users; execution enforces OpenClaw auth and replies “not authorized”.
  • Default slash command settings: ephemeral: true (channels.discord.slashCommand.ephemeral).
See Slash commands for the command catalog and behavior.

Tools and action gates

Discord message actions cover messaging, channel admin, moderation, presence, and metadata. Core examples:
  • messaging: sendMessage, readMessages, editMessage, deleteMessage, threadReply
  • reactions: react, reactions, emoji-list
  • moderation: timeout, kick, ban
  • presence: setPresence
Use emoji-list to discover the current server’s custom emoji:
guildId defaults to the current conversation’s server; provide it explicitly to query another server. Results are sorted by name, and limit defaults to and cannot exceed 100:
Pass identifier directly to react. Discord accepts Unicode emoji, custom name:id identifiers, and the <:name:id> or <a:name:id> forms. emoji-list, react, and reactions are all controlled by channels.discord.actions.reactions. The event-create action accepts an optional image parameter (URL or local file path) to set the scheduled event cover image. Action gates live under channels.discord.actions.*. Default gate behavior: