Skip to content

fix: extract <at> tags as standalone post elements for real mentions#480

Open
iamkentzhu wants to merge 2 commits into
larksuite:mainfrom
iamkentzhu:fix/buildPostContent-at-mention
Open

fix: extract <at> tags as standalone post elements for real mentions#480
iamkentzhu wants to merge 2 commits into
larksuite:mainfrom
iamkentzhu:fix/buildPostContent-at-mention

Conversation

@iamkentzhu
Copy link
Copy Markdown

Problem

When an LLM response contains <at user_id="ou_xxx">Name</at> tags, the current buildPostContent() function wraps the entire text — including <at> tags — inside a single {tag: "md", text: "..."} element. Lark's post message API treats <at> tags embedded in markdown text as visual rendering only — it does NOT populate the mentions array or trigger im.message.receive_v1 events.

This blocks multi-bot collaboration scenarios where Bot A needs to @mention Bot B in group chats.

Verified behavior

Payload format mentions array Event triggered
{tag: "md", text: "...<at>..."} (current) empty No
{tag: "at", user_id: "..."} as standalone element populated Yes

Tested with Lark API POST /open-apis/im/v1/messages and verified via im.message.receive_v1 WebSocket events.

Change

buildPostContent() in src/messaging/outbound/deliver.ts now:

  1. Unescapes \"" (LLM output may contain escaped quotes)
  2. Splits text on <at user_id="...">...</at> boundaries
  3. Emits <at> matches as {tag: "at", user_id: "..."} elements
  4. Emits surrounding text as {tag: "md", text: "..."} elements
  5. Falls back to original behavior when no <at> tags are present

Impact

  • Non-breaking: Messages without <at> tags behave identically to before
  • Additive: Messages with <at> tags now produce real mentions
  • Works with normalizeAtMentions() which already fixes common AI-generated <at> format errors

Use case

Multi-bot group chats where agents @mention each other to create discussion chains. Without this fix, the mention is rendered visually but the target bot never receives the event.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Kent seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Kent and others added 2 commits May 13, 2026 11:55
`buildPostContent()` previously wrapped all text in a single `{tag: "md"}`
element. When the text contained `<at user_id="...">Name</at>` tags, Feishu
rendered them visually but did NOT populate the `mentions` array or trigger
`im.message.receive_v1` events for the mentioned user/bot.

This change splits the text around `<at>` tags, emitting each as a standalone
`{tag: "at", user_id: "..."}` post element alongside `{tag: "md"}` elements
for the surrounding text. Feishu correctly recognises these as real mentions.

This is critical for multi-bot collaboration scenarios where Bot A needs to
@mention Bot B in group chats and have the mention trigger Bot B's event
handler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous commit (849c35b) fixed buildPostContent in deliver.ts but
missed three identical patterns in send.ts (single-locale, multi-locale,
and editMessage). All paths still embedded <at> tags inside {tag: "md"}
elements, which Feishu renders visually but does not treat as real
mentions (empty mentions array, no im.message.receive_v1 event).

- Extract buildPostElements() as a shared helper from deliver.ts
- Replace inline [[{tag: "md", text}]] in send.ts with
  [buildPostElements(text)] across all three code paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@iamkentzhu iamkentzhu force-pushed the fix/buildPostContent-at-mention branch from 2071af8 to 6fdb80d Compare May 13, 2026 03:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants