为什么OpenClaw的心跳机制在免费模型使用中可能产生隐性成本【必读】
OpenClaw 的心跳机制默认每 30 分钟唤醒一次智能体,表面看只是个周期性的“体检”动作。但如果没做会话隔离、系统提示缓存、活动时段限制,以及响应格式规范,这 30 分钟一次的“体检”就会变成隐形成本黑洞——本地模型 OOM、Token 白白烧掉、硬件空转、冗余重试,一个都跑不掉。

具体来说,即便你配置的是免费模型(比如 Ollama 本地模型或 Gemini Flash),由于上下文膨胀、提示重复注入、会话未隔离等配置疏忽,每一次心跳都可能触发云端 API 调用或本地模型的高负载推理。这些开销不是被隐藏的账单,而是实打实的资源损耗。
心跳未隔离导致上下文持续累积
默认情况下,心跳任务在主会话里运行,每次加载全部历史对话、SOUL.md 文件、记忆快照和工具输出缓存。一个运行了 7 天的智能体,会话上下文可能轻松突破 15 万 tokens——哪怕你用的是本地 Llama3.2:1b 模型,单次推理也得把整个上下文塞进显存。结果就是 OOM 崩溃,或者强制分块处理,间接拉高 GPU 内存占用和响应延迟。
在 openclaw.json 中添加以下配置可以解决:
{"agents":{"defaults":{"heartbeat":{"isolatedSession":true,"lightContext":true}}}}
注意:isolatedSession:true 必须开启
系统提示词未缓存,每次心跳重复发送
HEARTBEAT.md 的内容、SOUL.md 里的指令、默认心跳 prompt(比如“Read HEARTBEAT.md if it exists…”)——这些固定文本,默认会在每次心跳请求中完整重传一遍。对云端模型来说,这是纯纯的 Token 浪费;对本地模型,则意味着反复把相同字符串加载进 KV Cache,挤占推理空间。
启用提示缓存只需要两步:
- 确保模型后端支持
cacheSystemPrompts(llama.cpp v0.4+、Ollama 0.3.5+ 已支持); - 在 openclaw.json 对应模型配置中加入:
"cacheSystemPrompts": true, "cacheRetention": "6h"
这一步不做的话,哪怕用免费模型,单次心跳也会多消耗 800–2000 tokens 的冗余提示。
活动时段未设限,深夜仍在空转
心跳默认全天候运行。凌晨 2 点系统空闲时,它仍然每 30 分钟拉一次本地模型、读 HEARTBEAT.md、做空判断、写日志——CPU 白跑,SSD 被频繁读写,风扇转得飞起,电费照涨不误。这不光是 API 账单问题,而是真实的物理成本。
配置活动时段就能彻底规避:
{"agents":{"defaults":{"heartbeat":{"activeHours":{"start":"08:00","end":"23:00","timezone":"Asia/Shanghai"}}}}}
注意:timezone 必须显式声明,否则按 UTC 解析,会导致国内用户实际生效时间偏移 8 小时。
心跳响应未规范,触发冗余重试
OpenClaw 要求心跳成功响应必须以 HEARTBEAT_OK 开头或结尾,且剩余内容不超过 300 字符,才会自动丢弃。如果你自定义的 HEARTBEAT.md 中指令太模糊(比如写“检查所有邮件”而不是“检查 Gmail 未读数>5 的发件人”),模型可能生成带分析过程的长回复,OpenClaw 判定为“需人工介入”,进而启动失败重试逻辑——3 次重试就是 3 倍本地推理开销。
解决方法有两种:
- 严格限定 HEARTBEAT.md 末尾加一行
# ACK_ONLY,强制模型只输出 HEARTBEAT_OK 或空行; - 在 openclaw.json 中设置
"ackMaxChars": 100,收紧丢弃阈值。