Hermes Agent 定时任务三件套:monitor-mode、notepad 与 preflight 校验


定时任务(cron)是 Hermes Agent 最实用的自动化能力之一:每天 9 点抓取 Hacker News 热榜、每 30 分钟检查一次构建状态、每小时汇总订阅源…… 但跑得越勤,问题也越明显——大部分 tick 都在烧 token 做重复劳动,配置一旦写坏还会白白消耗一次 LLM 调用,任务间要传递状态(比如“上次处理到哪条”)更是只能靠外挂文件。

2026 年 8 月初合入 main 的这批更新,给 cron 补上了三件关键装备:

  1. monitor-mode(监控模式)——用廉价脚本/URL 先跑一步,输出哈希没变就直接跳过整个 agent 运行,零 LLM 开销;
  2. notepad(任务便签)——每个任务一块持久化 KV 存储,游标、水位线、待办清单跨运行存活;
  3. preflight(预检)——每次调度前先验证任务配置能否跑通,坏配置直接标记 blocked_config,一次警告、绝不烧 token。

外加一个 usage_audit.jsonl 日志,把每次 cron 运行的 token 花费如实记账。本文逐一展开,附真实 CLI 与配置示例。


1. monitor-mode:让定时任务先“嗅”再跑

为什么需要它

一个典型的监控型定时任务长这样:“每 5 分钟检查一下订阅源有没有更新,有就总结给我”。在没有 monitor-mode 之前,Hermes 每个 tick 都会完整构建 agent、把 prompt 喂给 LLM——即使订阅源这 5 分钟根本没变化,你也在为一个“什么也没发生”的结果付费。

monitor-mode 的思路是把变化检测从 agent 里剥离出来:每个 tick 先用一个廉价脚本(或一次限时 GET 请求)拿到监控源的输出,按原始字节做哈希:

  • 哈希没变 → 整个 agent 运行被抑制,记为一次静默的 no_change tick(不产生 LLM 调用、不投递任何消息);
  • 哈希变了 → 一段 MONITOR CHANGE DETECTED 块(截断的 unified diff + 新输出)被注入 prompt,agent 正常运行;
  • 首次 tick 总是运行(建立 baseline);
  • 监控源本身失败 → 视为配置错误,任务不会偷偷静默。

用法

CLI 创建:

# 用脚本做监控源(放在 ~/.hermes/scripts/ 下,或给绝对路径)
hermes cron create "every 5m" \
  "Summarize any new items on the page" \
  --monitor-script feed_watch.sh

# 用 URL 做监控源(每次 tick 一次限时 GET)
hermes cron create "every 5m" \
  "Summarize changes on the status page" \
  --monitor-url https://status.example.com/api/health

# 修改已有任务
hermes cron edit <job_id> --monitor-script feeds.sh

聊天内用 cronjob 工具创建:

cronjob(
    action="create",
    schedule="every 5m",
    prompt="Summarize any new items on the page",
    monitor_script="feed_watch.sh",
)

三条约束(源码里写死,违反会在创建时直接报错)

  • monitor_scriptmonitor_url 互斥,一个任务只能有一个监控源;
  • monitor 模式与 no_agent=True 不兼容——监控的意义就是“抑制或唤醒 agent”,纯脚本任务请用普通 script 模式;
  • 监控脚本应输出稳定内容(不要带时间戳),否则每次哈希都会变,等于每次都触发。

另外注意 --monitor-script 的解析规则与 script 一致:相对于 ~/.hermes/scripts/ 解析,.sh/.bash 用 bash 执行,其余按 Python 执行。已发布版之外,这部分实现在 cron/jobs.pycreate_job 与调度器的 hash-suppression 逻辑中。

2. notepad:跨运行存状态,告别外挂文件

为什么需要它

状态型定时任务有个经典痛点:任务 A 每天凌晨抓一次数据,任务 B 每天早上处理“新增部分”——那“上次处理到哪条”这个游标存在哪?以前只能写到本地文件,还得自己处理并发和清理。notepad 把这个场景变成了一等公民:每个任务一块持久的 key/value 便签,存在独立的 SQLite 里(~/.hermes/cron/notepad.db),每次运行前由调度器渲染进任务 prompt——agent 能看到上次留下的状态,并在本次运行中通过 CLI 更新它。

用法

# 查看任务便签(默认 list)
hermes cron notepad <job_id>

# 读一个键
hermes cron notepad <job_id> get cursor

# 写一个键
hermes cron notepad <job_id> set cursor 128

# 删除一个键
hermes cron notepad <job_id> delete cursor

配合 monitor-mode 的典型用法:监控任务在检测到变化后,把“已处理到哪条”写进 notepad,下次 tick 就知道从哪里继续。容量上限(写入超限会大声失败而非静默截断):

  • 单值 16 KB;
  • 键名最长 128 字符;
  • 每个任务总计 64 KB。

notepad 的读取路径与 context_from 输出在同一处注入 prompt,写入路径则是运行中的 agent 通过 hermes cron notepad ... set 完成——实现细节在 cron/notepad.py,连接/pragma 模式与 cron/executions.py 保持一致。

3. preflight:坏配置一次警告,绝不烧 token

为什么需要它

cron 任务最常见的翻车方式不是代码写错,而是环境悄悄变了:provider 的 API key 过期了、附加的 skill 缺了个环境变量、投递平台的凭据失效了。旧行为是——tick 照跑,agent 建起来,LLM 调完才发现跑不通,钱花了,错误还往往看不明白。

preflight 在构建任何 agent 机制之前先验证任务配置,校验内容(源码与文档 cron.md 确认):

  • provider API key 能解析(配置了 fallback_providers 链则跳过,因为降级路径可能救回缺失的主 key);
  • 附加的 skill 就绪(没有缺失的必需环境变量、命令或凭据文件);
  • 投递平台目标已知且有 gateway 凭据(local/origin 目标从不检查)。

校验失败的后果:

  • 任务 last_status 变为 blocked_config
  • 只投递一次警告preflight_alerted 去重标记,不会每个 tick 都轰炸你),恢复健康后标记清除,下次再坏会再次警告;
  • 零 LLM 调用——误配置的任务永远不会烧 token。

默认开启,cron.preflight: true。想关掉恢复旧行为:

# config.yaml
cron:
  preflight: false

# 或命令行
hermes config set cron.preflight false

所有检查fail open——preflight 本身出问题不会拦住任务运行,宁可多跑一次也不误杀正常任务。

4. usage_audit:cron token 花费账本

同一批合入的还有 token 泄露治理的一部分:cron 会话不再派发后台 review(skip_background_review 标志),并新增了每次调度运行的 token 花费审计日志 ~/.hermes/cron/usage_audit.jsonl,逐行 JSONL 记录每次 fire 的 token 用量——想量化“monitor-mode 到底帮我省了多少 token”,看这个文件就一目了然。

5. 组合示例:一个省钱的“变化感知”监控任务

把三件套串起来,一个典型的“网站变化监控 + 增量摘要”任务长这样:

# 1) 监控源脚本:输出稳定内容(例如订阅源条目的标题列表)
cat > ~/.hermes/scripts/feed_watch.sh <<'EOF'
#!/bin/bash
curl -s https://example.com/feed.xml | grep -o '<title>[^<]*</title>'
EOF
chmod +x ~/.hermes/scripts/feed_watch.sh

# 2) 创建监控任务:哈希不变就静默跳过
hermes cron create "every 5m" \
  "Summarize new feed items and remember the last seen count in the notepad" \
  --monitor-script feed_watch.sh \
  --deliver telegram

此后:feed 没变 → no_change 静默 tick,零 token;feed 变了 → agent 醒来,读 notepad 里的游标,总结新增条目,更新游标,投递到 Telegram。预算敏感用户还能配合 usage_audit.jsonl 核对每月实际开销。

6. 什么时候不该用

  • 必须每次运行的任务(比如整点报时、心跳保活)不需要 monitor-mode——它只会引入无谓的“变化判断”;
  • 需要跨任务共享状态时,notepad 不是答案——它是 per-job 的,任务间传数据仍用 context_from 链或外部存储;
  • 想完全跳过 agent 的纯脚本任务,用现成的 no_agent=True + script,不要硬套 monitor 模式。

小结

这三件套让 cron 从“定时烧钱机”变成了“按需唤醒器”:monitor-mode 负责省(无变化零开销),notepad 负责记(状态跨运行存活),preflight 负责稳(坏配置不烧钱、一次警告)。对跑着大量定时任务的开发者来说,这是实打实的账单优化和运维减负。

想从零搭建一套 cron 自动化,可先看我们此前的 Hermes Agent 定时任务完全指南;把任务挂进长时后台不卡死的配置技巧见 让 Hermes 长任务不再卡死的配置指南;更多日常提效技巧汇总在 Hermes Agent 效率技巧合集。还没装 Hermes?安装指南 五分钟上手。