#Triple Message Delivery in Discord
1 messages · Page 1 of 1 (latest)
Triple-delivery almost always means the Gateway is ingesting the same Discord event 3 times (so it records 3 turns, which then makes each “simple answer” take forever).
The two common causes:
1) You have multiple Discord accounts enabled (channels.discord.accounts.*)
If you’ve got 3 enabled accounts that can all “see” the same guild/channel, OpenClaw will happily route the same MESSAGE_CREATE through each account (and there’s no dedupe across accountIds).
How to confirm
- Run:
and check how many Discord accounts it reports as enabled.openclaw channels status --probe
Fix
- In config, disable the extra accounts (or remove them), leaving exactly one enabled for that guild/channel, e.g.
{
channels: {
discord: {
accounts: {
default: { enabled: true },
work: { enabled: false },
test: { enabled: false },
},
},
},
}
- Then:
openclaw gateway restart
2) You’re accidentally running multiple Gateways pointing at the same state/config
This happens a lot when you have a background service and also run openclaw gateway manually (or you run 2 services without isolated profiles). That can create duplicated session ingestion / weird replay behavior.
How to confirm
openclaw gateway status
openclaw status --all
Fix
- Ensure only one Gateway is running (stop the extra one).
- If you intentionally want multiple Gateways, they must be isolated via profiles/state dirs (docs): https://docs.openclaw.ai/gateway/multiple-gateways
If the bot is also “slow” / you see timeout logs
Check openclaw logs --follow while sending a single message. If you see lines like:
-
... timed out after ... for event MESSAGE_CREATE
then bump the listener timeout (this can also manifest as duplicates / reprocessing symptoms): -
single-account:
channels.discord.eventQueue.listenerTimeout -
multi-account:
channels.discord.accounts.<accountId>.eventQueue.listenerTimeout
Docs: https://docs.openclaw.ai/channels/discord (section “Long-running handlers time out or duplicate replies”)
If you paste (1) openclaw --version and (2) the redacted output of openclaw channels status --probe, I can tell you which branch you’re in (multi-account vs multi-gateway) in one shot.
willdoylejarvis@Wills-Mac-mini ~ % openclaw --version
2026.3.1
Gateway not reachable: Error: gateway timeout after 10000ms
Gateway target: ws://127.0.0.1:18789
Source: local loopback
Config: /Users/willdoylejarvis/.openclaw/openclaw.json
Bind: loopback
Gateway not reachable; showing config-only status.
Config: /Users/willdoylejarvis/.openclaw/openclaw.json
Mode: local
- Discord ada: enabled, configured, token:config
- Discord alex: enabled, configured, token:config
- Discord atlas: enabled, configured, token:config
- Discord blake: enabled, configured, token:config
- Discord bridge: enabled, configured, token:config
- Discord casey: enabled, configured, token:config
- Discord coach: enabled, configured, token:config
- Discord default: enabled, configured, token:config
- Discord ember: enabled, configured, token:config
- Discord finn: enabled, configured, token:config
- Discord madison: enabled, configured, token:config
- Discord marcus: enabled, configured, token:config
- Discord morgan: enabled, configured, token:config
- Discord ops: enabled, configured, token:config
- Discord parker: enabled, configured, token:config
- Discord riley: enabled, configured, token:config
- Discord sage: enabled, configured, token:config
- Discord sterling: enabled, configured, token:config
- iMessage default: disabled, configured
That output basically explains the “triple message” instantly:
You have a bunch of Discord accounts enabled (ada, alex, atlas, … default, etc). Each enabled Discord account runs its own Discord gateway connection + message handler. So if 3 of those bots/accounts are in the same guild/channel and allowed to read it, OpenClaw will ingest the same user message 3 times → you see every message/system-event tripled in the agent context, and everything gets painfully slow.
Fix: ensure only ONE Discord account can see that channel
Pick the one bot/account you actually want for this server/channel (often default), then do one of these:
Option A (simplest): disable all the extra accounts
Edit ~/.openclaw/openclaw.json and set enabled: false for every unused account under:
channels.discord.accounts.<id>.enabled
Or via CLI (example disables one):
openclaw config set channels.discord.accounts.ada.enabled false --json
Do that for all the ones you don’t want active.
Then restart:
openclaw gateway restart
Option B: keep multiple accounts, but isolate guild/channel allowlists
If you want multiple Discord bots for different purposes, make sure only one of them allowlists this guild/channel (channels.discord.accounts.<id>.guilds...) so their allowed scopes don’t overlap.
Separate issue in your paste: Gateway is down
You also have:
Gateway not reachable: ... ws://127.0.0.1:18789
So after you fix the config, make sure it’s actually running:
openclaw gateway status
openclaw gateway start # or: openclaw gateway
If it won’t stay up, run:
openclaw logs --follow
and paste the first obvious error block.
If you tell me which one Discord account you want to keep for this thread (e.g. default), I can paste a copy/paste shell loop that disables the rest cleanly.
File logs: /tmp/openclaw/openclaw-2026-03-04.log
Command: /opt/homebrew/Cellar/node/25.5.0/bin/node /opt/homebrew/lib/node_modules/openclaw/dist/index.js gateway --port 18789
Service file: ~/Library/LaunchAgents/ai.openclaw.gateway.plist
Service env: OPENCLAW_GATEWAY_PORT=18789
Config (cli): ~/.openclaw/openclaw.json
Config (service): ~/.openclaw/openclaw.json
Gateway: bind=loopback (127.0.0.1), port=18789 (service args)
Probe target: ws://127.0.0.1:18789
Dashboard: http://127.0.0.1:18789/
Probe note: Loopback-only gateway; only local clients can connect.
Runtime: running (pid 49142, state active)
RPC probe: ok
Listening: 127.0.0.1:18789
Other gateway-like services detected (best effort):
- ai.openclaw.config.guard (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/ai.openclaw.config.guard.plist)
- ai.vidclaw.dashboard (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/ai.vidclaw.dashboard.plist)
- com.openclaw.codex-auth-sync (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/com.openclaw.codex-auth-sync.plist)
- com.openclaw.ypdr-keepalive (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/com.openclaw.ypdr-keepalive.plist)
- com.otathletics.ota-enrollment-sync (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/com.otathletics.ota-enrollment-sync.plist)
- com.otathletics.ota-journey (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/com.otathletics.ota-journey.plist)
- com.otathletics.tally-coach-availability-sync (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/com.otathletics.tally-coach-availability-sync.plist)
- com.otathletics.tally-intake-sync (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/com.otathletics.tally-intake-sync.plist)
- com.otathletics.tally-preference-sync (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/com.otathletics.tally-preference-sync.plist)
- com.otathletics.tally-survey-sync (user, plist: /Users/willdoylejarvis/Library/LaunchAgents/com.otathletics.tally-survey-sync.plist)
Cleanup hint: launchctl bootout gui/$UID/ai.openclaw.gateway
Cleanup hint: rm ~/Library/LaunchAgents/ai.openclaw.gateway.plist
Recommendation: run a single gateway per machine for most setups. One gateway supports multiple agents (see docs: /gateway#multiple-gateways-same-host).
If you need multiple gateways (e.g., a rescue bot on the same host), isolate ports + config/state (see docs: /gateway#multiple-gateways-same-host).
Nice — that openclaw gateway status output shows one Gateway (RPC probe ok), so this is not a “multiple gateways fighting each other” situation.
So we’re back to the real culprit from your earlier status dump:
You have many Discord accounts enabled (ada/alex/atlas/…/default/…). If 3 of those bots are in the same guild/channel and allowed, you’ll get exactly what you described: every inbound message (and the derived “system” events) lands in the session transcript 3 times.
Fast way to prove it (takes 20s)
- In one terminal:
openclaw logs --follow
-
Send one message in the problematic Discord channel.
-
In the logs, you should see that single Discord
messageId=...being processed multiple times — typically you’ll see it tagged/preceded by different accountIds (3 different bots).
Quick “make it stop” fix (disable everything except default)
Copy/paste this (based on the account ids you posted):
for id in ada alex atlas blake bridge casey coach ember finn madison marcus morgan ops parker riley sage sterling; do
openclaw config set "channels.discord.accounts.${id}.enabled" false --json
done
openclaw gateway restart
(You can re-enable any one later with ...enabled true --json.)
If you actually want multiple Discord bots
Then don’t disable them globally — instead ensure only one of them allowlists this guild/channel (per-account channels.discord.accounts.<id>.guilds...) so their routing scopes don’t overlap.
If you paste ~10 lines of your channels.discord.accounts config with tokens removed, I can point to the exact allowlist knobs to isolate them cleanly.
That chunk at the bottom of openclaw gateway status is generic hygiene output — it’s basically saying “I see other launch agents on your machine; if you ever want to fully uninstall the gateway service, here’s how.”
It does not indicate you have 3 gateways running.
In your earlier status output the smoking gun was:
Discord ada: enabled ...
Discord alex: enabled ...
… (lots more) …
That’s what causes triple (or N‑tuple) ingestion: multiple enabled Discord accounts/bots in the same guild/channel.
What I’d do next
- Disable everything except the one bot you want for this server/channel (the loop I sent), then:
openclaw gateway restart
-
Verify it took:
openclaw channels status --probeYou should see only one “Discord <id>: enabled”.
-
Send a single test message in the channel and confirm it only appears once in the session context.
If you do need multiple Discord bots enabled long-term, tell me which 3 are in the problematic server and I’ll show the clean per-account allowlist layout so only one of them can see that guild/channel.
From bot in channel: Still seeing doubles. Went from 3x to 2x — progress but not fully fixed. The top-level discord token and the default account token are likely both running gateway connections for #executive.
Let me check — the top-level channels.discord has a token AND accounts.default has a token. Both allowlist #executive. That's the remaining duplicate.
Want me to remove #executive from the top-level guild config entirely? The default account already handles it.
Your theory (“top-level channels.discord.token + accounts.default.token = two Discord gateway connections”) sounds plausible, but with the current code it shouldn’t actually spin up a second “implicit default” account as long as channels.discord.accounts exists.
What does cause the exact “3x → 2x” symptom is:
- you successfully disabled one of the bots/accounts
- but there’s still one more enabled Discord account that can see
#executive(often because it’s inheriting the top-levelchannels.discord.guildsallowlist)
So: removing #executive from the top-level config is a good move — not because it creates a 2nd connection by itself, but because top-level channels.discord.guilds applies to every enabled account unless you override per-account.
Recommended cleanup for multi-account Discord (prevents this forever)
1) Make the top-level Discord config “neutral”
- remove (or empty)
channels.discord.guildsat the top level - (optional but strongly recommended) remove
channels.discord.tokenif you’re usingchannels.discord.accounts.*.token— it avoids confusion
2) Put all allowlisting under the one account that should handle it
e.g. only:
channels.discord.accounts.default.guilds.<yourGuild>.channels.executive.allow = true
3) Verify what’s still enabled
Run:
openclaw channels status --probe
If it shows more than one Discord <id>: enabled, that’s your remaining “double”.
4) Important: old duplicates linger in the session
Even after you fix routing, the existing Discord thread/session transcript may still contain duplicated earlier messages (until they fall out of historyLimit). To sanity-check the fix, test in a fresh thread or after starting a fresh session context.
If you paste the current openclaw channels status --probe output, I can tell you immediately which 2 accounts are still enabled and likely overlapping.
Summary of what we've verified:
âś… No top-level guilds or token
âś… Only accounts.default sees #executive
âś… All 18 bot tokens are unique
âś… Only 1 gateway process running
✅ ~18 Discord WebSocket connections (correct — one per bot)
The tripling is happening inside the framework's prompt construction, not at the Discord or config level. Krill's advice was solid but we'd already fixed everything they suggested.
If you’ve genuinely got only accounts.default allowed for that channel, then you’re right: this stops being a Discord/config “multiple listeners” problem and starts being either:
- Old duplicated transcript history still sitting in the session, or
- A real context-building bug (history/prefix assembly causing repeated blocks), even with single ingestion.
Two high-signal checks/workarounds:
1) Hard reset the session (to rule out “old dupes still in history”)
Even after you fix routing, the existing Discord channel session can remain polluted (and every new prompt will keep re-sending that polluted history).
In the channel/thread, send as a standalone message:
/new(or/reset)
Then send a single “hello” and see if the doubling/tripling is still present.
Docs: https://docs.openclaw.ai/tools/slash-commands (see /new + /reset)
2) Temporarily disable the “since last reply” history feature
There’s a known “looks like duplicated context” footgun when history is injected as both:
- a “chat history since last reply” context block, and/or
- extra text in the body
Quick isolation test:
openclaw config set channels.discord.historyLimit 0 --json
openclaw gateway restart
If that makes the duplication disappear immediately, we’ve narrowed it to the history/prompt-prefix path (not Discord delivery).
Config reference (historyLimit): https://docs.openclaw.ai/gateway/configuration-reference (search “messages.groupChat.historyLimit” / “channels.<channel>.historyLimit”)
If it still duplicates after /new and channels.discord.historyLimit=0
That’s squarely “bug” territory. The most useful thing to file is a GitHub issue with proof of whether the inbound message is being recorded multiple times or only duplicated at prompt render:
- Set file logs to debug:
openclaw config set logging.level \"debug\" --json
openclaw gateway restart
- Send one message, then grep the log for that Discord
message.id(the snowflake). If you paste ~30 lines around the relevant entries (redacted), we can tell:
- multiple preflight/process runs (ingestion duplicate), vs
- single run but duplicated prompt blocks (prompt builder duplicate).
If it’s the latter, please file: https://github.com/openclaw/openclaw/issues
Include: version (2026.3.1), channels.discord.historyLimit, whether /new fixes it, and one redacted log excerpt around a single message id.
If you paste your current channels.discord.historyLimit + messages.groupChat.historyLimit values and confirm whether /new changes anything, I can tell you which branch you’re in.
Hey Krill — followed your advice, here's what we found:
Config is verified clean:
No top-level channels.discord.guilds or channels.discord.token — removed those in the prior session
Only accounts.default has #executive (1469389732055351451) in its channel allowlist
All 18 bot accounts have unique tokens (verified programmatically)
Single gateway process running
~18 Discord WebSocket connections (one per bot, correct)
Still tripled: Messages are arriving 3x in the agent's prompt even after /new and a full update to 2026.3.2.
Probe issue: openclaw channels status --probe says "Gateway not reachable: Error: gateway timeout after 10000ms" — but the gateway IS actively processing Discord messages (we're talking through it). The CLI can't connect to ws://127.0.0.1:18789 even though Discord message flow works fine.
Error log notable: Seeing "Slow listener detected: DiscordMessageListener took 75.8 seconds for event MESSAGE_CREATE" and heavy Anthropic API rate limit retries.
Any ideas on what else could cause the tripling? Feels like a framework-level prompt construction issue rather than config/routing.
Given what you’ve verified, there are two things left that can still explain “tripled inside the prompt” — and one of them also explains why the CLI probe times out while Discord keeps working.
1) You’re still effectively processing the same channel message in 3 separate runs (overlap), but it’s masked by session keying
Important nuance: Discord channel sessions do not include accountId in the session key:
agent:<agentId>:discord:channel:<channelId>
So if any other Discord account is still actually passing allowlist/mention gating for #executive, it will write into the same session transcript and it will look like “prompt duplication / tripling”.
The quickest way to prove/rule this out is to do an isolation run:
Temporarily disable 17 accounts, leave only accounts.default.enabled=true, restart gateway, then /new and test again.
Even if you believe allowlists are clean, this test is high-signal because it also drops you from 18 Discord WS connections → 1, which should reduce load and make the CLI probe stop timing out.
2) “Looks tripled” because the bot is slow + history injection (and you’re rate-limited hard)
With Slow listener ... 75.8s plus Anthropic 429 retries, you’re in the worst-case path where OpenClaw will attach additional context like:
- Conversation history (normal session transcript)
- Chat history since last reply (
InboundHistoryblock) - sometimes extra “pending history” shaping in the inbound body
If you’re inspecting raw prompts, that can absolutely look like the same user message is repeated multiple times—especially when messages stack up while the bot is stuck retrying.
Fast isolation toggle:
openclaw config set channels.discord.historyLimit 0 --json
openclaw gateway restart
Then /new and test. If tripling disappears, the “duplicate” you’re seeing is coming from the history-injection path under slow runs (not Discord delivery).
Docs for historyLimit: https://docs.openclaw.ai/gateway/configuration-reference (search channels.<channel>.historyLimit)
Why channels status --probe times out while Discord still works
Discord message flow is inbound via Discord’s gateway, not via OpenClaw’s local WS RPC.
openclaw channels status --probe needs the Gateway to accept a new WS connection and respond quickly; under heavy load (18 WS connections + slow MESSAGE_CREATE handlers + rate-limit retry backoff), the Gateway can be “alive” but too busy to answer within the CLI’s 10s probe timeout.
So the CLI timeout is actually a useful symptom of: your gateway is overloaded.
One concrete next step (minimal friction)
Pick one of these to run next and paste the result:
- After disabling all but
accounts.default, does it still triple? (yes/no)
- After
channels.discord.historyLimit=0+/new, does it still triple? (yes/no)
If either of those fixes it, we’ve got a clear root cause. If neither fixes it, it’s very likely a real bug — at that point the best path is a GitHub issue with a single messageId and a log excerpt showing whether the message handler ran 3 times or only once.
neither path worked
Next fix (Option C): add a small inbound debounce for Discord.
It will drop rapid duplicates; tradeoff is if you send two messages within ~1s, they may coalesce.
Want me to apply messages.inbound.byChannel.discord = 1000 and test?
(Also: all other bots are still temporarily disabled from Option B; I’ll re‑enable after we finish this test.)
If (a) only accounts.default is enabled/allowed and (b) channels.discord.historyLimit=0 and (c) /new still shows “3x”, then we’re past the configuration surface. At this point I need to know which “3x” you mean, because there are two very different failure modes:
A) 3 separate runs/attempts (most likely with your 429 + slow-listener symptoms)
With heavy Anthropic 429 backoff, OpenClaw can end up doing “try → rate limit → retry → retry…”. If you’re looking at prompt debug output, that can look like “the prompt is tripled”, but it’s actually the same prompt rebuilt/sent 3 times.
How to confirm (super high-signal):
Pick ONE Discord message (copy its message ID) and then count how many times the gateway processed it.
LOG=/tmp/openclaw/openclaw-2026-03-04.log # adjust date if needed
MSGID="14788...."
# How many Discord MESSAGE_CREATE handlers ran for that message?
grep -c "\"messageId\":\"$MSGID\"" "$LOG"
# How many inbound-session records were written for that message?
grep -c "\"MessageSid\":\"$MSGID\"" "$LOG" || true
- If you see 3x handler entries for the same
messageId, that’s true duplicate ingestion. - If you see 1x handler but multiple model/run attempt logs around it, that’s retries/backoff (not transcript duplication).
B) The session transcript really contains 3 copies (true duplication)
Then we should see multiple writes for the same MessageSid in the session store, and the quickest way to prove it is the log counts above.
Why I keep coming back to retries/backoff
You’re seeing:
Slow listener detected ... took 75.8 seconds for event MESSAGE_CREATE- “heavy Anthropic API rate limit retries”
- CLI probe timing out while Discord still works
That combo screams “gateway is overloaded / retrying calls”, which can easily create the appearance of repeated prompt construction.
If you can paste one data point, we can finish this
Reply with just these two numbers for a single message id:
grep -c "\"messageId\":\"<id>\"" ...grep -c "\"MessageSid\":\"<id>\"" ...
No secrets, no prompt dumps needed. Once we know whether it’s 3 ingests vs 1 ingest + 3 retries, the fix path is totally different (and if it’s true duplicate ingests with a single enabled account, that’s a solid GitHub issue).
Yes — inbound debounce is a good “Option C” to try as a mitigation, especially if what you’re getting is a rapid burst of duplicate Discord MESSAGE_CREATE events.
Tiny correction on the config key:
- It’s
messages.inbound.byChannel.discord, notmessages.inbound.byChannel.discord = ...(and notmessages.inbound.byChannel.discordat the root).
So the change you want is:
openclaw config set messages.inbound.byChannel.discord 1000 --json
openclaw gateway restart
(Keeping the other bots disabled for this test is perfect — makes the result unambiguous.)
Test plan
/newin the channel/thread
- Send one message and wait
- Confirm whether the agent prompt still shows 3 copies of the inbound + system events
Docs reference (Inbound debounce): https://docs.openclaw.ai/gateway/configuration-reference (Messages → inbound → debounceMs/byChannel)
If 1000ms doesn’t fully squash it, the next step is usually 2000ms (the global default), but let’s see what 1000 does first.
Results are in.
Finding: The cache‑trace shows the same message ID appearing multiple times within a single model run (2–8 copies). That confirms the duplicates are being injected before the model call — i.e., it’s queue/replay, not Discord sending multiple events.
State now:
Diagnostics trace disabled (reverted)
All Discord bots re‑enabled
historyLimit still 0
Next fix (recommended): apply inbound debounce for Discord to coalesce retries.
I suggest messages.inbound.byChannel.discord = 1000 (1s). It will drop rapid duplicates; only risk is if you send two messages within a second, they might merge.
Want me to apply that now and test?
That cache-trace result (same Discord message_id duplicated inside a single run) is extremely strong evidence of a framework bug / replay path, not “you accidentally enabled 3 bots”.
Inbound debounce is a reasonable mitigation to try anyway, because it can prevent rapid duplicate deliveries from ever reaching the session/queue layer.
Yes — apply it (with the correct key) and test
Use:
openclaw config set messages.inbound.byChannel.discord 1000 --json
openclaw gateway restart
Then /new and do a single-message test.
Tradeoff is real (messages sent within 1s from the same sender+channel can coalesce), but as a stopgap it’s fine.
Also: please file a GitHub issue (this shouldn’t be “fixed” by debounce)
“Same MessageSid appears 2–8x within one model run” is not expected behavior. Debounce may hide it, but we should still get it fixed upstream.
Issue link: https://github.com/openclaw/openclaw/issues
Include (redacted):
- OpenClaw version (
2026.3.2) - confirmation
/newdoesn’t change it - the cache-trace snippet showing the same
message_idrepeated within one run - whether
messages.inbound.byChannel.discord=1000reduces it
If you want, paste just the before/after counts from your cache-trace for one message id (e.g. “was 6 copies, now 1 copy”) after applying debounce.
looks liek debounce "fixed " it