字节笔记本
2026年6月21日
hermes教程-定时任务 (Cron)
定时任务 (Cron)
使用自然语言或 cron 表达式自动运行任务。Hermes 通过一个统一的 cronjob 工具(采用动作式操作,而非独立的 schedule/list/remove 工具)来管理 cron 任务。
当前 cron 能做什么
Cron 任务可以:
- 安排一次性或重复性任务
- 暂停、恢复、编辑、触发和删除任务
- 为任务附加零个、一个或多个技能
- 将结果传回原始聊天、本地文件或已配置的平台目标
- 在具有正常静态工具列表的全新 agent 会话中运行
- 在无 agent 模式下运行——按计划运行的脚本,其标准输出原样传递,完全不涉及 LLM(请参阅下面的无 agent 模式部分)
所有这些功能都可以通过 cronjob 工具供 Hermes 自身使用,因此您可以通过自然语言提问来创建、暂停、编辑和删除任务——无需 CLI。
提示
Cron 任务使用
hermes model选择的任何提供商。hermes setup --portal是无人值守运行的最低摩擦选项,因为 OAuth 刷新是自动的。请参阅 Nous Portal。
警告
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 maps从独立 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 maps \
--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", "maps"],
prompt="Look for new local events and interesting nearby places, then combine them into one short brief.",
schedule="every 6h",
name="Local brief",
)当您希望定时 agent 继承可重用工作流,而无需将完整的技能文本塞入 cron 提示本身时,这非常有用。
在项目目录内运行任务
Cron 任务默认与任何仓库分离运行——不会加载 AGENTS.md、CLAUDE.md 或 .cursorrules,终端/文件/代码执行工具从网关启动时的工作目录运行。传递 --workdir(CLI)或 workdir=(工具调用)来更改:
## 独立 CLI(schedule 和 prompt 是位置参数)
hermes cron create "every 1d at 09:00" \
"Audit open PRs, summarize CI health, and post to #eng" \
--workdir /home/me/projects/acme## 从聊天中,通过 cronjob 工具
cronjob(
action="create",
schedule="every 1d at 09:00",
workdir="/home/me/projects/acme",
prompt="Audit open PRs, summarize CI health, and post to #eng",
)当设置了 workdir 时:
- 来自该目录的
AGENTS.md、CLAUDE.md和.cursorrules会被注入到系统提示中(发现顺序与交互式 CLI 相同) terminal、read_file、write_file、patch、search_files和execute_code都使用该目录作为其工作目录- 路径必须是存在的绝对目录——相对路径和不存在的目录在创建/更新时会被拒绝
- 在编辑时传递
--workdir ""(或通过工具传递workdir="")以清除它并恢复旧行为
注意——序列化
带有
workdir的任务在调度器滴答时顺序运行,而不是在并行池中。这是有意为之:cron 工作器通过进程全局终端状态应用任务工作目录,因此同时运行两个 workdir 任务会相互破坏对方的 cwd。没有 workdir 的任务仍然像以前一样并行运行。
编辑任务
您无需为了更改任务而删除并重新创建它们。
提示——任务引用
下面的
<job_id>占位符(以及生命周期操作中的)也接受任务的名称(不区分大小写)——当您记得morning-digest但不记得十六进制 ID 时很方便。精确的任务 ID 优先于名称匹配;如果引用不是 ID 且名称匹配多个任务,命令会拒绝并打印候选 ID,以便您消除歧义。
聊天
/cron edit <job_id> --schedule "every 4h"
/cron edit <job_id> --prompt "Use the revised task"
/cron edit <job_id> --skill blogwatcher --skill maps
/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 maps
hermes cron edit <job_id> --add-skill maps
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_or_name>
hermes cron resume <job_id_or_name>
hermes cron run <job_id_or_name>
hermes cron remove <job_id_or_name>
hermes cron edit <job_id_or_name> [...flags]
hermes cron status
hermes cron tick它们的作用:
pause— 保留任务但停止调度resume— 重新启用任务并计算下一次运行时间run— 在下一个调度器滴答时触发任务remove— 完全删除edit— 修改调度、提示、投递等
基于名称的查找。 所有四个可变动词(pause、resume、run、remove、edit)以及 agent 的 cronjob 工具现在都接受任务名称(不区分大小写)来代替十六进制 ID。agent 和 CLI 都优先选择精确的 ID 匹配(如果存在);模糊的名称匹配(多个任务共享相同名称)会被拒绝,并显示完整的候选 ID 列表,以便您明确选择一个。名称不是唯一的,因此此保护是重要的——它防止在共享名称时静默地修改错误的任务。
工作原理
Cron 执行由网关守护进程处理。 网关每 60 秒滴答一次调度器,在隔离的 agent 会话中运行任何到期的任务。
hermes gateway install # 安装为用户服务
sudo hermes gateway install --system # Linux:服务器的启动时系统服务
hermes gateway # 或在前台运行
hermes cron list
hermes cron status网关调度器行为
每次滴答时,Hermes:
- 从
~/.hermes/cron/jobs.json加载任务 - 检查
next_run_at与当前时间 - 为每个到期的任务启动一个新的
AIAgent会话 - 可选地将一个或多个附加技能注入到该新会话中
- 运行提示直到完成
- 投递最终响应
- 更新运行元数据和下一次调度时间
~/.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" | 飞书/Lark | |
"wecom" | 企业微信 | |
"weixin" | 微信 | |
"bluebubbles" | BlueBubbles (iMessage) | |
"qqbot" | QQ 机器人 (腾讯 QQ) | |
"all" | 扇出到所有已连接的主频道 | 在触发时解析 |
"telegram,discord" | 扇出到特定的一组频道 | 逗号分隔列表 |
"origin,all" | 投递到原始位置加上所有其他已连接的频道 | 组合任意令牌 |
agent 的最终响应会自动投递。您无需在 cron 提示中调用 send_message。
路由意图 (all)
all 允许您将一个 cron 任务发送到您配置的每个消息频道,而无需按名称枚举它们。它在触发时解析,因此您在设置 Telegram 之前创建的任务,在您设置 TELEGRAM_HOME_CHANNEL 后的下一个滴答时会自动包含 Telegram。
语义:all 扩展为每个配置了主频道的平台。零个也可以;任务只是没有投递目标,并在上游记录为投递失败。
all 可以与显式目标组合。origin,all 投递到原始聊天加上所有其他已连接的主频道,按 (platform, chat_id, thread_id) 去重。
Telegram cron 主题 (TELEGRAM_CRON_THREAD_ID)
当启用 Telegram 主题模式时,根 DM 被保留为系统大厅——发送到那里的回复会被拒绝并附带大厅提醒,并且 reply_to_message_id 被丢弃,因此您无法回复落在主聊天中的 cron 消息。
将 cron 指向一个专门的论坛主题:
- 在 Telegram 中,打开机器人 DM 并创建一个名为
Cron的主题。长按主题标题 → 复制链接;末尾的整数是主题的message_thread_id。 - 在您的
.env中设置TELEGRAM_CRON_THREAD_ID=<该 id>。
这仅适用于 cron 投递。TELEGRAM_HOME_CHANNEL_THREAD_ID(在其他地方使用,例如重启通知)保持不变。显式的 deliver="telegram:chat_id:thread_id" 目标继续优先于环境变量。对 cron 消息的回复现在会进入现有主题会话,因此您可以直接对其采取行动。
响应包装
默认情况下,投递的 cron 输出会带有页眉和页脚,以便收件人知道它来自定时任务:
Cronjob Response: Morning feeds
-------------
<agent output here>
Note: The agent cannot see this message, and therefore cannot respond to it.要投递原始 agent 输出而不带包装,请将 cron.wrap_response 设置为 false:
## ~/.hermes/config.yaml
cron:
wrap_response: false静默抑制
如果 agent 的最终响应包含 [SILENT],则完全抑制投递。输出仍会本地保存以供审计(在 ~/.hermes/cron/output/ 中),但不会向投递目标发送消息。
这对于仅应在出现问题时报告的监控任务非常有用:
Check if nginx is running. If everything is healthy, respond with only [SILENT].
Otherwise, report the issue.失败的任务始终会投递,无论 [SILENT] 标记如何——只有成功的运行可以被静默。对于安静的监控任务,提示 agent 在无事可报告时仅回复 [SILENT]。
脚本超时
预运行脚本(通过 script 参数附加)的默认超时时间为 120 秒。如果您的脚本需要更长时间——例如,包含随机延迟以避免类似机器人的定时模式——您可以增加此值:
## ~/.hermes/config.yaml
cron:
script_timeout_seconds: 300 # 5 分钟或者设置 HERMES_CRON_SCRIPT_TIMEOUT 环境变量。解析顺序为:环境变量 → config.yaml → 120s 默认值。
无 agent 模式(仅脚本任务)
对于不需要 LLM 推理的重复性任务——经典的看门狗、磁盘/内存警报、心跳、CI 探测——在创建时传递 no_agent=True。调度器按计划运行您的脚本并直接投递其标准输出,完全跳过 agent:
hermes cron create "every 5m" \
--no-agent \
--script memory-watchdog.sh \
--deliver telegram \
--name "memory-watchdog"语义:
- 脚本标准输出(修剪后)→ 原样投递为消息。
- 空标准输出 → 静默滴答,不投递。这是看门狗模式:“只有在出问题时才说话”。
- 非零退出或超时 → 投递错误警报,因此损坏的看门狗不会静默失败。
- 最后一行
{"wakeAgent": false}→ 静默滴答(与 LLM 任务使用的相同门控)。 - 无令牌、无模型、无提供商回退——任务从不触及推理层。
.sh / .bash 文件在 /bin/bash 下运行;其他文件在当前 Python 解释器(sys.executable)下运行。脚本必须位于 ~/.hermes/scripts/ 中(与预运行脚本门控相同的沙盒规则)。
Agent 为您设置这些
cronjob 工具的模式直接向 Hermes 暴露了 no_agent,因此您可以在聊天中描述一个看门狗,让 agent 将其连接起来:
Ping me on Telegram if RAM is over 85%, every 5 minutes.
Hermes 将通过 write_file 将检查脚本写入 ~/.hermes/scripts/,然后调用:
cronjob(action="create", schedule="every 5m",
script="memory-watchdog.sh", no_agent=True,
deliver="telegram", name="memory-watchdog")当消息内容完全由脚本决定时(看门狗、阈值警报、心跳),它会自动选择 no_agent=True。同一个工具还允许 agent 暂停、恢复、编辑和删除任务——因此整个生命周期由聊天驱动,无需任何人接触 CLI。
请参阅仅脚本 Cron 任务指南以获取工作示例。
使用 context_from 链接任务
Cron 任务在隔离的会话中运行,没有之前运行的内存。但有时一个任务的输出正是下一个任务所需要的。context_from 参数自动连接该连接——任务 B 的提示在运行时将任务 A 的最新输出作为上下文前置。
## 任务 1:收集原始数据
cronjob(
action="create",
prompt="Fetch the top 10 AI/ML stories from Hacker News. Save them to ~/.hermes/data/briefs/raw.md in markdown format with title, URL, and score.",
schedule="0 7 * * *",
name="AI News Collector",
)
## 任务 2:分类——接收任务 1 的输出作为上下文
## 从 cronjob(action="list") 获取任务 1 的 ID
cronjob(
action="create",
prompt="Read ~/.hermes/data/briefs/raw.md. Score each story 1–10 for engagement potential and novelty. Output the top 5 to ~/.hermes/data/briefs/ranked.md.",
schedule="30 7 * * *",
context_from="<job1_id>",
name="AI News Triage",
)
## 任务 3:发送——接收任务 2 的输出作为上下文
cronjob(
action="create",
prompt="Read ~/.hermes/data/briefs/ranked.md. Write 3 tweet drafts (hook + body + hashtags). Deliver to telegram:7976161601.",
schedule="0 8 * * *",
context_from="<job2_id>",
name="AI News Brief",
)工作原理:
- 当任务 2 触发时,Hermes 从
~/.hermes/cron/output/{job1_id}/*.md读取任务 1 的最新输出 - 该输出自动前置到任务 2 的提示中
- 任务 2 不需要硬编码“读取此文件”——它接收内容作为上下文
- 链可以是任意长度:任务 1 → 任务 2 → 任务 3 → ...
context_from 接受的内容:
| 格式 | 示例 |
|---|---|
| 单个任务 ID(字符串) | context_from="a1b2c3d4" |
| 多个任务 ID(列表) | context_from=["job_a", "job_b"] |
输出按列出的顺序连接。
何时使用:
- 多阶段流水线(收集 → 过滤 → 格式化 → 投递)
- 依赖任务,其中步骤 N 的工作依赖于步骤 N−1 的输出
- 扇出/扇入模式,其中一个任务聚合来自其他几个任务的结果
提供商恢复
Cron 任务继承您配置的回退提供商和凭据池轮换。如果主 API 密钥被限速或提供商返回错误,cron agent 可以:
- 回退到备用提供商,如果您在
config.yaml中配置了fallback_providers(或旧的fallback_model) - 轮换到下一个凭据,在您的凭据池中用于同一提供商
这意味着在高频率或高峰时段运行的 cron 任务更具弹性——单个被限速的密钥不会导致整个运行失败。
调度格式
agent 的最终响应会自动投递——您不需要在 cron 提示中包含 send_message 来发送到同一目标。如果 cron 运行调用 send_message 到调度器已经要投递的确切目标,Hermes 会跳过该重复发送,并告诉模型将面向用户的内容放在最终响应中。仅对额外或不同的目标使用 send_message。
相对延迟(一次性)
30m → 30 分钟后运行一次
2h → 2 小时后运行一次
1d → 1 天后运行一次间隔(重复)
every 30m → 每 30 分钟
every 2h → 每 2 小时
every 1d → 每天Cron 表达式
0 9 * * * → 每天上午 9:00
0 9 * * 1-5 → 工作日每天上午 9:00
0 */6 * * * → 每 6 小时
30 8 1 * * → 每月第一天上午 8:30
0 0 * * 0 → 每个星期日午夜ISO 时间戳
2026-03-15T09:00:00 → 一次性,2026 年 3 月 15 日上午 9:00
重复行为
| 调度类型 | 默认重复 | 行为 |
|---|---|---|
一次性(30m,时间戳) | 1 | 运行一次 |
间隔(every 2h) | 永远 | 运行直到被移除 |
| Cron 表达式 | 永远 | 运行直到被移除 |
您可以覆盖它:
cronjob(
action="create",
prompt="...",
schedule="every 2h",
repeat=5,
)以编程方式管理任务
面向 agent 的 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=[] 以移除所有附加技能。
Cron 任务可用的工具集
Cron 在每个任务的新 agent 会话中运行,没有附加聊天平台。默认情况下,cron agent 获得您为 hermes tools 中的 cron 平台配置的工具集——而不是 CLI 默认值,也不是所有可用工具。
hermes tools
## → 在 curses UI 中选择 "cron" 平台
## → 像为 Telegram/Discord 等一样切换工具集通过 cronjob.create 上的 enabled_toolsets 字段(或通过 cronjob.update 对现有任务)可以进行更精细的每任务控制:
cronjob(action="create", name="weekly-news-summary",
schedule="every sunday 9am",
enabled_toolsets=["web", "file"], # 仅 web + file,无 terminal/browser 等
prompt="Summarize this week's AI news: ...")当在任务上设置了 enabled_toolsets 时,它优先;否则 hermes tools cron 平台配置优先;否则 Hermes 回退到内置默认值。这对于成本控制很重要:将 moa、browser、delegation 带入每个微小的“获取新闻”任务会膨胀每次 LLM 调用的工具模式提示。
完全跳过 agent:wakeAgent
如果您的 cron 任务附加了预检查脚本(通过 script=),脚本可以在运行时决定 Hermes 是否应该调用 agent。发出标准输出最后一行,格式为:
{"wakeAgent": false}
…然后 cron 在此滴答中完全跳过 agent 运行。对于频繁轮询(每 1-5 分钟)非常有用,这些轮询仅在状态实际更改时才需要唤醒 LLM——否则您会反复为空内容的 agent 轮次付费。
## 预检查脚本
import json, sys
latest = fetch_latest_issue_count()
prev = read_state("issue_count")
if latest == prev:
print(json.dumps({"wakeAgent": False})) # 跳过此滴答
sys.exit(0)
write_state("issue_count", latest)
print(json.dumps({"wakeAgent": True, "context": {"new_issues": latest - prev}}))当省略 wakeAgent 时,默认值为 true(照常唤醒 agent)。
配方:廉价的预运行门控
wakeAgent 门控为您提供了一种 $0 的方式来决定定时任务是否应该花费任何 LLM 令牌。三种模式涵盖了大多数用例。
文件更改门控——仅当被监视的文件自上次成功滴答以来有新内容时才运行。调度器记录每个任务的 last_run_at;将其与文件的 mtime 进行比较。
#!/bin/bash
## ~/.hermes/scripts/feed-changed.sh
FEED="$HOME/data/feed.json"
STATE="$HOME/.hermes/scripts/.feed-changed.last"
test -f "$FEED" || { echo '{"wakeAgent": false}'; exit 0; }
mtime=$(stat -c %Y "$FEED")
last=$(cat "$STATE" 2>/dev/null || echo 0)
if [ "$mtime" -le "$last" ]; then
echo '{"wakeAgent": false}'
else
echo "$mtime" > "$STATE"
echo '{"wakeAgent": true}'
ficronjob(action="create", name="process-feed",
schedule="every 30m",
script="feed-changed.sh",
prompt="A new ~/data/feed.json has landed. Summarize what changed.")外部标志门控——仅当其他进程已发出就绪信号时才运行(例如,部署钩子放置一个文件,CI 任务在您的状态存储中设置一个值)。
#!/bin/bash
## ~/.hermes/scripts/flag-ready.sh
if test -f /tmp/new-data-ready; then
rm -f /tmp/new-data-ready
echo '{"wakeAgent": true}'
else
echo '{"wakeAgent": false}'
ficronjob(action="create", name="nightly-analysis",
schedule="0 9 * * *",
script="flag-ready.sh",
prompt="Run the nightly analysis over today's batch.")SQL 计数门控——仅当您自己的数据库中有新行要处理时才运行。脚本还可以通过 context 将计数传递给 agent,以便 agent 知道它正在查看多少数据而无需重新查询。
#!/usr/bin/env python
## ~/.hermes/scripts/new-rows.py
import json, sqlite3
conn = sqlite3.connect("/home/me/data/app.db")
n = conn.execute(
"SELECT COUNT(*) FROM messages WHERE ts > strftime('%s','now','-2 hours')"
).fetchone()[0]
if n < 1:
print(json.dumps({"wakeAgent": False}))
else:
print(json.dumps({"wakeAgent": True, "context": {"new_rows": n}}))cronjob(action="create", name="summarize-new-msgs",
schedule="every 2h",
script="new-rows.py",
prompt="Summarize the new messages from the last 2 hours.")同样的模式适用于您可以从脚本查询的任何数据源——Postgres、HTTP API、您自己的状态存储——而无需在 cron 子系统中内置 SQL 评估器。
提示
Hermes 自己的
~/.hermes/state.db是一个内部模式,在不同版本之间会发生变化。不要从预运行门控中查询它——请指向您自己的数据库或数据源。
致谢:这组配方是由 @iankar8 在 #2654 中的探索促成的,该探索提议添加 sql/file/command 触发器作为并行机制。script + wakeAgent 门控已经以 $0 覆盖了所有三种情况,因此这项工作以文档形式落地。
链接任务:context_from
Cron 任务可以通过在 context_from 中列出其他任务的名称(或 ID)来使用一个或多个其他任务的最新成功输出:
cronjob(action="create", name="daily-digest",
schedule="every day 7am",
context_from=["ai-news-fetch", "github-prs-fetch"],
prompt="Write the daily digest using the outputs above.")被引用任务的最新完成输出在此运行中作为上下文注入到提示之上。每个上游条目必须是有效的任务 ID 或名称(请参阅 cronjob action="list")。注意:链接读取最近完成的输出——它不会等待在同一滴答中运行的上游任务。
任务存储
任务存储在 ~/.hermes/cron/jobs.json 中。任务运行的输出保存到 ~/.hermes/cron/output/{job_id}/{timestamp}.md。
任务可能将 model 和 provider 存储为 null。当这些字段被省略时,Hermes 在执行时从全局配置中解析它们。仅当设置了每任务覆盖时,它们才会出现在任务记录中。
存储使用原子文件写入,因此中断的写入不会留下部分写入的任务文件。
自包含提示仍然重要
警告——重要
Cron 任务在全新的 agent 会话中运行。提示必须包含 agent 所需的所有内容,这些内容尚未由附加技能提供。
错误: "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 后门尝试或明显秘密泄露载荷的提示会被阻止。