Skip to content

Bug: Web Control UI messages incorrectly routed to other channels when dmScope: "per-channel-peer" is configured #39557

Description

@NovaKepler513

Description

When session.dmScope is set to "per-channel-peer", the Web Control UI does not create an independent session key and instead reuses the global session agent:main:main. This causes all Web UI responses to be delivered to whichever channel last updated the session's deliveryContext, leading to message routing conflicts.


Environment

  • OpenClaw Version: 2026.3.2
  • Configuration:
    {
      "session": {
        "dmScope": "per-channel-peer"
      }
    }
  • Active Channels: Telegram, Slack, WhatsApp, Web Control UI

Steps to Reproduce

  1. Configure session.dmScope: "per-channel-peer" in openclaw.json
  2. Restart OpenClaw Gateway
  3. Send a message via Telegram (creates session agent:main:telegram:direct:{user_id})
  4. Send a message via Web Control UI
  5. Observe response delivery

Current Behavior

Session keys created:

{
  "agent:main:telegram:direct:8658588041": {
    "deliveryContext": {
      "channel": "telegram",
      "to": "telegram:8658588041"
    }
  },
  "agent:main:slack:direct:u049par1b98:thread:...": {
    "deliveryContext": {
      "channel": "slack",
      "to": "user:U049PAR1B98"
    }
  },
  "agent:main:main": {
    "origin": {
      "provider": "telegram",        // ❌ Wrong!
      "surface": "webchat"
    },
    "deliveryContext": {
      "channel": "telegram",          // ❌ Should be "webchat"
      "to": "telegram:8658588041"     // ❌ Should be webchat target
    }
  }
}

Result: Web UI messages are delivered to Telegram instead of staying in the Web UI.


Expected Behavior

Web Control UI should create an independent session when dmScope: "per-channel-peer":

{
  "agent:main:webchat:direct:{user_id}": {
    "deliveryContext": {
      "channel": "webchat",
      "to": "webchat:{user_id}"
    }
  }
}

OR if Web UI must remain global, its deliveryContext.channel should always be "webchat" regardless of other sessions.


Root Cause Analysis

Code Location

File: /app/dist/session-key-a6av96Fj.js

Function: buildAgentMainSessionKey

function buildAgentMainSessionKey(params) {
  return `agent:${normalizeAgentId(params.agentId)}:${normalizeMainKey(params.mainKey)}`;
}

Issue: Web Control UI (sender: "openclaw-control-ui") always uses this function, which returns agent:main:main instead of respecting dmScope: "per-channel-peer".

Why Other Channels Work

Telegram, Slack, and WhatsApp use buildAgentPeerSessionKey, which correctly implements per-channel-peer logic:

function buildAgentPeerSessionKey(params) {
  const peerKind = params.peerKind ?? "direct";
  if (peerKind === "direct") {
    const dmScope = params.dmScope ?? "main";
    // ... creates agent:main:{channel}:direct:{peer_id}
  }
}

Web UI Special Handling

File: /app/dist/gateway-cli-*.js

errorShape(ErrorCodes.INVALID_REQUEST, 
  `webchat clients cannot ${params.action} sessions; use chat.send for session-scoped updates`)

This suggests Web UI has intentional special handling, but it breaks channel isolation when multiple channels are active.


Impact

  • Works: Single-channel setups (e.g., only Telegram)
  • Broken: Multi-channel setups with dmScope: "per-channel-peer"
  • Affects: Message routing, session isolation, privacy expectations

Proposed Fix

Option 1: Make Web UI respect dmScope (Recommended)

When dmScope: "per-channel-peer", Web UI should:

  1. Generate session key: agent:main:webchat:direct:{user_id_or_device_id}
  2. Set deliveryContext.channel: "webchat"
  3. Route replies back to the Web UI only

Option 2: Isolate Web UI deliveryContext

If Web UI must remain global (agent:main:main), ensure:

  1. deliveryContext.channel is always "webchat"
  2. Never inherit deliveryContext from other channels
  3. Prevent cross-contamination with Telegram/Slack/etc.

Option 3: Document the limitation

If this is intentional behavior:

  1. Update docs to warn that Web UI shares session with other channels
  2. Recommend avoiding multi-channel usage with Web UI
  3. Add config option to disable Web UI when using per-channel-peer

Workaround (Temporary)

For users affected by this bug:

  1. Use only one channel at a time (Web UI XOR Telegram/Slack/etc.)
  2. OR: Set session.dmScope: "main" (disables per-channel isolation)
  3. OR: Manually clear Web UI session before switching channels

Additional Context

  • User reference: Issue discovered during multi-channel deployment testing
  • Related config: session.identityLinks (cross-channel identity mapping)
  • Memory architecture: Shared vs private memory per channel

Conclusion

This bug prevents users from safely running multi-channel setups with the Web Control UI. The fix should ensure Web UI creates an independent session key or at least isolates its deliveryContext to prevent cross-channel message leakage.

Thank you for maintaining OpenClaw! 🙏

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions