Skip to content

Feishu channel displays markdown tables as raw source code instead of rendering them #25452

@wait4xx

Description

@wait4xx

Problem

When the Feishu (飞书) channel sends AI responses containing markdown tables, the table syntax is displayed as raw source code instead of being rendered as a visual table.

This is because Feishu's post message type with md tags does not support markdown table syntax. The current workaround (since PR #20275) detects tables and falls back to text type messages, which prevents blank messages but displays the raw markdown.

Reproduction

  1. Connect Hermes Agent to a Feishu group or DM
  2. Send a message that triggers a table response, e.g.:
    • "请用表格对比 Python 和 Go 的特点"
    • "List the pros and cons in a table"
  3. Observe the response in Feishu client — table syntax shown as | col1 | col2 |

Root Cause

_build_outbound_payload() in gateway/platforms/feishu.py detects markdown tables via regex and forces msg_type="text", because Feishu's post type md elements render tables as blank.

Proposed Solution

Use Feishu Interactive Cards (msg_type="interactive") with native table components, using Card JSON 2.0 ("schema": "2.0"):

  1. Parse markdown tables from AI response content
  2. Split content into "table segments" and "prose segments"
  3. Convert table segments to Feishu card table components
  4. Convert prose segments to card markdown elements (preserving original markdown — no conversion needed)
  5. Assemble as a single interactive card message using Card JSON 2.0 structure

Feishu Interactive Cards (JSON 2.0) support:

  • Native table rendering with headers, rows, pagination
  • Mixed content: markdown text + tables in one card
  • Full markdown syntax in markdown elements: headings, blockquotes, inline code, code blocks, bold, lists, etc.
  • lark_md column type for rich formatting in table cells

Approach

Message content Current behavior Proposed behavior
Contains tables text (raw source) interactive card with table components
No tables, has markdown post post (unchanged)
Plain text only text text (unchanged)

Safety measures

  • Tables inside fenced code blocks (```) are not parsed
  • Card JSON limited to 100KB; falls back to text on overflow
  • Max 5 tables per card, 50 columns per table (Feishu API limits)
  • Full fallback: interactive card → text on any API failure

Environment

  • Hermes Agent v0.13.0
  • Feishu channel via WebSocket
  • Python 3.13.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/gatewayGateway runner, session dispatch, deliveryplatform/feishuFeishu / Lark adaptertype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions