从“等你说话”到“主动巡逻”——让 Agent 真正 7×24 运转

1. 从 Cron 到 Heartbeat:自主巡检的范式跃迁

定时任务 vs 心跳巡检:你的 Agent 该怎么“醒”

很多人搭第一个 AI Agent 都会选择日报 Agent:每天定时触发,搜索热门新闻,推送到微信 / 飞书。 看起来很好用,但是这里面有个认知误区……

这个“定时推送”有什么问题?
  1. 每天固定时间执行,不管有没有值得推送的内容。 无条件
  2. 每次都推送同样格式的消息——即使今天全是你不关心的领域。 无筛选
  3. 如果搜索失败了呢?它不知道,你也不知道。 无反馈

这真的是“智能”吗?还是只是一个高级闹钟?

这个 case 做的是 Cron,不是 Heartbeat

Cron ≠ Heartbeat

Cron Task = 定时闹钟:到点就响,无条件执行。 Heartbeat = 自主巡检:醒来先看清单,判断后再决定做什么。 一个是“机械执行”,一个是“带脑子巡逻”。

1.1 Heartbeat 执行流程全景

  1. 定时触发 every: 30m,固定间隔唤醒。
  2. activeHours 过滤 非活跃时段直接跳过,省 Token。
  3. 上下文加载 SOUL.md + MEMORY + Session 完整注入。
  4. 静默拦截 HEARTBEAT_OK 被 Gateway 丢弃,用户零感知。 暂时无法在飞书文档外展示此内容

1.2 静默机制:HEARTBEAT_OK 的拦截逻辑

核心概念:Agent 回复 HEARTBEAT_OK = “一切正常,不用打扰用户”。

  • HEARTBEAT_OK 出现在回复的开头或结尾 → 识别为静默信号。
  • 剥离后剩余内容 ≤ 300 字符(ackMaxChars)→ 整条消息被丢弃。
  • HEARTBEAT_OK 出现在回复中间 → 不做特殊处理。
  • 告警消息:不包含 HEARTBEAT_OK,直接输出告警文本。
  • 普通对话中出现 HEARTBEAT_OK → 自动剥离并记录日志。

看个例子: [图片]

1.3 Cron vs Heartbeat:核心区别

Cron Task(定时任务)

触发后:无条件执行预设动作 每次都有输出,可用独立 Session

上下文:隔离执行,无记忆 独立 Session 无对话历史

类比:闹钟,7:00 响就是 7:00 响

Heartbeat(心跳巡检)

触发后:先读检查清单,评估后决策 无事发生时静默(HEARTBEAT_OK)

上下文:携带完整 SOUL + MEMORY 默认在主 Session 中运行

类比:保安巡逻,每半小时转一圈,没事不打扰

两个关键差异:1. “有没有决策能力”,2. “能不能静默”。 Cron 不管三七二十一都会推消息,Heartbeat 没大事汇报就闭嘴。

调试技巧:手动唤醒

问题:心跳默认每 30 分钟触发一次,调试时不可能每次都等半小时。 解决方案:直接在飞书中用自然语言让 Agent 执行巡检。

请立刻执行一次心跳巡检
现在跑一遍你的巡检清单
检查一下 HEARTBEAT.md 里的所有检查项,告诉我结果

注意区别:自然语言触发是对话式执行,Agent 可能在当前对话中回复结果,与真正定时心跳有差异(后者走 Gateway 静默拦截)。调试阶段够用,验证静默行为时需等自然心跳周期触发。

AI check AI:你的 Agent 现在有什么“定时能力”?

在飞书中发送: [图片] [图片]

2. Cron 还是 Heartbeat?场景选型与组合策略

五个问题帮你做决定。

选型决策树:五个问题定方案

  • Q1-Q2 → Cron 精确时间、需要隔离的任务。
  • Q3 → Heartbeat 同频率检查可合并,节省成本。
  • Q4-Q5 → Cron 一次性提醒或需指定模型。
  • 默认 → Heartbeat 大多数监控类任务最终落到 Heartbeat。 暂时无法在飞书文档外展示此内容

一句话记住:心跳看状态,Cron 干活 Heartbeat 擅长“看” Cron 擅长“做” 收件箱有没有紧急邮件? 每天 7:00 生成晨间简报 日历上 2 小时内有没有会议? 每周五 17:00 生成周报 服务器磁盘是不是快满了? 20 分钟后提醒我开会 共同特征:检查状态 → 判断 → 静默或告警 共同特征:在指定时间执行具体任务

成本差距:5 个 Cron VS 5 个任务 1 个 Heartbeat 5x

Token 成本差距 5 次 方案 A: 5 个 Cron job 每次 5 份 Token 消耗 1 次 方案 B: 1 个 HEARTBEAT.md 每次 1 份 Token 消耗 场景:5 个每 30 分钟检查的监控任务(邮件、日历、磁盘、任务、Git)。

  • 方案 A:创建 5 个 Cron Job → 每次触发 5 次 Agent turn → 5 份 Token 消耗。
  • 方案 B:写入 1 个 HEARTBEAT.md → 每次触发 1 次 Agent turn → 1 份 Token 消耗。 结论:同频率监控任务,合并到 Heartbeat 比拆成多个 Cron 便宜。

Cron vs Heartbeat 完整对比矩阵 维度 Cron Heartbeat 触发方式 精确时间 / cron 表达式 / –at 固定间隔 Session 通常是独立 Session 默认主 Session 上下文 独立 Session 无对话历史 携带完整 Agent 上下文 静默能力 无(每次都有输出) 有(HEARTBEAT_OK 被拦截) 模型选择 可为每个 Job 指定不同模型 统一使用心跳配置的模型 适用场景 报告生成、数据抓取、定时提醒 状态监控、异常检测、例行巡检 成本特征 每个 Job 独立计费 多项检查合并为一次调用 Cron 灵活但贵,Heartbeat 省钱但粗——根据场景选择。

四种典型组合模式 模式1:纯 Cron 每天 9:00 发周报、20 分钟后提醒开会 时间精确、一次性任务 模式2:纯 Heartbeat 每 30 分钟检查邮件 + 日历 + 服务器 多项监控合并、成本最优 模式3:Cron 干活 + Heartbeat 巡检 Cron 7:00 抓数据写文件 Heartbeat 8:00 检查文件是否生成 模式4:Cron 启动 + Heartbeat 持续监控 Cron 触发一个长任务 Heartbeat 持续检查任务是否完成 适合耗时较长的工作流

社区实践:什么情况下 Heartbeat 不合适?

  • “每周一 9:00 发周报”——需要精确时间,用 Cron。
  • “17 分钟后提醒我”——一次性提醒,用 Cron –at。
  • 重型任务(代码库分析、长文本生成)——会阻塞主 Session。
  • 需要用高阶模型(Opus)处理——用 Cron 指定 –model。
  • 心跳间隔太短(5 分钟)检查一天只变两次的日历——浪费 Token。

适合 Heartbeat 的信号:同频率、轻量级、需要判断、正常情况应该静默。

3. HEARTBEAT.md 设计方法与社区案例

写好心跳清单:社区案例与避坑指南。

HEARTBEAT.md 的定位:心跳清单,不是任务手册

官方定义:小而稳定、每 30 分钟安全注入一次的检查清单。

  • 文件为空(只有标题没有内容)→ OpenClaw 自动跳过心跳,节省 API 调用
  • 文件不存在 → 心跳仍会运行,模型自行决定做什么(不推荐)
  • 核心原则:Keep it Tiny —— 精简才是正义
  • 每次心跳都会把 HEARTBEAT.md 注入 Prompt,内容越长 → Token 消耗越大
官方建议:控制在 200 tokens 以内。社区常见错误就是把清单写成几百行的任务手册。

社区案例

社区案例一:VPS 运维巡检(最简模式)

原始代码

# HEARTBEAT.md

- VPS disk: run `df -h` and alert
  if any partition is above 85%.
- VPS memory: run `free -h` and alert
  if used is above 90%.
- Inbox: scan for urgent emails and
  draft replies when clearly needed.
- Calendar: check next 2 hours and
  remind me 15 min before events.
- If nothing needs attention
  reply HEARTBEAT_OK.

中文翻译

# 心跳巡检清单

- 磁盘:执行 df -h,
  任何分区超过 85% 则告警
- 内存:执行 free -h,
  使用率超过 90% 则告警
- 收件箱:扫描紧急邮件,
  必要时起草回复
- 日历:检查未来 2 小时日程,
  提前 15 分钟提醒
- 以上均无异常,
  回复 HEARTBEAT_OK

来源:LumaDock 社区教程。特点:每条一行,阈值明确。关键:最后一行停止条件必须有。

社区案例二:轮转心跳(多任务调度模式)

原始代码

# HEARTBEAT.md

## Cadence-Based Checks

Read `heartbeat-state.json`.
Run whichever check is most overdue.

**Cadences:**

- Email: every 30 min (9AM-9PM)
- Calendar: every 2h (8AM-10PM)
- Tasks: every 30 min (anytime)
- Git: every 24h (anytime)
- System: every 24h (3 AM only)

**Process:**

1. Load timestamps from state file
2. Find most overdue check
3. Run that check
4. Update timestamp
5. Report or HEARTBEAT_OK

中文翻译

# 心跳巡检清单

## 基于节奏的轮转检查

读取状态文件,
执行最过期的那项检查。

**各任务频率:**

- 邮件:每 30 分钟(9 点-21 点)
- 日历:每 2 小时(8 点-22 点)
- 任务:每 30 分钟(全天)
- Git:每 24 小时(全天)
- 系统:每 24 小时(仅凌晨 3 点)

**执行流程:**

1. 从状态文件加载上次时间
2. 计算哪项最过期
3. 执行该项检查
4. 更新时间戳
5. 有事报告,没事静默

来源:digitalknk。特点:每次只跑最过期一项。适合任务 5+ 的场景。

官方推荐:结构化 tasks: block(自动调度)

原始代码

tasks:
- name: inbox-triage
    interval: 30m
    prompt: "Check for urgent unread emails and flag anything time sensitive."

- name: calendar-scan
    interval: 2h
    prompt: "Check for upcoming meetings that need prep or follow-up."

# Additional instructions
- Keep alerts short.
- If nothing needs attention after all due tasks, reply HEARTBEAT_OK.

中文翻译

任务列表:
- 名称:邮件分诊
    间隔:30 分钟
    指令:“检查紧急未读邮件,标记时间敏感的内容”

- 名称:日历扫描
    间隔:2 小时
    指令:“检查即将到来的会议,是否需要准备或跟进”

# 补充指令
- 告警保持简短
- 所有到期任务均无异常,回复 HEARTBEAT_OK

OpenClaw 自动解析 tasks: block,只有到期任务注入心跳 Prompt。

没有任务到期 → 整次心跳被跳过(reason=no-tasks-due)。

openclaw.json 心跳配置项全景

配置项 默认值 说明
every “30m” 心跳间隔,“0m” = 禁用
target “none” 消息投递目标,“last” = 最近联系的渠道
activeHours.start / end 活跃时段窗口(本地时区)
model 继承默认 心跳专用模型(可用便宜模型降本)
lightContext false true = 只加载 HEARTBEAT.md,不加载完整上下文
isolatedSession false true = 每次心跳用独立 Session(省 Token,但无对话历史)
directPolicy “allow” DM 投递策略,“block” = 禁止私聊推送
includeReasoning false true = 额外发送推理过程消息

日常三件套:every(多久跑一次)+ target(消息发到哪)+ activeHours(几点到几点活跃)。其余为进阶配置。

检查项编写四步法:条件 → 判断 → 动作 → 静默

  1. 条件:什么时段执行?(时段窗口)
  2. 判断:检查什么?判断标准是什么?(明确、可验证)
  3. 动作:异常时做什么?(具体的告警文本或执行操作)
  4. 静默:正常时怎么处理?(回复 HEARTBEAT_OK,不多说一个字)

模板示例:

在 HH:MM-HH:MM 时段内执行此项检查

检查 [目标] 是否满足 [条件]

如果不满足:[具体动作]

如果满足:回复 HEARTBEAT_OK

反模式警示:心跳的两种“翻车姿势”

“狼来了”模式

症状 每次心跳都推送消息,用户被轰炸后直接忽略

原因 检查项写得太模糊,Agent 总能找到点什么说

修复 判断条件必须可量化(“>85%” 而非“磁盘快满了”)

Token 焚烧炉模式

症状 每月 Token 费用暴增

原因 HEARTBEAT.md 写了一整页,注入频率太高

修复 精简清单( < 200 tokens)+ 合理间隔(30-45min)

社区翻车实录:1 分钟心跳的教训

案例来源:Medium 用户 @C.Dalrymple 的 OpenClaw 实战日志。

场景:用户将心跳设为 1 分钟以快速测试 X/Twitter 监控功能。

WhatsApp 消息疑似刷屏,Agent 不断回显 SOUL.md 内容和错误信息。

更严重:Agent 在尝试发帖时,暴露了用户的手机号码。

对话历史被大量心跳消息淹没,正常交互无法进行。

用户总结:

OpenClaw 需要明确的指令和防护栏,光告诉它“做什么”不够,还必须告诉它“不做什么”

这正是 SOUL.md Boundaries 层的意义所在

HEARTBEAT.md 四条黄金法则

法则 01

精简至上

控制在 200 tokens 以内,每条检查项一两行 清单不是论文

法则 02

阈值明确

用可量化的判断条件 “>85%”、“文件不存在”、“缺少标记”

法则 03

必须有停止条件

最后一行写明“以上均无异常时,回复 HEARTBEAT_OK” 没有这行 = “狼来了”

法则 04

设定时段窗口

每个检查项标注适用时段“08:00-09:00” 避免凌晨 3 点推送“今日日报未生成”

小结

  1. 心跳清单不是任务手册 检查项四步法:条件 → 判断 → 动作 → 静默。三种写法:自由文本 / 轮转调度 / tasks: block。
  2. 配置三件套 every + target + activeHours,日常最常用的三个参数。
  3. 四条黄金法则 精简、阈值明确、有停止条件、设时段窗口——避免“狼来了”和 Token 焚烧炉。

4. 实战:Cron + Heartbeat 打造高质量日报

每天早上 7 点,让 Agent 帮你读完全网资讯。

为什么一次抓取不够?

  1. 单次搜索覆盖面有限,容易遗漏重要信息 —— 质量问题
  2. 所有逻辑塞在一次执行中,Token 消耗大且不可控 —— 成本问题
  3. 新方案:拆分为“两轮抓取 + 一次巡检”的组合架构 —— 解决方案

Cron 负责干活(抓数据、写文件),Heartbeat 负责巡检(检查质量、异常告警)

三阶段组合架构总览

  1. 07:00 第一轮抓取
    Cron + 独立 Session,三领域广覆盖。
  2. 07:30 第二轮补充
    读取第一轮结果,定向补充薄弱领域。
  3. 08:00 心跳巡检
    检查日报是否完整,异常才推送。

设计要点:Cron 用独立 Session,Heartbeat 用主 Session。

Step 1:确认当前状态

飞书对话:

帮我检查一下当前的 Heartbeat 配置状态:
1. 读取 openclaw.json 中 heartbeat 相关配置
2. 读取当前 HEARTBEAT.md 的内容
3. 列出 memory/ 目录下现有的文件
4. 确认当前的时区设置

确认要点:

  • heartbeat 已启用
  • every / target / activeHours 三件套配置
  • 巡检清单
  • 每日记录
  • 时区正确

Step 2:注册第一轮 Cron 任务(07:00 三领域抓取)

heartbeat-practice-1

Step 3:注册第二轮 Cron 任务(07:30 定向补充)

heartbeat-practice-2 heartbeat-practice-3

Step 4:编写 HEARTBEAT.md 巡检清单

heartbeat-practice-4

对应设计:

  1. 时段窗口 黄金法则 4:08:00-09:00。
  2. 明确判断条件 黄金法则 2:文件存在 / 缺失 / 包含标记。
  3. 三种结果分支 告警 / 提醒 / 静默。
  4. 停止条件 黄金法则 3

Step 5:配置心跳参数三件套

heartbeat-practice-5 heartbeat-practice-6

Step 6:手动触发验证

第一轮抓取

heartbeat-practice-7

第二轮抓取

heartbeat-practice-8 heartbeat-practice-9

Step 7:巡检三种场景

场景 状态 预期结果
场景 A 日报缺失 收到「⚠️ 今日资讯日报未生成」
场景 B 日报半完成 收到「资讯日报第二轮采集尚未完成」
场景 C 日报完整 期望静默

heartbeat-practice-10 heartbeat-practice-11

注意:对话式触发下如果 Agent 会回复检查结果(如“日报完整,无异常”)——这是正常的。

真正的静默验证:观察 Dashboard 心跳日志,或等下一个自然心跳周期,确认飞书无新消息。

小结

  1. 组合架构 Cron 负责干活(两轮抓取),Heartbeat 负责巡检(质量检查)。
  2. 两轮抓取策略 第一轮广覆盖,第二轮定向补充薄弱领域。
  3. 三分支设计 HEARTBEAT.md 的三分支:完整 → 静默、缺失 → 告警、半完成 → 提醒。

5. 总结

知识点 一句话总结
Cron vs Heartbeat Cron = 定时闹钟,Heartbeat = 带脑子的巡逻保安
选型决策树 五个问题定方案:精确时间?隔离?可合并?一次性?特殊模型?
成本口诀 同频率监控合并到 Heartbeat,Token 成本降 5 倍
静默机制 HEARTBEAT_OK 被 Gateway 拦截,用户零打扰
四条黄金法则 精简、阈值明确、有停止条件、设时段窗口
组合架构 Cron 干活 + Heartbeat 巡检 = 高质量自动化
机制 > 规则 规则只是期望,心跳才是执行保障