Caricamento in corso...
Caricamento in corso...
Last synced: Today, 22:00
Technical reference for the OpenClaw framework. Real-time synchronization with the official documentation engine.
Use this file to discover all available pages before exploring further.
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.
You will need to create a new application with a bot, add the bot to your server, and pair it to OpenClaw. We recommend adding your bot to your own private server. If you don't have one yet, create one first (choose Create My Own > For me and my friends).
textClick **Bot** on the sidebar. Set the **Username** to whatever you call your OpenClaw agent.
text* **Message Content Intent** (required) * **Server Members Intent** (recommended; required for role allowlists and name-to-ID matching) * **Presence Intent** (optional; only needed for presence updates)
text<Note> Despite the name, this generates your first token — nothing is being "reset." </Note> Copy the token and save it somewhere. This is your **Bot Token** and you will need it shortly.
textScroll down to **OAuth2 URL Generator** and enable: * `bot` * `applications.commands` A **Bot Permissions** section will appear below. Enable at least: **General Permissions** * View Channels **Text Permissions** * Send Messages * Read Message History * Embed Links * Attach Files * Add Reactions (optional) This is the baseline set for normal text channels. If you plan to post in Discord threads, including forum or media channel workflows that create or continue a thread, also enable **Send Messages in Threads**. Copy the generated URL at the bottom, paste it into your browser, select your server, and click **Continue** to connect. You should now see your bot in the Discord server.
text1. Click **User Settings** (gear icon next to your avatar) → **Advanced** → toggle on **Developer Mode** 2. Right-click your **server icon** in the sidebar → **Copy Server ID** 3. Right-click your **own avatar** → **Copy User ID** Save your **Server ID** and **User ID** alongside your Bot Token — you'll send all three to OpenClaw in the next step.
textThis lets server members (including bots) send you DMs. Keep this enabled if you want to use Discord DMs with OpenClaw. If you only plan to use guild channels, you can disable DMs after pairing.
text```bash} export DISCORD_BOT_TOKEN="YOUR_BOT_TOKEN" cat > discord.patch.json5 <<'JSON5' { channels: { discord: { enabled: true, token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" }, }, }, } JSON5 openclaw config patch --file ./discord.patch.json5 --dry-run openclaw config patch --file ./discord.patch.json5 openclaw gateway ``` If OpenClaw is already running as a background service, restart it via the OpenClaw Mac app or by stopping and restarting the `openclaw gateway run` process. For managed service installs, run `openclaw gateway install` from a shell where `DISCORD_BOT_TOKEN` is present, or store the variable in `~/.openclaw/.env`, so the service can resolve the env SecretRef after restart. If your host is blocked or rate-limited by Discord's startup application lookup, set the Discord application/client ID from the Developer Portal so startup can skip that REST call. Use `channels.discord.applicationId` for the default account, or `channels.discord.accounts.<accountId>.applicationId` when you run multiple Discord bots.
text> "I already set my Discord bot token in config. Please finish Discord setup with User ID `<user_id>` and Server ID `<server_id>`." </Tab> <Tab title="CLI / config"> If you prefer file-based config, set: ```json5} { channels: { discord: { enabled: true, token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN", }, }, }, } ``` Env fallback for the default account: ```bash} DISCORD_BOT_TOKEN=... ``` For scripted or remote setup, write the same JSON5 block with `openclaw config patch --file ./discord.patch.json5 --dry-run` and then rerun without `--dry-run`. Plaintext `token` values are supported. SecretRef values are also supported for `channels.discord.token` across env/file/exec providers. See [Secrets Management](/gateway/secrets). For multiple Discord bots, keep each bot token and application ID under its account. A top-level `channels.discord.applicationId` is inherited by accounts, so only set it there when every account should use the same application ID. ```json5} { channels: { discord: { enabled: true, accounts: { personal: { token: { source: "env", provider: "default", id: "DISCORD_PERSONAL_TOKEN" }, applicationId: "111111111111111111", }, work: { token: { source: "env", provider: "default", id: "DISCORD_WORK_TOKEN" }, applicationId: "222222222222222222", }, }, }, }, } ``` </Tab> </Tabs>
text<Tabs> <Tab title="Ask your agent"> Send the pairing code to your agent on your existing channel: > "Approve this Discord pairing code: `<CODE>`" </Tab> <Tab title="CLI"> ```bash} openclaw pairing list discord openclaw pairing approve discord <CODE> ``` </Tab> </Tabs> Pairing codes expire after 1 hour. You should now be able to chat with your agent in Discord via DM.
Once DMs are working, you can set up your Discord server as a full workspace where each channel gets its own agent session with its own context. This is recommended for private servers where it's just you and your bot.
text<Tabs> <Tab title="Ask your agent"> > "Add my Discord Server ID `<server_id>` to the guild allowlist" </Tab> <Tab title="Config"> ```json5} { channels: { discord: { groupPolicy: "allowlist", guilds: { YOUR_SERVER_ID: { requireMention: true, users: ["YOUR_USER_ID"], }, }, }, }, } ``` </Tab> </Tabs>
textIn guild channels, normal assistant final replies stay private by default. Visible Discord output must be sent explicitly with the `message` tool, so the agent can lurk by default and only post when it decides a channel reply is useful. <Tabs> <Tab title="Ask your agent"> > "Allow my agent to respond on this server without having to be @mentioned" </Tab> <Tab title="Config"> Set `requireMention: false` in your guild config: ```json5} { channels: { discord: { guilds: { YOUR_SERVER_ID: { requireMention: false, }, }, }, }, } ``` To restore legacy automatic final replies for group/channel rooms, set `messages.groupChat.visibleReplies: "automatic"`. </Tab> </Tabs>
text<Tabs> <Tab title="Ask your agent"> > "When I ask questions in Discord channels, use memory\_search or memory\_get if you need long-term context from MEMORY.md." </Tab> <Tab title="Manual"> If you need shared context in every channel, put the stable instructions in `AGENTS.md` or `USER.md` (they are injected for every session). Keep long-term notes in `MEMORY.md` and access them on demand with memory tools. </Tab> </Tabs>
Now create some channels on your Discord server and start chatting. Your agent can see the channel name, and each channel gets its own isolated session — so you can set up
#coding#home#researchsession.dmScope=mainagent:main:mainagent:<agentId>:discord:channel:<channelId>channels.discord.dm.groupEnabled=falseagent:<agentId>:discord:slash:<userId>CommandTargetSessionKeyDiscord forum and media channels only accept thread posts. OpenClaw supports two ways to create them:
channel:<forumId>openclaw message thread create--message-idExample: send to forum parent to create a thread
bashopenclaw message send --channel discord --target channel:<forumId> \ --message "Topic title\nBody of the post"
Example: create a forum thread explicitly
bashopenclaw message thread create --channel discord --target channel:<forumId> \ --thread-name "Topic title" --message "Body of the post"
Forum parents do not accept Discord components. If you need components, send to the thread itself (
channel:<threadId>OpenClaw supports Discord components v2 containers for agent messages. Use the message tool with a
componentsreplyToModeSupported blocks:
textsectionseparatoractionsmedia-galleryfilestringuserrolementionablechannelBy default, components are single use. Set
components.reusable=trueTo restrict who can click a button, set
allowedUsers*The
/model/models/models addFile attachments:
fileattachment://<filename>mediapathfilePathmedia-galleryfilenameModal forms:
components.modaltextcheckboxradioselectrole-selectuser-selectExample:
json5{ channel: "discord", action: "send", to: "channel:123456789012345678", message: "Optional fallback text", components: { reusable: true, text: "Choose a path", blocks: [ { type: "actions", buttons: [ { label: "Approve", style: "success", allowedUsers: ["123456789012345678"], }, { label: "Decline", style: "danger" }, ], }, { type: "actions", select: { type: "string", placeholder: "Pick an option", options: [ { label: "Option A", value: "a" }, { label: "Option B", value: "b" }, ], }, }, ], modal: { title: "Details", triggerLabel: "Open form", fields: [ { type: "text", label: "Requester" }, { type: "select", label: "Priority", options: [ { label: "Low", value: "low" }, { label: "High", value: "high" }, ], }, ], }, }, }
text* `pairing` (default) * `allowlist` * `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: * `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` 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.
text* `open` * `allowlist` * `disabled` Secure baseline when `channels.discord` exists is `allowlist`. `allowlist` behavior: * guild must match `channels.discord.guilds` (`id` preferred, slug accepted) * optional sender allowlists: `users` (stable IDs recommended) and `roles` (role IDs only); if either is configured, senders are allowed when they match `users` OR `roles` * direct name/tag matching is disabled by default; enable `channels.discord.dangerouslyAllowNameMatching: true` only as break-glass compatibility mode * names/tags are supported for `users`, but IDs are safer; `openclaw security audit` warns when name/tag entries are used * 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: ```json5} { channels: { discord: { groupPolicy: "allowlist", guilds: { "123456789012345678": { requireMention: true, ignoreOtherMentions: true, users: ["987654321098765432"], roles: ["123456789012345678"], 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="allowlist"` (with a warning in logs), even if `channels.defaults.groupPolicy` is `open`.
textMention 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...`). `ignoreOtherMentions` optionally drops messages that mention another user/role but not the bot (excluding @everyone/@here). Group DMs: * default: ignored (`dm.groupEnabled=false`) * optional allowlist via `dm.groupChannels` (channel IDs or slugs)
Use
bindings[].match.rolespeerguildIdrolesjson5{ bindings: [ { agentId: "opus", match: { channel: "discord", guildId: "123456789012345678", roles: ["111111111111111111"], }, }, { agentId: "sonnet", match: { channel: "discord", guildId: "123456789012345678", }, }, ], }
commands.native"auto"channels.discord.commands.nativecommands.native=falseSee Slash commands for command catalog and behavior.
Default slash command settings:
ephemeral: trueDiscord message actions include messaging, channel admin, moderation, presence, and metadata actions.
Core examples:
sendMessagereadMessageseditMessagedeleteMessagethreadReplyreactreactionsemojiListtimeoutkickbansetPresenceThe
event-createimageAction 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 |
OpenClaw uses Discord components v2 for exec approvals and cross-context markers. Discord message actions can also accept
componentsembedschannels.discord.ui.components.accentColorchannels.discord.accounts.<id>.ui.components.accentColorembedsExample:
json5{ channels: { discord: { ui: { components: { accentColor: "#5865F2", }, }, }, }, }
Discord has two distinct voice surfaces: realtime voice channels (continuous conversations) and voice message attachments (the waveform preview format). The gateway supports both.
Setup checklist:
botapplications.commandscommands.nativechannels.discord.commands.nativechannels.discord.voiceUse
/vc join|leave|statusbash/vc join channel:<voice-channel-id> /vc status /vc leave
Auto-join example:
json5{ channels: { discord: { voice: { enabled: true, model: "openai/gpt-5.4-mini", autoJoin: [ { guildId: "123456789012345678", channelId: "234567890123456789", }, ], daveEncryption: true, decryptionFailureTolerance: 24, tts: { provider: "openai", openai: { voice: "onyx" }, }, }, }, }, }
Notes:
voice.ttsmessages.ttsvoice.modeltools.media.audiovoice.modelallowFromdm.allowFromgatewaycronchannels.discord.voice.enabled=falseGuildVoiceStateschannels.discord.intents.voiceStatesvoice.enabledvoice.daveEncryptionvoice.decryptionFailureTolerance@discordjs/voice@discordjs/voicedaveEncryption=truedecryptionFailureTolerance=24DecryptionFailed(UnencryptedWhenPassthroughDisabled)@discordjs/voiceVoice channel pipeline:
tools.media.audioopenai/gpt-4o-mini-transcribevoice.modelvoice.ttsmessages.ttsCredentials are resolved per component: LLM route auth for
voice.modeltools.media.audiomessages.ttsvoice.ttsDiscord voice messages show a waveform preview and require OGG/Opus audio. OpenClaw generates the waveform automatically, but needs
ffmpegffprobebashmessage(action="send", channel="discord", target="channel:123", path="/path/to/audio.mp3", asVoice=true)
Primary reference: Configuration reference - Discord.
DISCORD_BOT_TOKENopenclaw channels status --probe© 2024 TaskFlow Mirror
Powered by TaskFlow Sync Engine