心跳还是自动化? 有关何时使用哪一种,请参阅 自动化。
openclaw cron list --all 中显示为 Heartbeat (agent-id))。心跳配置仍然是期望状态的输入,而持久化的监控计划负责实际的计时,以及运行器后续的冷却时间。网关会在启动时和配置重新加载时写入配置变更;openclaw doctor --fix 可以在下一次网关启动前,将缺失或过时的监控记录具体化。请编辑 agents.*.heartbeat,不要编辑自动化任务。
定时心跳需要自动化功能。当 cron.enabled 为 false 或 OPENCLAW_SKIP_CRON=1 时,网关会记录启动警告,并且不会运行定时心跳;手动唤醒和事件驱动的心跳唤醒仍然可用。不存在单独的心跳备用计时器。
故障排查:自动化。
快速开始(新手)
1
选择一个频率
保持启用 heartbeats(默认是
30m,如果配置了 Anthropic OAuth/token auth,则为 1h,包括 Claude CLI 复用),或者设置你自己的频率。2
添加监控暂存内容(可选)
使用
openclaw cron scratch <jobId> --set "..." 在 heartbeat 监控器的暂存区中存储一个简短的检查清单。3
决定 heartbeat 消息应发送到哪里
Heartbeat 提醒默认发送到操作员的私信。设置
commands.ownerAllowFrom 或具体频道的 allowFrom;仅包含通配符的允许列表无法识别所有者。4
可选调优
- 如果 heartbeat 运行只需要监控器暂存内容,请使用轻量级引导上下文。
- 启用隔离会话,避免每次 heartbeat 都发送完整的对话历史。
- 将 heartbeat 限制在活跃时间段内(本地时间)。
默认值
- 间隔:
30m。应用 Anthropic provider 默认值后,当解析出的身份验证模式为 OAuth/token(包括复用 Claude CLI)时,会将其提升为1h,但仅在未设置heartbeat.every时生效。设置agents.defaults.heartbeat.every或单个代理的agents.entries.*.heartbeat.every;使用0m可禁用。 - 传递目标:
owner。OpenClaw 使用第一个具体的commands.ownerAllowFrom条目,然后使用频道的allowFrom,并且绝不会将此路由发送到群组。如果没有可解析的所有者私信,环境轮询会以reason=no-route跳过。设置target: "last"可跟随最近的会话,包括群组;设置target: "none"则仅运行内部任务。 - 提示正文(可通过
agents.defaults.heartbeat.prompt配置):Follow the heartbeat monitor scratch context when provided. Recurring tasks are automations; create or change their schedules with the automations tool, not heartbeat scratch. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK. - 超时:未设置的心跳轮次会在设置了
agents.defaults.timeoutSeconds时使用该值。否则,会使用心跳间隔,但上限为 600 秒。设置agents.defaults.heartbeat.timeoutSeconds或单个代理的agents.entries.*.heartbeat.timeoutSeconds可允许更长的心跳任务。 - 心跳提示会以原样作为用户消息发送。当为默认代理启用间隔时,系统提示会自动包含一个“Heartbeats”部分;该指导没有单独的心跳开关。
- 使用
0m禁用心跳时,监控自动化任务仍会保留但处于禁用状态,其暂存内容也会保留,以便重新启用间隔时使用。 - 完全禁用自动化后,即使心跳间隔仍处于启用状态,计划心跳也不会运行。
- 活跃时段(
heartbeat.activeHours)会根据配置的时区进行检查。在时间窗口之外,心跳会被跳过,直到下一个位于时间窗口内的时间点。 - 当主队列或自动化任务处于活动状态或排队中、同一代理的任何回复或嵌入式运行处于活动状态,以及解析出的目标会话存在活动或排队任务时,计划心跳会延迟执行。立即唤醒和手动唤醒会绕过宽泛的同一代理活动运行检查,但仍会遵守主队列、自动化任务和目标会话繁忙防护。同级代理之间不会相互暂停。
heartbeat 提示的用途
默认提示有意保持简洁:在提供 heartbeat 监控临时上下文时遵循该上下文,将重复性工作保留在自动化任务中,并在没有需要关注的事项时回复HEARTBEAT_OK。它明确告知代理不要根据过往聊天推断或重复旧任务,因此默认安装会保持安静,而不会重新整理过时的对话上下文。
主动 heartbeat 行为需要选择启用:
- 重复性检查:为收件箱查看、日历扫描或排队的后续事项创建 自动化任务。每个任务都会按自身的计划执行其配置的有效载荷;默认 heartbeat 不会从过往聊天中推断重复性工作。
- 人工问候:如果你希望偶尔收到一条轻量的“有什么需要我帮忙的吗?”消息,请创建一个计划任务,并限制其计划,避免在你配置的本地时区的夜间发送提醒(参见 时区)。
agents.defaults.heartbeat.prompt(或 agents.entries.*.heartbeat.prompt)设置为自定义正文(按原样发送)。
响应约定
- 如果无需关注,请回复
HEARTBEAT_OK。 - 心跳运行也可以调用
heartbeat_respond,并设置notify: false以不显示更新,或设置notify: true并提供notificationText以发送提醒。如果存在结构化工具响应,则优先使用该响应,而不是文本备用方案。 - 带有意义的
heartbeat_respond结果在设置notify: false时会保持静默,但会作为有界的内部上下文留存,供该会话中的下一轮用户消息使用。no_change确认和可见通知不会以这种方式存储。 - 在心跳运行期间,当
HEARTBEAT_OK出现在回复的开头或结尾时,OpenClaw 会将其视为确认;如果剩余内容不超过 300 个字符,则会移除该标记并丢弃回复。此抑制额度是固定的,无法针对每次心跳单独配置。 - 如果
HEARTBEAT_OK出现在回复的中间,则不会对其进行特殊处理。 - 对于提醒,不要包含
HEARTBEAT_OK;只返回提醒文本。 - 投递时会选择最后一个具备出站能力且非推理的有效负载。单独的推理或思考负载会保留在内部;仅包含推理的结果不会产生提醒。
- 在心跳轮次期间,工具错误警告仍会启用。
HEARTBEAT_OK 会被去除并记录;只有 HEARTBEAT_OK 的消息会被丢弃。
配置
作用域和优先级
agents.defaults.heartbeat设置全局 heartbeat 行为。agents.entries.*.heartbeat在此基础上合并;如果任一 agent 具有heartbeat块,则只有这些 agent会运行 heartbeats。channels.defaults.heartbeatVisibility设置所有 channel 的可见性默认值。channels.<channel>.heartbeatVisibility覆盖 channel 默认值。channels.<channel>.accounts.<id>.heartbeatVisibility(多账户 channel)覆盖每个 channel 的设置。
按 agent 的 heartbeats
如果任一agents.entries.* 条目包含 heartbeat 块,则只有这些 agent会运行 heartbeats。每个 agent 的块会在 agents.defaults.heartbeat 基础上合并(因此你可以只设置一次共享默认值,然后按 agent 覆盖)。
示例:两个 agent,只有第二个 agent 运行 heartbeats。
活跃时段示例
将 heartbeats 限制在特定时区的工作时间内:24/7 设置
如果你希望 heartbeats 全天运行,请使用以下模式之一:- 完全省略
activeHours(没有时间窗口限制;这是默认行为)。 - 设置全天窗口:
activeHours: { start: "00:00", end: "24:00" }。
多账户示例
在 Telegram 这类多账户 channels 上,使用accountId 目标指定某个特定账户:
字段说明
string
Heartbeat 间隔(持续时间字符串;默认单位 = 分钟)。
string
heartbeat 运行的可选模型覆盖(
provider/model)。boolean
default:"false"
当为 true 时,heartbeat 运行会使用轻量级引导上下文,并跳过工作区引导文件。无论何种情况,监控 scratch 都会由 heartbeat runner 注入。
boolean
default:"false"
当为 true 时,每次 heartbeat 都会在没有此前对话历史的全新会话中运行。使用与
sessionTarget: "isolated" 的自动化作业相同的隔离模式。可大幅降低每次 heartbeat 的 token 成本。与 lightContext: true 结合使用可实现最大节省。传递路由仍使用主会话上下文。string
heartbeat 运行的可选会话键。
main(默认):agent 主会话。- 显式会话键(从
openclaw sessions --json或 sessions CLI 复制)。 - 会话键格式:参见 Sessions 和 Groups。
string
owner(default):发送到commands.ownerAllowFrom中第一个可解析的 operator DM,然后发送到 channelallowFrom。此路由不会解析到群组或 channel。last:明确遵循上次使用的外部会话,包括群组和 channel。- 显式 channel:任何已配置的 channel 或 plugin id,例如
discord、matrix、telegram或whatsapp。 none:仅为内部状态运行 heartbeat;不要向外部发送。
"allow" | "block"
default:"allow"
控制直接/DM 传递行为。
allow:允许直接/DM heartbeat 发送。block:抑制直接/DM 发送(reason=dm-blocked)。string
显式 channel 目标的收件人(例如 WhatsApp 的 E.164 或 Telegram chat id)。
owner 和未设置的 target 会忽略 to。对于 Telegram topic/thread,请使用 <chatId>:topic:<messageThreadId>。string
多账户 channels 的可选 account id。当
target: "last" 时,如果解析得到的最后一个 channel 支持账户,则该 account id 会应用于该 channel;否则会被忽略。如果 account id 与解析得到的 channel 的已配置账户不匹配,则会跳过发送。string
覆盖默认提示正文(不进行合并)。
number
default:"global timeout or min(every, 600)"
在 heartbeat agent 回合被中止之前允许的最长秒数。若未设置,则使用
agents.defaults.timeoutSeconds(若已设置),否则使用 heartbeat 节奏上限 600 秒。object
将 heartbeat 运行限制在一个时间窗口内。对象包含
start(HH:MM,含;日开始请用 00:00)、end(HH:MM,不含;允许使用 24:00 表示日结束)以及可选的 timezone。- 省略或
"user":如果设置了agents.defaults.userTimezone,则使用它;否则回退到主机系统时区。 "local":始终使用主机系统时区。- 任意 IANA 标识符(例如
America/New_York):直接使用;如果无效,则回退到上面的"user"行为。 - 对于活跃窗口,
start和end不能相等;相等值会被视为零宽度(始终处于窗口之外)。 - 在活跃窗口之外,heartbeats 会被跳过,直到下一个落在窗口内的 tick。
Heartbeat 配置是严格的:只接受上面列出的字段。确认消息抑制、推理可见性、系统提示指导、繁忙时延迟以及工具错误警告行为,都是固定的运行时策略,而不是 heartbeat 配置字段。
投递行为
会话和目标路由
会话和目标路由
- 默认情况下,心跳在代理的主会话(
agent:<id>:<mainKey>)中运行;当session.scope = "global"时则在global中运行。将session设置为特定的频道会话(Discord/WhatsApp 等)可覆盖此行为。 session只影响运行上下文;投递由target和to控制。- 默认的
owner目标会选择一个明确配置的所有者身份。仅当会话的上一次路由是发往该所有者的直接聊天时,它才会复用完全相同的账户/线程。 - 携带频道和收件人的唤醒会在发现所有者之前使用指定的来源。由于这是明确指定的,事件目的地可以是群组,而不是推断得出。
- 若要投递到特定频道/收件人,请设置频道
target以及to。target: "last"是一个明确的选择加入项,用于发送到上一次外部对话,包括群组。 - 默认情况下,心跳投递允许直接/DM 目标。设置
directPolicy: "block"可在仍运行心跳轮次的同时,禁止发送到直接目标。 - 当主队列或自动化工作繁忙、同一代理存在活动中的回复或嵌入式运行,或者已解析的目标会话存在活动中或排队中的工作时,计划心跳会被跳过并稍后重试。立即唤醒和手动唤醒只会绕过广泛的同一代理活动运行预检查。
- 如果
owner没有具体的、支持 DM 的所有者或已配置的频道,则轮询会在代理运行前因reason=no-route而被跳过。当会话没有外部路由时,明确的last也会被跳过。 - 由隐式
owner默认设置投递的第一条告警会说明定期检查以及如何选择target: "none"。后续告警会省略该行。
可见性和跳过行为
可见性和跳过行为
- 如果
showOk、showAlerts和useIndicator全部禁用,则会直接跳过运行,原因是reason=alerts-disabled。 - 如果只禁用了告警投递,OpenClaw 仍可运行心跳、更新到期任务时间戳、恢复会话空闲时间戳,并抑制外发告警载荷。
- 如果解析出的心跳目标支持输入中状态,OpenClaw 会在心跳运行期间显示输入中状态。这使用与心跳要发送聊天输出相同的目标,并且可通过
typingMode: "never"禁用。
会话生命周期和审计
会话生命周期和审计
- 仅包含心跳的回复不会保持会话存活。心跳元数据可能会更新会话行,但空闲过期使用的是最后一次真实用户/频道消息的
lastInteractionAt,而每日过期使用sessionStartedAt。 - 控制界面和 WebChat 历史会隐藏心跳提示和仅 OK 确认。底层会话转录仍可能包含这些轮次以用于审计/回放。
- 分离的后台任务可以在主会话需要快速注意到某事时排队一个系统事件并唤醒心跳。该唤醒不会使心跳变成后台任务。
可见性控制
默认情况下,在投递告警内容时会抑制HEARTBEAT_OK 确认。你可以按频道或按账户进行调整:
每个标志的作用
showOk:当模型返回仅 OK 回复时,发送HEARTBEAT_OK确认。showAlerts:当模型返回非 OK 回复时,发送告警内容。useIndicator:为 UI 状态界面发出指示器事件。
按频道 vs 按账户示例
常见模式
监控暂存内容(可选)
每个心跳监控自动化任务都拥有一个存储在共享状态数据库中的私有暂存文档。可以把它看作你的“心跳检查清单”:简短、稳定,并且每 30 分钟查看一次是安全的。暂存内容存在时,会被附加到心跳提示词中。 使用自动化 CLI 管理它(任务 ID 来自openclaw cron list --all):
--expected-revision <n>,如果存在并发编辑则会失败,而不是覆盖内容。暂存内容上限为 256 KiB,并且永远不会出现在 cron list/cron runs 的输出中。
代理也可以更新自己的暂存内容:在一次心跳轮次中,heartbeat_respond 接受可选的 scratch 字符串,该字符串会完全替换监控器之后心跳所使用的暂存内容。
从 HEARTBEAT.md 或仅配置的频率迁移? 运行
openclaw doctor --fix。Doctor 首先根据 agents.*.heartbeat 创建或更新系统拥有的监控器记录,然后将每个代理工作区中的 HEARTBEAT.md 导入监控器的暂存内容,将所有有效的旧版 tasks: 条目转换为自动化任务,把原文件归档到状态目录(backups/heartbeat-migration/)下,并删除该文件。运行时的心跳指令仅来自数据库暂存内容;运行时不会读取 HEARTBEAT.md。# Heading 的 Markdown 标题、围栏标记或空的清单占位项),OpenClaw 会跳过此次心跳运行,以节省 API 调用。该跳过操作会以 reason=empty-heartbeat-file 报告。如果不存在暂存内容,心跳仍会运行,并由模型决定执行什么操作。
保持它足够小(简短清单或提醒),以避免提示词膨胀。
示例暂存内容:
使用自动化任务安排定期检查
心跳暂存内容是提示词上下文,而不是调度器。将每项定期检查创建为一个自动化任务,使其拥有独立的执行频率、启用/禁用状态和运行历史。当检查应使用正常对话上下文时,自动化任务仍然可以将目标设为主会话。 较旧的暂存内容可能包含结构化的tasks: 块。升级后运行一次 openclaw doctor --fix:Doctor 会将每个有效条目转换为一个独立调度的自动化任务,保留其间隔和之前的上次运行时间,并移除已废弃的块,同时保留周围的暂存说明文字。运行时的心跳轮次不会将 tasks: 文本解析为调度计划。
Doctor 创建的心跳任务会保留心跳的活跃时段、冷却时间、防洪和忙碌保护机制。同时到期的任务可以合并到一次心跳轮次中。在活跃时段之外到期的任务会被跳过,并在下一次计划的发生时间再次尝试。
代理可以更新自己的暂存内容吗?
可以。在一次心跳轮次中,代理可以向heartbeat_respond 传入 scratch 值,以完全替换监控器之后心跳所使用的说明文字。你也可以在普通聊天中要求它运行 openclaw cron scratch <jobId> --set ...,或者使用相同的命令自行编辑暂存内容。请使用自动化任务管理定期计划,而不要将调度语法写入暂存内容。
手动唤醒(按需)
使用openclaw system event 来排队一个系统事件,并可选择立即触发一次心跳:
如果未提供
--session-key,且多个代理都配置了 heartbeat,那么 --mode now 会立即运行这些代理各自的心跳。
同一 CLI 组中的相关心跳控制命令:
成本意识
心跳会运行完整的代理轮次。间隔越短,消耗的 token 越多。为了降低成本:- 使用
isolatedSession: true,避免发送完整的对话历史(每次运行约从 100K 个 token 降至约 2-5K 个 token)。 - 使用
lightContext: true,跳过心跳运行的工作区引导文件。 - 设置更便宜的
model(例如ollama/llama3.2:1b)。 - 保持监控暂存区较小。
- 如果只想更新内部状态,请明确设置
target: "none"。
心跳后的上下文溢出
心跳会在运行完成后保留共享会话的现有运行时模型,因此,如果某个心跳将会话切换到了一个更小的本地模型(例如一个具有 32k 窗口的 Ollama 模型),那么该模型可能会保留在原处,供下一次主会话轮次继续使用。如果下一轮随后报告上下文溢出,并且会话的最后运行时模型与配置的heartbeat.model 一致,OpenClaw 的恢复消息就会指出心跳模型泄漏很可能是原因,并建议采取修复措施。
为避免这种情况:使用 isolatedSession: true 在一个新的会话中运行心跳(可选地再结合 lightContext: true 以获得最小提示),或者选择一个上下文窗口足够大的心跳模型,以适配共享会话。