Skip to content

[Bug]: msteams channel threads share the same session key (cross-thread context bleed) #58615

@atharva-getboon

Description

@atharva-getboon

Bug type

Behavior bug (incorrect output/state without crash)

Summary

When users post in different threads within the same Teams channel, the bot mixes conversation context between threads. A question in Thread A includes context from Thread B. Each thread should have its own isolated session.

Version

  • OpenClaw: 2026.3.24 (also confirmed unchanged in 2026.3.31)
  • Channel: msteams (bundled plugin)

Root Cause Analysis

After tracing through the bundled plugin code, the issue is in how the msteams plugin constructs session keys for channel messages.

normalizeMSTeamsConversationId() strips the thread-identifying ;messageid=XXX suffix from the Teams conversation ID:

function normalizeMSTeamsConversationId(raw) {
    return raw.split(";")[0] ?? raw;
}

Teams delivers thread replies with conversation IDs like:
19:[email protected];messageid=1234567890

After normalization, this becomes just:
19:[email protected]

This normalized (channel-level) ID is then passed to resolveAgentRoute() as peer.id, so all threads in a channel share the same session key: agent:main:msteams:channel:19:[email protected].

extractMSTeamsConversationMessageId() does correctly extract the thread-specific message ID — but it's only used for Graph API media URL construction, never for session routing.

The core session module already has resolveThreadSessionKeys() which appends :thread:{threadId} to a base session key, but the msteams plugin never calls it.

Expected Behavior

Each Teams channel thread should get its own session key, e.g.:
agent:main:msteams:channel:19:[email protected]:thread:1234567890

The resolveThreadSessionKeys() function in session-key-*.js already supports this pattern — the msteams plugin just needs to call it with the conversationMessageId after route resolution.

Steps to Reproduce

  1. Configure the msteams channel plugin
  2. In a Teams channel, create Thread A and ask the bot a question
  3. Create Thread B and ask the bot a different question
  4. Observe that responses in Thread B reference context from Thread A

Additional Context

  • session.threadBindings.enabled: true is set in config but has no effect since the msteams plugin doesn't extract/pass thread IDs
  • historyLimit also contributes to bleed since it loads the last N messages from the channel (across all threads), but the session key issue is the primary cause
  • The resolveAgentRoute() function doesn't accept a threadId parameter, so the fix likely needs to happen after route resolution in the msteams message handler

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions