跳到主要内容

定时任务(Cron)

使用自然语言或 Cron 表达式自动调度任务。Hermes 通过单一的 cronjob 工具提供 Cron 管理功能,采用操作式(action-style)命令,而非分离的 schedule/list/remove 工具。

当前 Cron 的功能

Cron 任务可以:

  • 调度一次性或重复性任务
  • 暂停、恢复、编辑、触发和删除任务
  • 为任务附加零个、一个或多个技能(skills)
  • 将结果返回到原始聊天会话、本地文件或已配置的平台目标
  • 在全新的代理会话中运行,使用正常的静态工具列表
注意

Cron 执行的会话无法递归创建更多 Cron 任务。Hermes 会在 Cron 执行过程中禁用 Cron 管理工具,以防止出现无限调度循环。

创建定时任务

在聊天中使用 /cron

/cron add 30m "Remind me to check the build"
/cron add "every 2h" "Check server status"
/cron add "every 1h" "Summarize new feed items" --skill blogwatcher
/cron add "every 1h" "Use both skills and combine the result" --skill blogwatcher --skill find-nearby

通过独立 CLI

hermes cron create "every 2h" "Check server status"
hermes cron create "every 1h" "Summarize new feed items" --skill blogwatcher
hermes cron create "every 1h" "Use both skills and combine the result" \
--skill blogwatcher \
--skill find-nearby \
--name "Skill combo"

通过自然对话

正常向 Hermes 提问:

Every morning at 9am, check Hacker News for AI news and send me a summary on Telegram.

Hermes 将在内部使用统一的 cronjob 工具。

基于技能的 Cron 任务

Cron 任务可在运行提示前加载一个或多个技能。

单个技能

cronjob(
action="create",
skill="blogwatcher",
prompt="Check the configured feeds and summarize anything new.",
schedule="0 9 * * *",
name="Morning feeds",
)

多个技能

技能按顺序加载。提示将作为任务指令叠加在这些技能之上。

cronjob(
action="create",
skills=["blogwatcher", "find-nearby"],
prompt="Look for new local events and interesting nearby places, then combine them into one short brief.",
schedule="every 6h",
name="Local brief",
)

这在希望定时代理继承可复用的工作流,而又不想将完整技能文本嵌入 Cron 提示本身时非常有用。

编辑任务

无需删除并重新创建任务即可修改任务。

聊天中

/cron edit <job_id> --schedule "every 4h"
/cron edit <job_id> --prompt "Use the revised task"
/cron edit <job_id> --skill blogwatcher --skill find-nearby
/cron edit <job_id> --remove-skill blogwatcher
/cron edit <job_id> --clear-skills

独立 CLI

hermes cron edit <job_id> --schedule "every 4h"
hermes cron edit <job_id> --prompt "Use the revised task"
hermes cron edit <job_id> --skill blogwatcher --skill find-nearby
hermes cron edit <job_id> --add-skill find-nearby
hermes cron edit <job_id> --remove-skill blogwatcher
hermes cron edit <job_id> --clear-skills

说明:

  • 重复使用 --skill 会替换任务的附加技能列表
  • --add-skill 会追加到现有列表中,而不替换
  • --remove-skill 会移除指定的附加技能
  • --clear-skills 会移除所有附加技能

生命周期操作

Cron 任务现在拥有比“创建/删除”更完整的生命周期。

聊天中

/cron list
/cron pause <job_id>
/cron resume <job_id>
/cron run <job_id>
/cron remove <job_id>

独立 CLI

hermes cron list
hermes cron pause <job_id>
hermes cron resume <job_id>
hermes cron run <job_id>
hermes cron remove <job_id>
hermes cron status
hermes cron tick

它们的作用如下:

  • pause — 保留任务但停止调度
  • resume — 重新启用任务并计算下一次未来运行时间
  • run — 在下一个调度周期立即触发任务
  • remove — 完全删除任务

工作原理

Cron 执行由网关守护进程(gateway daemon)处理。 网关每 60 秒触发一次调度器,对所有到期的任务在隔离的代理会话中运行。

hermes gateway install     # Install as a user service
sudo hermes gateway install --system # Linux: boot-time system service for servers
hermes gateway # Or run in foreground

hermes cron list
hermes cron status

网关调度器行为

每次触发时,Hermes 执行以下步骤:

  1. ~/.hermes/cron/jobs.json 加载任务
  2. next_run_at 与当前时间进行比较
  3. 为每个到期任务启动一个全新的 AIAgent 会话
  4. 可选地将一个或多个附加技能注入该新会话
  5. 运行提示直至完成
  6. 交付最终响应
  7. 更新运行元数据和下次计划时间

文件锁 ~/.hermes/cron/.tick.lock 防止多个调度器触发重叠执行同一任务批次。

输出交付选项

调度任务时,需指定输出的去向:

选项描述示例
"origin"返回到任务创建的位置消息平台的默认值
"local"仅保存到本地文件(~/.hermes/cron/output/CLI 的默认值
"telegram"Telegram 主频道使用 TELEGRAM_HOME_CHANNEL
"telegram:123456"通过 ID 指定 Telegram 聊天直接投递
"telegram:-100123:17585"指定 Telegram 主题chat_id:thread_id 格式
"discord"Discord 主频道使用 DISCORD_HOME_CHANNEL
"discord:#engineering"指定 Discord 频道通过频道名称
"slack"Slack 主频道
"whatsapp"WhatsApp
"signal"Signal
"matrix"Matrix 主房间
"mattermost"Mattermost 主频道
"email"邮件
"sms"通过 Twilio 发送短信
"homeassistant"Home Assistant
"dingtalk"钉钉
"feishu"飞书/飞书
"wecom"企业微信
"weixin"微信(WeChat)
"bluebubbles"BlueBubbles(iMessage)

代理的最终响应将自动交付。您无需在 Cron 提示中调用 send_message

响应包装

默认情况下,交付的 Cron 输出会被包裹在标题和页脚中,以便接收者知道其来自定时任务:

Cronjob Response: Morning feeds
-------------

<agent output here>

Note: The agent cannot see this message, and therefore cannot respond to it.

若要交付原始代理输出而不带包装,请将 cron.wrap_response 设置为 false

# ~/.hermes/config.yaml
cron:
wrap_response: false

静默抑制

如果代理的最终响应以 [SILENT] 开头,则完全抑制交付。输出仍会本地保存以供审计(位于 ~/.hermes/cron/output/),但不会发送到目标交付渠道。

这在希望监控任务仅在出错时报告时非常有用:

Check if nginx is running. If everything is healthy, respond with only [SILENT].
Otherwise, report the issue.

失败的任务始终会交付,无论是否存在 [SILENT] 标记 — 仅成功运行可被静默。

脚本超时

预运行脚本(通过 script 参数附加)的默认超时时间为 120 秒。如果您的脚本需要更长时间运行——例如,包含随机延迟以避免类似机器人的定时模式——您可以进行延长:

# ~/.hermes/config.yaml
cron:
script_timeout_seconds: 300 # 5 minutes

或者设置 HERMES_CRON_SCRIPT_TIMEOUT 环境变量。优先级顺序为:环境变量 → config.yaml → 120 秒默认值。

提供商恢复

定时任务继承您配置的备用提供方和凭证池轮换策略。如果主 API 密钥被限流或提供方返回错误,定时代理可以:

  • 回退到备用提供方(如果您在 config.yaml 中配置了 fallback_providers 或旧版的 fallback_model
  • 切换到同一提供方的下一个凭证,使用您的 凭证池

这意味着在高频率运行或高峰时段执行的定时任务更具容错能力——单个被限流的密钥不会导致整个任务失败。

计划格式

代理的最终响应会自动发送——您不需要在定时任务提示中包含 send_message 来发送到相同的目标。如果定时任务调用 send_message 的目标与调度器将要发送的目标完全一致,Hermes 会跳过重复发送,并指示模型将面向用户的内容放入最终响应中。仅当需要发送到额外或不同的目标时才使用 send_message

相对延迟(一次性)

30m     → Run once in 30 minutes
2h → Run once in 2 hours
1d → Run once in 1 day

间隔(重复执行)

every 30m    → Every 30 minutes
every 2h → Every 2 hours
every 1d → Every day

Cron 表达式

0 9 * * *       → Daily at 9:00 AM
0 9 * * 1-5 → Weekdays at 9:00 AM
0 */6 * * * → Every 6 hours
30 8 1 * * → First of every month at 8:30 AM
0 0 * * 0 → Every Sunday at midnight

ISO 时间戳

2026-03-15T09:00:00    → One-time at March 15, 2026 9:00 AM

重复行为

计划类型默认重复次数行为
一次性(30m,时间戳)1仅运行一次
间隔(every 2h无限次持续运行直至被移除
Cron 表达式无限次持续运行直至被移除

您可以覆盖默认行为:

cronjob(
action="create",
prompt="...",
schedule="every 2h",
repeat=5,
)

通过程序化方式管理任务

面向代理的 API 是一种工具:

cronjob(action="create", ...)
cronjob(action="list")
cronjob(action="update", job_id="...")
cronjob(action="pause", job_id="...")
cronjob(action="resume", job_id="...")
cronjob(action="run", job_id="...")
cronjob(action="remove", job_id="...")

对于 update 操作,传入 skills=[] 可移除所有附加技能。

任务存储

任务存储在 ~/.hermes/cron/jobs.json。任务运行的输出保存在 ~/.hermes/cron/output/{job_id}/{timestamp}.md

存储使用原子文件写入,因此中断的写入不会留下部分写入的任务文件。

自包含提示仍然重要

重要

定时任务在完全全新的代理会话中运行。提示必须包含代理所需的所有内容,除非这些内容已由附加技能提供。

错误示例: "Check on that server issue"

正确示例: "SSH into server 192.168.1.100 as user 'deploy', check if nginx is running with 'systemctl status nginx', and verify https://example.com returns HTTP 200."

安全性

在创建和更新时,调度任务的提示会扫描提示注入和凭证泄露模式。包含不可见 Unicode 技巧、SSH 后门尝试或明显凭证泄露载荷的提示将被阻止。