# 模块三:进化篇 — Skills、Hooks、Plugins、Cron
# 目录
# 1. Skills 技能系统
官方文档:https://hermes-agent.nousresearch.com/docs/user-guide/features/skills
Skills 是 Hermes Agent 最核心的差异化能力 —— 自进化。Agent 解决复杂问题后,会把可复用流程保存为 Skill,下次遇到类似任务时自动加载。Skill 是透明的人类可读 Markdown 文件,你可以随时查看、编辑或删除。
Skills 系统包含 166 个已追踪的技能(87 个内置 + 79 个可选),覆盖 26+ 个类别。
已安装的技能会以斜杠命令的形式提供。
# 1.1 基本操作
hermes skills list # 列出已安装的技能 | |
hermes skills browse # 浏览可用的技能 | |
hermes skills search honcho # 搜索技能 | |
hermes skills install honcho # 通过 ID 安装技能 | |
hermes skills install https://example.com/my-skill/SKILL.md # 通过 URL 安装技能 | |
hermes skills uninstall honcho # 卸载技能 | |
/skills # 会话内管理技能 |
# 1.2 技能目录结构
所有技能默认存放在 ~/.hermes/skills/ :
~/.hermes/skills/ | |
├── mlops/ # 类别目录 | |
│ ├── axolotl/ # 技能目录 | |
│ │ ├── SKILL.md # 主说明文件,必需 | |
│ │ ├── references/ # 额外参考资料 | |
│ │ ├── templates/ # 输出模板 | |
│ │ ├── scripts/ # 技能可调用的辅助脚本 | |
│ │ └── assets/ # 图片、数据等附加资源 | |
│ └── vllm/ | |
│ └── SKILL.md | |
├── devops/ | |
│ └── deploy-k8s/ | |
│ ├── SKILL.md | |
│ └── references/ | |
├── .hub/ # Skills Hub 状态 | |
│ ├── lock.json | |
│ ├── quarantine/ | |
│ └── audit.log | |
└── .bundled_manifest # 记录内置技能同步状态 |
SKILL.md 是每个技能的入口文件。 references/ 、 templates/ 、 scripts/ 、 assets/ 都是可选目录。
可以把 Skill 粗略分成三种层级:
| 类型 | 例子 | 含义 |
|---|---|---|
| 普通具体 Skill | mlops/axolotl | 面向某个具体工具或流程 |
| 总括型 Skill(umbrella) | mlops/training | 覆盖一组相关流程 |
| 类别级总括型 Skill | software-development/debugging | 抽象到任务类别 |
一个完整的 SKILL.md 示例( ~/.hermes/skills/writing/tech-blog/SKILL.md ):
# Technical Blog Post Writing | |
Write technical blog posts targeting AI/ML developers. Follow this workflow: | |
## Pre-writing | |
1. Read all provided research summaries | |
2. Identify 3-5 key takeaways that readers will find actionable | |
3. Check for conflicting claims — flag them before writing | |
## Structure | |
- **Hook** (100-150 words): Start with a real problem or surprising finding | |
- **Background** (200-300 words): Context that makes the topic accessible | |
- **Deep Dive** (1000-1500 words): Core content with code examples | |
- **Implications** (200-300 words): Why this matters for practitioners | |
- **Key Takeaways** (bullet points): 3-5 actionable conclusions | |
## Code Examples | |
- Must be complete and runnable | |
- Use Python 3.11+ syntax | |
- Include error handling in production-facing code | |
- Prefer `uv` over `pip` for package management commands | |
## Language | |
- Main content in Chinese, technical terms in English | |
- Target 2000-2500 words | |
- Avoid passive voice in Chinese | |
## Frontmatter Template | |
```yaml | |
--- | |
title: "<English Title>" | |
date: <YYYY-MM-DD> | |
tags: [<3-5 relevant tags>] | |
author: "AI+Human" | |
--- |
可以看到,SKILL.md 就是一份结构化的工作指南,Agent 加载后会自动按照其中的流程执行。
### 1.3 外部技能目录
如果团队已经有共享技能目录,可以让 Hermes 额外扫描:
```yaml
# ~/.hermes/config.yaml
skills:
external_dirs:
- ~/.agents/skills
- /home/shared/team-skills
- ${SKILLS_REPO}/skills
外部目录支持 ~ 展开和 ${VAR} 环境变量替换。规则:
- 只读扫描:Agent 创建或修改技能时仍然写入
~/.hermes/skills/ - 本地优先:本地版本覆盖外部同名技能
- 完整集成:出现在技能索引、
skills_list、skill_view和斜杠命令中 - 路径可选:不存在的外部目录会被静默跳过
# 1.4 Skill Bundles(v0.15+ ★ 新增)
Skill Bundles 允许用一个斜杠命令同时加载多个技能。例如,创建一个 writing-day bundle:
hermes skills bundle create writing-day --skills blogwatcher,markdown-style,seo-check |
之后只需执行 /writing-day 即可加载全部三个技能。
# 1.5 Skills Hub 与 agentskills.io
Hermes Skills 兼容 agentskills.io 开放标准。你可以:
- 从 Skills Hub 浏览和安装社区技能
- 将自定义技能发布到 Hub 共享
- 通过 URL 直接安装技能
v0.16 精简了内置技能集,将 NVIDIA/skills 添加为内置可信 Skills Hub tap。
# 1.6 Conditional Activation(条件激活)
技能可以根据工具可用性自动显示 / 隐藏。例如,如果 Firecrawl API Key 缺失,Hermes 会自动回退到 DuckDuckGo 搜索技能。
# 1.7 Platform-Specific Skills(平台特定技能)
技能可以限定在特定操作系统上生效:
# SKILL.md frontmatter | |
platforms: | |
- linux | |
- macos | |
# - windows # 此技能不在 Windows 上显示 |
# 1.8 Agent-Managed Skills (skill_manage)
Hermes 可以通过 skill_manage 工具创建、修改和删除自己的技能。这是 Agent 的「程序记忆」:当它解决了一个有复用价值的复杂问题,就可以把流程沉淀成 Skill。
触发策略主要靠提示词驱动。整体规则:
- 复杂任务成功、克服错误、用户纠正后的方法有效、发现可复用流程,或用户要求记住流程时,可以创建 Skill
- 发现 Skill 过时、缺步骤、命令错误、OS 相关失败或新坑点时,应优先
patch现有 Skill
skill_manage 常见动作:
| 动作 | 用途 |
|---|---|
create | 从零创建一个新技能 |
patch | 对现有技能做小范围修改,优先使用 |
edit | 整体重写技能内容 |
delete | 删除技能 |
write_file | 添加或更新 references/ 、 scripts/ 等支持文件 |
remove_file | 删除支持文件 |
create 完整调用示例:当 Agent 发现一个值得沉淀的工作流程后:
skill_manage( | |
action="create", | |
name="docker-troubleshooting", | |
category="devops", | |
description="Systematic Docker troubleshooting workflow for production environments.", | |
content="# Docker Troubleshooting\n...", | |
umbrella="devops/troubleshooting", # 可选:归到已有 umbrella 下 | |
) | |
# 返回:技能已创建在 ~/.hermes/skills/devops/docker-troubleshooting/SKILL.md |
patch 使用示例:发现已有技能需要修正一小部分:
skill_manage( | |
action="patch", | |
name="docker-troubleshooting", | |
old_string="docker logs --tail 50", | |
new_string="docker logs --tail 100 --timestamps", | |
reason="增加时间戳和日志行数,便于关联时间线排查", | |
) |
Agent 优先使用 patch 而非 edit ,避免意外覆盖用户手动调整的内容。
# 1.9 Curator 技能维护系统
官方文档:https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Curator 是 Hermes 的技能维护系统,专门管理由后台自我改进 review agent 创建并标记的本地技能。它会跟踪这些技能的查看、使用和修改频率,把长期不用的技能从 active 推进到 stale ,再归档到 ~/.hermes/skills/.archive/ 。
Curator 的存在是为了防止通过自我提升循环产生的技能无限累积。如果不进行维护,最终会导致数十个功能相近但范围狭窄的重复技能,污染目录并浪费 token。
# Pinned 技能保护
如果某个技能很重要,可以把它 pin 住。Pinned 技能有三层保护:
- Curator 不会把它自动迁移到
stale或archived - Curator 的 LLM Review 会跳过它
- Agent 的
skill_manage delete也不能删除它,但仍然可以patch/edit
# 运行机制
Curator 在 Hermes 启动或 Gateway 后台 tick 时检查。自动运行需要同时满足:
curator.enabled未被设为false- 未被
hermes curator pause暂停 - 距离上次运行超过
interval_hours(默认 168 小时 / 7 天) - Agent 已空闲超过
min_idle_hours(默认 2 小时)
每次运行按两阶段执行:
- 自动状态迁移(不调用 LLM):超过
stale_after_days(30 天) 未使用的技能变成stale,超过archive_after_days(90 天) 未使用的移动到.archive/ - LLM Review:启动辅助模型,决定保留、修补、合并或归档。目标是构建 "类别级指令和经验知识" 的库
# 配置
# ~/.hermes/config.yaml | |
curator: | |
enabled: true | |
interval_hours: 168 | |
min_idle_hours: 2 | |
stale_after_days: 30 | |
archive_after_days: 90 |
可以为 Curator 指定更便宜的辅助模型:
# ~/.hermes/config.yaml | |
auxiliary: | |
curator: | |
provider: openrouter | |
model: google/gemini-3-flash-preview | |
timeout: 600 |
# 常用命令
hermes curator status # 查看技能状态 | |
hermes curator run # 手动运行策展 | |
hermes curator run --background # 后台运行 | |
hermes curator run --dry-run # 只预览,不修改技能库 | |
hermes curator pause # 暂停自动运行 | |
hermes curator resume # 恢复自动运行 | |
hermes curator pin my-important-skill # 固定某个技能 | |
hermes curator unpin my-important-skill # 取消固定 | |
hermes curator restore my-skill # 恢复已归档的技能 | |
hermes curator rollback # 恢复最新备份 |
同样的子命令也可以在会话中通过 /curator 斜杠命令使用。
# 哪些技能会被处理
Curator 只处理同时满足以下条件的技能:
- 位于本地技能目录
~/.hermes/skills/ - 不是 bundled 内置技能
- 不是 Skills Hub 安装的技能
- 被标记为
created_by: "agent"或agent_created: true
用户手写的 SKILL.md、外部技能目录中的 Skill、bundled 内置技能和 Skills Hub 安装的技能都不会被 Curator 自动归档或合并。
# 2. Hooks 钩子系统
官方文档:https://hermes-agent.nousresearch.com/docs/user-guide/features/hooks
Hermes 提供了三种钩子系统,允许在关键生命周期点执行自定义代码。所有钩子都是非阻塞设计,错误会被捕获并记录,不会影响 Agent 运行。
三种钩子对比:
| 维度 | Shell Hooks | Plugin Hooks | Gateway Hooks |
|---|---|---|---|
| 语言 | 任意(Bash、Python、Go 等) | 仅 Python | 仅 Python |
| 运行环境 | CLI + Gateway | CLI + Gateway | 仅 Gateway |
| 事件名 | Agent 内部事件名 | Agent 内部事件名 | 带冒号的 Gateway 事件名 |
| 注册位置 | ~/.hermes/config.yaml 的 hooks: | 插件 register(ctx) 中注册 | ~/.hermes/hooks/<name>/HOOK.yaml |
| 典型用例 | 阻止危险命令、自动格式化、注入 git 状态 | 工具拦截、指标采集、防护措施、记忆召回 | 日志记录、告警通知、Webhook 回调 |
常见钩子事件:
| 钩子 | 适用系统 | 触发时机 | 常见用途 | 是否能影响流程 |
|---|---|---|---|---|
pre_tool_call | Shell / Plugin | 工具执行前 | 阻止危险命令、检查参数、审计调用 | 可以返回 block 阻止 |
post_tool_call | Shell / Plugin | 工具返回后 | 记录结果、采集指标、跟踪生成文件 | 观察型 |
pre_llm_call | Shell / Plugin | 每轮 LLM 调用前 | 注入 git 状态、外部上下文、策略提示 | 可以返回 context 注入 |
post_llm_call | Shell / Plugin | 每轮 LLM 调用结束后 | 记录响应、同步记忆、采集 token 指标 | 观察型 |
on_session_start | Shell / Plugin | 新会话开始时 | 初始化会话状态、打开外部连接 | 观察型 |
on_session_end | Shell / Plugin | 会话结束、重置或退出时 | 清理资源、flush 缓存、发送通知 | 观察型 |
gateway:startup | Gateway | Gateway 进程启动时 | 启动检查、告警、注册 Webhook | 观察型 |
session:start / session:end / session:reset | Gateway | Gateway 会话创建、结束或重置时 | 记录消息平台会话、审计用户行为 | 观察型 |
agent:start / agent:step / agent:end | Gateway | Gateway 中 Agent 处理消息的过程 | 监控长任务、记录工具循环、统计耗时 | 观察型 |
command:* | Gateway | Gateway 里执行任意斜杠命令时 | 命令审计、权限统计、外部通知 | 观察型 |
# 2.1 Shell Hook 示例:会话结束后弹出桌面通知
适合在 WSL / Git Bash / Windows 终端里使用 Hermes。
- 注册 shell hook:
# ~/.hermes/config.yaml | |
hooks: | |
on_session_end: | |
- command: "~/.hermes/agent-hooks/windows-session-end-popup.sh" | |
timeout: 15 |
windows 创建方式:
hooks: | |
on_session_end: | |
- command: C:/PROGRA~1/Git/bin/bash.exe "C:/Users/merge/AppData/Local/hermes/hooks/windows-session-end-popup.sh" | |
timeout: 15 | |
hooks_auto_accept: true |
- 创建脚本目录:
mkdir -p ~/.hermes/agent-hooks |
- 创建脚本
~/.hermes/agent-hooks/windows-session-end-popup.sh:
#!/usr/bin/env bash | |
cat - >/dev/null # 丢弃 hook payload(stdin) | |
if command -v powershell.exe >/dev/null 2>&1; then | |
powershell.exe -NoProfile -WindowStyle Hidden -Command ' | |
Add-Type -AssemblyName System.Windows.Forms | |
Add-Type -AssemblyName System.Drawing | |
$f = New-Object System.Windows.Forms.Form | |
$f.Text = "Hermes" | |
$f.Width = 300 | |
$f.Height = 100 | |
$f.FormBorderStyle = "None" | |
$f.StartPosition = "CenterScreen" | |
$f.BackColor = [System.Drawing.Color]::FromArgb(32, 32, 32) | |
$f.ForeColor = [System.Drawing.Color]::White | |
$f.TopMost = $true | |
$f.ShowInTaskbar = $false | |
$label = New-Object System.Windows.Forms.Label | |
$label.Text = "Session finished" | |
$label.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold) | |
$label.ForeColor = [System.Drawing.Color]::White | |
$label.AutoSize = $true | |
$label.Location = New-Object System.Drawing.Point(20, 30) | |
$f.Controls.Add($label) | |
$timer = New-Object System.Windows.Forms.Timer | |
$timer.Interval = 3000 | |
$timer.Add_Tick({ $f.Close() }) | |
$timer.Start() | |
$f.ShowDialog() | |
$f.Dispose() | |
' >/dev/null 2>&1 & | |
fi | |
printf '{}\n' |
- 赋予执行权限:
chmod +x ~/.hermes/agent-hooks/windows-session-end-popup.sh |
首次运行时 Hermes 会询问是否允许这个 (event, command) 组合。
# 2.2 pre_tool_call 安全拦截示例
pre_tool_call 是唯一能阻止工具执行的钩子,适合安全防护场景。
场景:阻止 Agent 执行危险的终端命令(如 rm -rf / 、 DROP TABLE 、未授权的 SSH 连接)。
- 注册 hook:
# ~/.hermes/config.yaml | |
hooks: | |
pre_tool_call: | |
- command: "~/.hermes/agent-hooks/danger-guard.sh" | |
timeout: 5 |
- 创建
~/.hermes/agent-hooks/danger-guard.sh:
#!/usr/bin/env bash | |
PAYLOAD=$(cat) # Hermes 把工具调用信息通过 stdin 传入(JSON 格式) | |
TOOL_NAME=$(echo "$PAYLOAD" | python3 -c "import sys,json; print(json.load(sys.stdin).get('name',''))") | |
PARAMS=$(echo "$PAYLOAD" | python3 -c "import sys,json; print(json.dumps(json.load(sys.stdin).get('parameters',{})))") | |
# 仅检查 terminal 工具 | |
if [ "$TOOL_NAME" != "terminal" ]; then | |
printf '{"action":"allow"}\n' # 返回 allow 表示放行 | |
exit 0 | |
fi | |
# 从参数中提取命令 | |
CMD=$(echo "$PARAMS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('command',''))") | |
# 危险模式黑名单 | |
if echo "$CMD" | grep -qiE "rm\s+-rf\s+/|DROP\s+TABLE|shutdown|mkfs\.|>\/dev\/sda|chmod\s+-R\s+777\s+/"; then | |
printf '{"action":"block","reason":"Dangerous command blocked by guard hook"}\n' | |
exit 0 | |
fi | |
printf '{"action":"allow"}\n' |
- 赋予权限:
chmod +x ~/.hermes/agent-hooks/danger-guard.sh |
关键: pre_tool_call 脚本返回 {"action":"block"} 会阻止工具执行并告知 Agent 原因;返回 {"action":"allow"} 则放行。
# 3. Plugins 插件系统
官方文档:https://hermes-agent.nousresearch.com/docs/user-guide/features/plugins
Hermes 拥有一个插件系统,无需修改核心代码即可添加自定义工具、钩子和集成。
# 3.1 插件能做什么
插件通过 register(ctx) 函数接入 Hermes, ctx 上所有公开 API 均可使用:
| 扩展类型 | 说明 |
|---|---|
| 工具 | 给模型增加可调用能力,例如外部 API、本地服务或自定义逻辑 |
| 钩子 | 在工具调用、LLM 调用、会话开始 / 结束等生命周期点执行代码 |
| 命令 | 增加 /name 斜杠命令,或增加 hermes <plugin> ... 子命令 |
| 会话注入 | 把外部事件、消息或数据注入当前会话 |
| Skill / 数据 | 随插件附带 Skill、模板、配置、静态数据等资源 |
| Gateway 平台 | 接入新的消息平台或自定义平台适配器 |
| 后端提供商 | 接入新的记忆、上下文压缩、图像生成、视频生成或 LLM 提供商 |
v0.14+ 插件可以通过
ctx.llm直接在插件代码中调用当前活跃的模型提供商。
v0.13+ 第三方提供商可通过
ProviderProfileABC(抽象基类)实现自定义 LLM 提供商插件。
# 3.2 插件目录
用户插件目录是 ~/.hermes/plugins/ ,每个插件一个独立子目录。最小可用插件只需要两个文件:
~/.hermes/plugins/hello-world/ | |
├── plugin.yaml # 插件清单:名称、版本、描述等元信息 | |
└── __init__.py # 定义 register(ctx),在这里注册工具 / hook / 命令 |
plugin.yaml 让 Hermes 知道 "这里有一个插件", register(ctx) 决定 "这个插件实际提供什么能力"。
# 3.3 插件示例:shake_window
注册一个 shake_window 工具,让当前 Windows 前台窗口轻微晃动。
创建目录:
mkdir -p ~/.hermes/plugins/shake-window |
创建 ~/.hermes/plugins/shake-window/plugin.yaml :
name: shake-window | |
version: "1.0" | |
description: Provides a shake_window tool that briefly shakes the current Windows foreground window. |
创建 ~/.hermes/plugins/shake-window/__init__.py :
import json | |
import shutil | |
import subprocess | |
POWERSHELL_SHAKE = r""" | |
Add-Type @" | |
using System; | |
using System.Runtime.InteropServices; | |
public static class Win32 { | |
[DllImport("user32.dll")] | |
public static extern IntPtr GetForegroundWindow(); | |
[DllImport("user32.dll")] | |
public static extern bool GetWindowRect(IntPtr hWnd, out RECT rect); | |
[DllImport("user32.dll")] | |
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
public struct RECT { | |
public int Left; public int Top; public int Right; public int Bottom; | |
} | |
"@ | |
$hwnd = [Win32]::GetForegroundWindow() | |
if ($hwnd -eq [IntPtr]::Zero) { exit 1 } | |
$rect = New-Object RECT | |
[Win32]::GetWindowRect($hwnd, [ref]$rect) | Out-Null | |
$x = $rect.Left; $y = $rect.Top | |
$w = $rect.Right - $rect.Left; $h = $rect.Bottom - $rect.Top | |
for ($i = 0; $i -lt 8; $i++) { | |
[void][Win32]::MoveWindow($hwnd, $x - 12, $y, $w, $h, $true) | |
Start-Sleep -Milliseconds 45 | |
[void][Win32]::MoveWindow($hwnd, $x + 12, $y, $w, $h, $true) | |
Start-Sleep -Milliseconds 45 | |
} | |
[void][Win32]::MoveWindow($hwnd, $x, $y, $w, $h, $true) | |
""" | |
def register(ctx): | |
schema = { | |
"name": "shake_window", | |
"description": "Shake the current Windows foreground window.", | |
"parameters": { | |
"type": "object", | |
"properties": {}, | |
}, | |
} | |
def handle_shake(params, **kwargs): | |
del params, kwargs | |
powershell = shutil.which("powershell.exe") | |
if powershell is None: | |
return json.dumps({"ok": False, "error": "powershell.exe not found"}) | |
result = subprocess.run( | |
[powershell, "-NoProfile", "-Command", POWERSHELL_SHAKE], | |
text=True, capture_output=True, check=False, | |
) | |
return json.dumps({ | |
"ok": result.returncode == 0, | |
"stdout": result.stdout.strip(), | |
"stderr": result.stderr.strip(), | |
}) | |
ctx.register_tool( | |
name="shake_window", | |
toolset="desktop_fun", | |
schema=schema, | |
handler=handle_shake, | |
description="Shake the current Windows foreground window.", | |
) |
启用插件:
hermes plugins enable shake-window |
重新启动 Hermes 后,模型就能调用 shake_window 工具。
# 3.4 插件发现
Hermes 会从多个来源发现插件:
| 来源 | 路径 / 方式 | 用途 |
|---|---|---|
| Bundled | Hermes 仓库内置 plugins/ | 官方随 Hermes 发布的插件 |
| User | ~/.hermes/plugins/ | 用户自己的本地插件 |
| Project | .hermes/plugins/ | 当前工作目录插件;默认不扫描,需设置 HERMES_ENABLE_PROJECT_PLUGINS=true |
| pip | hermes_agent.plugins entry points | 通过 Python 包分发的插件 |
# 3.5 管理插件
hermes plugins # 交互式开关插件 | |
hermes plugins list # 查看已安装插件 | |
hermes plugins install user/repo # 从 GitHub 安装插件 | |
hermes plugins update <name> # 更新插件 | |
hermes plugins remove <name> # 移除插件 | |
hermes plugins enable <name> # 启用插件 | |
hermes plugins disable <name> # 禁用插件 |
新安装或捆绑的插件默认不启用,必须加入 ~/.hermes/config.yaml :
# ~/.hermes/config.yaml | |
plugins: | |
enabled: | |
- my-plugin | |
disabled: | |
- noisy-plugin |
plugins.disabled 是拒绝列表,如果同一个插件同时出现在 enabled 和 disabled ,禁用优先。
# 4. Cron 定时任务
官方文档:https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Hermes 内置定时任务系统,可以用自然语言、cron 表达式安排任务。
定时任务通过 Gateway daemon 执行:Gateway 每 60 秒 tick 一次,检查到期任务。为每个到期任务启动一个新的 Agent 会话执行 prompt,然后投递最终结果。Cron 运行时会禁用 cron 管理工具,避免递归创建更多定时任务造成调度循环。
# 4.1 创建任务
可在会话中通过 /cron ,或使用 CLI 命令 hermes cron 来创建:
/cron add 30m "提醒我检查构建结果" | |
/cron add "every 2h" "检查服务器状态" | |
/cron add "every 1h" "总结新动态" --skill blogwatcher | |
/cron add "every 1h" "加载两个技能并合并结果" --skill blogwatcher --skill maps | |
hermes cron create "every 2h" "检查服务器状态" | |
hermes cron create "every 1h" "总结新动态" --skill blogwatcher |
也可以直接用自然语言让 Hermes 创建:
每天早上 9 点检查 Hacker News 上的 AI 新闻,然后发一份摘要到 Telegram。 |
Hermes 会在内部调用 cronjob 工具完成创建:
cronjob( | |
action="create", | |
schedule="every 1d at 09:00", | |
prompt="检查 Hacker News 上的 AI 新闻,筛选值得关注的条目,并写成中文摘要。", | |
name="HN AI daily", | |
deliver="telegram", | |
) |
# 4.2 调度格式
| 类型 | 示例 | 行为 |
|---|---|---|
| 相对延迟 | 30m 、 2h 、 1d | 一次性运行 |
| 循环间隔 | every 30m 、 every 2h 、 every 1d | 持续重复运行 |
| Cron 表达式 | 0 9 * * * 、 0 9 * * 1-5 、 0 */6 * * * | 按 cron 规则重复运行 |
| ISO 时间 | 2026-03-15T09:00:00 | 指定时间运行一次 |
Cron 表达式格式为 分 时 日 月 周 :
0 9 * * *每天 9:00 执行0 9 * * 1-5工作日每天 9:00 执行0 */6 * * *每 6 小时执行30 8 1 * *每月 1 日 8:30 执行
# 4.3 管理任务
/cron list # 查看定时任务 | |
/cron list --all # 查看所有任务,包括已暂停的 | |
/cron edit <job_id> --schedule "every 4h" # 修改调度时间 | |
/cron edit <job_id> --prompt "使用新的任务说明" # 修改任务说明 | |
/cron edit <job_id> --skill blogwatcher --skill maps # 替换技能列表 | |
/cron edit <job_id> --add-skill maps # 追加技能 | |
/cron edit <job_id> --remove-skill blogwatcher # 移除指定技能 | |
/cron pause <job_id> # 暂停任务 | |
/cron resume <job_id> # 恢复任务 | |
/cron run <job_id> # 下一个 scheduler tick 触发任务 | |
/cron remove <job_id> # 删除任务 | |
hermes cron status # 查看调度器状态 | |
hermes cron tick # 手动触发一次 scheduler tick |
任务存储在 ~/.hermes/cron/jobs.json ,运行输出保存到 ~/.hermes/cron/output/{job_id}/{timestamp}.md 。
# 4.4 运行结果投递方式
deliver 控制定时任务运行完成后,把 Agent 的最终回复发送到哪里:
| deliver | 说明 |
|---|---|
origin | 回到创建任务的聊天来源,消息平台默认值 |
local | 只保存到本地文件,CLI 默认值 |
telegram 、 discord 、 slack | 投递到对应平台的 home channel |
telegram:123456 | 投递到指定 Telegram chat ID |
discord:#engineering | 投递到指定 Discord 频道 |
all | 投递到所有已配置 home channel 的平台 |
telegram,discord | 投递到多个指定平台 |
origin,all | 投递到来源聊天 + 所有 home channel |
ntfy | v0.15+:推送通知,无需账号 |
示例:
hermes cron create "every 30m" "检查服务状态" --deliver telegram | |
hermes cron create "every 1d" "生成日报" --deliver telegram,discord |
如果 Agent 的最终回复以 [SILENT] 开头,成功运行时会抑制投递,但输出仍会保存到本地。失败任务仍会投递错误信息。适合只有出现问题才需要报告的作业:
Check if nginx is running. If everything is healthy, respond with only [SILENT]. | |
Otherwise, report the issue. |
# 4.5 No-Agent 模式
对于不需要 LLM 推理的周期性任务(监控程序、磁盘 / 内存警报、心跳检测、CI ping 等),可传递 no_agent=True :
hermes cron create "every 5m" \ | |
--no-agent \ | |
--script memory-watchdog.sh \ | |
--deliver telegram \ | |
--name "memory-watchdog" |
脚本必须放在 ~/.hermes/scripts/ 中。 .sh / .bash 用 /bin/bash 执行,其他脚本用当前 Python 解释器执行。
脚本运行默认超时 120 秒,可调整:
# ~/.hermes/config.yaml | |
cron: | |
script_timeout_seconds: 300 |
# 4.6 使用 context_from 链接作业
Cron 任务彼此之间默认隔离。 context_from 用来把一个任务的最新输出接到另一个任务的 prompt 前面。它只能由 Agent 通过 cronjob 工具设置,CLI 命令不支持。
典型流程:
Job 1:收集原始数据 | |
Job 2:读取 Job 1 的最新输出,筛选 / 排序 | |
Job 3:读取 Job 2 的最新输出,生成最终报告并投递 |
示例:
# Job 1:收集 AI 新闻 | |
cronjob(action="create", name="ai-news-fetch", | |
schedule="0 7 * * *", | |
prompt="Fetch the top 10 AI/ML stories from Hacker News.") | |
# Job 2:使用 Job 1 的最新输出做筛选 | |
cronjob(action="create", name="ai-news-rank", | |
schedule="30 7 * * *", | |
context_from="<job1_id>", | |
prompt="Score each story for novelty and engagement. Keep the top 5.") | |
# Job 3:使用 Job 2 的最新输出生成日报 | |
cronjob(action="create", name="ai-news-brief", | |
schedule="0 8 * * *", | |
context_from="<job2_id>", | |
prompt="Write a concise daily brief and deliver it to Telegram.") |
context_from 支持单个或多个 job ID。多个上游输出会按列表顺序拼接,每个上游输出在注入前被截断至 8,000 字符。
注意:
context_from读取的是上游任务「最近一次已完成输出」,不会等待同一个 tick 中仍在运行的上游任务。需要强依赖同一批数据时,应把上下游任务错开足够长时间。
