fix(routing): prevent cross-channel reply routing in same-provider multi-channel setups#52423
fix(routing): prevent cross-channel reply routing in same-provider multi-channel setups#52423maximveksler wants to merge 1 commit intoopenclaw:mainfrom
Conversation
…lti-channel setups Fixes openclaw#45514
Greptile SummaryThis PR fixes a cross-channel reply routing bug (#45514) where, in same-provider multi-channel setups (e.g., two Slack channels monitored by one agent), the Key changes:
Note: The PR description states "Added 15 regression tests" — the test file actually contains 3 test cases (with roughly 15 Confidence Score: 5/5
Reviews (1): Last reviewed commit: "fix(routing): prevent cross-channel repl..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 259d68d740
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| originatingChannel: source.originatingChannel, | ||
| originatingTo: source.originatingTo, | ||
| originatingAccountId: source.originatingAccountId, | ||
| originatingThreadId: source.originatingThreadId, |
There was a problem hiding this comment.
Normalize empty thread IDs before routing metadata
resolveOriginRoutingMetadata() now returns source.originatingThreadId verbatim, but this function still treats "" as “no thread” when selecting source (line 55). With this change, a collect batch can emit originatingThreadId: "" instead of undefined, and downstream followup routing checks queued.originatingThreadId != null, so an empty string is treated as an explicit thread target rather than absent metadata. That can mis-thread or mis-route replies for providers where blank thread IDs are invalid; preserve prior behavior by mapping empty-string thread IDs back to undefined here.
Useful? React with 👍 / 👎.
Summary
Fixes #45514
When two Slack channels are monitored by the same agent, auto-replies can be delivered to the wrong channel. The
messagetool (explicit target) routes correctly, but the gateway auto-reply goes to the wrong destination.Root Cause
resolveOriginRoutingMetadata()insrc/auto-reply/reply/queue/drain.tsresolved each routing field (originatingChannel,originatingTo,originatingAccountId,originatingThreadId) independently via separate.find()calls across the queue items batch.When the queue contains items from different channels (e.g., two Slack channels), this can combine
originatingChannelfrom one item withoriginatingTofrom another — silently routing the reply to the wrong channel.Fix
Resolve all routing fields from a single consistent source item instead of picking each field independently. This prevents cross-item field mixing.
Before:
After:
Reproduction scenario
Two Slack channels (
#channel-A=C0AGC5F8WCW,#channel-B=C0AM7TH1NSZ) monitored by the same agent. Each gets correct session keys andlastTovalues. When a message from#channel-Bis processed while#channel-Atriggers a reply, the auto-reply goes to#channel-Binstead.Tests
Added 15 regression tests in
src/auto-reply/reply/queue/drain.test.tscovering:Verification
pnpm vitest run src/auto-reply/reply/queue/drain.test.ts src/auto-reply/reply/session-delivery.test.ts # 15/15 passPre-existing test failures in
session.test.ts(2) andreply-flow.test.ts(1) confirmed present onmainbefore this change.