Skip to content

fix(queue): deduplicate followup queue entries#600

Merged
steipete merged 2 commits intoopenclaw:mainfrom
samratjha96:fix/discord-duplicate-messages
Jan 9, 2026
Merged

fix(queue): deduplicate followup queue entries#600
steipete merged 2 commits intoopenclaw:mainfrom
samratjha96:fix/discord-duplicate-messages

Conversation

@samratjha96
Copy link
Copy Markdown
Contributor

@samratjha96 samratjha96 commented Jan 9, 2026

Was facing some issues with multiple responses to my questions on Discord. Did some digging with Claude and it's because Discord seems to fire off multiple events if the previous one took a while to get processed.

I think this is a safe assumption to always drop the EXACT same message from being enqueued if it's already in the queue. Didn't test with other providers tbf but seems like the right behavior

Summary

  • Add exact-match deduplication to the followup queue to prevent duplicate responses
  • Extracted isPromptAlreadyQueued() helper for clarity

Problem

When messages arrived while the agent was busy processing, the same message could be enqueued multiple times into the followup queue. This caused the bot to respond to the same user message 2-4+ times.

Root cause: Discord's event system can emit the same message multiple times (e.g., during reconnects or slow listener processing), and the followup queue had no deduplication logic.

Solution

Add simple exact-match deduplication in enqueueFollowupRun(): if a prompt is already in the queue, skip adding it again.

Changes:

  • src/auto-reply/reply/queue.ts - Added isPromptAlreadyQueued() helper
  • src/auto-reply/reply/queue.collect-routing.test.ts - Added test coverage

Testing

  • pnpm lint
  • pnpm build
  • pnpm test
  • Manually verified on Discord: single response per message even when multiple events fire

Closes: #598

@thewilloftheshadow
Copy link
Copy Markdown
Member

The prompt from Discord does include the message ID in it, so if a user truly wants to send the same message multiple times that will still work

@steipete steipete self-assigned this Jan 9, 2026
@samratjha96
Copy link
Copy Markdown
Contributor Author

The prompt from Discord does include the message ID in it, so if a user truly wants to send the same message multiple times that will still work

There's an envelope created in https://github.com/clawdbot/clawdbot/blob/main/src/auto-reply/envelope.ts#L26-L36 that includes the timestamp so the prompt ends up looking like:

[Discord Guild #channel 2026-01-09T17:10Z] Hello world
[from: username user id:456]

The [message_id: xxx] seems to be added separately by: https://github.com/clawdbot/clawdbot/blob/main/src/auto-reply/reply/body.ts#L33-L38 but only when the message runs through the main path!! not when it's queued.

Not disagreeing because we are saying the same thing :) just wanted to mention that's what i ended up finding.

Duplicate events for the same message -> same timestamp -> same prompt -> deduplicated
User sends same text twice -> different timestamp -> different prompt -> both processed

I think the key ends up being the timestamp

samratjha96 and others added 2 commits January 9, 2026 20:40
…esponses

## Problem

When messages arrived while the agent was busy processing a previous message,
the same message could be enqueued multiple times into the followup queue.
This happened because Discord's event system can emit the same message multiple
times (e.g., during reconnects or due to slow listener processing), and the
followup queue had no deduplication logic.

This caused the bot to respond to the same user message 2-4+ times.

## Solution

Add simple exact-match deduplication in `enqueueFollowupRun()`: if a prompt
is already in the queue, skip adding it again. Extracted into a small
`isPromptAlreadyQueued()` helper for clarity.

## Testing

- Added test cases for deduplication (same prompt rejected, different accepted)
- Manually verified on Discord: single response per message even when multiple
  events fire during slow agent processing
@steipete steipete force-pushed the fix/discord-duplicate-messages branch from aaae31c to d3a0114 Compare January 9, 2026 19:45
@steipete steipete merged commit fb989cd into openclaw:main Jan 9, 2026
18 checks passed
@steipete
Copy link
Copy Markdown
Contributor

steipete commented Jan 9, 2026

Landed via temp rebase onto main.

  • Gate: pnpm lint && pnpm build && pnpm test
  • Land commit: d3a0114
  • Merge commit: fb989cd

Thanks @samratjha96!

@samratjha96
Copy link
Copy Markdown
Contributor Author

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⣶⣶⣶⣤⣄⡀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⠿⢋⣉⠀⠀⠀⠀⠀⠉⠻⣷⡀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡿⠋⠀⢾⣿⡆⢠⣾⡿⢿⣦⢸⣿⣷⡀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⠁⠀⠀⠈⠉⠀⣾⡏⠀⠈⣿⡇⠀⠹⣷⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⡟⠀⠀⠀⠀⠀⠀⢿⣇⠀⠀⣿⡇⠀⠀⢻⡇⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⠀⠀⠀⠀⠀⠀⠀⠘⣿⣆⣰⣿⠃⠀⠀⣸⡇⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⠃⠀⠀⢀⣿⠁⠀⠀
⠀⠀⠀⠀⠀⠀⢀⣼⠟⠀⠻⣷⡀⠀⠀⠀⠀⠀⠀⠀⠈⠃⠀⠀⠀⣾⠇⠀⠀⠀
⠀⠀⠀⠀⠀⣰⡿⠋⠀⠀⠀⠘⠿⣶⣤⣤⡄⠀⠀⠀⠀⠀⠀⠀⢸⡿⠀⠀⠀⠀
⠀⠀⠀⣠⡾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⢸⣇⠀⠀⠀⠀
⠀⠀⣼⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡀⠀⠀⠀

zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
…e-messages

fix(queue): deduplicate followup queue entries
alexey-pelykh added a commit to remoteclaw/remoteclaw that referenced this pull request Mar 11, 2026
…erry-pick openclaw#600 1/4) (#1064)

* fix: tighten isSilentReplyText to match whole-text only

Cherry-picked-from: 2f2110a
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(auto-reply): align reply-flow tests with whole-text silent token matching

Update test expectations in reply-flow.test.ts to match the tightened
isSilentReplyText regex from the previous commit. Partial matches like
"NO_REPLY -- nope" are no longer considered silent.

Cherry-picked-from: openclaw/openclaw@e64d72299e (partial — test-only)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(auto-reply): align route-reply and msteams tests with whole-text matching

Update test expectations that assumed partial silent-token matching.
With whole-text matching, "NO_REPLY -- explanation" is no longer
considered a silent reply and must be delivered normally.

Cherry-picked-from: openclaw/openclaw@e64d72299e (partial — test-only)
Cherry-picked-from: openclaw/openclaw@fec3fdf7ef
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
alexey-pelykh added a commit to remoteclaw/remoteclaw that referenced this pull request Mar 12, 2026
…penclaw#600 2/4) (#1065)

* fix(auto-reply): tighten silent token semantics and prefix streaming

Add isSilentReplyPrefixText checks alongside isSilentReplyText in
agent-runner-execution, streaming-directives, and typing controller.
This prevents partial silent-token prefixes from triggering typing
indicators or being sent as replies.

Cherry-picked-from: openclaw/openclaw@e64d72299e
Co-Authored-By: Ayaan Zaidi <zaidi@uplause.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(auto-reply): add missing HEARTBEAT_TOKEN export to tokens.ts

The cherry-picked commit imports HEARTBEAT_TOKEN in
agent-runner-execution.ts but the constant was not defined in the
fork's tokens.ts. Add the export to fix the build.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Ayaan Zaidi <zaidi@uplause.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants