Skip to content

Cron 定時

源码版本v2026.7.20

職責

讓 agent 能「到點自動跑」:定時報告、備份、簡報等不必人在場。cron/ 子系統提供排程器、作業儲存、執行記錄、生命週期守衛、藍圖/建議目錄,以及獨立的 toolsets 隔離(定時任務可停用部分工具 (tool),防止無人值守時幹危險事)。網關 (gateway) 用 60s 心跳驅動排程器。

設計動機

無人值守是這套子系統的核心問題。agent 在凌晨三點自己跑起來,誰盯著?Hermes 的回答是「排程鏈路上層層降權」:toolsets 預設裁掉互動類和能再開 cron 的 cronjob;lifecycle_guard 把腳本裡 systemctl restart hermes-gateway 這類命令攔在排程前;executions 表給每次執行留可查的痕跡,崩潰後標 unknown 而不是冒充成功。讓「agent 自己跑」能稽核、能回滾。

關鍵檔案

資料流

  1. 網關啟動 _start_cron_ticker:22335,每 60s 觸發排程器。
  2. 排程器讀作業儲存(cron/jobs.py:106),按 cron 表達式選出到期作業。
  3. 每個到期作業:
  4. 執行中崩潰 → 下次 recover_interrupted_executions(cron/executions.py:156)恢復標記。
  5. 結果經網關投遞(或 mirror 到指定平台)。

排程器對 toolset 的裁剪硬編碼三項,疊加使用者 config.yamlagent.disabled_toolsets:

python
def _resolve_cron_disabled_toolsets(cfg: dict) -> list[str]:
    """Toolsets a cron-spawned agent must never receive."""
    disabled = ["cronjob", "messaging", "clarify"]
    agent_cfg = (cfg or {}).get("agent") or {}
    user_disabled = agent_cfg.get("disabled_toolsets") or []
    for name in user_disabled:
        name = str(name).strip()
        if name and name not in disabled:
            disabled.append(name)
    return disabled

cronjob 被禁是不讓 cron 自己再造 cron(誤觸能級聯開一堆作業),messaging/clarify 是互動類,無人值守只會掛著等不到人。腳本型作業走 _run_job_script,路徑被關在 HERMES_HOME/scripts/ 裡防 traversal。

執行狀態機在 executions.py,狀態只有 claimed → running → completed/failed/unknown,終態只能寫一次(finish_execution 的 UPDATE 加 WHERE status IN ('claimed','running') 保護,重複寫直接 rowcount=0 回傳 None)。崩潰恢復只把「程序已不存在」的執行標成 unknown,不假裝成功也不自動重跑——子程序可能已經寫了副作用,也可能沒,留給操作者去查,而不是猜 failed 讓人以為重跑就完事。lifecycle_guardsystemctl restart hermes-gatewaypkill hermes gateway 編成正則,建立時和執行前各掃一次,把 prompt 和 script 拼起來掃,堵住「prompt 裡說一句、腳本裡幹一刀」的拆分繞過。

邊界與失敗

  • 秒級漂移與誤傷:60s 心跳意味著觸發點最多差一分鐘。mark_running_jobs_interrupted 不區分哪個 PID 被殺,凡在殺的時刻在跑的作業統統打斷,可能誤傷快收尾的作業。
  • unknown 狀態的副作用:崩潰恢復標 unknown 後不重跑,但腳本可能已發過訊息/寫過檔案。下游不能假設「未完成」。
  • 租約心跳卡死:_run_job_script_with_claim_heartbeat 用獨立執行緒續租,心跳執行緒本身卡住(如 GIL 長持有)時,另一個排程程序可能把同一個 one-shot 作業再派一次,產生重複副作用。
  • prompt 注入盲區:執行時才掃 assembled prompt(含 skill 內容),惡意 skill 要等排程那一刻才被攔下,建立作業時看不到。

小結

Cron 子系統的重點是「無人值守的安全性」:toolsets 隔離、lifecycle_guard 防誤操作、execution 狀態機做崩潰恢復。排程本身由網關心跳驅動,不需要外部 cron 常駐程式。

非官方社群學習站,內容以 MIT 授權的 NousResearch/hermes-agent 原始碼為依據。