Skip to content

msteams: agent never reads files attached to Teams **channel** messages — 3 bugs (wrong team id, fetch never triggered, thread-reply URL; relates to #89594) #90733

Description

@colton-octaria

Summary

The Microsoft Teams plugin (@openclaw/msteams) cannot read a file a user attaches to a channel message. The agent gets the message text but reports "no attachment." For thread replies it's worse — it silently fetches and answers about the thread root's file instead of the reply's actual file.

Reproduced on @openclaw/msteams 2026.5.7 and confirmed the same code exists on current main (2026-06-05). The bot has Graph application permission ChannelMessage.Read.All (admin-consented) and a manifest with RSC ChannelMessage.Read.Group, so this is not a permissions problem — it's three independent URL/flow bugs.

Root causes

1. Wrong team id in the Graph URL → HTTP 400

buildMSTeamsGraphMessageUrls (extensions/msteams/src/attachments/graph.ts) derives the team id as:

const teamId =
  readNestedString(params.channelData, ["team", "id"]) ??
  readNestedString(params.channelData, ["teamId"]);

channelData.team.id is the 19:[email protected] thread/conversation id, not the team's AAD group GUID. The Graph /teams/{team-id}/channels/... path requires the group GUID (channelData.team.aadGroupId). With team.id, every channel fetch returns 400.

Fix:

const teamId =
  readNestedString(params.channelData, ["team", "aadGroupId"]) ??
  readNestedString(params.channelData, ["aadGroupId"]) ??
  readNestedString(params.channelData, ["team", "id"]) ??
  readNestedString(params.channelData, ["teamId"]);

2. The Graph fetch is never attempted for channel @mentions

In resolveMSTeamsInboundMedia (extensions/msteams/src/monitor-handler/inbound-media.ts) the Graph-message fetch is gated on hasHtmlFileAttachment — an <attachment id> marker extracted from the message HTML. A channel @mention activity delivers only a text/html stub without that marker, so hasHtmlFileAttachment is false and the fetch never runs. The bot reports "no attachment" although the file is fetchable via Graph.

Fix: for channel (non-personal) conversations, attempt the Graph message fetch even when the HTML marker is absent (if no inline media was resolved).

3. Thread replies fetch the wrong message (relates to #89594)

For a reply, params.replyToId is empty, so the existing /replies/ branch is skipped. The fallback builds /messages/{candidate} for every candidate — including the thread root (carried in conversationMessageId). The reply's own id returns 404 (a reply id is not a top-level message), so it falls back to /messages/{root} (200) and returns the root message's attachment for every reply in the thread.

A reply is addressable only at /teams/{team}/channels/{channel}/messages/{rootId}/replies/{replyId}.

Fix: treat any candidate that isn't the current message id (params.messageId) as a potential parent, build /messages/{parent}/replies/{selfId} (tried first), and only fetch /messages/{selfId} for the current message — never the bare parent/root.

Reproduction

  1. In a channel, @mention the bot with a file attached on a top-level message → bot reports "no attachment" (bugs 1 + 2).
  2. Reply in a thread (whose root message has a different file) with a new file attached → bot answers about the root's file, not the reply's (bug 3).

Evidence (direct Graph calls)

  • GET /teams/{team.id == 19:…@thread.tacv2}/channels/{chan}/messages/{id}400
  • GET /teams/{aadGroupId GUID}/channels/{chan}/messages/{topLevelId}200 (+ attachment)
  • GET /teams/{aadGroupId}/channels/{chan}/messages/{replyId}404
  • GET /teams/{aadGroupId}/channels/{chan}/messages/{rootId}/replies/{replyId}200 (+ the reply's actual attachment)

Environment

  • @openclaw/msteams 2026.5.7 (same code on main).
  • Graph app permission ChannelMessage.Read.All admin-consented; RSC ChannelMessage.Read.Group in the manifest.

With all three fixes applied, channel file reading works for top-level and thread-reply messages, for documents and audio. Happy to open a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions