Feishu Card UX Retrospective · 2026-06-05 → 06-07

为什么今天的卡片修复,比昨天 presentation 更有效

这次复盘把三天的卡片修复串起来:先经历 Feishu 通道事故,再识别 presentation 的边界,最后真正修到自动触发器与原生卡片正文渲染路径。

三天时间线

从“卡片看起来不够好”到“系统默认该什么时候用卡片”,真正的修复点逐步浮出水面。

06-02起点

Channel SDK 让卡片体验第一次“活起来”

Makaron card runner 接入官方 Feishu Channel SDK:streaming card、update-in-place、回调按钮、任务状态都进入一个真实工作台。关键认知:好卡片来自原生 Channel SDK 路径,而不是普通文本自动美化。

06-05事故

PlanMode / openclaw-lark 双通道事故

Feishu 原生通道和 openclaw-lark 插件曾同时监听同一 app,导致卡片/消息链路近似卡死。恢复后确认:必须保留 channels.feishu 原生通道,旧插件入口要退场;生产通道不能靠临时混插。

06-06 上午诊断

定位 presentation 的边界

presentation 是 OpenClaw generic schema 的可移植 fallback,适合快速结构化,但布局固定、自由度低,无法复刻之前 Channel SDK/native card 的质感。继续打磨 presentation 只能局部改善,不能根治。

06-06 中午证据

回查历史配置:没有神秘的旧 auto-card

旧备份显示早期 Feishu streaming=false、无 renderMode;所谓“以前好用”的卡片体验,大多来自显式卡片路径:approval、Makaron task card、Channel SDK demo,而不是普通 assistant reply 自动变卡。

06-07 13:44规则

把偏好升级成行为规则

Tianyi 指出“多用飞书卡片”放在 user-patterns 里基本不触发。修复:晋升到 ai-patterns,明确长任务、报告、进度、交付、审批、客户状态默认用卡片。

06-07 13:49根治

真正修触发器:shouldUseCard()

renderMode=auto 原本只识别代码块和 Markdown 表格。补上标题、多段 bullet、状态/进度/报告/交付/链接/QC/下一步等结构化信号,让 assistant final path 能自然触发卡片。

06-07 13:56打磨

修正文 typography:标题不再巨大

Feishu markdown card 会把 ## 小节标题渲染成超大字号。补 normalizeFeishuAutoCardMarkdown:正文 #/##/### 降级成加粗小节,代码块不受影响。

昨天 vs 今天

昨天主要在 presentation 这层试图变漂亮;今天修的是“什么时候自动用卡片”和“卡片正文怎么渲染”。

昨天:presentation 打磨

  • 优点:快、可移植、适合轻量结构化。
  • 问题:普通回复不会自动进入 presentation。
  • 问题:布局固定,难以复刻 Channel SDK/native card 的自由度。
  • 结论:适合 fallback,不适合作为 Feishu 高质量卡片主路径。

今天:触发器 + 原生正文修复

  • 把偏好从 user-patterns 晋升到 ai-patterns。
  • 扩大 shouldUseCard 的 auto-card 判断范围。
  • 修 Channel SDK streaming card 与 Markdown card 正文 typography。
  • 结论:直接改变默认体验,所以体感提升更明显。

三条渲染路径的定位

以后不再把所有卡片问题都塞进 presentation,而是按路径选择工具。

Generic presentation

便携 fallback / 快速轻量卡片

布局固定,难以呈现之前 Feishu native/card SDK 的自由度和质感。

Markdown auto-card

结构化 assistant final 回复自动卡片化

需要良好的 shouldUseCard 与 typography sanitizer,否则容易误触发或字号失控。

Native / Channel SDK card

长任务、实时进度、按钮、交付工作台主路径

需要正确 bot 身份、target、连接回收;实现成本高但体验最好。

沉淀下来的原则

这些不是一次性修 bug,而是以后 V 处理 Feishu 卡片体验的路线图。

触发路径优先于视觉 schema

如果系统不会主动用卡片,再漂亮的 presentation 都只会偶发出现。先修路由,再修样式。

native / Channel SDK 是高质量主路径

长任务、Makaron、审批、工作台、实时进度应优先走官方 Channel SDK 或 native card;presentation 保留为轻量 fallback。

短回复保持文本

Tianyi 喜欢卡片,但不是所有消息都卡片化。短确认、轻量问答、情绪回应继续文本,避免交互负担。

卡片正文要为移动端写

少用 Markdown heading;用加粗小节、短段落、清晰 bullet、链接按钮。结构清楚比字号大更重要。

runtime patch 必须可重复

node_modules 临时 patch 有风险,所以必须保留脚本、备份、验证命令和最终迁移到上游/skill 的路径。

事故记忆要进入执行层

user-patterns 只是偏好;会影响默认行为的规则必须进入 ai-patterns、skill 或 runtime heuristic。

已改动与可重复补丁

node_modules patch 不是最终上游方案,但这次保留了脚本和验证路径,避免下次升级后失忆。

memory/ai-patterns.md

新增“Feishu 结构化任务优先用卡片”:把卡片从偏好升级为默认工作流。

@openclaw/feishu/dist/channel.runtime-*.js

patch shouldUseCard:普通 outbound text 的 auto-card 判断。

@openclaw/feishu/dist/monitor.account-*.js

patch shouldUseCard + streaming compose:assistant final / streaming card 路径。

@openclaw/feishu/dist/send-*.js

patch buildMarkdownCard:auto-card 正文 typography 规范化。

scripts/patch-feishu-should-use-card.mjs

可重复重打 shouldUseCard patch,防包升级覆盖。

scripts/patch-feishu-card-typography.mjs

可重复重打 typography patch,防 heading 过大回归。

最终结论

这次真正有效,是因为我们从“让卡片更好看”转向“让正确的内容默认进入正确的卡片路径”。

一句话:Feishu 卡片体验的主路径应该是 smart auto + native / Channel SDK cards;presentation 是 portable fallback,不是终局。

下一步应该把这些 runtime patch 上游化或插件化,减少 node_modules patch 风险;同时继续保持短回复文本、结构化工作卡片的边界。