9.4 KiB
summary, read_when
| summary | read_when | |
|---|---|---|
| Discord bot support status, capabilities, and configuration |
|
Discord (Bot API)
Updated: 2025-12-07
Status: ready for DM and guild text channels via the official Discord bot gateway.
Goals
- Talk to Clawdbot via Discord DMs or guild channels.
- Share the same
mainsession used by WhatsApp/Telegram/WebChat; guild channels stay isolated asdiscord:group:<channelId>(display names usediscord:<guildSlug>#<channelSlug>). - Group DMs are ignored by default; enable via
discord.dm.groupEnabledand optionally restrict bydiscord.dm.groupChannels. - Keep routing deterministic: replies always go back to the surface they arrived on.
How it works
- Create a Discord application → Bot, enable the intents you need (DMs + guild messages + message content), and grab the bot token.
- Invite the bot to your server with the permissions required to read/send messages where you want to use it.
- Configure Clawdbot with
DISCORD_BOT_TOKEN(ordiscord.tokenin~/.clawdbot/clawdbot.json). - Run the gateway; it auto-starts the Discord provider only when a
discordconfig section exists and the token is set (unlessdiscord.enabled = false).- If you prefer env vars, still add
discord: { enabled: true }to~/.clawdbot/clawdbot.jsonand setDISCORD_BOT_TOKEN.
- If you prefer env vars, still add
- Direct chats: use
user:<id>(or a<@id>mention) when delivering; all turns land in the sharedmainsession. - Guild channels: use
channel:<channelId>for delivery. Mentions are required by default and can be set per guild or per channel. - Optional DM control: set
discord.dm.enabled = falseto ignore all DMs, ordiscord.dm.allowFromto allow specific users (ids or names). Usediscord.dm.groupEnabled+discord.dm.groupChannelsto allow group DMs. - Optional guild rules: set
discord.guildskeyed by guild id (preferred) or slug, with per-channel rules. - Optional slash commands: enable
discord.slashCommandto accept user-installed app commands (ephemeral replies). Slash invocations respect the same DM/guild allowlists. - Optional guild context history: set
discord.historyLimit(default 20) to include the last N guild messages as context when replying to a mention. Set0to disable. - Reactions: the agent can trigger reactions via the
discordtool (gated bydiscord.actions.*).- The
discordtool is only exposed when the current surface is Discord.
- The
- Slash commands use isolated session keys (
${sessionPrefix}:${userId}) rather than the sharedmainsession.
Note: Discord does not provide a simple username → id lookup without extra guild context, so prefer ids or <@id> mentions for DM delivery targets.
Note: Slugs are lowercase with spaces replaced by -. Channel names are slugged without the leading #.
Note: Guild context [from:] lines include author.tag + id to make ping-ready replies easy.
Capabilities & limits
- DMs and guild text channels (threads are treated as separate channels; voice not supported).
- Typing indicators sent best-effort; message chunking honors Discord’s 2k character limit.
- File uploads supported up to the configured
discord.mediaMaxMb(default 8 MB). - Mention-gated guild replies by default to avoid noisy bots.
- Reply context is injected when a message references another message (quoted content + ids).
- Native reply threading is off by default; enable with
discord.replyToModeand reply tags.
Config
{
discord: {
enabled: true,
token: "abc.123",
mediaMaxMb: 8,
actions: {
reactions: true,
stickers: true,
polls: true,
permissions: true,
messages: true,
threads: true,
pins: true,
search: true,
memberInfo: true,
roleInfo: true,
roles: false,
channelInfo: true,
voiceStatus: true,
events: true,
moderation: false
},
replyToMode: "off",
slashCommand: {
enabled: true,
name: "clawd",
sessionPrefix: "discord:slash",
ephemeral: true
},
dm: {
enabled: true,
allowFrom: ["123456789012345678", "steipete"],
groupEnabled: false,
groupChannels: ["clawd-dm"]
},
guilds: {
"*": { requireMention: true },
"123456789012345678": {
slug: "friends-of-clawd",
requireMention: false,
reactionNotifications: "own",
users: ["987654321098765432", "steipete"],
channels: {
general: { allow: true },
help: { allow: true, requireMention: true }
}
}
}
}
}
dm.enabled: setfalseto ignore all DMs (defaulttrue).dm.allowFrom: DM allowlist (user ids or names). Omit or set to["*"]to allow any DM sender.dm.groupEnabled: enable group DMs (defaultfalse).dm.groupChannels: optional allowlist for group DM channel ids or slugs.guilds: per-guild rules keyed by guild id (preferred) or slug.guilds."*": default per-guild settings applied when no explicit entry exists.guilds.<id>.slug: optional friendly slug used for display names.guilds.<id>.users: optional per-guild user allowlist (ids or names).guilds.<id>.channels: channel rules (keys are channel slugs or ids).guilds.<id>.requireMention: per-guild mention requirement (overridable per channel).guilds.<id>.reactionNotifications: reaction system event mode (off,own,all,allowlist).slashCommand: optional config for user-installed slash commands (ephemeral responses).mediaMaxMb: clamp inbound media saved to disk.historyLimit: number of recent guild messages to include as context when replying to a mention (default 20,0disables).actions: per-action tool gates; omit to allow all (setfalseto disable).reactions(covers react + read reactions)stickers,polls,permissions,messages,threads,pins,searchmemberInfo,roleInfo,channelInfo,voiceStatus,eventsroles(role add/remove, defaultfalse)moderation(timeout/kick/ban, defaultfalse)
Reaction notifications use guilds.<id>.reactionNotifications:
off: no reaction events.own: reactions on the bot's own messages (default).all: all reactions on all messages.allowlist: reactions fromguilds.<id>.userson all messages (empty list disables).
Tool action defaults
| Action group | Default | Notes |
|---|---|---|
| reactions | enabled | React + list reactions + emojiList |
| stickers | enabled | Send stickers |
| polls | enabled | Create polls |
| permissions | enabled | Channel permission snapshot |
| messages | enabled | Read/send/edit/delete |
| threads | enabled | Create/list/reply |
| pins | enabled | Pin/unpin/list |
| search | enabled | Message search (preview spec) |
| memberInfo | enabled | Member info |
| roleInfo | enabled | Role list |
| channelInfo | enabled | Channel info + list |
| voiceStatus | enabled | Voice state lookup |
| events | enabled | List/create scheduled events |
| roles | disabled | Role add/remove |
| moderation | disabled | Timeout/kick/ban |
replyToMode:off(default),first, orall. Applies only when the model includes a reply tag.
Reply tags
To request a threaded reply, the model can include one tag in its output:
[[reply_to_current]]— reply to the triggering Discord message.[[reply_to:<id>]]— reply to a specific message id from context/history. Current message ids are appended to prompts as[message_id: …]; history entries already include ids.
Behavior is controlled by discord.replyToMode:
off: ignore tags.first: only the first outbound chunk/attachment is a reply.all: every outbound chunk/attachment is a reply.
Allowlist matching notes:
allowFrom/users/groupChannelsaccept ids, names, tags, or mentions like<@id>.- Prefixes like
discord:/user:(users) andchannel:(group DMs) are supported. - Use
*to allow any sender/channel. - When
guilds.<id>.channelsis present, channels not listed are denied by default.
Slash command notes:
- Register a chat input command in Discord with at least one string option (e.g.,
prompt). - The first non-empty string option is treated as the prompt.
- Slash commands honor the same allowlists as DMs/guild messages (
discord.dm.allowFrom,discord.guilds, per-channel rules). - Clawdbot will auto-register
/clawd(or the configured name) if it doesn't already exist.
Tool actions
The agent can call discord with actions like:
react/reactions(add or list reactions)sticker,poll,permissionsreadMessages,sendMessage,editMessage,deleteMessagethreadCreate,threadList,threadReplypinMessage,unpinMessage,listPinssearchMessages,memberInfo,roleInfo,roleAdd,roleRemove,emojiListchannelInfo,channelList,voiceStatus,eventList,eventCreatetimeout,kick,ban
Discord message ids are surfaced in the injected context ([discord message id: …] and history lines) so the agent can target them.
Emoji can be unicode (e.g., ✅) or custom emoji syntax like <:party_blob:1234567890>.
Safety & ops
- Treat the bot token like a password; prefer the
DISCORD_BOT_TOKENenv var on supervised hosts or lock down the config file permissions. - Only grant the bot permissions it needs (typically Read/Send Messages).
- If the bot is stuck or rate limited, restart the gateway (
clawdbot gateway --force) after confirming no other processes own the Discord session.