Use case
When the bot needs to post a proactive new root post / new thread in a Microsoft Teams channel — e.g. for warehouse warnings, broadcasts, cross-team announcements — there is currently no way to do this on a per-call basis. The channels.msteams.replyStyle setting is purely static (per-team / per-channel config). Setting it globally to "top-level" is not desirable: regular @mention replies in existing threads must still land inside their thread.
Two distinct behaviours are needed in the same channel:
- Reply path (existing): bot is @mentioned inside a thread → reply lands inside the same thread. (Currently works via
replyStyle: "thread".)
- Proactive new-thread path (missing): bot is asked, via DM/cron/skill, to post a stand-alone announcement → must surface as a fresh root post, not as a reply under whichever thread happened to last seed the conversation reference.
Why the static config is insufficient
In dist/probe-<hash>.js resolveMSTeamsSendContext() the replyStyle is resolved strictly from cfg:
const replyStyle = resolveMSTeamsProactiveReplyStyle({
cfg: msteamsCfg,
conversationId,
ref: safeRef,
conversationType
});
There is no override slot. In dist/channel-<hash>.js describeMSTeamsMessageTool() the send action exposes no topLevel / replyStyle schema property either, so the agent has no signal it could set. The Standard message-action param allowlist already lists topLevel (in dist/channel-target-<hash>.js STANDARD_MESSAGE_ACTION_PARAM_KEYS), but the msteams plugin never consumes it. The Telegram plugin treats thread-create as topic-create; there is no msteams equivalent.
Proposal
-
Add topLevel: Type.Optional(Type.Boolean(...)) to the schema returned by describeMSTeamsMessageTool(), with action scope including send. Description should make clear that it forces a new root post (channel only) and is ignored for DMs / group chats.
-
In handleAction for action === "send", when params.topLevel === true, call sendMessageMSTeams({ ..., replyStyleOverride: "top-level" }) (and analogously for sendAdaptiveCardMSTeams if presentation is set).
-
In sendMessageMSTeams and sendAdaptiveCardMSTeams, accept an optional replyStyleOverride param and forward it to resolveMSTeamsSendContext.
-
In resolveMSTeamsSendContext, honour params.replyStyleOverride before falling back to the config-derived resolveMSTeamsProactiveReplyStyle():
const replyStyle = params.replyStyleOverride ?? resolveMSTeamsProactiveReplyStyle({ ... });
Net change is ~10 lines in two files. Backwards compatible: when topLevel is omitted, behaviour is unchanged.
Workaround in place
We have applied this exact patch locally against version 2026.5.28 (msteams plugin install path ~/.openclaw/npm/projects/openclaw-msteams-*/node_modules/@openclaw/msteams/dist/) and verified end-to-end: agent invokes the message tool with topLevel: true, send goes out without the ;messageid= suffix on the conversation reference, surfaces as a fresh root post with its own thread. Regression check: omitting topLevel leaves the existing thread-reply behaviour intact.
A re-apply script restores the patch after openclaw plugins install @openclaw/msteams. Happy to open a PR from a fork (versando-it) once you confirm the proposal direction.
Sample usage
Environment
- OpenClaw
2026.5.28
@openclaw/msteams 2026.5.28
- Windows Server (SVR-APP2), Node
24.15.0
- Bot Framework public cloud
- Channel: classic “Posts” style (so
replyStyle: "thread" is the correct default for replies)
Use case
When the bot needs to post a proactive new root post / new thread in a Microsoft Teams channel — e.g. for warehouse warnings, broadcasts, cross-team announcements — there is currently no way to do this on a per-call basis. The
channels.msteams.replyStylesetting is purely static (per-team / per-channel config). Setting it globally to"top-level"is not desirable: regular @mention replies in existing threads must still land inside their thread.Two distinct behaviours are needed in the same channel:
replyStyle: "thread".)Why the static config is insufficient
In
dist/probe-<hash>.jsresolveMSTeamsSendContext()the replyStyle is resolved strictly fromcfg:There is no override slot. In
dist/channel-<hash>.jsdescribeMSTeamsMessageTool()thesendaction exposes notopLevel/replyStyleschema property either, so the agent has no signal it could set. The Standard message-action param allowlist already liststopLevel(indist/channel-target-<hash>.jsSTANDARD_MESSAGE_ACTION_PARAM_KEYS), but the msteams plugin never consumes it. The Telegram plugin treatsthread-createastopic-create; there is no msteams equivalent.Proposal
Add
topLevel: Type.Optional(Type.Boolean(...))to the schema returned bydescribeMSTeamsMessageTool(), with action scope includingsend. Description should make clear that it forces a new root post (channel only) and is ignored for DMs / group chats.In
handleActionforaction === "send", whenparams.topLevel === true, callsendMessageMSTeams({ ..., replyStyleOverride: "top-level" })(and analogously forsendAdaptiveCardMSTeamsif presentation is set).In
sendMessageMSTeamsandsendAdaptiveCardMSTeams, accept an optionalreplyStyleOverrideparam and forward it toresolveMSTeamsSendContext.In
resolveMSTeamsSendContext, honourparams.replyStyleOverridebefore falling back to the config-derivedresolveMSTeamsProactiveReplyStyle():Net change is ~10 lines in two files. Backwards compatible: when
topLevelis omitted, behaviour is unchanged.Workaround in place
We have applied this exact patch locally against version
2026.5.28(msteams plugin install path~/.openclaw/npm/projects/openclaw-msteams-*/node_modules/@openclaw/msteams/dist/) and verified end-to-end: agent invokes themessagetool withtopLevel: true, send goes out without the;messageid=suffix on the conversation reference, surfaces as a fresh root post with its own thread. Regression check: omittingtopLevelleaves the existing thread-reply behaviour intact.A re-apply script restores the patch after
openclaw plugins install @openclaw/msteams. Happy to open a PR from a fork (versando-it) once you confirm the proposal direction.Sample usage
Environment
2026.5.28@openclaw/msteams2026.5.2824.15.0replyStyle: "thread"is the correct default for replies)