Summary
With session.dmScope: "main", a user's DMs to an agent across channels (Slack, Telegram, webchat) share one session. On a channel switch (for example Slack to Telegram), the session origin's per-channel identity fields are not reset. mergeOrigin only overwrites a field when the new inbound supplies it; Telegram DMs supply no nativeChannelId (or threadId), so the previous channel's Slack channel id persists in a now-Telegram session, and keeps persisting on every subsequent Telegram turn until the user messages on the original channel again.
Reproduction (deterministic, verified on two separate agents)
- Message an agent in a Slack DM (Slack channel id like
Dxxxxxxxx).
- As the same user, message that agent on Telegram (same
dmScope:"main" session).
- Inspect the session origin:
provider, surface, from, to, and accountId correctly become Telegram, but origin.nativeChannelId still holds the Slack channel id.
It does not clear on subsequent Telegram turns. It is re-stamped only when the user later sends a message on the original (Slack) channel, or on a session reset.
Root cause
mergeOrigin merges field by field, overwriting only when the new value is present:
const merged = existing ? { ...existing } : {};
if (next?.provider) merged.provider = next.provider; // updates
if (next?.nativeChannelId) merged.nativeChannelId = next.nativeChannelId; // only if supplied
if (next?.threadId != null && next.threadId !== "") merged.threadId = next.threadId;
Channels that do not carry a native channel id (Telegram DMs) leave the previous channel's value in place, and nothing resets it when provider or surface changes.
Impact
Message delivery is unaffected (route.target.to updates correctly). But native-channel-keyed operations (reactions, native threading, native message references) and any status or inspection that reads origin.nativeChannelId will reference the previous channel for the entire duration of the new-channel session. For example, an agent on Telegram reports the prior Slack account and channel when asked about its current context.
Suggested fix
When provider (or surface) differs from the existing origin, reset the channel-specific fields (nativeChannelId, nativeDirectUserId, threadId) rather than preserving them, treating a provider change as a fresh channel identity.
Environment
OpenClaw 2026.6.1, Linux, Node 24. session.scope: per-sender, session.dmScope: main.
Summary
With
session.dmScope: "main", a user's DMs to an agent across channels (Slack, Telegram, webchat) share one session. On a channel switch (for example Slack to Telegram), the session origin's per-channel identity fields are not reset.mergeOriginonly overwrites a field when the new inbound supplies it; Telegram DMs supply nonativeChannelId(orthreadId), so the previous channel's Slack channel id persists in a now-Telegram session, and keeps persisting on every subsequent Telegram turn until the user messages on the original channel again.Reproduction (deterministic, verified on two separate agents)
Dxxxxxxxx).dmScope:"main"session).provider,surface,from,to, andaccountIdcorrectly become Telegram, butorigin.nativeChannelIdstill holds the Slack channel id.It does not clear on subsequent Telegram turns. It is re-stamped only when the user later sends a message on the original (Slack) channel, or on a session reset.
Root cause
mergeOriginmerges field by field, overwriting only when the new value is present:Channels that do not carry a native channel id (Telegram DMs) leave the previous channel's value in place, and nothing resets it when
providerorsurfacechanges.Impact
Message delivery is unaffected (
route.target.toupdates correctly). But native-channel-keyed operations (reactions, native threading, native message references) and any status or inspection that readsorigin.nativeChannelIdwill reference the previous channel for the entire duration of the new-channel session. For example, an agent on Telegram reports the prior Slack account and channel when asked about its current context.Suggested fix
When
provider(orsurface) differs from the existing origin, reset the channel-specific fields (nativeChannelId,nativeDirectUserId,threadId) rather than preserving them, treating a provider change as a fresh channel identity.Environment
OpenClaw 2026.6.1, Linux, Node 24.
session.scope: per-sender,session.dmScope: main.