定时任务与心跳
一句话概括
定时服务管理计划任务(提醒、周期性任务)和心跳 — 后者是隐性的 token 消耗源,每 10 分钟发送完整会话上下文只为得到一个 "HEARTBEAT_OK" 回复。
职责
- 调度和执行周期性任务(cron 表达式、间隔式、一次性)
- 管理心跳 — 在主会话上定期执行健康检查 LLM 调用
- 在隔离 agent 会话或主会话中执行任务
- 处理错误退避、卡住运行检测和漏执行追赶
- 持久化任务状态并追踪执行遥测(包括 token 用量)
架构图
关键源码文件
数据流
计时器循环
心跳流程(高 token 消耗路径)
关键常量
错误退避时间表(timer.ts:108-114)
连续 3 次调度错误 → 自动禁用任务(MAX_SCHEDULE_ERRORS = 3)。
Token 优化影响
心跳是 OpenClaw 中最低效的 token 消费者:
为什么心跳昂贵
- 发送完整上下文:心跳使用与普通消息相同的代码路径 —
runHeartbeatOnce()触发完整 LLM 调用,包含完整 system prompt、会话历史、工具定义和 skills 目录 - 响应极少:Agent 通常只回复
HEARTBEAT_OK(约 2 个输出 token),而输入 50,000+ tokens - 随会话增长:心跳成本与会话历史长度线性增长
- 默认 6 次/小时:每 10 分钟,为 2 个 token 的响应消耗大量 token
优化机会
- 最小心跳上下文:只发送身份行 + "有待处理事项吗?" 而非完整上下文
- 自适应心跳频率:会话空闲时增加间隔,活跃时减少
- 最近活跃时跳过:如果用户在最近 N 分钟内发过消息,跳过心跳
- 心跳专用 prompt 模式:使用
PromptMode = "none"(15 tokens)而非"full"(5,000 tokens)
时间表类型
任务 payload 类型
与其他模块的关系
-
依赖:
auto-reply/—runHeartbeatOnce()、隔离 agent 执行agents/pi-embedded-runner/— 心跳和 agent 轮次的 LLM 执行sessions/— 会话定向、key 解析config/— 心跳设置、cron 配置channels/— 投递到消息平台
-
被依赖:
gateway/— 随 gateway 生命周期启停定时服务- System prompt — 包含心跳提示词指令章节
我的认知盲区
-
isolated-agent.ts— 隔离 agent 任务 vs 主会话的精确执行流程 -
delivery.ts— 多渠道投递的投递计划如何工作 -
session-reaper.ts— 何时以及如何清理旧的 cron 会话 - 心跳是否使用 prompt caching(Anthropic)— 这会大幅降低心跳成本
- 精确的心跳提示词文本以及是否可按 agent 自定义
-
stagger.ts— 避免惊群效应的错开窗口逻辑
相关贡献
- 暂无
变更频率
timer.ts:中 — 退避逻辑、心跳重试行为、计时常量演进jobs.ts:中 — 调度逻辑随新时间表类型变更ops.ts:中 — CRUD 操作随新功能扩展(分页、过滤)service.ts:低 — 薄包装层,很少变更types.ts:低 — 类型添加是增量的且少见