openclaw - 💡(How to fix) Fix Bug: message tool routes to webchat when Signal session has stale currentChannelProvider=webchat (session-key channel ignored)

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…

When the message tool is invoked from inside a non-webchat agent session (e.g. agent:main:signal:direct:+13093634600), it can send to webchat instead of the session's true channel if options.currentChannelProvider has drifted to webchat. The session key already encodes the correct channel and target, but the tool only uses options.currentChannelProvider / options.currentChannelId and ignores the session-key context.

Net effect: the model calls message expecting it to reply on Signal (because that's the session it's running in), and the message silently lands in the internal webchat UI sink instead — invisible to the user on the channel they messaged from.

Root Cause

dist/openclaw-tools-*.jsfunction createMessageTool(options) derives every downstream delivery context (toolContext, schema context, description context, secret scope fallback) from raw options.currentChannelProvider / options.currentChannelId. When those are stale-webchat but options.agentSessionKey clearly encodes a different transport (e.g. signal:direct:+...), the session-key context is the source of truth — but it isn't consulted.

const toolContext = options?.currentChannelId || options?.currentChannelProvider || ...
  ? {
      currentChannelId: options?.currentChannelId,
      currentChannelProvider: options?.currentChannelProvider,
      ...

Fix Action

Fix / Workaround

Sister issue #78274 describes a similar dispatch-to-wrong-session symptom for Feishu group chats.

Local patch

We've been running this fix locally as part of post-update-hook.sh Hook 39 (scripts/patch-message-tool-routing-and-result.sh) since the 2026.5.x line. Patch applies cleanly to dist/openclaw-tools-*.js matched by the marker function createMessageTool(options), and the resulting file passes node --check. Sentinel preferSessionDeliveryContext is what the script checks for idempotency.

Code Example

const toolContext = options?.currentChannelId || options?.currentChannelProvider || ...
  ? {
      currentChannelId: options?.currentChannelId,
      currentChannelProvider: options?.currentChannelProvider,
      ...

---

const sessionDelivery = inferDeliveryFromSessionKey(options?.agentSessionKey);
const sessionDeliveryChannel = normalizeMessageChannel(sessionDelivery?.channel);
const preferSessionDeliveryContext =
    normalizeMessageChannel(options?.currentChannelProvider) === "webchat" &&
    sessionDeliveryChannel && sessionDeliveryChannel !== "webchat" &&
    Boolean(sessionDelivery?.to);
const effectiveCurrentChannelProvider = preferSessionDeliveryContext
    ? sessionDeliveryChannel : options?.currentChannelProvider;
const effectiveCurrentChannelId = preferSessionDeliveryContext
    ? sessionDelivery?.to : options?.currentChannelId;
// then use `effective*` everywhere instead of `options?.current*` in the four locations
RAW_BUFFERClick to expand / collapse

Summary

When the message tool is invoked from inside a non-webchat agent session (e.g. agent:main:signal:direct:+13093634600), it can send to webchat instead of the session's true channel if options.currentChannelProvider has drifted to webchat. The session key already encodes the correct channel and target, but the tool only uses options.currentChannelProvider / options.currentChannelId and ignores the session-key context.

Net effect: the model calls message expecting it to reply on Signal (because that's the session it's running in), and the message silently lands in the internal webchat UI sink instead — invisible to the user on the channel they messaged from.

Repro

  1. Start a Signal direct session (agent:main:signal:direct:<E.164>).
  2. Trigger a control-path turn that updates the session's currentChannelProvider to webchat while deliveryContext still points at Signal (this happens routinely via the per-channel-peer route updates — see #36614).
  3. Inside that turn, have the agent call the message tool without an explicit channel/target (the common "just reply to the user" shape).
  4. Observed: tool delivery goes to sourceReplySink=internal-ui (webchat). Expected: Signal.

Sister issue #78274 describes a similar dispatch-to-wrong-session symptom for Feishu group chats.

Root cause

dist/openclaw-tools-*.jsfunction createMessageTool(options) derives every downstream delivery context (toolContext, schema context, description context, secret scope fallback) from raw options.currentChannelProvider / options.currentChannelId. When those are stale-webchat but options.agentSessionKey clearly encodes a different transport (e.g. signal:direct:+...), the session-key context is the source of truth — but it isn't consulted.

const toolContext = options?.currentChannelId || options?.currentChannelProvider || ...
  ? {
      currentChannelId: options?.currentChannelId,
      currentChannelProvider: options?.currentChannelProvider,
      ...

Proposed fix

Prefer the session-key-inferred delivery context whenever currentChannelProvider is webchat, the session-key channel is non-webchat, and the session-key delivery has a to. Then thread the effective values through the four downstream uses (schema, description, secret scope, runtime toolContext).

Pseudocode in createMessageTool(options):

const sessionDelivery = inferDeliveryFromSessionKey(options?.agentSessionKey);
const sessionDeliveryChannel = normalizeMessageChannel(sessionDelivery?.channel);
const preferSessionDeliveryContext =
    normalizeMessageChannel(options?.currentChannelProvider) === "webchat" &&
    sessionDeliveryChannel && sessionDeliveryChannel !== "webchat" &&
    Boolean(sessionDelivery?.to);
const effectiveCurrentChannelProvider = preferSessionDeliveryContext
    ? sessionDeliveryChannel : options?.currentChannelProvider;
const effectiveCurrentChannelId = preferSessionDeliveryContext
    ? sessionDelivery?.to : options?.currentChannelId;
// then use `effective*` everywhere instead of `options?.current*` in the four locations

The narrow guard (webchat + non-webchat session-inferred + to set) means this only kicks in for the contaminated-context shape — it does not change behavior for normal webchat sessions or sessions where the model passes an explicit channel/target.

Local patch

We've been running this fix locally as part of post-update-hook.sh Hook 39 (scripts/patch-message-tool-routing-and-result.sh) since the 2026.5.x line. Patch applies cleanly to dist/openclaw-tools-*.js matched by the marker function createMessageTool(options), and the resulting file passes node --check. Sentinel preferSessionDeliveryContext is what the script checks for idempotency.

Happy to open a PR if a maintainer can confirm the approach direction (in particular whether inferDeliveryFromSessionKey is the right helper to reuse vs. introducing a new resolver).

Related

  • #36614 — per-channel-peer: updateLastRoute still contaminates main session with channel-specific delivery context (this is the upstream cause of the currentChannelProvider=webchat drift)
  • #78274 — Feishu agent dispatches to wrong session (main webchat instead of agent session) — same family of routing-context-vs-session-context mismatch

Environment

  • openclaw 2026.5.12
  • Linux 6.12.x (Pop!_OS), Node v24.15.0
  • Agent runtime: Codex GPT-5.5 (codex-app-server) and Claude CLI Opus 4.7
  • Reproduced on Signal direct sessions; should reproduce on any non-webchat channel where currentChannelProvider can drift to webchat.

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…

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 - 💡(How to fix) Fix Bug: message tool routes to webchat when Signal session has stale currentChannelProvider=webchat (session-key channel ignored)