Concepts 导读

消息从进到出,OpenClaw 替你管了排队、去重、流式回复

先看消息流总图(Inbound → 路由 → 队列 → 推理 → 出站),再根据你的渠道调 `messages.inbound.debounceMs` 和 `agents.defaults.blockStreaming`。最容易踩的坑:去重缓存是短期的,同一消息重连后可能重复触发;防抖只对纯文本生效,带媒体或控制命令会立即执行。

先讲这一页到底在解决什么

消息从进到出,OpenClaw 替你管了排队、去重、流式回复

先看消息流总图(Inbound → 路由 → 队列 → 推理 → 出站),再根据你的渠道调 `messages.inbound.debounceMs` 和 `agents.defaults.blockStreaming`。最容易踩的坑:去重缓存是短期的,同一消息重连后可能重复触发;防抖只对纯文本生效,带媒体或控制命令会立即执行。

原文共 14 节,先看 Start Here 路径:/concepts/messages 查看官方原文

第一站

📨 先想画面:一条消息从门口进来,不会直接冲进工厂

它会先经过路由、会话键、队列,再进 agent run。最后才是回复。

Inbound message

像一封刚进门的信,先放到前台,不是直接扔进后厨。

Routing / bindings

像门卫先看这封信该送去哪一间屋子。

Session key

像给这封信贴上一个“属于哪本聊天本”的书签。

Queue -> run -> replies

像先排队,再请工人处理,最后把回信分段送出去。

第二站

🧷 重复投递不该让它重复开工,所以有个小记忆盒

官方说得很实在:通道重连以后,同一条消息可能又来一次。OpenClaw 会先认出来,别让它重复跑一遍。

📦

Inbound dedupe

像门口放了一只短期记忆盒,同样的包裹再来时,会先认出它来。

🧾

按 channel/account/peer/session/message id 认人

像信封上写了很多标签,门卫就能更稳地判断是不是同一封信。

🚫

认出来就不重复开工

不是冷漠,是为了不让同一件事被做两遍。

📌

一句话

重复投递应该像复印件,不该像新工单。

第三站

⏳ 连续几封小纸条来了,它可以先抱成一团

这就是 debouncing。意思是,连着来的几条消息,可以先稍微等一下,合成一次更像人话的回复。

messages.inbound.debounceMs

像前台设一个小缓冲区:别一条条刚进来就急着喊工人,先等一小会儿看还有没有后续。

按通道可以不同

WhatsApp 可以等久一点,Slack 和 Discord 可以短一点。像不同门口的人说话节奏不一样。

text-only 才会等

纯文字会先等,图片和附件通常会立刻放行,不然用户会觉得机器人卡住了。

控制命令直接过

像店长的手势,不需要跟普通闲聊一起凑热闹。

🛠 配置像在做什么

debounceMs: 2000 就像说“先等两秒,看对方是不是还要接着说”。

byChannel

像不同门口有不同的等候时间表。WhatsApp 这扇门慢一点,Slack 那扇门快一点。

一条消息变一轮

合并以后,OpenClaw 就拿一组更完整的话去想答案,而不是每个碎碎念都单独开工。

🎈 一句话

debounce 不是拖延,是先听完再回。

第四站

🗂 Session 是门卫手里的那本“这位客人属于哪一间屋”的本子

这页特别强调:会话是 gateway 的,不是客户端各自私藏的。控制台和 TUI 看到的,才是主本子。

🏠

Direct chats

直聊通常会折叠到主会话。像同一个人一直来前台,还是记在同一本聊天本上。

👥

Groups / channels

群聊和频道通常会有自己的会话键。像每个房间都有自己的记录本。

🔒

Gateway 是总账本

客户端只是来读,不是各写各的。真正的历史由 gateway host 负责保存。

📌

一句话

谁属于哪本本子,别让手机自己猜,交给 gateway 记。

第五站

🪧 prompt body 和 command body 不一样,像“给小工人的话”和“给门卫的原话”

官方把这两层拆开,是为了让历史和命令解析都更稳。

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