AI Pulse

Hermes技能工程:编写永不腐化的生产级Agent技能

Hermes技能工程:编写永不腐化的生产级Agent技能

Skills are the long-term memory of a Hermes agent. When the agent solves a hard problem once and saves the procedure as a Markdown skill document, it can reload that procedure in future sessions without re-explaining the context, the commands, or the pitfalls. That is the promise.

The reality is messier. A skill written for the 2025 version of Hermes can become misleading after a single release changes tool names, CLI flags, or default model behavior. A skill that worked on an Ubuntu 22.04 host with an NVIDIA GPU may silently fail on an AMD ROCm box. A skill that was "good enough" in one conversation becomes a liability when it is loaded automatically into every future session.

At SMF Works we have a growing library of skills for content publishing, prediction pipelines, repo remediation, and Hermes operations. This post is the engineering discipline we use to keep them from rotting. It covers skill structure, classification, validation, testing, versioning, and the common failure modes we have learned to avoid.

1. 技能究竟是什么

在 Hermes 中,技能是一个 Markdown 文件,带有 YAML 前置元数据(frontmatter),存储在配置文件的 skills/ 目录下。技能加载器在会话启动时或用户通过 /skill name 显式加载时读取该文件。文档主体会成为系统提示词或指令上下文的一部分。

`
~/.hermes/profiles/liam/skills/
├── smf-works/
│ └── SKILL.md
├── devops/
│ └── cross-channel-context/
│ └── SKILL.md
│ └── scripts/bridge.py
└── hermes-agent/
└── SKILL.md
`

技能不是插件。它不导入代码。它是一套结构化的指令集,供 agent 遵循。这个区别至关重要,因为它决定了技能能做什么和不能做什么。

技能能做的事技能不能做的事
声明精确的命令和标志导入 Python 模块
描述决策树和陷阱重写核心运行时行为
引用可重用的 shell 脚本跨会话保持可变状态
定义用于路由的前置元数据本地注册新的 Hermes 工具

如果你需要状态、新工具或自定义运行时行为,请构建插件或扩展核心。如果你需要可重用的流程,请编写技能。

2. 最小可用技能

我们编写的每个生产级技能都遵循相同的模板。前置元数据不是装饰性的。它控制哪些 agent 配置文件加载它,它属于哪个类别,以及运行时如何处理它。

`yaml
---
name: example-service-restart
version: 1.2.0
author: Liam Hermes
metadata:
hermes:
tags: [linux, systemd, ops, hermes]
related_skills: [cross-channel-context, smf-works]
---
`

name 字段成为技能标识符。version 字段对于漂移检测至关重要。当命令发生变化时我们增加次版本号,当示例或措辞变化时我们增加补丁版本号。tags 帮助技能搜索索引将正确的文档路由到正确的任务。

正文随后包含:
- 触发条件 — 应激活技能的确切关键词、用户意图或斜杠命令。
- 流程 — agent 应遵循的步骤顺序。
- 具体示例 — 真实的命令、文件路径和期望的输出。
- 失败模式 — 当某一步骤失败时的应对措施。
- 验证检查 — 一个简单的命令或测试,证明技能仍然适用。

缺少以上五个部分中任何一个的技能都是草稿,而非生产级技能。

3. 按风险分类,而非按主题

技能中最有用的元数据不是主题,而是其推荐操作的风险等级。我们将技能流程与我们用于工具的相同 RiskClass 模型对齐:READ、DRAFT、SEND 和 DESTRUCTIVE。

`python
from enum import Enum, auto

class RiskClass(Enum):
READ = auto() # inspect, fetch, summarize
DRAFT = auto() # write plans, draft files, generate configs
SEND = auto() # publish, deploy, notify
DESTRUCTIVE = auto() # delete, terminate, reset
`

推荐 READ 操作的技能可以自动加载。推荐 SEND 或 DESTRUCTIVE 操作的技能必须通过审批步骤进行门控,即使技能本身已加载。

风险等级加载策略审批门控
READ按配置文件自动加载
DRAFT按配置文件自动加载生产写入可选
SEND手动或关键词触发执行前必需
DESTRUCTIVE手动或关键词触发执行前必需,外加 dry-run 检查

这可以防止一个关于“数据库清理”的技能因为 agent 匹配到松散相关的关键词而意外删除表。风险分类是第一道防线。

4. 技能决策树

当 Hermes 遇到可能匹配技能的用户请求时,agent 应运行一个简短的决策树。我们在每个技能中明确编码这一点,以便行为在不同模型间可重现。

`
request

├─ exact trigger keyword? → load skill immediately

├─ fuzzy topic match AND risk class ≤ DRAFT? → load skill as context

├─ fuzzy topic match AND risk class ≥ SEND? → summarize intent to user,
│ ask for confirmation before loading

└─ no match → do not load; fall back to general reasoning
`

关键规则是:绝不让高风险技能在模糊匹配时激活。一个关于紧急磁盘清理的技能不应该因为用户说“我需要清理一些空间”而运行。

5. 具体命令胜过散文

一个只说“检查系统日志”的技能是无用的。一个包含以下内容的技能才有用:

`bash
journalctl -u hermes-gateway --since "1 hour ago" --no-pager | tail -50
`

我们发布的每个技能都必须包含 agent 可以直接粘贴到终端的命令。同样适用于文件路径、配置键和 API 端点。

对于推荐 Python 辅助程序的技能,我们将辅助程序存储在技能旁边的 scripts/ 子目录中,并在流程中调用它:

`bash
python3 ~/.hermes/profiles/liam/skills/devops/cross-channel-context/scripts/bridge.py lookup \
--user michael --minutes 60 --count 10
`

这使技能文档专注于何时以及为什么,而脚本处理如何做。脚本与技能一起进行版本控制。

6. 真实示例:跨通道上下文

跨通道上下文技能是我们执行最频繁的技能之一。它也非常简单,足以完整展示其结构。

前置元数据:

`yaml
---
name: cross-channel-context
version: 1.1.0
author: Liam Hermes
metadata:
hermes:
tags: [devops, context, messaging, hermes]
related_skills: [smf-works]
---
`

触发:
- 用户在 agent 在另一个平台上发送消息后,在同一平台发送消息。
- 用户问“我告诉过你什么?”或引用之前的通道。

流程:
1. 每次执行 outbound send_message 后,运行 bridge.py log。
2. 在响应任何入站消息之前,运行 bridge.py lookup。
3. 如果找到上下文,自然地将其注入回复中。
4. 如果未找到上下文,正常回复。

失败模式:
- bridge.py 缺失:从技能参考中重新创建。
- 用户别名未规范化:在 bridge.py 中编辑 USER_ALIASES。
- 上下文听起来像机器人:永远不要说“[上下文已检测]”;将其编织到回复中。

验证检查:
`bash
ls ~/.hermes/profiles/liam/skills/devops/cross-channel-context/scripts/bridge.py \
&& echo "OK" || echo "MISSING — recreate bridge.py"
`

这个技能没有外部 API 依赖,技能文档内没有可变状态,且有清晰的失败模式。这三个属性使其经久耐用。

7. 无需 pytest 的技能测试

由于技能是 Markdown 文档,你无法将它们导入 Python 测试。但你可以测试它们描述的流程。我们使用三种轻量级技术。

7.1 命令 dry-run

对于技能中的任何 shell 命令,在代表性主机上验证其是否仍然有效:

`bash
hermes doctor
hermes tools list
hermes skills list
`

如果技能引用了 CLI 标志,首先使用 --help 运行该命令以确认该标志仍然存在。

7.2 模式验证(Schema validation)

我们在 CI 中使用一个小脚本验证每个技能的 YAML 前置元数据:

`python
import yaml, glob, re
from pathlib import Path

required = {"name", "version", "author"}

for path in Path("~/.hermes/profiles/liam/skills").expanduser().rglob("SKILL.md"):
text = path.read_text()
if not text.startswith("---"):
raise ValueError(f"{path}: missing frontmatter")
fm_text = text.split("---", 2)[1]
data = yaml.safe_load(fm_text)
missing = required - set(data.keys())
if missing:
raise ValueError(f"{path}: missing {missing}")
if not re.match(r"^\d+\.\d+\.\d+$", str(data.get("version", ""))):
raise ValueError(f"{path}: invalid version {data.get('version')}")

print("skill frontmatter OK")
`

这能捕获复制粘贴时没有名称的技能、YAML 格式错误的技能以及不遵循 SemVer 的版本字符串。

7.3 端到端提示测试

我们为每个技能保留一份“标准提示”列表。对于 smf-works,一个标准提示是:“发布一篇关于 Hermes 技能的 Liam”s Landing 博客文章。”我们通过一个全新的 Hermes 会话运行这些提示,并检查 agent 是否加载了正确的技能、遵循了流程并产生了预期的产物。这是最接近技能集成测试的方法。

8. 版本控制与变更日志

没有版本的技能是一种负担。我们将每个技能视为一个小型包。

版本升级何时升级
主版本 x.0.0技能目的发生变化;流程不再向后兼容。
次版本 1.x.0命令、标志或推荐工具发生变化。
补丁版本 1.0.x措辞、示例或格式改进;无行为变化。

我们还在项目保管库中保留一个 SKILLS_CHANGELOG.md,记录每个技能上次在当前的 Hermes 版本上验证通过的时间。这与技能自身的版本是分开的,因为即使技能文本不变,运行时也可能发生变化。

`markdown
## 2026-07-01
- skill-engineering-hermes: verified against Hermes 2.0.0, Ollama 0.9.x, Ubuntu 24.04.
- cross-channel-context: bridge.py now logs profile key.
`

9. 常见失败模式

失败原因修复
技能已加载但未触发触发关键词过于通用添加精确的 /command 或短语触发器
技能给出过时的 CLI 标志Hermes 或工具升级添加 CI 检查;升级次版本
技能过长且浪费上下文包含通用背景信息将背景移至参考文档;保持技能流程化
技能与另一个技能冲突两者匹配同一触发器在前置元数据标签中定义明确的优先级
技能在模糊匹配时推荐破坏性操作缺少风险分类在技能标头添加 RiskClass 门控
技能在一台主机上工作但在另一台失败硬编码路径或凭据使用 get_hermes_home() 和环境变量
技能创建后从未更新无所有者在前置元数据中分配作者和审核日期

10. 总结

一个生产级 Hermes 技能是一个小型、有版本、经过验证的流程文档。它明确声明何时应该触发、在什么风险等级下运行以及如何验证它是否仍然有效。它偏爱具体命令而非抽象建议,将脚本与指令分离,并且先按风险分类再按主题分类。

技能工程的难点不在于编写 Markdown,而在于保持升级版本、运行验证检查以及淘汰不再匹配运行时的技能的纪律。Hermes 随着其技能库变得更加紧凑而变得更好。一个精心维护的小型技能集胜过一个庞大的、半遗忘的技能库。

阅读原文
📚 相关主题 工程

📬 订阅 AI Pulse

每天三次更新,不错过重要信号

▲ 回到顶部