
大家好,我是寂寞的熊猫。
之前写过一篇使用 OpenClaw 做定时日报,为什么看起来没执行?一次定时日报任务踩坑复盘,核心是:通知链路不要重复设计,否则失败信息会把状态弄脏。
今天讲的是另一块:心跳(Heartbeat)。
心跳是什么?
根据 OpenClaw 官方文档[1],心跳是一个周期性的后台执行机制,让 Agent 能够:
- 定期检查环境状态(新邮件、日历冲突、系统通知)
- 在主会话中执行巡检任务,拥有完整的对话上下文
- 正常时静默(
HEARTBEAT_OK),异常时才推送告警
心跳和 Cron 的核心区别:
| 特性 | 心跳(Heartbeat) | Cron 定时任务 |
|---|---|---|
| 执行环境 | 主会话,有完整上下文记忆 | 可隔离运行,独立会话 |
| 时间精度 | 固定间隔(如 30 分钟) | 精确到分钟(Cron 表达式) |
| 适用场景 | 周期性巡检、状态感知 | 重任务、精确定时、批量处理 |
| 输出逻辑 | 正常静默,异常才告警 | 默认播报结果 |
心跳让 OpenClaw 从"你问它答"变成"它会自己看、自己判断、有事情才找你"。
那心跳怎么配?
说实话,很多人根本没配置心跳,或者不知道该怎么配。
有人觉得"我平时和 OpenClaw 聊天挺好的,要什么后台自动运行";有人试过配了一下,结果遇到两个问题:
- 成本失控——token 消耗很大,每次心跳都要把整个会话上下文发给模型
- 静默失败——任务跑着跑着就停了,你以为它在干活,其实它早就挂了
我们不讲原理,直接讲配置。4 个关键设置,解决两个核心问题:
- 成本怎么控制——别让心跳把你的 token 额度烧光
- 稳定性怎么保证——防止记忆丢失、静默失败、任务中断
先说结论:
- 心跳要有时间窗——用
activeHours限制运行时段,夜间没必要一直轮询 - 记忆要在压缩前落盘——开启
memoryFlush,防止上下文压缩后丢掉关键信息 - 重任务要隔离——扫描、抓取类任务用 Cron 的
isolated会话,别污染主上下文 - 失败要可见——
showAlerts打开 + HEARTBEAT.md 里加巡检,别等问题堆积了才发现
下面逐个展开。
配置 1:心跳调度窗口化——activeHours
问题是什么
心跳默认每 30 分钟运行一次,24 小时不停。
如果你只是白天用 OpenClaw,夜间的心跳调用就是纯浪费——每次都要把整个会话上下文发给模型,积累下来是一笔不小的开销。
更关键的是,夜间没人响应,心跳产生的告警也没人处理,第二天早上还得重新看一遍。

怎么配
在 ~/.openclaw/openclaw.json 里加 activeHours:
{"agents":{"defaults":{"heartbeat":{"every":"30m","activeHours":{"start":"08:00","end":"23:00"}}}}}这样心跳只在 08:00-23:00 之间运行,夜间直接跳过。
配置逻辑
every: "30m":心跳间隔,默认 30 分钟够用,不用调太短activeHours:活动时间窗,根据自己的作息调整- 时区默认用系统时区,如果部署在服务器上,注意检查时区设置
一句话:让心跳在你需要的时候跑,而不是无脑 24/7 轮询。
配置 2:压缩前记忆落盘——memoryFlush
问题是什么
OpenClaw 运行久了,会话上下文会越来越长。当接近模型上下文窗口限制时,系统会自动触发压缩(Compaction)——把早期对话总结成摘要,释放空间。
问题来了:压缩过程会丢弃大量细节。你之前跟 Agent 说过的偏好、正在进行的任务状态、阶段性的判断,可能一压缩就没了。
社区有个真实案例:Meta 的 Summer Yue 配置 OpenClaw 帮她清理邮件,明确说了"删除前要先问我"。一开始运行正常,但运行几周后会话被压缩,那条关键指令从上下文中消失了。Agent 恢复成默认的激进模式,开始自动删邮件。

怎么配
开启压缩前记忆刷新,让 Agent 在压缩前把关键信息写入磁盘:
{"agents":{"defaults":{"compaction":{"reserveTokensFloor":20000,"memoryFlush":{"enabled":true,"softThresholdTokens":4000,"prompt":"Write any lasting notes to memory/YYYY-MM-DD.md (create memory/ if needed). IMPORTANT: If the file already exists, READ it first and APPEND new content — do not overwrite. If nothing to store, reply with NO_REPLY."}}}}}配置逻辑
reserveTokensFloor: 20000:为压缩前的内务操作预留 token 空间,默认值够用memoryFlush.enabled: true:开启压缩前记忆刷新prompt里的关键点:- APPEND not overwrite:追加写入,不要覆盖已有内容(这是社区踩过的坑)
- NO_REPLY:没事可写时静默返回,不产生噪音
一句话:把短期记忆变成可恢复的外部记忆,压缩就不会丢东西。
配置 3:重任务隔离运行——Cron sessionTarget: isolated
问题是什么
心跳适合做轻量级的周期性巡检:检查有没有新邮件、日历有没有冲突、系统状态正不正常。
但如果你把扫描、抓取、索引更新这类重任务也塞进心跳,会有两个问题:
- 主会话膨胀——工具输出会不断累积到上下文里,加速压缩
- 失败难定位——重任务失败和心跳逻辑混在一起,排查困难
怎么配
用 Cron 的隔离会话模式跑重任务:
openclaw cron add \ --name "Nightly scan & index" \ --cron "30 2 * * *" \ --tz "Asia/Shanghai" \ --session isolated \ --message "Scan sources, update indexes, and write a brief report. If failures occur, include error summary." \ --announce \ --channel telegram \ --to "your_chat_id"配置逻辑
--session isolated:在独立的cron:<jobId>会话中运行,不污染主会话--announce:任务完成后投递摘要到指定渠道--tz:显式指定时区,避免服务器时区漂移
一句话:心跳做巡检,Cron 做重活,各司其职。
配置 4:失败可见性——showAlerts + HEARTBEAT.md 巡检
问题是什么
定时任务最可怕的不是失败,而是静默失败——你以为系统在正常运行,其实它早就停了。
心跳默认有个机制:如果一切正常,Agent 会返回 HEARTBEAT_OK,这个消息会被系统静默抑制,不打扰用户。只有检测到异常时才会推送告警。
但如果你把告警开关关了,或者心跳本身出了问题,你就完全不知道系统状态。

怎么配
第一步:确保告警可见
{"channels":{"defaults":{"heartbeat":{"showOk":false,"showAlerts":true,"useIndicator":true}}}}showOk: false:正常心跳静默,不刷屏showAlerts: true:异常必须推送,不能关useIndicator: true:在界面上显示心跳状态指示器
第二步:在 HEARTBEAT.md 里加巡检逻辑
在工作区创建 HEARTBEAT.md:
# Heartbeat checklist- Quick health: anything urgent in inbox/notifications?- Cron safety: check recent cron runs; if any failures, alert me with jobId + reason.- If nothing needs attention, reply HEARTBEAT_OK.这样心跳不仅执行自己的巡检任务,还会帮你检查 Cron 任务有没有失败。
配置逻辑
- 告警必须可见,否则自动化就是"盲跑"
- HEARTBEAT.md 是心跳的任务清单,可以根据自己的需求定制
- 保持简短,避免每次心跳都塞太多 token
一句话:让失败暴露出来,而不是等问题堆积成灾难。
进阶:为什么这套配置能省钱?
前面讲的都是"怎么配",这里简单说一下"为什么能省钱"。
上下文缓存机制
现代大模型 API(如 Anthropic)支持上下文缓存(Prompt Caching)。
简单说:如果你的请求中有一部分内容是重复的(比如系统提示词、历史对话),模型可以把这部分缓存起来。下次请求时,缓存命中的部分成本只有原来的 10%。
心跳机制的上下文结构是:
- 静态部分:SOUL.md、AGENTS.md、TOOLS.md 等 —— 每次都一样
- 动态部分:新消息、环境状态变化 —— 每次不同
如果缓存配置得当,心跳每次只需要为动态部分付费,静态部分走缓存,成本大幅降低。
缓存 TTL 对齐
但缓存有生命周期(TTL),通常是 5 分钟左右。如果心跳间隔是 30 分钟,两次心跳之间缓存早就过期了,每次都是"冷启动"。
有一个反直觉的优化策略:让心跳跑得更频繁,反而更省钱。
比如把心跳设成每 4.5 分钟一次(略低于缓存 TTL),这样缓存一直保持"预热"状态。虽然请求次数增加了,但每次都命中缓存,总成本反而更低。
这个策略需要根据你使用的模型和 API 具体调整,核心思路是:让心跳频率和缓存 TTL 对齐。
模型路由
另一个省钱技巧:心跳任务通常不需要顶级模型。
你可以在路由层配置:
- 主聊天窗口的请求 → 走强模型
- 心跳后台请求 → 走等低成本模型
这样心跳在后台默默干活,用的是便宜模型,成本压到最低。
最后总结
4 个关键配置,解决两个核心问题:
| 配置 | 解决的问题 | 核心参数 |
|---|---|---|
activeHours | 控制运行时段,减少无效调用 | start / end |
memoryFlush | 防止压缩丢记忆 | enabled + APPEND 提示 |
Cron isolated | 隔离重任务,不污染主会话 | --session isolated |
showAlerts + 巡检 | 失败可见,避免静默失败 | showAlerts: true |
最小配置
如果你只想快速配好,至少做这三件事:
- 给心跳加
activeHours,限制在常用时段 - 开启
memoryFlush,prompt 里写明 APPEND - 确保
showAlerts: true,异常要推送
这样配完,OpenClaw 就能稳定跑在后台,成本可控,失败可感知。
想要学习AI,可以了解AI破局俱乐部星球,国内最大的AI学习社区,全年有多次免费实战。

夜雨聆风