系列第三篇。本文深入分析 Hermes 中 Skill 与 Tool 的本质区别:这不是便利性的划分,而是关于 AI 系统"可控性边界"的哲学立场。谁在控制执行路径,决定了系统的安全性、可预测性和可审计性。
当你第一次为 Hermes 贡献代码,想让 Agent 能做某件新事情时,你面对的第一个问题是:这应该是一个 Skill 还是一个 Tool?
错误答案一:Skill 是简单的,Tool 是复杂的。 如果这是一个简单的能力,做成 Skill;如果很复杂,做成 Tool。
这个答案导致的结果是:开发者倾向于把几乎所有东西做成 Tool,因为总可以把"自己实现的东西"理解为"很重要、很复杂"。Hermes 的 CONTRIBUTING.md 里就直接说:
The answer is almost always skill.
错误答案二:Skill 是文档,Tool 是代码。 Skill 就是写一段 Markdown 告诉 Agent 怎么做,Tool 是写 Python 代码真正实现功能。
这个答案在描述形式上大致正确,但它遗漏了最关键的维度。
正确的区分维度:谁在控制执行路径?
Tool 的执行路径由程序员在编写时固定。调用 web_search(query="python asyncio"),一定会发送一个 HTTP 请求到特定的搜索 API,解析返回的 JSON,返回结果。这个执行路径在代码里写死了,LLM 只决定"调用还是不调用"以及"传入什么参数",不决定"怎么执行"。
Skill 的执行路径由 LLM 在运行时解释。一个 Skill 可能说:"搜索 arXiv,找到相关论文,下载 PDF,提取摘要,然后用 web_extract 工具获取原始网页作为对比。"这段描述里隐含着许多执行决策:什么搜索词最合适?找几篇论文?摘要里哪些部分值得保留?LLM 在运行时根据当前上下文动态解释这些指令,每次执行的具体路径可能不同。
这个区别在安全性、可预测性和可审计性三个维度上有深远含义:
Tool 的危险行为可以在代码层面被约束。tools/approval.py 里的危险命令检测,对 terminal 工具的每次调用都做 regex 检查。这个检查是 100% 确定的——无论 LLM 决定调用什么命令,检查都会发生,没有"LLM 解释失误"的空间。
Skill 的安全依赖 LLM 对指令的正确解释。如果一个 Skill 说"删除临时文件",LLM 必须正确理解"临时"的含义,而不是把用户的代码目录也删掉。这类语义歧义是 Skill 的固有风险,没有办法完全消除——只能通过 Skill 的措辞清晰度、Skill 的测试覆盖来降低概率。
Tool 的行为是确定的(deterministic)。给定相同的输入参数,Tool 会产生相同的执行路径,除非外部依赖(API、文件系统)发生变化。这使得 Tool 可以被精确地单元测试:mock 掉 HTTP 请求,检查返回值格式,覆盖所有边界条件。