Best Minds Board Private
report-20260317-095539.html
OpenClaw · Feishu · Retrospective
群聊主时间线 / Topic 回复复盘
这次问题的本质不是“会不会发消息”,而是
普通群默认应该继续显示在主时间线 ,同时
Topic / Thread 场景又必须可显式保留 。
本地把群聊默认改成 chat_id 直发,解决了眼前 UX;
但真正更像 upstream 会接受的形状,是把这层能力收敛成
groupDeliveryMode + groupSessionScope + replyInThread。
Andrej Karpathy · simulate the maintainer, not your preference
Charity Majors · trust runtime behavior over config intent
OpenClaw maintainers · keep generic semantics, avoid Feishu-specific hacks
Feishu API semantics · root_id / thread_id / reply_to_id are not interchangeable
已验证 open issues
4
#35518 #35598 #35478 #39765
Direct Answer
你的真实目标不是“永远不要话题”,而是
默认普通群继续显示在主时间线;只有明确配置时才保留 Topic/Thread 。
所以这次复盘的结论是:
本地硬改有效
配置化兼容更值钱
把硬编码原样提 upstream 风险高
What You Wanted
群里继续展示
正常群聊多轮沟通应该留在主时间线,不要因为回复 API 选型错误,视觉上突然变成话题。
What Worked Locally
im.message.create(chat_id)
对普通群是有效止血,因为它直接绕过了 reply metadata 带来的 topic 化行为。
What Is Upstream-Worthy
显式 delivery mode
更好的抽象是把“发到哪里”和“会话如何分组”拆开,而不是继续把两者混在 replyInThread 里。
Timeline
Timeline · March 2026
2026-02-28
上游合并
PR #27325: replyInThread
2026-03-05
open issues 暴露
#35518 / #35598 / #35478
2026-03-16
本地用户问题暴露
普通群回复变成话题
2026-03-16
本地热修
群聊默认改成 chat_id 直发
2026-03-17
兼容式收敛
groupDeliveryMode + tests
真正重要的分水岭不是“有没有修复”,而是从“热修写死”转成“兼容式配置”的那一刻。
Four Principles
要点 1
先区分“普通群”和“显式 topic 群”,不要把两个场景混成同一个默认回复语义。
要点 2
把 session scope、delivery mode、reply target 拆开,才有可能兼容普通群和话题群。
要点 3
本地 hotfix 的价值在于验证用户体验,而不是证明它已经是最好的通用抽象。
要点 4
真正值得 upstream 的,是最小兼容补丁;不要把 ACP topic binding 和普通群默认行为混在一起提。
Sequence
Sequence A · Before
User
OpenClaw
Feishu UI
群内发消息
携带 root_id / reply metadata
选择 im.message.reply
回复落入 topic / 话题视图
主时间线可见性下降
错误不在“会不会发”,而在“把普通群误当成 thread 目标处理”。这正是用户体感最差的一段。
Sequence B · Normal Group, Main Timeline
User
OpenClaw
Feishu UI
普通群消息
groupDeliveryMode=direct
skip reply metadata in messages
im.message.create(chat_id)
继续显示在主时间线
这就是当前更合理的普通群默认行为。注意:它解决的是“投递模式”,不是 session scope。
Sequence C · Explicit Topic / Thread
User
OpenClaw
Feishu UI
话题内继续追问
group_topic + replyInThread=enabled
reply to root / keep thread
topic continuity preserved
继续留在同一话题
这条路径依然需要被支持,所以不能把“永远主时间线直发”做成全局硬编码。
Sequence D · Decision Split
Inbound message arrives
先判断是否显式 topic / thread,再决定发到主时间线还是回复 API。
Branch 1 · Normal group
delivery=direct
send via create(chat_id)
Branch 2 · Explicit topic
replyInThread / group_topic*
keep root + thread continuity
真正稳的抽象,是先分流场景,再决定投递模式;而不是让单个布尔值承受全部语义。
Supplemental Views
Score · Which layer matters most now
Local UX fix
91
Upstream fitness
71
Config clarity
78
Remaining risk
43
这张分数图的意思很简单:本地 UX 目标已经接近完成,但 upstream 仍有语义和边界问题。
Matrix · Scope vs Risk
低通用性
高通用性
低风险
高风险
全局硬编码主时间线
兼容式 delivery mode
现有 groupSessionScope / replyInThread
真正值得往 upstream 推的,是右下角那块:通用性高,但不会把 topic 场景一起打坏。
Risk · What can still go wrong
把 threadId 当成 messageId 使用,回复目标语义会错。
streaming card 如果不统一,也会和文本回复出现分叉。
bot.test.ts 的本地运行依赖仍不完整,回归验证要补。
剩余风险并不神秘,已经被收敛到三个非常具体的工程点。
Architecture · Separate concerns
Session scope
group / topic / sender
Delivery mode
reply / direct
Reply target
reply_to_id / root_id
这张架构图就是这次复盘最核心的一句话:三件事要分开,不要再混成一个布尔值。
Feedback Loop · How this should mature
用户体感
本地修正
配置抽象
上游提交
最佳节奏不是“发现问题后直接提大 PR”,而是先让用户体感闭环,再抽象成最小通用补丁。
Upstream Reality
官方现在已经有的东西
主干 Feishu 代码里已经存在 groupSessionScope 与 replyInThread。
官方文档明确写了 ACP 对 Feishu 重点支持的是 DM 和 topic conversations。
PR #27325 已经把 replyInThread 合进主干。
判断项
这次结论
为什么重要
这是不是纯配置问题
不是
因为当前上游虽然已有配置位,但行为语义还没完整收敛。
本地硬改是不是无价值
不是
它证明了普通群的真实 UX 诉求,但它只是局部 workaround。
能不能直接把硬改提 PR
不建议
maintainer 更关心 generic semantics,不喜欢把 Feishu 特殊行为硬塞成默认。
最佳单位是什么
兼容式配置 PR
让普通群与 topic 群都能被清晰表达,避免重复造轮子。
Local Refactor
这轮本地实现已经从“直接写死群聊直发”进一步收敛成配置兼容版:
schema 新增 groupDeliveryMode: "reply" | "direct",
普通群可以显式主时间线直发,显式 topic 场景仍然保留
groupSessionScope 和 replyInThread。
Normal Group
推荐默认
{
"groupDeliveryMode": "direct",
"groupSessionScope": "group",
"replyInThread": "disabled"
}
这代表:普通群继续显示在主时间线,session 也不按 topic 切分。
Explicit Topic Group
显式保留话题
{
"groupDeliveryMode": "reply",
"groupSessionScope": "group_topic_sender",
"replyInThread": "enabled"
}
这代表:这是一个明确依赖 topic continuity 的群,不应该被普通群默认覆盖。
已做
新增 groupDeliveryMode schema 与 channel config 暴露。
把群聊“主时间线直发”与“topic/thread 继续回复”从逻辑上拆开。
修正 streaming card 路径,避免文本直发而卡片又悄悄走 reply。
刻意没做
没有去碰 ACP outbound 的 threadId 语义补丁。
没有把 threadId 强行当成 replyToMessageId。
没有把你本地 workaround 原样包装成 upstream patch。
剩余风险
bot.test.ts 还受缺失的 plugin-runtime-mock.js 影响,当前目录单独跑不通。
上游文档与主干代码的语义解释仍然存在差距。
如果未来 maintainer 更想复用现有字段,可能会对新字段命名提出收缩意见。
Decision Matrix
层级
现在怎么做
值不值得 upstream
本地普通群止血
默认 groupDeliveryMode=direct
值,但应以配置化形式提,不是硬编码。
显式 topic 群
group_topic* + replyInThread=enabled
值,这是现有上游能力真正合理的落点。
ACP outbound threadId
单独处理
值,但必须避开“threadId 当 message id”的语义坑。
全局永不话题
不建议
不值,这会伤害真正依赖 topic continuity 的群。
Recommended Next Step
如果下一步要对外提交,只提一件事:
把“普通群主时间线直发”做成兼容式 delivery mode 。
不要把 ACP topic binding、threadId、reply_to_id、
normal group 默认行为混在同一个 PR 里。
更像 maintainer 会接受的版本
小补丁:只讨论 group outbound delivery mode。
保持现有 groupSessionScope 与 replyInThread 不被破坏。
配套测试覆盖 normal group / explicit topic / streaming card 三条路径。
最不该做的版本
“不管怎样都发主时间线”。
“只要有 threadId 就一律复用成 reply target”。
“把本地用户体验热修直接等价成通用语义”。