#Does anyone know how to configure multiple bots in Discord?
1 messages · Page 1 of 1 (latest)
This is a very strange problem. The bot can reply, but there are warnings in the logs
info gateway/channels/discord {"subsystem":"gateway/channels/discord"} discord channels unresolved: 1470000000000/1470000000001
The server ID and channel ID are correct, and the bot has admin privileges and can reply normally. However, when I change the default value in the account to oracle, there are no reaction.
That log line is coming from OpenClawâs Discord allowlist resolver at startup:
discord channels unresolved: <guildId>/<channelId>
It means: for the bot token of that Discord account, OpenClaw tried to look up that guild/channel (to resolve names/slugs â IDs and to sanity-check the allowlist) and Discordâs API said âI canât see thatâ.
Common causes (especially with multiple Discord bot accounts):
- The
oraclebot is not actually in that server, or doesnât have access to that channel (needs at least View Channel). - You switched the default account to
oracle, butoraclehas no token configured. Reminder:DISCORD_BOT_TOKENonly applies to the default account; other accounts must havechannels.discord.accounts.<id>.token. - Privileged intents are not enabled for the
oraclebot in the Discord Developer Portal (Message Content Intent is the big one for âbot connects but doesnât react to messagesâ).
What to do
- Verify
oraclehas a token and is enabled, e.g.channels.discord.accounts.oracle.token: "...". - Invite the oracle bot user to that guild, and make sure it can see the channel.
- In the Developer Portal for the oracle app, enable:
- Message Content Intent (required for reading most guild messages)
- (Optional but recommended) Server Members Intent (helps with allowlist/name lookups)
If you want different guild/channel allowlists per bot, put them under each account so the âotherâ bot doesnât try to resolve channels it canât access:
{
channels: {
discord: {
accounts: {
default: { token: "âŠ", guilds: { "GUILD_ID": { channels: { "CHANNEL_ID": { allow: true } } } } },
oracle: { token: "âŠ", guilds: { "OTHER_GUILD_ID": { channels: { "OTHER_CHANNEL_ID": { allow: true } } } } },
}
}
}
}
Docs:
- https://docs.openclaw.ai/channels/discord
- https://docs.openclaw.ai/gateway/configuration#channelstelegramaccounts--channelsdiscordaccounts--channelsslackaccounts--channelssignalaccounts--channelsimessageaccounts
If you paste your channels.discord config block (redact tokens) + openclaw --version, I can tell you which of the 3 cases above youâre hitting.
Yep â if #1 (oracle) is the case, that warning + âno reactionâ is exactly what youâd see.
discord channels unresolved: <guild>/<channel> means: using the oracle bot token, OpenClaw asked Discord âdo you have access to this guild/channel?â and Discord effectively answered no. That happens when the oracle bot is not in that guild or canât see that channel.
Fix checklist for the oracle bot:
- Invite the oracle bot user to the server (separate invite from the other bot).
- In that channel, grant at least: View Channel, Send Messages, Read Message History (Admin also works, but only if itâs actually assigned and the bot is in the guild).
- If you expect it to react to normal messages, enable Message Content Intent for the oracle application in the Developer Portal.
- Restart the gateway after changes.
One extra gotcha with multi-bot config: the âdefault accountâ is the account id literally named default. DISCORD_BOT_TOKEN only feeds that one. If you renamed/removed default and only have accounts.oracle, make sure you set:
channels: { discord: { accounts: { oracle: { token: "..." } } } }
If you paste your channels.discord block (redact tokens), I can point out the exact mismatch.
- Oracle has a token and it's enabled, but I shouldn't publicly display the token here.
- The bot is already on the server, can reply to me, and has admin privileges to see the channel.
- Message content intent is enabled.
- Server member intent is enabled.
{
"agentId": "oracle",
"match": {
"channel": "discord",
"accountId": "oracle"
}
},
{
"agentId": "sentinel",
"match": {
"channel": "discord",
"accountId": "sentinel"
}
}
] ```
"discord": {
"enabled": true,
"groupPolicy": "allowlist",
"textChunkLimit": 1800,
"mediaMaxMb": 8,
"actions": {
"reactions": true,
"permissions": true,
"messages": true,
"threads": true,
"pins": true,
"search": true,
"memberInfo": true,
"roleInfo": true,
"channelInfo": true,
"voiceStatus": true
},
"dm": {
"enabled": true,
"policy": "pairing",
"allowFrom": [
"*"
]
},
"execApprovals": {
"enabled": true
},
"accounts": {
"oracle": {
"name": "Oracle",
"token": "MTQ3MDc2Nzg4NDg4NzasDDASsas.GWsTVs.-L_GVDIXXXXXXXPJXbQpAA",
"allowBots": true,
"groupPolicy": "allowlist",
"guilds": {
"1470789789789789789": {
"users": [
"*"
],
"channels": {
"1470123123123123123": {
"allow": true,
"requireMention": true
}
}
}
}
},
"sentinel": {
"name": "Sentinel",
"token": "MTQ21aGASA4NDg4NzasDDASsas.GWsTVs.-L_GVDIXXXXsssssXbQpAA",
"allowBots": true,
"groupPolicy": "allowlist",
"guilds": {
"1470789789789789789": {
"users": [
"*"
],
"channels": {
"1470456456456456456": {
"allow": true,
"requireMention": true
}
}
}
}
}
}
}
} ```
Your bindings snippet looks fine.
The weird part is the warning:
discord channels unresolved: <guildId>/<channelId>
That warning is coming from OpenClawâs startup resolver that tries to turn guild/channel entries into IDs. Right now it treats the channel part after the / as a channel name, not a channel ID.
So if your config effectively contains channel keys like:
channels: { discord: { guilds: { "147âŠ": { channels: { "147âŠ": { allow: true } } } } } }
âŠthe resolver builds the string "147âŠ/147âŠ" and then goes âchannel named 147⊠not foundâ, and logs it as unresolved â even though the numeric ID is correct and the bot can still reply.
How to get rid of the warning
Use channel slugs (names) as the keys under guilds.<guildId>.channels, e.g.:
channels: {
discord: {
guilds: {
"1470000000000": {
channels: {
general: { allow: true }, // <- channel name / slug
help: { allow: true }
}
}
}
}
}
On startup it should then log a mapping (something like 147âŠ/generalâ147âŠ/147âŠ) instead of âunresolvedâ.
If you need different allowlists per bot
Put guilds inside each account so one bot doesnât try to resolve the other botâs channels:
channels: {
discord: {
accounts: {
oracle: { token: "...", guilds: { /* oracle guilds */ } },
sentinel: { token: "...", guilds: { /* sentinel guilds */ } },
}
}
}
About âno reactionâ
Do you mean no â
/đ ack reaction (the âI saw it / Iâm workingâ reaction), or no reply at all? Those are different code paths. If you paste (redacted) your channels.discord guilds block (just ids + allow/requireMention), I can tell which one youâre hitting.
Two big things from that config:
0) You leaked both bot tokens in a public channel
Please reset/rotate them immediately in the Discord Developer Portal (Bot â Reset Token), update your config, restart the gateway, and delete/edit the message you posted. Those tokens are passwords.
1) Why you get discord channels unresolved: <guildId>/<channelId>
This is not âbot canât see the channelâ in your case.
OpenClawâs startup resolver builds strings like:
147078âŠ/147012âŠ
âŠand then (today) it treats the part after the slash as a channel name/slug, not a channel id. So it tries to find a channel literally named 1470123123123123123, fails, and logs it as âunresolvedâ.
That means: using numeric IDs as keys hereâŠ
guilds: {
"1470âŠ": {
channels: {
"1470123123123123123": { allow: true }
}
}
}
âŠwill always warn, even though runtime routing can still work.
Fix (if you want clean logs)
Use the channel slug/name as the key instead of the numeric id:
guilds: {
"1470789789789789789": {
channels: {
"does-anyone-know-how-to-configure-multiple-bots-in-discord": {
allow: true,
requireMention: true
}
}
}
}
Tradeoff: IDs are stable, names can change. If you prefer stability, you can also just ignore the warning (itâs cosmetic).
2) âno reactionâ when switching accounts
With requireMention: true, the bot will only respond when that specific bot is mentioned. With two bots in the same server itâs easy to mention the âotherâ one and conclude nothing is happening.
Also: if by âreactionâ you mean the automatic âack emojiâ (đ/â
), thatâs controlled by messages.ackReaction + messages.ackReactionScope (not by channels.discord.actions.reactions).
If you tell me what âreactionâ means here (no reply at all vs no ack emoji vs no /react tool), I can point you to the exact knob to turn. Docs: https://docs.openclaw.ai/channels/discord
"responsePrefix": "**[ {identity.name} ]** ",
"ackReaction": "đ",
"ackReactionScope": "group-mentions",
"removeAckAfterReply": true
}
I've already configured it, but it's not working.
First: rotate both Discord bot tokens right now (Developer Portal â Bot â Reset Token). Those are fully-compromised as soon as they were pasted.
Now, about ack reactions:
What your config means
With:
ackReaction: "đ",
ackReactionScope: "group-mentions",
removeAckAfterReply: true
OpenClaw will only add đ when all of these are true:
- itâs a guild message (not a DM / not a group DM),
- the channel effectively has
requireMention: true,
- OpenClaw can detect mentions (
botUserIdwas fetched successfully), - and the message actually mentioned that bot (or it was a bypassed control command).
Then it will often remove it immediately after replying (removeAckAfterReply: true), which can look like âit never happenedâ in some Discord clients.
Quick 2-step test (to pinpoint the cause)
Temporarily change to:
messages: {
ackReaction: "đ",
ackReactionScope: "all",
removeAckAfterReply: false
}
Restart gateway, then send a message in that channel.
-
If you still get no đ at all: this is almost certainly Discord permissions. Even with âadminâ claims, double-check the bot role in that channel has Add Reactions (and ideally Read Message History).
-
If đ works with
allbut not withgroup-mentions: mention detection is failing for that bot account. Check your gateway logs right after startup for:discord: failed to fetch bot identity: ...
If that line appears,
botUserIdis missing âgroup-mentionsack reactions will never fire.
One more gotcha with your current setup
Youâre using channel IDs as keys under guilds.<id>.channels. Thatâs fine for allowlisting, but itâs also why you see:
discord channels unresolved: <guildId>/<channelId>
(itâs trying to resolve the channel part as a name, not an id). Cosmetic, but confusing.
If you paste the log lines around startup for the oracle account (redact tokens), especially anything mentioning âfetch bot identityâ or âreact failed / 403â, I can tell you exactly which branch youâre in.
It's not a permissions issue; this is a very strange problem. When I change the accountid from oracle to default, the bot can reaction normally.
If the same guild/channel + same message gets đ when the Discord account is default, but never when itâs oracle, then weâre down to two realistic causes:
A) Oracleâs reaction call is failing (most often 403)
Discord permissions are per bot user. Itâs totally possible that both bots can send messages, but only the default bot has Add Reactions in that channel.
The only way to stop guessing: check the reaction error in logs. OpenClaw logs it as:
discord react failed for channel <id>: Discord API ... failed (403) ...
To see that line, turn on debug logging temporarily:
logging: { consoleLevel: "debug", level: "debug" }
Restart gateway, then trigger a message and look for discord react failed (please paste just that error line; no tokens).
B) Oracle canât fetch its own bot identity (botUserId)
Thereâs a specific edge-case in the Discord handler:
- If OpenClaw fails to fetch the botâs own user id for that account, then
ackReactionScope: "group-mentions"will never fire (because it canât reliably confirm âwas I mentioned?â). - Meanwhile, the bot can still reply (so it looks like âonly reactions are brokenâ).
In logs on startup youâll see one of these:
logged in to discord as <someId>âdiscord: failed to fetch bot identity: ...â (this breaks mention-based ack reactions)
Can you paste the oracle startup line(s) around that?
Once we know whether itâs 403 vs failed to fetch bot identity, the fix is straightforward.
02:29:49 info bonjour: advertised gateway fqdn=GuluMew (OpenClaw)._openclaw-gw._tcp.local. host=openclaw.local. port=18789 state=announcing
02:29:50 info gateway/channels/discord {"subsystem":"gateway/channels/discord"} [sentinel] Discord Message Content Intent is limited; bots under 100 servers can use it without verification.
02:29:50 info gateway/channels/discord {"subsystem":"gateway/channels/discord"} [sentinel] starting provider (@Sentinel)
02:29:50 info gateway/channels/discord {"subsystem":"gateway/channels/discord"} [oracle] Discord Message Content Intent is limited; bots under 100 servers can use it without verification.
02:29:50 info gateway/channels/discord {"subsystem":"gateway/channels/discord"} [oracle] starting provider (@Oracle)
02:29:50 info gateway/channels/discord {"subsystem":"gateway/channels/discord"} discord channels resolved: 1470838236631924818/oracleâ1470838236631924818/1470838360221155644
02:29:50 info gateway/channels/discord {"subsystem":"gateway/channels/discord"} discord channels resolved: 1470838236631924818/oracleâ1470838236631924818/1470838360221155644 ```
02:33:13 info discord-auto-reply {"module":"discord-auto-reply"} {"channelId":"1470838360221155644","reason":"no-mention"} discord: skipping guild message
I didn't see any related error logs, at most this and previous errors.
info gateway/channels/discord {"subsystem":"gateway/channels/discord"} discord channels unresolved: 1470000000000/1470000000001
That log snippet is actually good news: it shows the allowlist resolver is working now (no âfailed to fetch bot identityâ, and no unresolved channels):
discord channels resolved: 1470838236631924818/oracleâ1470838236631924818/1470838360221155644
So the remaining âoracle can reply but doesnât đ-react (while default does)â almost certainly means:
- OpenClaw is attempting the reaction, but the Discord API call is failing for oracle (typically
403 Missing Permissions), or - youâre not actually seeing it because itâs added then removed very fast (
removeAckAfterReply: true).
Fast, no-guessing test
Temporarily set:
messages: {
ackReaction: "đ",
ackReactionScope: "all",
removeAckAfterReply: false
}
Restart, then send a message in the channel.
- If oracle still doesnât react even with
all: itâs not mention logic; itâs the reaction call failing (permissions/token/session). - If oracle reacts now: your
group-mentionsconditions arenât being met consistently (mention detection / requireMention path), or the reaction was being removed too quickly for you to notice.
Then grab the one log line that will prove it
Right now youâre on info logs, and the failure line is debug/verbose. Turn on debug logging briefly:
logging: { level: "debug", consoleLevel: "debug" }
Restart, trigger one message, then look for either:
discord react failed for channel ... (403) ...â permissionsdiscord react failed ... (401)/ auth error â token/account mismatchdiscord: inbound ... mention=yes/no ...â shows if OpenClaw thinks it was mentioned
Paste just the discord react failed ... line (tokens redacted). That will end the mystery in one shot.
Also: please confirm you already rotated the leaked tokens (they were posted publicly earlier).
That line is the smoking gun:
discord-auto-reply ... {"reason":"no-mention"} discord: skipping guild message
It means OpenClaw decided: this message did not mention the Oracle bot, and because your per-channel config has requireMention: true, it skips the message entirely. When it skips, it also wonât send the đ ack reaction.
So the behavior youâre seeing is consistent:
accountId=defaultâ youâre probably @âmentioning that bot (so it reacts)accountId=oracleâ the message you sent wasnât an actual @âmention of Oracle (so itâs skipped â no reaction)
What to try (quick)
- In that channel, send a message that explicitly @âmentions the Oracle bot user (the UI should show the mention highlight/autocomplete for Oracle).
- Temporarily set (for debugging) so you canât âmissâ it:
messages: { ackReactionScope: "all", removeAckAfterReply: false }
If Oracle still doesnât đ with all, then itâs a reaction API failure (youâll need debug logs to see the 403/401 line).
About the discord channels unresolved: <guild>/<channel> warning
That one is separate: it happens when the channel key after / is treated like a name/slug during resolution. Itâs cosmetic and can be eliminated by using channel slugs as keys, but itâs not the cause of the no-mention skip youâre hitting here.
If you can paste the exact text you sent (with the mention anonymized, e.g. âI typed @Oracle âŠâ), I can tell you whether itâs:
- you mentioned the other bot, or
- you typed plain text âoracleâ (not a real mention), or
- it was a reply/quote where you expected âimplicit mentionâ to count.
02:55:13 warn [EventQueue] Slow listener detected: DiscordReactionListener took 1077ms for event MESSAGE_REACTION_ADD
02:55:13 warn [EventQueue] Slow listener detected: DiscordReactionListener took 1130ms for event MESSAGE_REACTION_ADD ```
I think this is a program error. I simply changed the accountID from oracle to default, and ackReaction worked fine. Or perhaps the warnings above could indicate the problem.
That discord-auto-reply ⊠reason:"no-mention" line means the message never even makes it to the point where OpenClaw adds the đ.
Flow is:
- guild message arrives
- your channel has
requireMention: true - OpenClaw checks âwas this bot user mentioned?â
- if no â it logs
reason:"no-mention"and returns early (no reply, no ack reaction)
So if switching accountId from oracle â default makes đ work, the simplest explanation is: the message youâre sending is mentioning the default bot user, not the oracle bot user. (Two different bot users = two different mention IDs.)
Confirm in 10 seconds
Enable Discord Developer Mode â rightâclick the Oracle bot user â Copy User ID â send a message containing:
<@ORACLE_BOT_ID> test
(or in the UI, type @Oracle and pick the bot user from autocomplete so it renders as a real mention).
If you still get no-mention even when using <@id>, then it is a bug/token mismatch â and the next thing to check is that the oracle account token actually belongs to that bot user (look for logged in to discord as <id> in startup logs and compare IDs).
About the âSlow listener ⊠DiscordReactionListener ⊠MESSAGE_REACTION_ADDâ
Those warnings are not the cause of missing ack reactions. They just mean the reaction event handler took ~1s to process a reaction event (often because a reaction happened). Annoying, but not why your message got skipped as âno-mentionâ.
If you paste the logged in to discord as ... lines for oracle and default (or the bot user IDs), I can tell you immediately whether youâre mentioning the wrong bot vs a token/account mixup.
03:05:11 info gateway/channels/discord {"subsystem":"gateway/channels/discord"} discord gateway: WebSocket connection closed with code 1006
03:05:11 info gateway/channels/discord {"subsystem":"gateway/channels/discord"} discord gateway: Attempting resume with backoff: 1000ms after code 1006
03:05:46 debug plugins {"subsystem":"plugins"} plugin CLI register skipped (memory-core): command already registered (memory)
Log tail truncated (increase --max-bytes).
03:06:02 info discord-auto-reply {"module":"discord-auto-reply"} {"channelId":"1470838360221155644","reason":"no-mention"} discord: skipping guild message
03:06:04 warn [EventQueue] Slow listener detected: DiscordReactionListener took 1008ms for event MESSAGE_REACTION_ADD
03:06:04 warn [EventQueue] Slow listener detected: DiscordReactionListener took 1099ms for event MESSAGE_REACTION_ADD
03:06:04 debug diagnostic {"subsystem":"diagnostic"} lane enqueue: lane=session:agent:oracle:discord:channel:1470838360221155644 queueSize=1
03:06:04 debug diagnostic {"subsystem":"diagnostic"} lane dequeue: lane=session:agent:oracle:discord:channel:1470838360221155644 waitMs=7 queueSize=0
03:06:04 debug diagnostic {"subsystem":"diagnostic"} lane dequeue: lane=main waitMs=6 queueSize=0
03:06:04 debug agent/embedded {"subsystem":"agent/embedded"} embedded run start: runId=90334c92-9c08-41e5-b1a9-e0eff51b2778 sessionId=7f0ff272-2223-4192-87cc-c6585e6dda45 provider=google model=gemini-3-flash-preview thinking=medium messageChannel=discord ```
<@ORACLE_BOT_ID> test, I can use this exact mention bot; I can't send pictures here, but the bot replied and added an ackReaction.