Hermes Agent cron jobs:ちゃんと動くスケジューリング
こんにちは、Lena です。ある cron job を3日ほど設定したままにしていて、ようやく気づきました。実は、自分が思っていたことをしていなかったのです。
一覧では問題なさそうに見えました。schedule も正しい。火曜の午後に書いた prompt も、そのときは分かりやすく見えました。でも実行結果は、どこか少し違っていました。壊れているわけではありません。ただ……普通のチャットで同じことを agent に頼んだときの出力とは、種類が違う感じがしたのです。**ここで一度、立ち止まりました。**私はそれを Linux cron のように扱っていました。けれど、Hermes Agent cron は本当の意味では Linux cron ではありません。schedule syntax を借りているだけです。
これは、Hermes の中で cron が実際にどう動いているのか、私が少しずつ理解してきたことのメモです。そして、なぜ多くの jobs が「正しく scheduled されているように見えるのに、実行すると微妙」になってしまうのかについての話でもあります。こういうことは、必要になるまではたぶん急ぎではありません。必要になった瞬間に、急に重要になります。
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 が渡す必要があります。あるいは、attach した skills が渡す必要があります。
2つ目。**gateway が動いている必要があります。**scheduler は、無視してよい別 daemon ではありません。gateway mode では、scheduler tick は gateway の main event loop の一部で、だいたい60秒ごとに呼ばれます。gateway が起動していなければ、job は jobs.json の中で待ち続けます。完璧に scheduled されているように見えながら、何もしません。私はこれを偶然学びました。「動いていない」と思っていた job は、実は正常でした。2日前に gateway が crash していただけでした。
3つ目は 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 を読む。次の 5 run times を sanity-check する。30秒で終わるのに、午後まるごとの debug を救ってくれる類の作業です。
--skill name で skills を attach できます(1つでも複数でも)。--deliver で destination を設定できます。job に名前を付けたり、job ごとに model を override したりすることもできます。Job records は ~/.hermes/cron/jobs.json に JSON として保存され、atomic writes が使われます。つまり、書き込みが途中で中断されても、半分壊れた file が残ることはありません。
実運用に耐える jobs を作る
私が最終的に使うようになった pattern は、だいたいこんな形です。
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"
ここで触れておきたいことが3つあります。
- schedule が明示的です。
0 9 * * 1-5、平日の朝9時。every day at 9ではありません。cron expression は、この syntax を知っている人なら誰にとっても曖昧ではありません。土曜に発火した理由を夜11時に debug している未来の私にとっても。 - **prompt が self-contained です。**repo がどこにあるかを書いています。何を summarize するかを書いています。bullet の数も書いています。agent が previous runs の何かを覚えているとは仮定していません。
- skill が attach されています。
git-summaryskill(ここでは仮の例です)が、実際の procedure を持っています。git log をどう読むか、どんな format を使うか、何を “unusual” と見なすか。cron prompt が言うべきなのは what to do であって、how ではありません。
この3つ目を、私は何度も学び直しています。
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” と読んでも、比較するものがありません。
実際に動く version はこうです。
"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 を初めて、単独で、attach した skills 以外の context なしに読んでいると仮定する。その prompt が、見知らぬ人への standalone 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 service または system service として入れるまでは、foreground で動かしている hermes gateway は、terminal を閉じた瞬間に失敗します。
**implicit context に依存する脆い prompts。**これはすでに話しました。いちばんよく見る形は “summarize what's new” です。new とは何と比べて?いつから?agent には分かりません。
頻度の見積もり違いによる overlapping runs。every 1m に設定した job が、完了まで90秒かかるとします。少し面白い問題が生まれます。Hermes は scheduler tick に file-based locking を使い、同じ due-job batch が並列に2回処理されることを防ぎます。これは良いことです。ただ、より深い問いは、そもそも本当に 1-minute resolution が必要なのか、です。たいていは不要です。
**prompt 側の delivery 指示による duplicate sends。**prompt の最後に、scheduler がすでに deliver しようとしている同じ destination への send_message(...) がある場合、Hermes は重複を検出して2回目の送信を skip します。それ自体は問題ありません。ただ、反射的にすべての prompt に send_message calls を書き込んでいると、job の intent が読みにくくなります。delivery は scheduler に任せ、prompt は task に集中させるほうがきれいです。
**job が読む data 経由の prompt injection。**cron job が webpage を取得して summarize する場合、その webpage は理論上、agent の動作を別方向へ誘導しようとする instructions を含むことができます。Hermes は creation と update time に cron prompts の prompt-injection patterns を scan します。ただし、runtime に job が取り込む external content を sanitize するわけではありません。これは 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 と、何を summarize するかを明確に書いた self-contained prompt を組み合わせます。 - Periodic health check。
*/15 * * * *、つまり15分ごとに、小さな script で endpoint を ping し、何か問題があるときだけ message を deliver します。cron job の script field は各 agent turn の前に実行され、その stdout が agent の context になります。1日に96回のうるさい出力を出したくない change-detection patterns では便利です。 - **Multi-skill jobs。**2つか3つの skills を attach すると、1つの job で data-collection skill と analysis skill を組み合わせられます。cron prompt は “use both skills and report.” になります。
- **Fallback-aware jobs。**Cron jobs は、設定済みの fallback providers と credential pool rotation を継承します。だから午前3時に job が走り、primary provider が rate-limit error を返した場合でも、その run は fallback provider に route され、job 全体の失敗を避けられます。私はこの機能を、救われるまであまり評価していませんでした。resolution chain が具体的にどう動くか確認したい場合は、Hermes cron internals page に詳しい説明があります。
自分に言い聞かせているのは、これです。**動く cron job は、エレガントな cron job より価値があります。**退屈で、長くて、self-contained な prompts。明示的な schedules。service としてインストールされた gateway。重い作業を担う skills。この組み合わせが、「設定した」と「3週間静かに動き続けて、存在を忘れていた」の差になります。
FAQ
なぜ私の cron job は previous chat history にアクセスできないのですか?
各 run は設計上、新しい agent session です。history も memory carryover もありません。agent が見る context は、prompt と attached skills だけです。
prompt の中で send_message を呼ぶ必要がありますか?
いいえ。できれば呼ばないほうがよいです。scheduler が agent の final response を自動で deliver します。prompt も同じ destination に send_message を呼ぶ場合、Hermes は重複を検出し、2回目の送信を skip します。
job は動いているのに、schedule が一度も fire しません。何が悪いのでしょう?
多くの場合、gateway が動いていません。hermes cron status で scheduler を確認してください。Cron jobs は gateway が up のとき、または CLI mode で active session が動いているときだけ fire します。
cron job がさらに cron jobs を作ることはできますか?
できません。cron-run sessions では runaway scheduling loops を防ぐため、cronjob toolset が無効化されています。
cron job はどれくらい長く実行できますか?
デフォルトの timeout は wall-clock ではなく inactivity ベースです。actively making tool calls している、または streaming tokens している job は、理論上いつまでも実行できます。HERMES_CRON_TIMEOUT(デフォルト 600s)より長く idle になった job は kill されます。
たぶん私は、これからも prompt の書き方を少しずつ refine していくと思います。Cron は、うまく動かすために大事なものの多くが schedule field には見えない種類のものです。prompt、skill、そして下にある system が本当に動いているか。この3つが、今も置いた場所にあるかどうか。ときどき確認する価値があります。
関連記事:
- 👉 複数の scheduled tasks を設定しているなら、Hermes Cron Memory & Context Limits が cron jobs にどう影響するかを理解しておくとよさそうです。
- 👉 overlapping runs や slow execution を troubleshooting しているなら、Safe Hermes MCP Setup for Cron Jobs の guide も参考になります。
- 👉 明確な prompts と instructions で agent behavior を改善する方法をさらに知りたい場合:How to Write Effective Hermes Agent Skills
- 👉 real-time monitoring を自動化しようとしているなら、この guide が役に立ちます:Periodic Health Check Cron Jobs with Hermes
- 👉 cron delivery を最適化して安定した結果を得たい場合は、Managing Agent Capabilities and Tool Access も読んでみてください。




