Inbound dedupe
像门口放了一只短期记忆盒,同样的包裹再来时,会先认出它来。
Concepts 导读
先看消息流总图(Inbound → 路由 → 队列 → 推理 → 出站),再根据你的渠道调 `messages.inbound.debounceMs` 和 `agents.defaults.blockStreaming`。最容易踩的坑:去重缓存是短期的,同一消息重连后可能重复触发;防抖只对纯文本生效,带媒体或控制命令会立即执行。
先讲这一页到底在解决什么
先看消息流总图(Inbound → 路由 → 队列 → 推理 → 出站),再根据你的渠道调 `messages.inbound.debounceMs` 和 `agents.defaults.blockStreaming`。最容易踩的坑:去重缓存是短期的,同一消息重连后可能重复触发;防抖只对纯文本生效,带媒体或控制命令会立即执行。
第一站
它会先经过路由、会话键、队列,再进 agent run。最后才是回复。
像一封刚进门的信,先放到前台,不是直接扔进后厨。
像门卫先看这封信该送去哪一间屋子。
像给这封信贴上一个“属于哪本聊天本”的书签。
像先排队,再请工人处理,最后把回信分段送出去。
第二站
官方说得很实在:通道重连以后,同一条消息可能又来一次。OpenClaw 会先认出来,别让它重复跑一遍。
像门口放了一只短期记忆盒,同样的包裹再来时,会先认出它来。
像信封上写了很多标签,门卫就能更稳地判断是不是同一封信。
不是冷漠,是为了不让同一件事被做两遍。
重复投递应该像复印件,不该像新工单。
第三站
这就是 debouncing。意思是,连着来的几条消息,可以先稍微等一下,合成一次更像人话的回复。
messages.inbound.debounceMs像前台设一个小缓冲区:别一条条刚进来就急着喊工人,先等一小会儿看还有没有后续。
WhatsApp 可以等久一点,Slack 和 Discord 可以短一点。像不同门口的人说话节奏不一样。
纯文字会先等,图片和附件通常会立刻放行,不然用户会觉得机器人卡住了。
像店长的手势,不需要跟普通闲聊一起凑热闹。
debounceMs: 2000 就像说“先等两秒,看对方是不是还要接着说”。
byChannel像不同门口有不同的等候时间表。WhatsApp 这扇门慢一点,Slack 那扇门快一点。
合并以后,OpenClaw 就拿一组更完整的话去想答案,而不是每个碎碎念都单独开工。
debounce 不是拖延,是先听完再回。
第四站
这页特别强调:会话是 gateway 的,不是客户端各自私藏的。控制台和 TUI 看到的,才是主本子。
直聊通常会折叠到主会话。像同一个人一直来前台,还是记在同一本聊天本上。
群聊和频道通常会有自己的会话键。像每个房间都有自己的记录本。
客户端只是来读,不是各写各的。真正的历史由 gateway host 负责保存。
谁属于哪本本子,别让手机自己猜,交给 gateway 记。
第五站
官方把这两层拆开,是为了让历史和命令解析都更稳。
Body像真正送进工人脑袋里的工作单,可能已经包好历史和外壳了。
CommandBody像门卫拿到的原话,专门用来识别是不是在下命令。
RawBody就是旧名字,像以前的老标签,还能认,但现在更推荐看 CommandBody。
群聊常会先放“从你上次回复之后发生了什么”的历史条,再放“这一次请直接回应”的当前消息条。这样工人不会把故事顺序搞乱。
第六站
如果工人正在干活,新来的消息可以马上插手、等下一轮、一起收拢,或者把旧排队再带一点回来。
interrupt像把正在说话的人打断,换成最新一封信先上。
steer像轻轻在工人耳边补一句:“方向往这边拐。”
followup / collect像把后续纸条先收在篮子里,等当前这一轮做完再一起处理。
队列是在帮消息排队,不是在帮消息打架。
第七站
官方这里讲 streaming、chunking、prefix、reply threading,还有 reasoning visibility。它们本质上都是“回信怎么摆出来”。
blockStreaming像让工人边想边递草稿,不必等整篇写完再亮给你看。
blockStreamingChunk像决定草稿一口气递多大块,别把句子切得太碎。
/reasoning on|off|stream像决定脑内小火花要不要给你看,是全藏起来、全部关掉,还是边想边亮。
responsePrefix 像回信前先加个称呼,replyToMode 像决定是不是把回信挂回原来那条线上。
最后总结
Messages 这页讲的是一条消息从门口进来、被认出是谁、是否先排队、怎么喂给工人、以及最后如何分段回家。
如果你想继续看“怎么让登录结果像一把稳定的小钥匙”,下一页就去 /concepts/oauth。