Skip to content

feishu: renderMode config not respected in outbound messages causing markdown tables to fail #28616

@mbC6zC

Description

@mbC6zC

Problem Description

The renderMode: "card" configuration is not being respected when sending messages through the Feishu outbound adapter (extensions/feishu/src/outbound.ts). This causes markdown tables to be filtered out or not displayed correctly in the Feishu client.

Expected Behavior

When renderMode: "card" is configured, outbound messages should be sent as interactive cards (using sendMarkdownCardFeishu()) which support markdown table rendering via the markdown tag, just like reply messages do.

Actual Behavior

Outbound messages are always sent as post messages (using sendMessageFeishu()) regardless of the renderMode configuration. Post messages use the md tag which does not support markdown tables, causing table content to be filtered out.

Root Cause

The reply-dispatcher.ts correctly uses renderMode to decide between sendMarkdownCardFeishu() and sendMessageFeishu():

// extensions/feishu/src/reply-dispatcher.ts:145-196
const useCard = renderMode === "card" || (renderMode === "auto" && shouldUseCard(text));

if (useCard) {
  await sendMarkdownCardFeishu({ ... });
} else {
  await sendMessageFeishu({ ... });
}

However, outbound.ts always calls sendMessageFeishu() and ignores the renderMode configuration entirely.

Impact

  • Inconsistent behavior: Reply messages respect renderMode, but outbound messages don't
  • Missing feature: Users cannot enable markdown table support for outbound messages (e.g., via openclaw message send or tool calls)
  • Configuration ignored: Setting renderMode: "card" has no effect on outbound messages

Steps to Reproduce

  1. Configure Feishu with renderMode: "card":
    {
      "channels": {
        "feishu": {
          "renderMode": "card",
          "markdown": {
            "tables": "off"
          }
        }
      }
    }
  2. Send a message containing a markdown table:
    openclaw message send --channel feishu --to "ou_xxx" "## 商品清单
    
名称 数量 单价
苹果 10 3.5元
香蕉 5 2.0元
3. Observe that the table content is not displayed in the Feishu client (only title and summary text appear)

## Solution

The fix adds `renderMode` checking to `outbound.ts` to match the behavior of `reply-dispatcher.ts`:

```typescript
sendText: async ({ cfg, to, text, accountId }) => {
// Check if card mode is enabled
const accountConfig = accountId
 ? ((cfg.channels?.feishu as Record<string, unknown>)?.accounts as Record<string, unknown>)?.[accountId] as Record<string, unknown> | undefined
 : ((cfg.channels?.feishu as Record<string, unknown>)?.accounts as Record<string, unknown>)?.default as Record<string, unknown> | undefined;
const renderMode = accountConfig?.renderMode ?? (cfg.channels?.feishu as Record<string, unknown>)?.renderMode ?? "auto";

// Use card mode when renderMode is "card" to support markdown tables
if (renderMode === "card") {
 const result = await sendMarkdownCardFeishu({ cfg, to, text, accountId: accountId ?? undefined });
 return { channel: "feishu", ...result };
}

const result = await sendMessageFeishu({ cfg, to, text, accountId: accountId ?? undefined });
return { channel: "feishu", ...result };
}

Technical Details

Feishu Message Types:

  • post type with md tag: Does NOT support markdown tables
  • interactive type with markdown tag: DOES support markdown tables

Functions:

  • sendMessageFeishu(): Sends post type (md tag, no tables)
  • sendMarkdownCardFeishu(): Sends interactive type (markdown tag, supports tables)

Related Configuration

The renderMode option is documented in the config schema (extensions/feishu/src/config-schema.ts:135) and used in reply-dispatcher.ts, but was missing from outbound.ts.

Related Files

  • extensions/feishu/src/outbound.ts - Fix applied
  • extensions/feishu/src/reply-dispatcher.ts - Already implements renderMode correctly
  • extensions/feishu/src/config-schema.ts:135 - Config schema definition

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions