Bug Description
Channel thread replies in MS Teams frequently land as new top-level channel posts or in the wrong thread. This happens because the conversation store uses the channel ID as the key (stripping the ;messageid= thread suffix), so all threads in a channel share one stored conversation reference with a single activityId that gets overwritten by every new message.
Root Cause
In extensions/msteams/src/monitor-handler/access.ts, normalizeMSTeamsConversationId() strips the thread-identifying ;messageid=THREAD_ROOT suffix:
function normalizeMSTeamsConversationId(raw: string): string {
return raw.split(";")[0] ?? raw;
}
This means:
- All threads in a channel share one
conversationId key in the conversation store
- Each new message overwrites the stored
activityId (which identifies the thread)
- When proactive fallback fires, it picks up whatever
activityId was last stored — often from a different thread
- Result: reply lands in the wrong thread, or as a new top-level post if the stored
activityId does not match any thread root
Symptoms
- Reply to Thread A → response appears as new top-level post in the channel
- Reply to Thread A → response appears in Thread B (whichever thread was most recently active)
- Responses work initially but break after activity in other threads
Proposed Fix
The conversation store and reference lookup need to be thread-aware for channel conversations:
- For channel thread messages, preserve the full conversation ID including
;messageid= suffix as the store key (or use a composite key of channelId + threadRootId)
- When building the proactive reference for channel threads, include the thread root
activityId from the original inbound message context, not from the latest stored reference
- Extract
messageid from activity.conversation.id (already done by extractMSTeamsConversationMessageId() but not used for routing)
PR #56608 partially addresses this for the proactive fallback path but does not fix the underlying shared-reference problem.
Environment
- OpenClaw 2026.3.28
- MS Teams with multiple active channel threads
- Bot configured with
replyStyle: "thread"
Reproduction
- Set up a bot in a Teams channel with mention-based activation
- Send a message in Thread A → bot replies correctly in Thread A
- Send a message in Thread B → bot replies correctly in Thread B
- Send another message in Thread A → response may land in Thread B or as a top-level post (because Thread B overwrote the stored activityId)
cc @onutc (MS Teams maintainer)
— Fitzy 🐾
Bug Description
Channel thread replies in MS Teams frequently land as new top-level channel posts or in the wrong thread. This happens because the conversation store uses the channel ID as the key (stripping the
;messageid=thread suffix), so all threads in a channel share one stored conversation reference with a singleactivityIdthat gets overwritten by every new message.Root Cause
In
extensions/msteams/src/monitor-handler/access.ts,normalizeMSTeamsConversationId()strips the thread-identifying;messageid=THREAD_ROOTsuffix:This means:
conversationIdkey in the conversation storeactivityId(which identifies the thread)activityIdwas last stored — often from a different threadactivityIddoes not match any thread rootSymptoms
Proposed Fix
The conversation store and reference lookup need to be thread-aware for channel conversations:
;messageid=suffix as the store key (or use a composite key ofchannelId + threadRootId)activityIdfrom the original inbound message context, not from the latest stored referencemessageidfromactivity.conversation.id(already done byextractMSTeamsConversationMessageId()but not used for routing)PR #56608 partially addresses this for the proactive fallback path but does not fix the underlying shared-reference problem.
Environment
replyStyle: "thread"Reproduction
cc @onutc (MS Teams maintainer)
— Fitzy 🐾