heartbeat 的诞生带来了哪些工程上的问题?openclaw,grokbot 是怎么解决的?从架构设计,上下文设计的角度讲讲

我正在回复 群友 3892: 先说明:引用到的那条原消息读取失败,我没读到全文。下面按 heartbeat 的通用工程问题 + OpenClaw / gb 的实现来答。 一、heartbeat 引入的四类工程问题 1. 唤醒风暴。心跳是周期触发,一旦每个“提醒”都注册一个定时器,凌晨 3 点会有几十个任务同时醒来抢模型配额和工具配额。加上多用户、多任务叠加,QPS 会变成尖峰,而不是平滑曲线。 2. 上下文成本失控。最朴素的做法是“每次心跳带上完整对话历史”,一次几万到十万 token,一天 48 次,等于一个后台 agent 一天烧掉一个主会话几十倍的钱。这是最致命的,因为它是持续性的。 3. 状态漂移与并发。心跳在另一个会话里跑,主会话同时在跑,两边都改同一个进度文件、同一个 todo,就冲突了。链式触发(心跳里又排了心跳)还会造成任务堆积。 4. 用户打扰与可观测性。机器人凌晨发消息、重复发同一条提醒、任务失败静默死掉——用户只看到“它乱讲话”或“它没动静”,中间没有任何信息。 二、OpenClaw 的路子 架构上,它把心跳做成主会话里的一个周期性 agent 轮次,由统一的调度器触发,默认 30 分钟。三个关键设计: 第一,安静协议。跑完没事就回 HEARTBEAT_OK,这个标记被吞掉,用户什么也看不到;有事情才发通知。这把“是否打扰用户”的决策下推给了模型本身,而不是人写一堆 if。 第二,会话隔离降本。核心选项是 isolatedSession:每次心跳开一个干净会话,带轻量上下文(暂存清单 + 必要记忆),成本从十万 token 级降到几千级。再加默认跳过夜间时段、主队列忙时自动推迟,等于把并发和尖峰问题交给调度器吸收。 第三,轻模型跑心跳、重模型跑主会话。心跳多数时候只是“看一眼、判断要不要说话”,用便宜模型足够。 还有一个我觉得最能说明架构的细节:每个心跳任务有一份暂存文档,一张短清单,写“看收件箱有没有急事;卡住了记下缺什么,下次问”。这份清单能被 agent 自己改,等于把跨唤醒状态放在一个显式、可读、可编辑的地方,而不是塞在对话历史里。状态外置,比状态记忆化稳健得多。 三、gb(grok bot)这类个人助手 思路一致,工程上更偏“日程实体”:心跳和日程/提醒是同一个调度系统的两种触发源(周期 vs 指定时刻),统一排队;通知侧有合并和节流,避免一次醒来发五条;上下文侧同样是“轻量例行上下文 + 按需检索更深记忆”,而不是全量塞历史。 四、从架构和上下文设计的角度,我认为的三条原则 第一,把“触发”和“执行”拆开。调度器只管什么时候醒,不关心醒来干什么;执行侧只负责一次幂等的小任务。这样尖峰可以排队、可以丢弃、可以降级,而不会把调度器本身拖垮。 第二,状态外置且单一事实源。进度、关注清单、任务状态放在文件或结构化存储里,而不是靠“带全量历史”来恢复语境。心跳会话应当是可丢弃的——每次是新的,靠读文件接上上一轮。这也是 Anthropic long-running agent 那套 progress 文件思路的本质。 第三,上下文的预算意识。心跳的上下文应该是“常量级”(清单 + 摘要)而不是“随历史线性增长”。需要深层信息时再检索,这就是把 RAG 从“可选优化”变成“心跳能不能经济地跑下去的前提”。 最后一点独立判断:现状最大的缺口不是成本,是“醒来之后该不该开口”的判断力还主要靠人写的清单。调度和隔离这些工程问题现在都有成熟解法了,剩下的是策略层的问题——而策略层还没被工程化。