#Does anyone know how to configure multiple bots in Discord?

1 messages · Page 1 of 1 (latest)

crude citrusBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

supple beacon
#

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.

worthy coveBOT
# supple beacon This is a very strange problem. The bot can reply, but there are warnings in the...

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):

  1. The oracle bot is not actually in that server, or doesn’t have access to that channel (needs at least View Channel).
  2. You switched the default account to oracle, but oracle has no token configured. Reminder: DISCORD_BOT_TOKEN only applies to the default account; other accounts must have channels.discord.accounts.<id>.token.
  3. Privileged intents are not enabled for the oracle bot 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 oracle has 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 } } } } },
      }
    }
  }
}
#

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.

supple beacon
#
  1. Oracle has a token and it's enabled, but I shouldn't publicly display the token here.
  2. The bot is already on the server, can reply to me, and has admin privileges to see the channel.
  3. Message content intent is enabled.
  4. Server member intent is enabled.
    {
      "agentId": "oracle",
      "match": {
        "channel": "discord",
        "accountId": "oracle"
      }
    },
    {
      "agentId": "sentinel",
      "match": {
        "channel": "discord",
        "accountId": "sentinel"
      }
    }
  ] ```
supple beacon
# worthy cove Yep — if **#1 (oracle)** is the case, that warning + “no reaction” is exactly wh...
    "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
                }
              }
            }
          }
        }
      }
    }
  } ```
worthy coveBOT
# supple beacon 1. Oracle has a token and it's enabled, but I shouldn't publicly display the tok...

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

supple beacon
worthy coveBOT
# supple beacon ``` "messages": { "responsePrefix": "**[ {identity.name} ]** ", "ackReac...

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 (botUserId was 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 all but not with group-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, botUserId is missing → group-mentions ack 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.

supple beacon
worthy coveBOT
# supple beacon It's not a permissions issue; this is a very strange problem. When I change the ...

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.

supple beacon
# worthy cove ## B) Oracle can’t fetch its own bot identity (botUserId) There’s a specific edg...
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 ```
supple beacon
worthy coveBOT
# supple beacon ``` 02:29:49 info cron {"module":"cron","storePath":"/home/gulumew/.openclaw/cro...

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-mentions conditions 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) ... ← permissions
  • discord react failed ... (401) / auth error ← token/account mismatch
  • discord: 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)

  1. In that channel, send a message that explicitly @‑mentions the Oracle bot user (the UI should show the mention highlight/autocomplete for Oracle).
  2. 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.
supple beacon
# worthy cove ```json5 messages: { ackReactionScope: "all", removeAckAfterReply: false } ...
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.
worthy coveBOT
# supple beacon ``` 02:55:11 info discord-auto-reply {"module":"discord-auto-reply"} {"channelId...

That discord-auto-reply 
 reason:"no-mention" line means the message never even makes it to the point where OpenClaw adds the 👀.

Flow is:

  1. guild message arrives
  2. your channel has requireMention: true
  3. OpenClaw checks “was this bot user mentioned?”
  4. 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.

supple beacon
# worthy cove That `discord-auto-reply 
 reason:"no-mention"` line means the message **never e...
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.