Heartbeat
Heartbeat 在主会话中运行定期的 agent 轮次,以便模型可以引起您对需要注意的事项的注意,而不会对您造成信息轰炸。
Heartbeat 是一个计划的主动话话轮 — 它不会创建后台任务记录。任务记录用于分离的工作(ACP 运行、子代理、独立的 cron 作业)。
故障排除:计划任务
快速开始(初学者)
Section titled “快速开始(初学者)”选择节奏
保持启用 heartbeats(默认为
30m,或者对于 Anthropic OAuth/token 认证(包括 Claude CLI 重用)为1h)或设置您自己的节奏。添加 HEARTBEAT.md(可选)
在代理工作区中创建一个微小的
HEARTBEAT.md检查清单或tasks:块。决定心跳消息的发送位置
target: "none"是默认值;设置target: "last"以路由到最后一个联系人。可选优化
- 启用心跳推理交付以提高透明度。
- 如果心跳运行只需要
HEARTBEAT.md,请使用轻量级引导上下文。 - 启用隔离会话以避免每次心跳都发送完整的对话历史记录。
- 将心跳限制在活动时间(当地时间)。
配置示例:
{ agents: { defaults: { heartbeat: { every: "30m", target: "last", // explicit delivery to last contact (default is "none") directPolicy: "allow", // default: allow direct/DM targets; set "block" to suppress lightContext: true, // optional: only inject HEARTBEAT.md from bootstrap files isolatedSession: true, // optional: fresh session each run (no conversation history) skipWhenBusy: true, // optional: also defer when this agent's subagent or nested lanes are busy // activeHours: { start: "08:00", end: "24:00" }, // includeReasoning: true, // optional: send separate `Thinking` message too }, }, },}- 间隔:
30m(或者当检测到 Anthropic OAuth/token 认证模式时为1h,包括 Claude CLI 重用)。设置agents.defaults.heartbeat.every或每个代理的agents.list[].heartbeat.every;使用0m禁用。 - 提示主体(可通过
agents.defaults.heartbeat.prompt配置):Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK. - 心跳提示会作为用户消息逐字发送。仅当为默认代理启用心跳时,系统提示中才会包含“心跳”部分,并且该运行会在内部被标记。
- 当使用
0m禁用心跳时,正常运行也会从启动上下文中省略HEARTBEAT.md,以便模型不会看到仅限心跳的指令。 - 在配置的时区中检查活动时间 (
heartbeat.activeHours)。在此时间窗口之外,将跳过心跳,直到窗口内的下一次检查。 - 当 cron 工作处于活动状态或排队中时,Heartbeat 会自动延迟。设置
heartbeat.skipWhenBusy: true也可以使该代理在其自身的会话键子代理或嵌套命令通道上延迟;兄弟代理不会仅仅因为另一个代理有子代理工作正在进行而暂停。
心跳提示的用途
Section titled “心跳提示的用途”默认提示是有意保持宽泛的:
- 后台任务:“考虑未完成的任务”会提示代理审查后续工作(收件箱、日历、提醒、排队的工作)并突出显示任何紧急事项。
- 人工检查:“白天偶尔检查你的使用者”会提示偶尔发送一条轻量级的“你需要什么?”消息,但通过使用你配置的本地时区来避免夜间骚扰(请参阅时区)。
Heartbeat 可以对已完成的后台任务做出反应,但 Heartbeat 运行本身不会创建任务记录。
如果你希望心跳执行非常具体的操作(例如“检查 Gmail PubSub 统计数据”或“验证网关运行状况”),请将 agents.defaults.heartbeat.prompt(或 agents.list[].heartbeat.prompt)设置为自定义内容(逐字发送)。
- 如果不需要关注,请回复
HEARTBEAT_OK。 - 具备工具能力的心跳运行可能会改为调用
heartbeat_respond并附带notify: false以表示没有可见更新,或者调用notify: true加上notificationText以发出警报。当存在结构化工具响应时,它优先于文本回退。 - 在心跳运行期间,OpenClaw 将
HEARTBEAT_OK视为确认,当它出现在回复的开头或结尾时。该标记会被剥离,如果剩余内容**≤ackMaxChars**(默认值:300),则回复将被丢弃。 - 如果
HEARTBEAT_OK出现在回复的中间,则不会对其进行特殊处理。 - 对于警报,请勿包含
HEARTBEAT_OK;仅返回警报文本。
在心跳之外,消息开头/结尾处孤立的 HEARTBEAT_OK 将被剥离并记录;仅包含 HEARTBEAT_OK 的消息将被丢弃。
{ agents: { defaults: { heartbeat: { every: "30m", // default: 30m (0m disables) model: "anthropic/claude-opus-4-6", includeReasoning: false, // default: false (deliver separate Thinking message when available) lightContext: false, // default: false; true keeps only HEARTBEAT.md from workspace bootstrap files isolatedSession: false, // default: false; true runs each heartbeat in a fresh session (no conversation history) skipWhenBusy: false, // default: false; true also waits for this agent's subagent/nested lanes target: "last", // default: none | options: last | none | <channel id> (core or plugin, e.g. "imessage") to: "+15551234567", // optional channel-specific override accountId: "ops-bot", // optional multi-account channel id prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.", ackMaxChars: 300, // max chars allowed after HEARTBEAT_OK }, }, },}作用域和优先级
Section titled “作用域和优先级”agents.defaults.heartbeat设置全局心跳行为。agents.list[].heartbeat在此基础上合并;如果任何代理具有heartbeat块,则仅这些代理运行心跳。channels.defaults.heartbeat为所有渠道设置可见性默认值。channels.<channel>.heartbeat覆盖渠道默认值。channels.<channel>.accounts.<id>.heartbeat(多账户渠道)覆盖按渠道设置。
每个代理的心跳
Section titled “每个代理的心跳”如果任何 agents.list[] 条目包含 heartbeat 块,则仅这些代理运行心跳。每个代理的块在 agents.defaults.heartbeat 之上合并(因此您可以设置一次共享默认值,并针对每个代理进行覆盖)。
示例:两个代理,只有第二个代理运行心跳。
{ agents: { defaults: { heartbeat: { every: "30m", target: "last", // explicit delivery to last contact (default is "none") }, }, list: [ { id: "main", default: true }, { id: "ops", heartbeat: { every: "1h", target: "whatsapp", to: "+15551234567", timeoutSeconds: 45, prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.", }, }, ], },}活跃时段示例
Section titled “活跃时段示例”将心跳限制在特定时区的工作时间内:
{ agents: { defaults: { heartbeat: { every: "30m", target: "last", // explicit delivery to last contact (default is "none") activeHours: { start: "09:00", end: "22:00", timezone: "America/New_York", // optional; uses your userTimezone if set, otherwise host tz }, }, }, },}在此时间窗口之外(美国东部时间上午 9 点之前或晚上 10 点之后),心跳将被跳过。时间窗口内的下一次计划滴答将正常运行。
24/7 设置
Section titled “24/7 设置”如果您希望心跳全天运行,请使用以下模式之一:
- 完全省略
activeHours(无时间窗口限制;这是默认行为)。 - 设置全天时间窗口:
activeHours: { start: "00:00", end: "24:00" }。
使用 accountIdTelegram 来定位多账户渠道(如 Telegram)上的特定账户:
{ agents: { list: [ { id: "ops", heartbeat: { every: "1h", target: "telegram", to: "12345678:topic:42", // optional: route to a specific topic/thread accountId: "ops-bot", }, }, ], }, channels: { telegram: { accounts: { "ops-bot": { botToken: "YOUR_TELEGRAM_BOT_TOKEN" }, }, }, },}main(默认):代理主会话。- 显式会话密钥(从
openclaw sessions --jsonCLI 或 sessions CLI 复制)。 - 会话密钥格式:参见 Sessions 和 Groups。
- 如果省略或为
"user":如果已设置则使用您的agents.defaults.userTimezone,否则回退到主机系统时区。 "local":始终使用主机系统时区。- 任何 IANA 标识符(例如
America/New_York):直接使用;如果无效,则回退到上述"user"的行为。 start和end在活动窗口内不得相等;相等的值将被视为零宽度(始终在窗口之外)。- 在活动窗口之外,心跳将被跳过,直到窗口内的下一次计时。
Session and target routing
- Heartbeats run in the agent’s main 会话 by default (`agent:
:
), or globalwhensession.scope = “global”. Set sessionto override to a specific 渠道 会话 (Discord/WhatsApp/etc.). -sessiononly affects the run context; delivery is controlled bytargetandto. - To deliver to a specific 渠道/recipient, set target+to. With target: “last”, delivery uses the last external 渠道 for that 会话. - Heartbeat deliveries allow direct/私信 targets by default. Set directPolicy: “block”to suppress direct-target sends while still running the heartbeat turn. - If the main queue, target 会话 lane, cron lane, or an active cron job is busy, the heartbeat is skipped and retried later. - IfskipWhenBusy: true, this agent's 会话-keyed subagent and nested lanes also defer heartbeat runs. Other agents' busy lanes do not defer this agent. - If target` resolves to no external destination, the run still happens but no outbound message is sent.
Visibility and skip behavior
- 如果
showOk、showAlerts和useIndicator均被禁用,则运行将作为reason=alerts-disabledOpenClawOpenClaw 从一开始就被跳过。 - 如果仅禁用了警报发送,OpenClaw 仍可运行心跳,更新到期任务时间戳,恢复会话空闲时间戳,并抑制向外的警报负载。
- 如果解析出的心跳目标支持“正在输入”,OpenClaw 会在心跳运行期间显示正在输入。这使用心跳将聊天输出发送到的同一目标,并且由
typingMode: "never"禁用。
Session lifecycle and audit
- 仅心跳的回复不会保持会话活跃。心跳元数据可能会更新会话行,但空闲过期使用的是来自最后一个真实用户/渠道消息的
lastInteractionAt,而每日过期使用的是sessionStartedAt。 - 控制UI和WebChat历史记录会隐藏心跳提示和仅OK的确认信息。底层的会话记录仍然可以包含这些轮次以供审计/重放。
- 分离的后台任务可以排队一个系统事件并在主会话需要快速注意某些事情时唤醒心跳。该唤醒不会导致心跳运行后台任务。
默认情况下,在传递警报内容时会抑制 HEARTBEAT_OK 确认。您可以针对每个渠道或每个帐户进行调整:
channels: defaults: heartbeat: showOk: false # Hide HEARTBEAT_OK (default) showAlerts: true # Show alert messages (default) useIndicator: true # Emit indicator events (default) telegram: heartbeat: showOk: true # Show OK acknowledgments on Telegram whatsapp: accounts: work: heartbeat: showAlerts: false # Suppress alert delivery for this account优先级:按帐户 → 按渠道 → 渠道默认值 → 内置默认值。
每个标志的作用
Section titled “每个标志的作用”showOk:当模型返回仅 OK 的回复时,发送HEARTBEAT_OK确认。showAlerts:当模型返回非 OK 的回复时,发送警报内容。useIndicator:为 UI 状态表面发出指示器事件。
如果这三个全为 false,OpenClaw 将完全跳过心跳运行(不调用模型)。
按渠道与按帐户的示例
Section titled “按渠道与按帐户的示例”channels: defaults: heartbeat: showOk: false showAlerts: true useIndicator: true slack: heartbeat: showOk: true # all Slack accounts accounts: ops: heartbeat: showAlerts: false # suppress alerts for the ops account only telegram: heartbeat: showOk: true| 目标 | 配置 |
|---|---|
| 默认行为(静默 OK,开启警报) | (无需配置) |
| 完全静默(无消息,无指示器) | channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: false } |
| 仅指示器(无消息) | channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: true } |
| 仅在一个渠道中显示 OK | channels.telegram.heartbeat: { showOk: true } |
HEARTBEAT.md(可选)
Section titled “HEARTBEAT.md(可选)”如果工作区中存在 HEARTBEAT.md 文件,默认提示会告诉代理去读取它。可以将其视为您的“心跳检查清单”:小巧、稳定,并且每30分钟考虑一次是安全的。
在正常运行中,只有在为默认代理启用心跳指导时,才会注入 HEARTBEAT.md。使用 0m 禁用心跳节奏或设置 includeSystemPromptSection: false 会将其从正常的引导上下文中省略。
在原生Codex harness上,HEARTBEAT.md 内容不会被注入到轮次中。如果文件存在且包含非空白内容,心跳协作模式指令会将Codex指向该文件并告诉它在继续之前先读取。
如果 HEARTBEAT.md 存在但实际上为空(仅包含空行和像 # Heading 这样的markdown标题),OpenClaw 会跳过心跳运行以节省API调用。该跳过会被报告为 reason=empty-heartbeat-file。如果文件缺失,心跳仍会运行,模型将决定做什么。
保持它非常小(简短的检查清单或提醒),以避免提示膨胀。
示例 HEARTBEAT.md:
# Heartbeat checklist
- Quick scan: anything urgent in inboxes?- If it's daytime, do a lightweight check-in if nothing else is pending.- If a task is blocked, write down _what is missing_ and ask Peter next time.tasks: 块
Section titled “tasks: 块”HEARTBEAT.md 还支持一个小型的结构化 tasks: 块,用于在心跳内部进行基于间隔的检查。
示例:
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.Behavior
- OpenClaw 解析
tasks:块,并根据其自己的interval检查每个任务。 - 只有到期的任务才会包含在该心跳周期的心跳提示中。
- 如果没有任务到期,则完全跳过心跳 (
reason=no-tasks-due),以避免浪费模型调用。 HEARTBEAT.md中的非任务内容会被保留,并作为附加上下文追加到到期任务列表之后。- 任务的最后运行时间戳存储在会话状态 (
heartbeatTaskState) 中,因此间隔在正常重启后依然有效。 - 只有在心跳运行完成其正常回复路径后,任务时间戳才会前进。跳过的
empty-heartbeat-file/no-tasks-due运行不会将任务标记为已完成。
当您希望一个心跳文件包含多个定期检查,而不必在每个周期为所有检查付费时,任务模式非常有用。
代理可以更新 HEARTBEAT.md 吗?
Section titled “代理可以更新 HEARTBEAT.md 吗?”可以 — 如果您要求它这样做。
HEARTBEAT.md 只是代理工作区中的一个普通文件,因此您可以(在正常聊天中)告诉代理类似这样的内容:
- “更新
HEARTBEAT.md以添加每日日历检查。” - “重写
HEARTBEAT.md,使其更简短并专注于收件箱跟进。”
如果您希望这种情况主动发生,您还可以在心跳提示中包含一行明确的内容,例如:“如果检查清单变得过时,请用更好的清单更新 HEARTBEAT.md。”
手动唤醒 (按需)
Section titled “手动唤醒 (按需)”您可以排队一个系统事件并通过以下方式触发即时心跳:
openclaw system event --text "Check for urgent follow-ups" --mode now如果配置了多个代理的 heartbeat,手动唤醒会立即运行每个代理的心跳。
使用 --mode next-heartbeat 等待下一次计划周期。
推理交付 (可选)
Section titled “推理交付 (可选)”默认情况下,心跳仅传递最终的 “answer” 有效载荷。
如果您需要透明度,请启用:
agents.defaults.heartbeat.includeReasoning: true
启用后,心跳还会发送一条前缀为 Thinking 的单独消息(形状与 /reasoning on 相同)。当代理正在管理多个会话/codex 并且你想查看它决定 ping 你的原因时,这可能很有用——但它也可能泄露比你想要的更多的内部细节。在群聊中建议保持关闭状态。
心跳运行完整的代理轮次。较短的间隔会消耗更多的 token。要降低成本:
- 使用
isolatedSession: true以避免发送完整的对话历史(每次运行从约 100K token 降至约 2-5K)。 - 使用
lightContext: true将引导文件限制为仅HEARTBEAT.md。 - 设置更便宜的
model(例如ollama/llama3.2:1b)。 - 保持
HEARTBEAT.md较小。 - 如果你只想要内部状态更新,请使用
target: "none"。
心跳后的上下文溢出
Section titled “心跳后的上下文溢出”如果心跳之前将现有会话留在了较小的本地模型上,例如具有 32k 窗口的 Ollama 模型,并且下一个主会话轮次报告了上下文溢出,则会将会话运行时模型重置回配置的主模型。当最后的运行时模型与配置的 heartbeat.model 匹配时,OpenClaw 的重置消息会指明这一点。
当前的心跳在运行完成后保留共享会话的现有运行时模型。你仍然可以使用 isolatedSession: true 在新会话中运行心跳,将其与 lightContext: true 结合以获得最小的提示,或者选择一个具有足够大的上下文窗口以适应共享会话的心跳模型。