openclaw - ✅(Solved) Fix sessions_send inter-agent messages overwrite session lastRoute to webchat, breaking Discord reply routing [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#54441Fetched 2026-04-08 01:27:26
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Participants
Timeline (top)
referenced ×4cross-referenced ×1

When agent A sends an inter-session message to agent B via sessions_send, the message arrives in B's session tagged as channel=webchat. OpenClaw then updates B's session lastRoute to webchat. B's next reply to a Discord user is routed to the webchat UI instead of Discord, making it invisible on mobile.

Root Cause

When agent A sends an inter-session message to agent B via sessions_send, the message arrives in B's session tagged as channel=webchat. OpenClaw then updates B's session lastRoute to webchat. B's next reply to a Discord user is routed to the webchat UI instead of Discord, making it invisible on mobile.

Fix Action

Fix / Workaround

  • In multi-agent fleet setups with heavy inter-agent communication, JP's Discord/mobile experience is broken repeatedly throughout the day
  • Every sessions_send from another agent poisons the reply route
  • Compounds with cron jobs that fire inter-agent alerts — each alert resets lastRoute to webchat
  • No config workaround exists — session.dmScope: main + allowFrom pinning doesn't apply to Discord channel sessions

Workaround (current)

PR fix notes

PR #58013: fix: inter-session messages must not overwrite established external lastRoute

Description (problem / solution / changelog)

Problem

Fixes #54441

Inter-session messages (sessions_send) always arrive with channel=webchat. When resolveLastChannelRaw / resolveLastToRaw processed these turns they could overwrite a previously-established external lastChannel/lastTo (e.g. discord, telegram) with webchat routing identifiers, breaking delivery on all subsequent turns of that session.

Root cause: both resolver functions had no visibility into whether the current turn originated from sessions_send (inter-session) vs a real user message. The existing guard only protected against the webchat-with-established-external-route case for direct-session keys (fix #47745), but not for the general inter-session case.

Fix

  • session-delivery.ts — add isInterSession?: boolean to both resolveLastChannelRaw and resolveLastToRaw. When true and an external route is already persisted, return the persisted route unchanged. The fast-path sits above all other logic and adds zero overhead for non-inter-session turns.
  • session.ts — import isInterSessionInputProvenance from src/sessions/input-provenance.ts and pass isInterSession: isInterSessionInputProvenance(ctx.InputProvenance) to both resolvers at the existing call site (~line 440).

Behaviour for sessions with no external route established is fully preserved — inter-session can still set the initial route on brand-new sessions.

Files changed

FileChange
src/auto-reply/reply/session-delivery.tsAdd isInterSession param + guard to both resolvers
src/auto-reply/reply/session.tsImport isInterSessionInputProvenance, pass flag at call sites
src/auto-reply/reply/session-delivery.test.ts6 new test cases covering the fix and edge cases

Tests

All 18 tests in session-delivery.test.ts pass (12 pre-existing + 6 new):

  • inter-session message does NOT overwrite established Discord lastChannel
  • inter-session message does NOT overwrite established Telegram lastChannel
  • inter-session message does NOT overwrite established external lastTo
  • regular Discord user message DOES update lastChannel normally
  • inter-session on a NEW session (no persisted external route) — falls through to normal resolution
  • inter-session with no persistedLastTo — no crash, falls through

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/auto-reply/reply/session-delivery.test.ts (modified, +77/-0)
  • src/auto-reply/reply/session-delivery.ts (modified, +17/-0)
  • src/auto-reply/reply/session.ts (modified, +4/-0)
RAW_BUFFERClick to expand / collapse

Summary

When agent A sends an inter-session message to agent B via sessions_send, the message arrives in B's session tagged as channel=webchat. OpenClaw then updates B's session lastRoute to webchat. B's next reply to a Discord user is routed to the webchat UI instead of Discord, making it invisible on mobile.

Steps to reproduce

  1. Agent A (e.g. Omega) has an active Discord channel session (agent:omega:discord:channel:XYZ)
  2. Agent B (e.g. Swiv) has an active Discord channel session (agent:swiv:discord:channel:XYZ)
  3. Agent A calls sessions_send(sessionKey: "agent:swiv:discord:channel:XYZ", message: "...")
  4. Agent B processes the inter-agent message
  5. Agent B replies to a user who messaged via Discord
  6. B's reply appears in webchat UI only — not delivered to Discord

Expected behavior

Inter-session messages should NOT update the receiving session's lastRoute. The session's reply channel should remain pinned to wherever the last external user message came from (Discord in this case).

Actual behavior

lastRoute is overwritten to webchat on every inter-session message. All subsequent replies route to webchat until the next external Discord message resets it.

Impact

  • In multi-agent fleet setups with heavy inter-agent communication, JP's Discord/mobile experience is broken repeatedly throughout the day
  • Every sessions_send from another agent poisons the reply route
  • Compounds with cron jobs that fire inter-agent alerts — each alert resets lastRoute to webchat
  • No config workaround exists — session.dmScope: main + allowFrom pinning doesn't apply to Discord channel sessions

Suggested fix

Option A (preferred): Inter-session messages (those arriving via sessions_send) should never update lastRoute. Only external user messages from actual channels should update it.

Option B: sessions_send carries an optional preserveRoute: true flag.

Option C: Per-agent config: session.pinRoute: "discord" that locks lastRoute to a specific channel.

Workaround (current)

Using [[reply_to_current]] tag in replies forces reply to the triggering Discord message. This helps but doesn't work for standalone replies after processing inter-agent content.

Setup

  • Multi-agent fleet (5 agents), all with dedicated Discord channel sessions
  • Heavy inter-agent communication via sessions_send throughout the day
  • OpenClaw gateway on macOS, Discord channel
  • Confirmed consistent reproduction across multiple agents (Omega, Swiv, Forge)

extent analysis

Fix Plan

To address the issue, we will implement Option A: Inter-session messages should never update lastRoute. Only external user messages from actual channels should update it.

Here are the concrete steps:

  • Modify the sessions_send endpoint to not update the lastRoute of the receiving session.
  • Add a check to ensure that only external user messages update the lastRoute.

Example code snippet (in JavaScript):

// sessions_send endpoint
app.post('/sessions_send', (req, res) => {
  const sessionKey = req.body.sessionKey;
  const message = req.body.message;
  
  // Get the receiving session
  const receivingSession = getSession(sessionKey);
  
  // Process the inter-session message
  processInterSessionMessage(receivingSession, message);
  
  // Do not update lastRoute for inter-session messages
  // receivingSession.lastRoute = 'webchat'; // Comment out or remove this line
});

// Update lastRoute only for external user messages
app.post('/external_message', (req, res) => {
  const sessionKey = req.body.sessionKey;
  const message = req.body.message;
  const channel = req.body.channel;
  
  // Get the receiving session
  const receivingSession = getSession(sessionKey);
  
  // Update lastRoute for external user messages
  receivingSession.lastRoute = channel;
});

Verification

To verify that the fix worked:

  • Send an inter-session message from Agent A to Agent B using sessions_send.
  • Check that Agent B's lastRoute is not updated to webchat.
  • Send a reply from Agent B to a Discord user.
  • Verify that the reply is delivered to Discord and not to the webchat UI.

Extra Tips

  • Make sure to test the fix thoroughly in a multi-agent fleet setup to ensure that it works as expected.
  • Consider adding logging or monitoring to track changes to lastRoute and ensure that it is being updated correctly.
  • If issues persist, consider implementing Option B or Option C as a fallback.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Inter-session messages should NOT update the receiving session's lastRoute. The session's reply channel should remain pinned to wherever the last external user message came from (Discord in this case).

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix sessions_send inter-agent messages overwrite session lastRoute to webchat, breaking Discord reply routing [1 pull requests, 1 participants]