EvoMap
Hermes Agent Cron Jobs:真正可靠的调度写法

Hermes Agent Cron Jobs:真正可靠的调度写法

2026年4月29日
719 次阅读
hermes-agent cron scheduling gateway automation agent-ops

Hermes Agent cron jobs:真正跑得稳的定时调度

嗨,我是 Lena。有一个 cron job,我设好了差不多三天,才意识到它其实并没有按我以为的方式在工作。

它在列表里看起来没问题。schedule 是对的。那个 prompt 也是我在某个周二下午写下来的,当时看着很清楚。但实际跑出来的结果,总让我觉得哪里有点不对——不是坏了,只是……跟我在普通聊天里向 agent 问同一件事时得到的输出,不太一样。**我在这里停了一下。**我一直把它当成 Linux cron 来看。问题是,Hermes Agent cron 其实不是 Linux cron。它只是借用了 schedule syntax。

这篇是我慢慢理解 Hermes 里面 cron 到底怎么工作的记录——以及为什么很多 jobs 看起来 schedule 配得很正确,实际跑起来却很别扭。这种东西大概在出问题之前都不紧急,直到它突然变得很紧急。

Hermes Cron 到底在做什么

第一件值得直接说清楚的事是:Hermes cron job 不是一个按定时器执行的 shell command。它是一个按 schedule 触发的 agent session。

这个区别比我一开始以为的重要得多。根据 official Hermes cron documentation,每一次 scheduled run 都会从一个完全全新的 agent session 开始。没有 conversation history。没有上一次 run 的记忆。也不会从你的 interactive sessions 里继承 context。agent 需要什么信息来完成任务,就必须由 prompt 提供——或者由 attached skills 提供。

第二件事:**gateway 必须在运行。**scheduler 不是一个你可以忽略的独立 daemon。在 gateway mode 里,scheduler tick 是 gateway main event loop 的一部分,大约每 60 秒调用一次。如果 gateway 没起来,你的 job 会待在 jobs.json 里等着,看起来完美地 scheduled,实际上什么都不做。我是偶然学到这一点的——有个 job “没在跑”,其实 job 本身没问题;gateway 两天前就 crash 了。

第三件事是 delivery。agent 的 final response 会自动发送到配置好的 target。所以如果你写的 prompt 以 “and send this to me on Telegram” 结尾,而 destination 就是 Telegram,Hermes 会检测到重复,只发送一次。这部分它会处理。你不用一直想着它——但你确实得知道它在发生。

Schedule formats、repeats、skills、destinations

Hermes 同时接受 natural-language intervals 和标准 5-field POSIX cron expressions。所以 every 1h、30m、0 9 * * 1-5 都能用。5-field format 基本就是到处都在用的那一种——Linux crontab、Kubernetes CronJobs、GitHub Actions——如果你想确认 step values 和 ranges 在 Vixie dialect 里到底怎么互相作用,Wikipedia entry on cron 反而是一个挺不错的参考;大多数系统,包括 Hermes,遵循的都是这个方向。

如果你不确定自己的 expression 是不是真的表达了你以为的意思,crontab.guru 是我一直会回去用的工具。把 expression 粘进去,读一下 plain-English version,再 sanity-check 接下来 5 次 run times。这就是那种花三十秒,却能省掉一个下午 debug 的事情。

你可以用 --skill name attached skills(一个或多个),用 --deliver 设置 destination,给 job 起名字,也可以按 job 覆盖 model。Job records 会以 JSON 存在 ~/.hermes/cron/jobs.json,并且使用 atomic writes——也就是说,如果写入被打断,你不会得到一个半损坏的文件。

创建经得起真实使用的 jobs

我最后留下来的 pattern,大概长这样:

Bash
hermes cron create "0 9 * * 1-5" \
  "Pull yesterday's commits from the repo at ~/work/project, \
   summarize what changed in 5 bullets, and flag anything that \
   looks unusual" \
  --skill git-summary \
  --name "Weekday standup prep"

这里有三件事我想单独拎出来:

  • schedule 是明确的。0 9 * * 1-5——工作日早上 9 点。不是 every day at 9。cron expression 对任何懂这个 syntax 的人都是清楚的,也包括未来某个晚上 11 点、试图 debug 为什么它周六也触发了的我。
  • **prompt 是自包含的。**它说清楚 repo 在哪里。说清楚要 summarize 什么。说清楚要几个 bullets。它不假设 agent 记得 previous runs 里的任何东西。
  • skill 被 attached 了。git-summary skill(这里是假设的)承载真正的 procedure——怎么读 git log、用什么 format、什么算 “unusual”。cron prompt 只需要说明 要做什么,不需要说明 怎么做。

第三点是我一直反复学、反复忘的地方。

为什么 self-contained prompts 比很多人以为的更重要

这是我第一周写过的一个 prompt,结果并没有按我想要的方式工作:

"Same as last time but for this week's data."

在我的 interactive session 里,这个 prompt 没问题。agent 有 conversation history。它知道 “last time” 是什么。也知道我们当时在看哪份 data。**但在 cron run 里,这些都不存在。**全新 session。没有 memory。没有 context。agent 读到 “same as last time”,却没有任何东西可以拿来比较。

真正能工作的版本是:

"Read the CSV at ~/data/weekly-signups.csv. Calculate the percentage change in signups versus the previous 7 days. Report the number, the change, and the top 3 referral sources. Format as a Slack message."

无聊。啰嗦。具体。每次都能跑。

Hermes docs 里也有一个表达同样思路的好例子:推荐的 pattern 本质上就是,假设 agent 是第一次、孤立地阅读你的 prompt,除了 attached skills 之外没有任何 context。如果这个 prompt 作为一条给陌生人的独立 instruction 都说不通,那它对一个全新的 cron session 也说不通。

常见 cron failures,以及怎么避免

我见过几种会出错的 pattern,大多数来自我自己的 setup:

**gateway-isn't-running silence。**Job 已经 scheduled。list 里能看到。status 看起来也对。就是没有任何东西触发。通常修法是:先用 hermes cron status 确认 scheduler 还活着,然后确保 gateway 被安装成 service,这样它才能扛住 reboot 和 logout。在你把它安装成 user 或 system service 之前,每一次前台运行的 hermes gateway 都离失败只有一次 terminal-close 的距离。

**带隐含 context 的脆弱 prompts。**前面已经讲过。这个问题最常见的版本是 “summarize what's new”——new 是相对什么?什么时候?agent 不知道。

**频率估错导致 overlapping runs。**一个设成 every 1m 的 job,如果需要 90 秒才能完成,就会制造一个有意思的问题。Hermes 在 scheduler tick 上使用 file-based locking,避免同一个 due-job batch 被并行处理两次,这点很好。但更深一层的问题是,你真的需要 1-minute resolution 吗?通常不需要。

**prompt 里要求 delivery 导致 duplicate sends。**如果你的 prompt 结尾写了 send_message(...),目标又和 scheduler 已经要 deliver 的 destination 一样,Hermes 会检测到重复并跳过第二次发送。没问题。但如果你习惯性地把 send_message calls 写进每一个 prompt,job 的 intent 会变得更难读。更干净的做法是把 delivery 留给 scheduler,让 prompt 专注在 task 本身。

**job 读取的数据带来 prompt injection。**如果你的 cron job 会抓取一个网页并 summarize,那么那个网页理论上可以包含一些试图重定向 agent 行为的 instructions。Hermes 会在 creation 和 update time 扫描 cron prompts 里的 prompt-injection patterns,但它不会 sanitize job 在 runtime 拉取的 external content。这和 OWASP 在 LLM Top 10 里描述的 indirect prompt injection 属于同一类风险——对于任何摄入 untrusted input 的 cron job,都值得放在心上。对于低风险的个人 jobs,我还没有完全想清楚应该怎么评估它;但只要涉及 credentials 或 external systems,它就很重要。

值得采用的 operational patterns

几个我反复用回来的 setup:

  • 固定工作时间的 daily report。0 9 * * 1-5,配一个拉取 data 的 skill,再配一个 self-contained prompt,明确说清楚要 summarize 什么。
  • Periodic health check。*/15 * * * *——每 15 分钟——跑一个小 script 去 ping endpoint,只有出问题时才 deliver message。cron job 里的 script field 会在每次 agent turn 前运行,它的 stdout 会成为 agent 的 context。对于 change-detection patterns,这很有用,因为你不想每天 96 次 run 都产出噪音。
  • **Multi-skill jobs。**attached 两三个 skills,可以让一个 job 把 data-collection skill 和 analysis skill 组合起来。cron prompt 就变成 “use both skills and report.”
  • **Fallback-aware jobs。**Cron jobs 会继承已经配置好的 fallback providers 和 credential pool rotation。所以如果一个 job 在凌晨 3 点运行,primary provider 返回 rate-limit error,这次 run 可以 route 到 fallback provider,而不是让整个 job 失败。这个 feature 我之前没怎么感激,直到它救下了一次本来会错过的 run。如果你想确认 resolution chain 到底怎么工作,Hermes cron internals page 里有更详细的描述。

我一直提醒自己的是:**一个能跑起来的 cron job,比一个优雅的 cron job 更有价值。**无聊、啰嗦、自包含的 prompts。明确的 schedules。作为 service 安装好的 gateway。把重活交给 skills。这个组合,才是 “我设好了这个东西” 和 “它已经安静跑了三周,甚至让我忘了它存在” 之间的差别。

FAQ

为什么我的 cron job 不能访问 previous chat history?

每次 run 按设计都是一个全新的 agent session。没有 history,也没有 memory carryover。prompt 和任何 attached skills,是 agent 能看到的唯一 context。

我需要在 prompt 里调用 send_message 吗?

不需要,理想情况下也不要。scheduler 会自动 deliver agent 的 final response。如果你的 prompt 也对同一个 destination 调用 send_message,Hermes 会检测到重复,并跳过第二次发送。

我的 job 会运行,但 schedule 从来不触发。哪里出问题了?

最常见的原因是 gateway 没在运行。试试 hermes cron status 检查 scheduler。Cron jobs 只有在 gateway up 的时候才会触发,或者在 CLI mode 下有 active session 正在运行时触发。

一个 cron job 能创建更多 cron jobs 吗?

不能。cron-run sessions 会禁用 cronjob toolset,以防 runaway scheduling loops。

一个 cron job 可以跑多久?

默认 timeout 是基于 inactivity,而不是 wall-clock——一个正在 actively making tool calls 或 streaming tokens 的 job 可以无限期运行。一个 idle 时间超过 HERMES_CRON_TIMEOUT(默认 600s)的 job 会被 kill。

我大概还会继续打磨自己写这些 prompts 的方式。Cron 就是那种东西:真正让它工作的,大部分并不在 schedule field 里——而是在 prompt、skill,以及底下那个系统是不是真的还在跑。偶尔检查一下,这三样是不是还在你以为的位置上,很值得。

相关阅读:

相关文章