Skip to content

[Bug]: MS Teams inbound mentions, quoted replies, and forwards are not normalized for agent text #102376

Description

@galiniliev

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

Microsoft Teams inbound text is not normalized before it is sent to the agent: user mentions are stripped, quotedReply / inline quoted markers are not converted into readable quote context, and forwarded-message payloads are not labeled as forwarded text.

Steps to reproduce

  1. Send an inbound Teams activity whose activity.text includes a Teams mention span such as <at>Example User One</at> and a matching mention entity.
  2. Send an inbound Teams quoted reply where activity.text includes a self-closing <quoted messageId="..."/> marker and activity.entities[] includes a quotedReply entity with senderName and preview.
  3. Send an inbound Teams forward where the author text is followed by forwarded body text and the HTML attachment contains a http://schema.skype.com/Forward blockquote.
  4. Observe the text OpenClaw dispatches to the agent.

Expected behavior

The agent-facing text should preserve non-bot mentions as readable display names, remove Teams inline quote markers, keep quoted-reply preview text in the normal supplemental quote context path, and label forwarded-message payloads so the agent can distinguish forwarded content from text authored by the sender.

Actual behavior

Current upstream/main builds Teams dispatch text with:

const text = stripMSTeamsMentionTags(rawText || htmlText || valueText || "");

stripMSTeamsMentionTags() removes all <at>...</at> content. Current main also has no quotedReply parser, no http://schema.skype.com/Forward parser, and no mention display-name normalizer under extensions/msteams/src, so the agent receives lossy or misleading message text.

OpenClaw version

upstream/main before the fix, checked at 30b3a7cded.

Operating system

NOT_ENOUGH_INFO

Install method

NOT_ENOUGH_INFO

Model

NOT_ENOUGH_INFO

Provider / routing chain

NOT_ENOUGH_INFO

Additional provider/model setup details

NOT_ENOUGH_INFO

Logs

Patch-backed wire-shape evidence from anonymized Teams fixtures:

RAW: Teams inlines `<at>Display Name</at>` spans into `activity.text` and emits one `mention` entity per span with the canonical `{ mentioned: { id, name }, text }` payload in `activity.entities[]`.
RAW: Teams inlines one self-closing `<quoted messageId="..."/>` marker per quote into `activity.text` and emits a parallel `quotedReply` entity (`{ messageId, senderId, senderName, preview }`) in `activity.entities[]`.
RAW: The forwarded body is inlined into `activity.text` with no inline signal; the marker is a `.../Forward` (`http://schema.skype.com/Forward`) blockquote in an HTML attachment.

Current-main source proof:
extensions/msteams/src/monitor-handler/message-handler.ts:
  const rawText = activity.text?.trim() ?? "";
  const htmlText = extractTextFromHtmlAttachments(attachments);
  const valueText =
    rawText || htmlText ? "" : serializeMSTeamsAdaptiveCardActionValue(activity.value);
  const text = stripMSTeamsMentionTags(rawText || htmlText || valueText || "");

extensions/msteams/src/inbound.ts:
  export function stripMSTeamsMentionTags(text: string): string {
    // Teams wraps mentions in <at>...</at> tags
    return text.replace(/<at[^>]*>.*?<\/at>/gi, "").trim();
  }

Negative search on current main:
  git grep -n "quotedReply\\|schema\\.skype\\.com/Forward\\|buildMSTeamsNormalizedText\\|normalizeMSTeamsMentionText\\|Forwarded message" upstream/main -- extensions/msteams/src
  # no matches

Screenshots, recordings, and evidence

No screenshot is available. Evidence is a sanitized patch-backed live-shape fixture set plus current-main source proof.

Impact and severity

Affected: Microsoft Teams channel users.

Severity: Medium user-visible comprehension bug.

Frequency: Always for the observed Teams shapes because current main lacks the normalizers/parsers for those inbound fields.

Consequence: The agent can receive incomplete or misleading text, including stripped user mentions, unreadable quoted reply markers, missing quoted context, or forwarded content presented as if the sender authored it.

Additional information

The local bug evidence did not include a raw gateway log excerpt or live tenant replay. The evidence is patch-backed and fixture-shaped, with private tenant values already anonymized.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.bugSomething isn't workingclawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.maintainerMaintainer-authored PR

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions