第九册:47 个内置工具全解 —— Hermes Agent 的瑞士军刀使用手册
本章你将学到
- Hermes 工具系统的整体架构和设计哲学,理解为什么工具是 Agent 的「手脚」
- 工具(Tool)与技能(Skill)的本质区别和协同关系
- ToolRegistry 单例模式的自注册机制,工具是如何自动被发现和加载的
- 安全审批流程的完整链条:哪些工具需要确认、确认界面长什么样、如何配置审批策略
- 47 个内置工具的详细参数说明、使用示例和注意事项
- 七大类工具的实战组合技巧,从单一工具到工具链的进阶用法
- 工具开发扩展方法:自定义工具、MCP 协议集成和社区贡献指南
- 工具使用的 10 大误区和最佳实践,让你少走弯路
1. 工具系统总览:Agent 的「手脚」是如何长出来的
1.1 什么是 Hermes 工具(Tool)
想象一下,你雇了一位智商 180 的顶级顾问。他上知天文下知地理,能跟你聊哲学、谈经济、写代码、做分析——但他有一个致命缺陷:他不能离开椅子,不能碰电脑,不能上网,不能操作文件,甚至连计算器都不能按。
这位顾问能做的事情,就是动动嘴皮子给你出主意。当你说「帮我搜一下今天的 AI 新闻」,他会说「根据我的知识,AI 领域最近有这些进展……」——但他说的可能是三个月前的旧闻,因为他没法上网查。
这就是没有工具的 AI Agent。
现在,你给这位顾问配了一套「智能义肢」:
- 一双能操作键盘鼠标的手(文件系统工具)
- 一双能看网页的眼睛(Web 交互工具)
- 一个能执行代码的大脑(代码执行工具)
- 一个能记住事情的笔记本(记忆管理工具)
- 一个能发号施令的对讲机(代理委托工具)
这套「义肢」,就是 Hermes 的工具系统(Tool System)。
工具的本质,是给大语言模型(LLM)赋予与外部世界交互的能力。 LLM 本身只能处理文本输入、生成文本输出。它无法读取你电脑上的文件,无法访问互联网,无法运行程序,无法发送通知。工具系统就是一座桥梁,把 LLM 的「思考能力」与计算机系统的「执行能力」连接起来。
在 Hermes 中,工具被设计为**函数调用(Function Calling)**的形式。当 Agent 决定需要执行某个外部操作时,它会构造一个工具调用请求,包含工具名称和参数,然后由工具执行层负责实际执行,最后把执行结果返回给 Agent,Agent 再根据结果决定下一步行动。
这个过程就像这样:
你:帮我分析一下项目根目录下的 package.json 文件
Agent(思考):用户要我分析 package.json,我需要先读取这个文件。
我应该调用 read_file 工具,参数是 file_path="package.json"。
Agent(工具调用):read_file(file_path="package.json")
工具执行层:读取 /Users/me/project/package.json 的内容
工具执行层(返回结果):{ "name": "my-project", "version": "1.0.0", ... }
Agent(思考):拿到了文件内容,现在我需要分析它的依赖结构、脚本命令等。
Agent(回复):这个 package.json 的依赖结构是这样的……
Tips
很多新手会混淆「工具调用」和「普通回复」。当你看到 Agent 的回复中有类似
read_file(...)这样的内容时,不要以为是 Agent 在「假装」调用工具——它是真的在执行!工具调用会被系统拦截,转交给对应的工具执行模块,执行完毕后再把结果喂回给 Agent。
1.2 工具与技能(Skill)的区别
在第八册中,我们详细讲解了 Skill(技能)系统。Skill 和 Tool 都是 Hermes 的核心能力,但它们的角色完全不同。
用一个类比来理解:
- Tool(工具) = 你手里的「工具」:锤子、螺丝刀、电钻、尺子
- Skill(技能) = 你脑子里的「工艺」:如何组装一个书架、如何修理一辆自行车
工具是被动的、原子化的能力单元。每个工具只做一件事:read_file 只负责读文件,web_search 只负责搜索网页。工具本身不知道「什么时候该用」,也不知道「用了之后下一步该做什么」。
技能是主动的、流程化的工作模板。一个技能会组织多个工具的调用顺序,定义每一步的参数模板,甚至包含条件分支和错误处理。比如「生成周报」这个技能,可能会按顺序调用:web_search(搜行业动态)→ read_file(读上周模板)→ write_file(写新周报)。
| 维度 | Tool(工具) | Skill(技能) |
|---|---|---|
| 粒度 | 原子操作(单一步骤) | 复合流程(多个步骤) |
| 智能性 | 被动执行,无决策能力 | 主动决策,包含条件分支 |
| 可复用性 | 被 Skill 调用 | 被用户触发或自动触发 |
| 存储位置 | 代码中的 Tool 类 | ~/.hermes/skills/ 下的 Markdown 文件 |
| 编写者 | 开发者(Python/TypeScript 代码) | 用户或社区(Markdown 配置) |
| 数量 | 47 个内置工具 | 700+ 个社区技能 |
注意
Tool 和 Skill 的关系是「被调用」与「调用者」的关系。Skill 会调用 Tool,但 Tool 不会调用 Skill。你也可以把 Skill 理解为「高级工具编排语言」,而 Tool 是「底层机器指令」。
1.3 ToolRegistry 单例模式与自注册机制
Hermes 的工具系统采用了一个非常优雅的设计:自注册(Self-Registration)机制。这意味着你不需要手动维护一个「工具清单」,新工具会自动被发现和注册。
核心组件:ToolRegistry
ToolRegistry 是一个**单例(Singleton)**类,整个 Hermes 进程中只有一个实例。它相当于工具的「中央数据库」,维护着所有可用工具的注册信息。
# 简化的 ToolRegistry 核心逻辑
class ToolRegistry:
_instance = None
_tools: Dict[str, Tool] = {}
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def register(self, tool: Tool):
"""注册一个工具到全局注册表"""
self._tools[tool.name] = tool
def get(self, name: str) -> Tool:
"""按名称获取工具实例"""
return self._tools.get(name)
def list_all(self) -> List[Tool]:
"""列出所有已注册的工具"""
return list(self._tools.values())自注册机制:装饰器魔法
Hermes 使用了 Python 装饰器来实现工具的自注册。开发者只需在工具类上添加一个 @tool 装饰器,这个工具就会自动被注册到 ToolRegistry 中。
from hermes.core.tools import tool
@tool(
name="read_file",
description="读取指定文件的内容",
parameters={
"file_path": {"type": "string", "description": "文件路径"},
"offset": {"type": "integer", "description": "起始偏移量", "default": 0},
"limit": {"type": "integer", "description": "读取行数限制", "default": 100}
},
requires_approval=False # 不需要用户审批
)
class ReadFileTool(Tool):
async def execute(self, params: dict) -> ToolResult:
file_path = params["file_path"]
# 实际的文件读取逻辑...
return ToolResult(content=file_content)当 Hermes 启动时,它会扫描 hermes/tools/ 目录下的所有 Python 文件,导入这些模块。由于装饰器在导入时就会执行,@tool 装饰器会把工具实例自动注册到 ToolRegistry 单例中。
这个过程就像是:
- Hermes 启动 → 扫描工具目录
- 发现
read_file_tool.py→ 导入模块 - 装饰器
@tool(...)执行 → 调用registry.register(read_file_tool) - 工具进入全局注册表 → 可供 Agent 随时调用
Tips
这种自注册机制的好处是「新增工具零配置」。你只需创建一个新的工具文件,放到正确的目录下,重启 Hermes,新工具就会自动生效。不需要修改任何配置文件,也不需要手动更新工具列表。
1.4 工具调用的安全审批流程
工具赋予了 Agent 强大的能力,但也带来了安全风险。想象一下,如果 Agent 可以不受限制地执行 rm -rf /(删除整个系统),那将是一场灾难。
Hermes 设计了一套分层的安全审批机制,根据工具的危险等级决定是否需要用户确认。
危险等级分类
| 等级 | 描述 | 典型工具 | 审批策略 |
|---|---|---|---|
| 🟢 安全 | 只读操作,不会修改任何数据 | read_file、web_search、list_directory | 无需审批 |
| 🟡 低风险 | 可能修改数据,但影响范围有限 | write_file(覆盖已有文件)、memory_write | 首次审批,可记住选择 |
| 🟠 中风险 | 会修改系统状态,有潜在副作用 | execute_python、run_command(白名单内) | 每次都需要审批 |
| 🔴 高风险 | 可能破坏数据或危害系统安全 | execute_shell、kill_process、rm -rf | 强制审批,无法跳过 |
审批界面长什么样
当 Agent 调用一个需要审批的工具时,你会在终端看到类似这样的提示:
┌─────────────────────────────────────────────────────────┐
│ ⚠️ 工具调用需要您的确认 │
├─────────────────────────────────────────────────────────┤
│ 工具: execute_shell │
│ 描述: 执行 Shell 命令 │
│ 风险等级: 🔴 高风险 │
│ │
│ 参数: │
│ command: "rm -rf /tmp/old_logs" │
│ │
│ 预估影响: 将删除 /tmp/old_logs 目录及其所有内容 │
├─────────────────────────────────────────────────────────┤
│ 请选择: │
│ [Y] 允许本次执行 │
│ [N] 拒绝本次执行 │
│ [A] 始终允许此类操作(记住选择) │
│ [D] 查看详细参数 │
└─────────────────────────────────────────────────────────┘
> Y
注意
即使选择了「始终允许」,某些极高风险的操作(如
rm -rf /、修改系统配置文件)仍然会强制要求确认。这是 Hermes 的「安全底线」,无法通过配置关闭。
配置审批策略
你可以在 ~/.hermes/config.yaml 中自定义审批策略:
# Hermes 安全配置
tools:
approval:
# 全局默认策略:对所有需要审批的工具生效
default_strategy: "prompt" # prompt | auto_allow | auto_deny
# 按工具单独配置
per_tool:
execute_shell:
strategy: "prompt" # 强制提示
require_confirmation: true
write_file:
strategy: "remember" # 首次确认,后续记住
remember_duration: "7d" # 记住 7 天
read_file:
strategy: "auto_allow" # 自动允许(只读操作)
# 命令黑名单:包含这些关键字的命令直接拒绝
command_blacklist:
- "rm -rf /"
- "mkfs."
- ":(){ :|:& };:"
- "> /dev/sda"
# 命令白名单:只允许执行这些命令(如果启用白名单模式)
command_whitelist:
- "git"
- "npm"
- "python"
- "ls"
- "cat"常见问题
Q: 为什么 read_file 也需要配置 approval?
A: 虽然 read_file 默认是安全操作,但在某些高安全要求的环境中(如处理敏感文件),你可能希望对所有文件访问进行审计。通过将
read_file的 strategy 设为"prompt",可以记录每次文件读取操作。Q: 我不小心点了「始终允许」,怎么撤销?
A: 运行
hermes approval reset命令,可以清除所有已记住的审批决策,恢复到初始状态。
1.5 hermes tools 命令使用
Hermes 提供了一个便捷的 CLI 命令来查看和管理工具。
# 列出所有可用工具
hermes tools list
# 查看某个工具的详细信息
hermes tools info read_file
# 查看工具的分类统计
hermes tools stats
# 测试一个工具(不经过 Agent,直接执行)
hermes tools test read_file --params '{"file_path": "README.md"}'
# 查看工具调用历史
hermes tools history
# 导出工具配置
hermes tools export > my_tools_config.yamlhermes tools list 的输出示例:
┌────────────────────────────────────────────────────────────┐
│ Hermes 内置工具清单(共 47 个) │
├──────────────┬──────────────────────────┬──────────────────┤
│ 工具名称 │ 类别 │ 需要审批 │
├──────────────┼──────────────────────────┼──────────────────┤
│ read_file │ 文件系统 │ 否 │
│ write_file │ 文件系统 │ 是(低风险) │
│ edit_file │ 文件系统 │ 是(低风险) │
│ execute_python │ 代码执行 │ 是(中风险) │
│ execute_shell │ 代码执行 │ 是(高风险) │
│ web_search │ Web 交互 │ 否 │
│ ... │ ... │ ... │
└──────────────┴──────────────────────────┴──────────────────┘
Tips
hermes tools test是调试工具的神器。当你怀疑某个工具行为异常时,可以直接用测试模式执行,绕过 Agent 的推理逻辑,快速验证工具本身是否正常工作。
本章小结
在本章中,我们建立了对 Hermes 工具系统的整体认知:
- 工具是 Agent 的「手脚」,让 LLM 从「只能动嘴」进化到「能够动手」
- 工具与技能的区别在于:工具是原子化的执行单元,技能是流程化的工作编排
- 自注册机制让工具的发现和加载完全自动化,新增工具零配置
- 安全审批流程通过四级风险分类和可配置的策略,在便利性和安全性之间取得平衡
hermes toolsCLI 命令提供了便捷的工具管理和调试手段
接下来的章节,我们将逐一深入讲解 47 个内置工具的详细用法。准备好你的「工具箱」了吗?让我们开始!
2. 第一类:文件系统工具 —— Agent 的「文件管家」
本章你将学到
- 6 个文件系统工具的完整参数说明和使用场景
- 如何安全地读取、写入、编辑文件而不损坏数据
- search_files 的搜索语法和性能优化技巧
- 文件操作中的常见陷阱和避坑指南
- 批量文件处理的高效工作流
文件系统工具是 Hermes 最基础也是最常用的工具类别。它们让 Agent 能够与你的本地文件系统交互——读取配置文件、修改代码、搜索日志、整理目录。可以说,没有文件系统工具,Agent 就像一个被蒙住眼睛的人,根本不知道周围有什么。
2.1 read_file —— 读取文件内容
功能说明
read_file 是 Hermes 中使用频率最高的工具之一。它负责读取指定文件的内容,并以文本形式返回给 Agent。
这个工具的设计非常注重安全性和性能:
- 默认只能读取用户有权限访问的文件
- 支持大文件的分段读取,避免一次性加载几百 MB 的日志文件导致内存爆炸
- 自动检测文件编码(UTF-8、GBK、Latin-1 等)
- 支持二进制文件的十六进制预览
参数详解
{
"file_path": {
"type": "string",
"required": true,
"description": "要读取的文件路径,支持相对路径和绝对路径"
},
"offset": {
"type": "integer",
"required": false,
"default": 0,
"description": "起始行偏移量(从 0 开始),用于读取大文件的一部分"
},
"limit": {
"type": "integer",
"required": false,
"default": 100,
"description": "最多读取多少行,防止大文件导致上下文溢出"
},
"encoding": {
"type": "string",
"required": false,
"default": "auto",
"description": "文件编码,可选值:auto、utf-8、gbk、latin-1、ascii"
},
"format": {
"type": "string",
"required": false,
"default": "text",
"description": "输出格式:text(纯文本)、hex(十六进制)、base64"
}
}使用示例
示例 1:读取普通文本文件
工具调用:
read_file(file_path="README.md")
返回结果:
# Hermes Agent
Hermes 是一个开源的 AI Agent 框架……
示例 2:读取代码文件的指定范围
工具调用:
read_file(file_path="src/main.py", offset=50, limit=30)
返回结果:
(从第 51 行到第 80 行的代码内容)
Tips
当你需要查看一个文件的特定函数或类时,先使用
search_files定位到行号,再用read_file的offset和limit参数精确读取。这比一次性读取整个文件高效得多,特别是对于几千行的大文件。
示例 3:读取二进制文件(预览模式)
工具调用:
read_file(file_path="data/sample.bin", format="hex", limit=20)
返回结果:
00000000: 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 .PNG........IHDR
00000010: 00 00 00 80 00 00 00 80 08 06 00 00 00 C3 3E 61 ..............>a
常见场景
| 场景 | 参数组合 | 说明 |
|---|---|---|
| 查看配置文件 | file_path="config.yaml" | 快速了解项目配置 |
| 查看日志尾部 | file_path="app.log", offset=-50 | 负数 offset 表示从末尾算起 |
| 查看大文件中间部分 | file_path="data.csv", offset=1000, limit=50 | 分段读取避免上下文溢出 |
| 检查文件编码 | file_path="legacy.txt", encoding="auto" | 自动检测编码 |
注意事项
注意
- 路径安全:
read_file默认被限制在当前工作目录及其子目录内。尝试读取/etc/passwd或../../secret.txt这样的路径会被拒绝。- 大文件保护:如果文件超过 10MB,Agent 会收到警告,建议使用
offset和limit分段读取。- 敏感文件:以
.env、.key、.pem结尾的文件读取时会额外提示,防止意外泄露密钥。
常见问题
Q: 为什么读取某些文件会显示乱码?
A: 这通常是编码问题。Windows 系统下的中文文件常用 GBK 编码,而 Hermes 默认按 UTF-8 读取。解决方法:显式指定
encoding="gbk"。如果不知道编码,可以先试encoding="auto",Hermes 会尝试自动检测。Q: 如何读取一个文件的最后 100 行?
A: 使用负数 offset:
read_file(file_path="app.log", offset=-100)。这相当于 Linux 命令tail -n 100。
2.2 write_file —— 写入/创建文件
功能说明
write_file 用于创建新文件或覆盖已有文件。这是 Agent「输出成果」的主要方式——生成报告、保存代码、导出数据,都离不开这个工具。
由于 write_file 会永久修改文件系统,它被归类为低风险操作,默认需要用户审批(首次可记住选择)。
参数详解
{
"file_path": {
"type": "string",
"required": true,
"description": "目标文件路径"
},
"content": {
"type": "string",
"required": true,
"description": "要写入的文件内容"
},
"encoding": {
"type": "string",
"required": false,
"default": "utf-8",
"description": "文件编码"
},
"append": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否在文件末尾追加内容(而不是覆盖)"
},
"create_dirs": {
"type": "boolean",
"required": false,
"default": true,
"description": "如果父目录不存在,是否自动创建"
},
"backup": {
"type": "boolean",
"required": false,
"default": false,
"description": "覆盖前是否创建 .bak 备份文件"
}
}使用示例
示例 1:创建一个新文件
工具调用:
write_file(
file_path="report.md",
content="# 项目分析报告\n\n## 概述\n本项目……"
)
示例 2:追加内容到日志文件
工具调用:
write_file(
file_path="logs/agent.log",
content="[2024-01-15 10:30:00] 任务完成\n",
append=true
)
示例 3:安全覆盖(带备份)
工具调用:
write_file(
file_path="config.yaml",
content="新的配置内容……",
backup=true
)
结果:
- 原 config.yaml 被重命名为 config.yaml.bak
- 新内容写入 config.yaml
Tips
在修改重要配置文件(如
package.json、pyproject.toml)时,强烈建议设置backup=true。这样如果修改出了问题,你可以随时用read_file查看.bak文件恢复原始内容。
常见场景
| 场景 | 参数组合 | 说明 |
|---|---|---|
| 生成报告 | file_path="report.md" | Agent 最常用的输出方式 |
| 保存代码 | file_path="src/utils.py" | 生成新模块或修改现有模块 |
| 追加日志 | append=true | 不覆盖已有内容 |
| 创建多级目录 | create_dirs=true | 自动创建不存在的父目录 |
注意事项
注意
- 覆盖警告:如果目标文件已存在且
append=false(默认值),工具会提示「文件已存在,是否覆盖?」这是防止意外丢失数据的重要保护。- 空内容保护:如果
content为空字符串,工具会拒绝执行,防止误删文件内容。- 二进制文件:虽然 write_file 主要处理文本,但也可以通过 base64 编码写入二进制内容。不过对于大二进制文件,建议使用专门的文件传输工具。
2.3 edit_file —— 编辑文件(差异替换)
功能说明
如果说 write_file 是「推土机」(全部推倒重来),那么 edit_file 就是「手术刀」——只修改文件的特定部分,保留其他内容不变。
edit_file 基于差异替换原理工作。你提供一段「旧文本」和一段「新文本」,工具会在文件中找到旧文本的位置,将其替换为新文本。这种方式非常适合代码修改、文本替换、配置更新等场景。
参数详解
{
"file_path": {
"type": "string",
"required": true,
"description": "要编辑的文件路径"
},
"old_string": {
"type": "string",
"required": true,
"description": "文件中要被替换的旧文本片段"
},
"new_string": {
"type": "string",
"required": true,
"description": "用于替换的新文本片段"
},
"occurrence": {
"type": "integer",
"required": false,
"default": 1,
"description": "替换第几次出现的旧文本(1=第一次,-1=最后一次)"
},
"backup": {
"type": "boolean",
"required": false,
"default": true,
"description": "编辑前是否自动创建 .bak 备份"
}
}使用示例
示例 1:简单的文本替换
假设 greeting.txt 内容如下:
Hello, World!
Welcome to Hermes.
工具调用:
edit_file(
file_path="greeting.txt",
old_string="World",
new_string="Hermes User"
)
结果:
Hello, Hermes User!
Welcome to Hermes.
示例 2:修改代码中的函数实现
假设 calculator.py 中有如下代码:
def add(a, b):
return a + b工具调用:
edit_file(
file_path="calculator.py",
old_string='def add(a, b):\n return a + b',
new_string='def add(a, b):\n """返回两个数的和"""\n return a + b'
)
结果:
def add(a, b):
"""返回两个数的和"""
return a + b
Tips
在编写
old_string时,一定要确保文本片段在文件中是唯一的。如果旧文本在文件中出现了多次,而你只想替换其中一处,就需要使用occurrence参数。否则工具会报错:「找到多处匹配,请使用 occurrence 参数指定」。
示例 3:替换第 N 次出现
工具调用:
edit_file(
file_path="data.txt",
old_string="apple",
new_string="orange",
occurrence=2 # 替换第二次出现的 "apple"
)
常见场景
| 场景 | 技巧 | 说明 |
|---|---|---|
| 修改函数签名 | 精确匹配整个函数定义行 | 确保 old_string 包含足够的上下文 |
| 更新版本号 | old_string="version = \"1.0.0\"" | 注意转义引号 |
| 添加 import 语句 | 在已有 import 块中插入 | 匹配最后一个 import,在其后追加 |
| 删除代码块 | new_string=""(空字符串) | 将 old_string 替换为空即可删除 |
注意事项
注意
- 匹配唯一性:
old_string必须在文件中能唯一标识要修改的位置。如果匹配到多处,工具会拒绝执行,防止误改。- 空白字符敏感:
old_string的匹配是精确的,包括空格和换行。如果文件中使用的是 Tab 缩进,而你的 old_string 用的是空格,匹配会失败。- 备份默认开启:
edit_file的backup默认为true,因为编辑操作通常比写入更危险——你可能只改了一行,却影响了整个文件的功能。
常见问题
Q: edit_file 匹配失败,但我确定文本是对的,怎么办?
A: 最常见的原因是不可见字符(如 BOM、不同换行符
\r\nvs\n、尾部空格)。解决方法:
- 先用
read_file精确读取目标区域- 直接复制工具返回的文本作为
old_string- 如果还是失败,检查是否有混合缩进(Tab + 空格)
Q: 如何一次性进行多处修改?
A:
edit_file一次调用只能修改一处。如果需要多处修改,可以:
- 连续调用多次
edit_file- 或者使用
write_file配合read_file先读取全部内容,在 Agent 内部修改后再写回
2.4 list_directory —— 列出目录内容
功能说明
list_directory 是 Agent 的「眼睛」——让它能看到某个目录下有什么文件和子目录。这是探索项目结构、查找文件、确认路径是否存在的必备工具。
参数详解
{
"directory_path": {
"type": "string",
"required": false,
"default": ".",
"description": "要列出的目录路径,默认为当前工作目录"
},
"recursive": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否递归列出子目录内容"
},
"show_hidden": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否显示隐藏文件(以 . 开头的文件)"
},
"filter": {
"type": "string",
"required": false,
"description": "文件过滤模式,如 *.py、*.md"
},
"sort_by": {
"type": "string",
"required": false,
"default": "name",
"description": "排序方式:name、size、mtime"
}
}使用示例
示例 1:列出当前目录
工具调用:
list_directory()
返回结果:
📁 src/
📁 tests/
📄 README.md
📄 package.json
📄 .gitignore
示例 2:递归列出项目结构
工具调用:
list_directory(directory_path=".", recursive=true)
返回结果:
.
├── src/
│ ├── main.py
│ ├── utils/
│ │ ├── helpers.py
│ │ └── constants.py
│ └── models/
│ └── user.py
├── tests/
│ └── test_main.py
├── README.md
└── requirements.txt
示例 3:筛选特定类型的文件
工具调用:
list_directory(directory_path="src", filter="*.py", recursive=true)
返回结果:
src/main.py
src/utils/helpers.py
src/utils/constants.py
src/models/user.py
Tips
当你刚接触一个新项目,不了解它的目录结构时,让 Agent 执行
list_directory(recursive=true)是最快的方式。Agent 可以基于目录结构判断项目类型(Python 项目、Node.js 项目、Go 项目等),并给出相应的操作建议。
常见场景
| 场景 | 参数 | 说明 |
|---|---|---|
| 探索新项目 | recursive=true | 快速了解项目全貌 |
| 查找配置文件 | filter="*.json", recursive=true | 定位所有 JSON 配置文件 |
| 查看隐藏文件 | show_hidden=true | 显示 .env、.gitignore 等 |
| 找最近修改的文件 | sort_by="mtime" | 按修改时间排序 |
注意事项
注意
- 递归深度限制:
recursive=true时,默认最大递归深度为 5 层。这是为了防止在包含大量子目录的项目(如node_modules)中卡死。- 权限过滤:没有读取权限的目录会被跳过,并在结果中标注
[权限不足]。- 符号链接:默认会跟随符号链接,但最多跟随 10 层,防止循环链接导致的无限递归。
2.5 search_files —— 搜索文件(grep 风格)
功能说明
search_files 是 Agent 的「搜索引擎」——在文件系统中搜索包含指定文本的文件。它类似于 Linux 的 grep 命令,但更加智能和易用。
这个工具支持正则表达式、多目录搜索、文件类型过滤等高级功能,是代码审查、日志分析、批量替换的利器。
参数详解
{
"pattern": {
"type": "string",
"required": true,
"description": "搜索模式,支持正则表达式"
},
"path": {
"type": "string",
"required": false,
"default": ".",
"description": "搜索的根目录"
},
"glob": {
"type": "string",
"required": false,
"description": "文件过滤模式,如 *.py、*.js、*.md"
},
"recursive": {
"type": "boolean",
"required": false,
"default": true,
"description": "是否递归搜索子目录"
},
"case_sensitive": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否区分大小写"
},
"max_results": {
"type": "integer",
"required": false,
"default": 50,
"description": "最多返回多少条结果"
},
"context_lines": {
"type": "integer",
"required": false,
"default": 2,
"description": "匹配行前后显示多少行上下文"
}
}使用示例
示例 1:搜索包含特定函数的代码
工具调用:
search_files(pattern="def calculate", glob="*.py")
返回结果:
src/math.py:42: def calculate_area(radius):
src/math.py:58: def calculate_volume(radius, height):
src/finance.py:15: def calculate_interest(principal, rate):
示例 2:使用正则表达式搜索
工具调用:
search_files(
pattern="class \w+View",
glob="*.py",
context_lines=3
)
返回结果:
src/views.py:10:
8: import json
9: from django.views import View
10: class UserView(View):
11: def get(self, request):
12: pass
示例 3:在日志中搜索错误
工具调用:
search_files(
pattern="ERROR|CRITICAL|FATAL",
path="logs",
glob="*.log",
max_results=20
)
返回结果:
logs/app.log:156: [ERROR] Connection timeout after 30s
logs/app.log:203: [CRITICAL] Database connection lost
logs/app.log:215: [ERROR] Failed to process request #12345
Tips
当你需要修改某个函数或变量时,先用
search_files找到它所有出现的位置,再决定用edit_file还是批量处理。这能有效避免「改了一处,漏了另一处」的问题。
搜索语法速查表
| 需求 | 模式示例 | 说明 |
|---|---|---|
| 精确匹配 | exact_word | 普通字符串匹配 |
| 忽略大小写 | 默认行为 | 不需要额外设置 |
| 正则匹配 | \d{4}-\d{2}-\d{2} | 匹配日期格式 YYYY-MM-DD |
| 匹配整词 | \bword\b | \b 表示单词边界 |
| 匹配行首 | ^import | ^ 表示行开头 |
| 匹配行尾 | \.py$ | $ 表示行结尾 |
| 或条件 | error|warn|fatal | | 表示「或」 |
| 排除文件 | 使用 glob 反向筛选 | 如 *.py 只搜 Python 文件 |
注意事项
注意
- 二进制文件跳过:
search_files会自动跳过二进制文件(图片、视频、压缩包等),避免无意义的匹配。- 大文件处理:超过 100MB 的文件会被标记为
[文件过大,仅搜索前 1000 行]。- 忽略目录:默认会跳过
.git、node_modules、__pycache__、vendor等常见依赖目录。如果需要搜索这些目录,可以显式指定path。
常见问题
Q: 搜索太慢怎么办?
A: 优化搜索速度的几种方法:
- 缩小
path范围,不要从根目录开始搜- 使用更精确的
glob过滤,如src/**/*.py- 减小
max_results,如果只需要前几个结果- 避免使用过于宽泛的正则,如
.*Q: 如何搜索不包含某文本的文件?
A:
search_files本身不支持反向搜索(搜索不包含某文本的文件)。 workaround:先搜索包含目标文本的文件,再用list_directory获取全部文件,两者做差集。或者使用execute_shell运行grep -v命令。
2.6 file_info —— 获取文件元信息
功能说明
file_info 用于获取文件的元数据(Metadata)——不是文件内容,而是关于文件的「信息的信息」。比如文件大小、创建时间、修改时间、权限、文件类型等。
这个工具在以下场景特别有用:
- 判断一个文件是不是二进制文件(决定用 read_file 还是其他方式处理)
- 检查文件最近是否被修改过(排查问题)
- 确认文件权限是否正确(排查访问错误)
- 获取文件哈希值(验证文件完整性)
参数详解
{
"file_path": {
"type": "string",
"required": true,
"description": "目标文件路径"
},
"compute_hash": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否计算文件的 MD5 和 SHA256 哈希值"
}
}使用示例
示例 1:查看文件基本信息
工具调用:
file_info(file_path="README.md")
返回结果:
{
"file_path": "README.md",
"exists": true,
"type": "file",
"size": 2458,
"size_human": "2.4 KB",
"created": "2024-01-10T08:30:00Z",
"modified": "2024-01-15T14:22:00Z",
"accessed": "2024-01-16T09:00:00Z",
"permissions": "644",
"owner": "jwangkun",
"group": "staff",
"is_binary": false,
"encoding": "utf-8",
"mime_type": "text/markdown"
}
示例 2:获取文件哈希值
工具调用:
file_info(file_path="installer.dmg", compute_hash=true)
返回结果:
{
"file_path": "installer.dmg",
"exists": true,
"type": "file",
"size": 52428800,
"size_human": "50.0 MB",
"md5": "5d41402abc4b2a76b9719d911017c592",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
Tips
当你怀疑两个文件是否相同时,不需要用
read_file逐字比较。使用file_info(compute_hash=true)比较它们的 SHA256 哈希值即可。如果哈希值相同,文件内容 100% 相同(忽略哈希碰撞这种极特殊情况)。
常见场景
| 场景 | 用法 | 说明 |
|---|---|---|
| 排查文件访问问题 | 检查 permissions 和 owner | 确认当前用户有读取权限 |
| 判断文件类型 | 查看 mime_type | 决定后续处理方式 |
| 检查文件新鲜度 | 对比 modified 时间 | 确认文件是否是最新版本 |
| 验证下载完整性 | compute_hash=true | 对比官方提供的哈希值 |
注意事项
注意
- 符号链接:如果目标文件是符号链接,
file_info默认返回链接目标的信息。如果你想获取链接本身的信息,目前需要配合execute_shell使用ls -la。- 不存在的文件:如果文件不存在,工具不会报错,而是返回
"exists": false。这在编写条件逻辑时很有用——你可以先检查文件是否存在,再决定是读取还是创建。
文件系统工具组合实战
下面是一个将多个文件系统工具组合使用的实战案例。
场景:你接手了一个遗留项目,需要快速了解它的代码结构,并找到所有使用 eval() 函数的地方(因为 eval() 有安全隐患)。
步骤 1:查看项目结构
→ list_directory(recursive=true)
步骤 2:找到所有 Python 文件
→ list_directory(filter="*.py", recursive=true)
步骤 3:搜索 eval() 的使用
→ search_files(pattern="eval\(", glob="*.py", context_lines=5)
步骤 4:读取某个可疑文件查看上下文
→ read_file(file_path="src/legacy_module.py", offset=40, limit=20)
步骤 5:修改问题代码
→ edit_file(
file_path="src/legacy_module.py",
old_string='result = eval(user_input)',
new_string='result = ast.literal_eval(user_input) # 更安全的替代方案'
)
Tips
文件系统工具的调用链通常遵循「探索 → 定位 → 读取 → 修改」的模式。先用
list_directory和search_files探索,用read_file确认细节,最后用edit_file或write_file执行修改。不要跳过「探索」和「确认」步骤直接修改——这就像不看路就开车,很容易出问题。
本章小结
本章我们详细讲解了 6 个文件系统工具:
read_file:读取文件内容,支持分段读取和编码自动检测write_file:创建或覆盖文件,支持追加模式和自动备份edit_file:精确替换文件中的特定文本片段,默认自动备份list_directory:列出目录内容,支持递归和过滤search_files:grep 风格的文件搜索,支持正则和上下文显示file_info:获取文件元数据,包括大小、时间、权限、哈希值
核心原则:
- 先读再写:修改文件前先
read_file确认内容 - 搜索定位:用
search_files找到精确位置,再用edit_file修改 - 备份保护:重要文件操作开启
backup=true - 分段读取:大文件使用
offset和limit,避免上下文溢出
3. 第二类:代码执行工具 —— Agent 的「编译器」和「解释器」
本章你将学到
- 4 个代码执行工具的功能和安全边界
- 沙箱环境的限制和逃逸防护
- 危险命令的分级处理机制
- 如何在安全的前提下最大化代码执行工具的价值
- 代码执行失败的排查和调试技巧
代码执行工具是 Hermes 最强大的工具类别之一,也是最需要谨慎使用的类别。它们让 Agent 能够运行 Python、JavaScript、Shell 脚本,执行数据分析、自动化测试、系统管理等任务。但强大的能力伴随着风险——恶意或错误的代码可能破坏数据、泄露隐私、甚至损害系统。
3.1 execute_python —— 执行 Python 代码
功能说明
execute_python 让 Agent 能够运行任意 Python 代码。这是数据分析、自动化脚本、快速原型验证的终极武器。
Hermes 的 Python 执行环境具有以下特点:
- 隔离的虚拟环境:每个执行请求在独立的 Python 进程中运行
- 超时保护:默认 30 秒超时,防止死循环
- 内存限制:默认限制 512MB 内存使用
- 网络访问控制:可选启用或禁用网络访问
- 文件系统沙箱:默认只能访问当前工作目录
参数详解
{
"code": {
"type": "string",
"required": true,
"description": "要执行的 Python 代码"
},
"timeout": {
"type": "integer",
"required": false,
"default": 30,
"description": "执行超时时间(秒)"
},
"memory_limit": {
"type": "integer",
"required": false,
"default": 512,
"description": "内存限制(MB)"
},
"network": {
"type": "boolean",
"required": false,
"default": true,
"description": "是否允许网络访问"
},
"working_dir": {
"type": "string",
"required": false,
"default": ".",
"description": "工作目录,代码只能访问此目录下的文件"
},
"packages": {
"type": "array",
"required": false,
"description": "需要临时安装的 Python 包列表"
}
}使用示例
示例 1:简单的数学计算
工具调用:
execute_python(
code="""
import math
# 计算复利
principal = 10000
rate = 0.05
years = 10
amount = principal * (1 + rate) ** years
print(f"本金: {principal}")
print(f"年利率: {rate*100}%")
print(f"年限: {years}")
print(f"最终金额: {amount:.2f}")
print(f"利息收入: {amount - principal:.2f}")
"""
)
返回结果:
本金: 10000
年利率: 5.0%
年限: 10
最终金额: 16288.95
利息收入: 6288.95
示例 2:数据分析(需要 pandas)
工具调用:
execute_python(
code="""
import pandas as pd
# 读取 CSV 文件
df = pd.read_csv('sales_data.csv')
# 基本统计
print("数据概览:")
print(df.describe())
print("\n按月份汇总销售额:")
monthly = df.groupby('month')['amount'].sum()
print(monthly)
""",
packages=["pandas"]
)
Tips
如果你不确定某个包是否已安装,可以在
packages中列出它。Hermes 会检查环境,如果包不存在会自动安装。但注意,自动安装需要联网,且会增加首次执行的等待时间。
示例 3:生成数据可视化图表
工具调用:
execute_python(
code="""
import matplotlib.pyplot as plt
import numpy as np
# 生成示例数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
# 绘制图表
plt.figure(figsize=(10, 6))
plt.plot(x, y1, label='sin(x)', linewidth=2)
plt.plot(x, y2, label='cos(x)', linewidth=2)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Trigonometric Functions')
plt.legend()
plt.grid(True, alpha=0.3)
# 保存图表
plt.savefig('trig_plot.png', dpi=150, bbox_inches='tight')
print("图表已保存到 trig_plot.png")
""",
packages=["matplotlib", "numpy"]
)
常见场景
| 场景 | 需要的包 | 说明 |
|---|---|---|
| 数据处理 | pandas, numpy | CSV/Excel 数据清洗和分析 |
| 数据可视化 | matplotlib, seaborn | 生成统计图表 |
| 文本处理 | re, json, csv | 正则匹配、JSON 解析 |
| 网络请求 | requests | 调用 API 获取数据 |
| 文件操作 | os, shutil, pathlib | 批量文件处理 |
| 科学计算 | scipy, numpy | 数值计算和算法 |
注意事项
注意
- 不要假设包已安装:Hermes 的基础 Python 环境只包含标准库。使用第三方库时,务必在
packages中声明。如果执行时 import 失败,工具会给出清晰的错误提示。- 输出长度限制:
print()的输出如果超过 10,000 字符,会被截断。对于大量数据,建议保存到文件,再用read_file读取。- 状态不持久:每次
execute_python调用都是独立的进程。你在上一次调用中定义的变量,下一次调用时就不存在了。如果需要跨调用保留数据,请写入文件。
常见问题
Q: 执行时报 ModuleNotFoundError,但包明明安装了?
A: 每次
execute_python都在新进程中运行。如果上次执行时通过pip install安装了包,下次执行时可能需要重新指定packages参数,或者确保包安装在 Hermes 使用的 Python 环境中。建议始终通过packages参数声明依赖。Q: 如何读取代码执行的结果?
A:
execute_python会把stdout(标准输出)和stderr(标准错误)都返回给 Agent。所以用print()输出结果即可。如果需要返回结构化数据,可以print(json.dumps(result))。
3.2 execute_shell —— 执行 Shell 命令
功能说明
execute_shell 让 Agent 能够运行系统 Shell 命令(bash/zsh)。这是最高风险的工具之一,因为它可以直接操作系统——创建、修改、删除文件,安装软件,甚至执行任意系统命令。
正因为风险高,execute_shell 被归类为高风险操作,每次调用都需要用户审批,且无法配置为自动允许。
参数详解
{
"command": {
"type": "string",
"required": true,
"description": "要执行的 Shell 命令"
},
"timeout": {
"type": "integer",
"required": false,
"default": 30,
"description": "执行超时时间(秒)"
},
"working_dir": {
"type": "string",
"required": false,
"default": ".",
"description": "命令执行的工作目录"
},
"env": {
"type": "object",
"required": false,
"description": "额外的环境变量(会合并到当前环境)"
}
}使用示例
示例 1:查看当前目录的 Git 状态
工具调用:
execute_shell(command="git status")
返回结果:
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit
示例 2:统计代码行数
工具调用:
execute_shell(command="find src -name '*.py' | xargs wc -l")
返回结果:
156 src/main.py
243 src/utils.py
89 src/models.py
488 total
示例 3:带环境变量的命令
工具调用:
execute_shell(
command="python -c 'import os; print(os.getenv(\"API_KEY\"))'",
env={"API_KEY": "sk-1234567890abcdef"}
)
返回结果:
sk-1234567890abcdef
Tips
对于复杂的 Shell 操作,建议先在终端手动测试命令,确认无误后再让 Agent 执行。尤其是涉及文件删除、系统修改的命令,一定要三思。
安全机制详解
execute_shell 有多层安全防护:
| 安全层 | 机制 | 说明 |
| -------- | -------------- | ---------------------------- | -------------------------- |
| 审批层 | 强制人工确认 | 每次调用都必须用户确认 |
| 黑名单层 | 命令关键字过滤 | 包含 rm -rf /、:(){ : | :& };: 等危险命令直接拒绝 |
| 沙箱层 | 文件系统隔离 | 默认只能在当前工作目录操作 |
| 超时层 | 执行时间限制 | 默认 30 秒超时,防止资源耗尽 |
| 审计层 | 操作日志记录 | 所有命令和输出都会被记录 |
绝对禁止执行的命令示例:
rm -rf / # 删除整个文件系统
rm -rf ~ # 删除用户主目录
mkfs.ext4 /dev/sda # 格式化硬盘
:(){ :|:& };: # Fork 炸弹(耗尽进程数)
dd if=/dev/zero of=/dev/sda # 清零硬盘注意
即使命令本身看起来无害,组合起来也可能危险。比如
rm -rf /tmp/app是正常的清理操作,但如果working_dir被恶意篡改,实际执行的可能是rm -rf /(利用变量注入)。因此 Hermes 会对命令进行静态分析,检测潜在的危险模式。
常见场景
| 场景 | 命令示例 | 替代方案 |
|---|---|---|
| Git 操作 | git log --oneline -10 | 可使用 run_command(审批更轻量) |
| 包管理 | npm install lodash | 可用,但注意依赖安全 |
| 查看进程 | ps aux | grep python | 建议使用 process_list 工具 |
| 压缩文件 | tar -czf backup.tar.gz src/ | 可用,建议设置 backup 前缀 |
| 系统信息 | uname -a | 建议使用 system_info 工具 |
常见问题
Q: 为什么某些合法命令也被拒绝了?
A: Hermes 的安全过滤器采用「宁可错杀,不可放过」的策略。如果命令包含危险关键字(如
mkfs、dd if=/dev),即使上下文是安全的,也会被拒绝。遇到这种情况,可以:
- 尝试用更安全的替代命令
- 或者手动在终端执行,然后把结果告诉 Agent
Q: 如何执行管道命令(如
cat file \| grep pattern)?A: 直接在
command中写完整的管道命令即可。Hermes 的 Shell 执行器支持管道、重定向、命令组合等标准 Shell 语法。
3.3 execute_javascript —— 执行 JavaScript
功能说明
execute_javascript 让 Agent 能够在 Node.js 环境中运行 JavaScript/TypeScript 代码。这对于前端项目分析、JSON 处理、npm 包操作等场景非常有用。
参数详解
{
"code": {
"type": "string",
"required": true,
"description": "要执行的 JavaScript/TypeScript 代码"
},
"timeout": {
"type": "integer",
"required": false,
"default": 30,
"description": "执行超时时间(秒)"
},
"packages": {
"type": "array",
"required": false,
"description": "需要临时安装的 npm 包列表"
},
"working_dir": {
"type": "string",
"required": false,
"default": ".",
"description": "工作目录"
}
}使用示例
示例 1:处理 JSON 数据
工具调用:
execute_javascript(
code="""
const data = {
users: [
{ name: 'Alice', age: 30, city: 'Beijing' },
{ name: 'Bob', age: 25, city: 'Shanghai' },
{ name: 'Charlie', age: 35, city: 'Beijing' }
]
};
// 按城市分组
const grouped = data.users.reduce((acc, user) => {
acc[user.city] = acc[user.city] || [];
acc[user.city].push(user);
return acc;
}, {});
console.log(JSON.stringify(grouped, null, 2));
"""
)
返回结果:
{
"Beijing": [
{ "name": "Alice", "age": 30, "city": "Beijing" },
{ "name": "Charlie", "age": 35, "city": "Beijing" }
],
"Shanghai": [
{ "name": "Bob", "age": 25, "city": "Shanghai" }
]
}
示例 2:分析 package.json 依赖
工具调用:
execute_javascript(
code="""
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
const sorted = Object.entries(deps).sort((a, b) => a[0].localeCompare(b[0]));
console.log(`共 ${sorted.length} 个依赖:`);
sorted.forEach(([name, version]) => {
console.log(` ${name}: ${version}`);
});
"""
)
Tips
execute_javascript与execute_python的选择原则:如果项目主要是 Node.js 生态(前端、npm 包),用 JavaScript 更自然;如果是数据科学、后端脚本,用 Python 更合适。对于纯 JSON 处理,两者都可以。
注意事项
注意
- Node.js 版本:Hermes 使用系统默认的 Node.js 版本。如果你需要特定版本,可以在
~/.hermes/config.yaml中配置tools.javascript.node_path。- TypeScript 支持:如果代码以
.ts语法编写(包含类型注解),Hermes 会自动调用ts-node或tsx执行。确保这些工具已全局安装。
3.4 sandbox_run —— 沙箱环境执行
功能说明
sandbox_run 是 Hermes 最安全的代码执行工具。它在完全隔离的容器化沙箱中运行代码,与宿主机系统完全隔离。
沙箱环境的特点:
- 文件系统隔离:沙箱内看不到宿主机的文件(除非显式挂载)
- 网络隔离:默认无网络访问
- 资源限制:CPU、内存、磁盘都有严格配额
- 临时性:沙箱执行完毕后自动销毁,不留痕迹
这个工具非常适合运行不可信代码——比如从互联网下载的脚本、AI 生成的未经审核的代码、第三方提供的示例代码。
参数详解
{
"code": {
"type": "string",
"required": true,
"description": "要执行的代码(Python 或 JavaScript)"
},
"language": {
"type": "string",
"required": false,
"default": "python",
"description": "代码语言:python、javascript"
},
"mounts": {
"type": "array",
"required": false,
"description": "挂载到沙箱的宿主机目录列表"
},
"timeout": {
"type": "integer",
"required": false,
"default": 60,
"description": "执行超时时间(秒)"
},
"memory_limit": {
"type": "integer",
"required": false,
"default": 256,
"description": "内存限制(MB)"
},
"cpu_limit": {
"type": "integer",
"required": false,
"default": 1,
"description": "CPU 核心数限制"
}
}使用示例
示例 1:运行不可信的 Python 脚本
工具调用:
sandbox_run(
language="python",
code="""
# 这段代码来自互联网,不确定是否安全
# 在沙箱中运行,即使有问题也不会影响主机
import os
print("当前目录:", os.getcwd())
print("文件列表:", os.listdir('.'))
# 尝试访问根目录(沙箱内被限制)
try:
print("根目录:", os.listdir('/'))
except PermissionError as e:
print("权限不足(这是预期的):", e)
""",
mounts=["/tmp/shared_data:/data:ro"] # 只读挂载
)
示例 2:安全的代码评测
工具调用:
sandbox_run(
language="python",
code="""
# 评测用户提交的算法代码
# 提供测试用例,在沙箱中运行
def solution(n):
# 用户提交的代码
return n * n
# 测试用例
test_cases = [(2, 4), (3, 9), (10, 100), (0, 0)]
for input_val, expected in test_cases:
result = solution(input_val)
status = "✓" if result == expected else "✗"
print(f"{status} solution({input_val}) = {result} (期望: {expected})")
""",
timeout=10,
memory_limit=128
)
Tips
当你让 Agent 从网上搜索代码示例并运行时,建议优先使用
sandbox_run而不是execute_python。这样即使代码包含恶意操作(如删除文件、发送网络请求),也会被沙箱隔离,不会危害你的系统。
沙箱限制说明
| 资源 | 默认限制 | 可调范围 | 说明 |
|---|---|---|---|
| 内存 | 256 MB | 64-2048 MB | 超过会被 OOM Kill |
| CPU | 1 核 | 1-4 核 | 限制 CPU 使用率 |
| 磁盘 | 100 MB | 10-1000 MB | 沙箱内可写空间 |
| 网络 | 禁用 | 可开启 | 默认完全隔离 |
| 执行时间 | 60 秒 | 10-300 秒 | 超时强制终止 |
注意
- 沙箱需要 Docker:
sandbox_run依赖 Docker 容器技术。如果你的系统没有安装 Docker,这个工具会报错。在 macOS 和 Linux 上,Docker Desktop 或 Docker Engine 都可以。- 首次启动较慢:创建沙箱容器需要几秒钟。如果需要频繁执行,可以考虑批量提交多个任务。
- 文件持久化:沙箱执行结束后,容器被销毁,内部文件也一并消失。如果需要保留输出,请确保代码将结果写入挂载的宿主机目录。
本章小结
本章我们深入讲解了 4 个代码执行工具:
execute_python:执行 Python 代码,适合数据分析、自动化脚本execute_shell:执行 Shell 命令,功能最强但风险最高,强制审批execute_javascript:执行 JavaScript/TypeScript,适合前端和 Node.js 项目sandbox_run:在隔离沙箱中执行代码,运行不可信代码的首选
安全使用原则:
- 默认用沙箱:不确定安全性的代码,先用
sandbox_run - 最小权限:只给代码执行所需的最小权限(网络、文件访问)
- 超时保护:对于可能死循环的代码,设置合理的
timeout - 审计日志:所有代码执行都有日志记录,定期审查
4. 第三类:Web 交互工具 —— Agent 的「浏览器」和「网络接口」
本章你将学到
- 8 个 Web 交互工具的功能边界和使用场景
- web_search 的高级搜索语法和结果过滤技巧
- web_browse 的浏览器自动化原理和操作示例
- HTTP 请求工具的各种认证方式和错误处理
- RSS 订阅获取和网页变化监控的实战配置
Web 交互工具让 Agent 能够连接到互联网——搜索信息、浏览网页、调用 API、监控变化。这是 Agent 从「本地助手」升级为「联网助手」的关键能力。
4.1 web_search —— 网络搜索
功能说明
web_search 是 Agent 获取实时信息的主要渠道。与 LLM 的「静态知识」不同,web_search 能够获取最新的、动态的、实时的信息——今天的新闻、最新的技术文档、当前的股价。
Hermes 的 web_search 支持多个搜索引擎后端:
- DuckDuckGo:默认后端,无需 API Key,隐私友好
- Google Custom Search:需要 API Key,结果更精准
- Bing Search:需要 API Key,中文搜索效果好
- SearXNG:自建搜索引擎,完全开源可控
参数详解
{
"query": {
"type": "string",
"required": true,
"description": "搜索查询词"
},
"engine": {
"type": "string",
"required": false,
"default": "duckduckgo",
"description": "搜索引擎:duckduckgo、google、bing、searxng"
},
"num_results": {
"type": "integer",
"required": false,
"default": 10,
"description": "返回结果数量(1-50)"
},
"time_range": {
"type": "string",
"required": false,
"description": "时间范围:day、week、month、year"
},
"site": {
"type": "string",
"required": false,
"description": "限制搜索特定网站,如 site:github.com"
},
"safe_search": {
"type": "boolean",
"required": false,
"default": true,
"description": "是否开启安全搜索"
}
}使用示例
示例 1:基础搜索
工具调用:
web_search(query="Hermes Agent AI framework 2024")
返回结果:
[
{
"title": "Hermes - An open-source AI agent framework",
"url": "https://github.com/NousResearch/hermes",
"snippet": "Hermes is an open-source AI agent framework developed by Nous Research..."
},
{
"title": "Getting Started with Hermes Agent",
"url": "https://docs.hermes.ai/quickstart",
"snippet": "Learn how to install and configure Hermes Agent in 5 minutes..."
}
]
示例 2:限定时间范围的搜索
工具调用:
web_search(
query="OpenAI GPT-5 release",
time_range="week",
num_results=5
)
示例 3:限定特定网站搜索
工具调用:
web_search(
query="machine learning tutorial",
site="arxiv.org",
num_results=10
)
Tips
搜索查询的质量直接影响结果质量。几个提升搜索效果的小技巧:
- 用英文搜索:技术类内容英文搜索结果通常更好
- 加关键词限定:如
Python asyncio best practices 2024比Python async更精准- 用 site: 限定来源:
error solution site:stackoverflow.com- 用引号精确匹配:
"Hermes Agent" framework
搜索语法速查表
| 技巧 | 语法 | 示例 |
|---|---|---|
| 精确短语 | "exact phrase" | "machine learning" |
| 排除关键词 | -keyword | Python -snake |
| 限定网站 | site:domain | site:github.com |
| 文件类型 | filetype:ext | filetype:pdf |
| 时间范围 | after:YYYY-MM-DD | after:2024-01-01 |
| OR 条件 | A OR B | React OR Vue |
| 通配符 | * | best * framework |
注意事项
注意
- 结果不保证实时:搜索引擎的索引有延迟,最新发布的内容可能需要几小时甚至几天才能被收录。
- API 配额:如果使用 Google 或 Bing 后端,注意 API 调用配额。DuckDuckGo 没有硬配额限制,但频繁请求可能触发反爬虫。
- 结果去重:Hermes 会自动对搜索结果进行去重和排序,优先返回权威来源(如官方文档、知名技术博客)。
常见问题
Q: 搜索返回空结果怎么办?
A: 尝试以下方法:
- 简化查询词,去掉过于具体的关键词
- 换用不同的搜索引擎(如从 DuckDuckGo 换到 Bing)
- 检查网络连接,确认能正常访问搜索引擎
- 如果是中文搜索,尝试用英文关键词
Q: 如何搜索学术论文?
A: 推荐使用
site:arxiv.org或site:scholar.google.com限定学术来源。或者使用专门的search_paper技能(如果已安装)。
4.2 web_extract —— 提取网页内容
功能说明
web_extract 用于从指定的 URL 提取网页的主要内容。与直接获取原始 HTML 不同,它会智能地去除广告、导航栏、页脚等噪音,只保留文章正文。
这个工具基于 Readability 算法和 AI 内容识别技术,能够从各种网页布局中准确提取核心内容。
参数详解
{
"url": {
"type": "string",
"required": true,
"description": "目标网页 URL"
},
"format": {
"type": "string",
"required": false,
"default": "markdown",
"description": "输出格式:markdown、text、html"
},
"max_length": {
"type": "integer",
"required": false,
"default": 10000,
"description": "最大提取字符数"
},
"include_images": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否保留图片链接"
},
"timeout": {
"type": "integer",
"required": false,
"default": 30,
"description": "请求超时时间(秒)"
}
}使用示例
示例 1:提取技术博客文章
工具调用:
web_extract(
url="https://blog.example.com/intro-to-async-python",
format="markdown",
max_length=5000
)
返回结果:
# Introduction to Async Python
## What is Async?
Asyncio is a library to write concurrent code using...
(提取的文章正文,已去除导航栏、广告、评论区等噪音)
示例 2:提取并保存为文本
工具调用:
web_extract(
url="https://docs.python.org/3/library/asyncio.html",
format="text",
max_length=8000
)
Tips
web_extract+write_file是制作「离线资料包」的经典组合。让 Agent 搜索一系列教程链接,逐个提取内容,然后合并保存为一个 Markdown 文件,你就得到了一份完整的离线学习资料。
注意事项
注意
- 动态内容限制:如果网页内容是通过 JavaScript 动态加载的(如 React/Vue 单页应用),
web_extract可能只能获取到初始 HTML 骨架,看不到动态内容。这种情况下需要使用web_browse工具。- 反爬虫机制:某些网站会检测并阻止自动化访问。如果遇到 403 或验证码,可以尝试:
- 使用
web_browse工具(它使用真实浏览器)- 检查网站的 robots.txt 是否允许爬取
- 减少请求频率
4.3 web_browse —— 浏览器控制
功能说明
web_browse 是 Hermes 最强大的网页交互工具。它控制一个真实的无头浏览器(Headless Browser,基于 Playwright),能够:
- 加载完整的网页(包括 JavaScript 动态内容)
- 模拟点击、滚动、填写表单等用户操作
- 截取网页截图
- 等待特定元素出现
- 在多个页面之间导航
这个工具是 web_extract 的「重武器版」——当简单的 HTTP 请求搞不定时,就派它上场。
参数详解
{
"url": {
"type": "string",
"required": true,
"description": "要访问的 URL"
},
"action": {
"type": "string",
"required": false,
"default": "navigate",
"description": "操作类型:navigate、click、type、scroll、wait、screenshot"
},
"selector": {
"type": "string",
"required": false,
"description": "CSS 选择器,用于定位元素(click、type 等操作需要)"
},
"text": {
"type": "string",
"required": false,
"description": "要输入的文本(type 操作需要)"
},
"wait_for": {
"type": "string",
"required": false,
"description": "等待某个选择器出现(如 .content-loaded)"
},
"viewport": {
"type": "object",
"required": false,
"description": "视口大小 {width, height}"
},
"user_agent": {
"type": "string",
"required": false,
"description": "自定义 User-Agent"
}
}使用示例
示例 1:访问动态加载的网页
工具调用:
web_browse(
url="https://spa-app.example.com/dashboard",
wait_for=".dashboard-content"
)
返回结果:
页面标题: Dashboard - SPA App
页面内容: (渲染后的完整 HTML,包含 JavaScript 动态生成的内容)
示例 2:模拟表单填写和提交
工具调用:
# 第一步:打开登录页
web_browse(url="https://app.example.com/login")
# 第二步:填写用户名
web_browse(
action="type",
selector="input[name='username']",
text="my_username"
)
# 第三步:填写密码
web_browse(
action="type",
selector="input[name='password']",
text="my_password"
)
# 第四步:点击登录按钮
web_browse(
action="click",
selector="button[type='submit']"
)
# 第五步:等待页面加载
web_browse(
action="wait",
wait_for=".welcome-message"
)
Tips
web_browse的浏览器实例在多次调用之间是保持状态的(Cookie、LocalStorage、SessionStorage 都会保留)。这意味着你可以先登录一个网站,然后在后续调用中访问需要登录才能看到的页面。但要注意,如果长时间没有操作,浏览器实例可能会被回收。
操作类型详解
| action | 作用 | 需要 selector | 需要 text |
|---|---|---|---|
| navigate | 打开/刷新页面 | 否 | 否 |
| click | 点击元素 | 是 | 否 |
| type | 在输入框中输入文本 | 是 | 是 |
| scroll | 滚动页面 | 否 | 否 |
| wait | 等待条件满足 | 可选 | 否 |
| screenshot | 截取页面截图 | 可选 | 否 |
| evaluate | 执行 JavaScript | 否 | 是(JS 代码) |
注意事项
注意
- 资源消耗:无头浏览器比普通 HTTP 请求消耗更多内存和 CPU。不要同时打开太多浏览器实例。
- 超时设置:某些网页加载很慢(特别是有大量 JavaScript 的页面)。如果
wait_for的元素一直没出现,工具会超时。可以适当增加timeout参数。- 人机验证:对于需要 CAPTCHA、短信验证的网站,无头浏览器通常无法通过验证。这种情况下需要人工介入。
4.4 web_screenshot —— 网页截图
功能说明
web_screenshot 专门用于截取网页的屏幕截图。虽然 web_browse 也能截图,但 web_screenshot 更加轻量和专注——它不需要维护浏览器会话,截图完就释放资源。
参数详解
{
"url": {
"type": "string",
"required": true,
"description": "要截图的网页 URL"
},
"viewport": {
"type": "object",
"required": false,
"default": { "width": 1280, "height": 720 },
"description": "视口大小"
},
"full_page": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否截取整个页面(而不仅是视口)"
},
"selector": {
"type": "string",
"required": false,
"description": "只截取某个元素的区域"
},
"output_path": {
"type": "string",
"required": false,
"description": "截图保存路径(默认返回 base64)"
},
"format": {
"type": "string",
"required": false,
"default": "png",
"description": "图片格式:png、jpeg、webp"
}
}使用示例
示例 1:截取网页全屏
工具调用:
web_screenshot(
url="https://hermes.ai",
full_page=true,
output_path="screenshots/hermes_homepage.png"
)
返回结果:
截图已保存到 screenshots/hermes_homepage.png
文件大小: 1.2 MB
分辨率: 1280x4520
示例 2:截取特定元素
工具调用:
web_screenshot(
url="https://dashboard.example.com",
selector=".chart-container",
output_path="screenshots/chart.png"
)
Tips
web_screenshot返回的截图可以被image_analyze工具分析。这意味着你可以让 Agent「看图说话」——截图一个网页,然后分析它的 UI 设计、数据图表、错误提示等。
4.5 http_request —— HTTP 请求
功能说明
http_request 是一个通用的 HTTP 客户端工具,支持 GET、POST、PUT、DELETE 等所有标准 HTTP 方法。它是调用 REST API、Webhook、微服务的首选工具。
参数详解
{
"url": {
"type": "string",
"required": true,
"description": "请求 URL"
},
"method": {
"type": "string",
"required": false,
"default": "GET",
"description": "HTTP 方法:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS"
},
"headers": {
"type": "object",
"required": false,
"description": "请求头"
},
"body": {
"type": "string",
"required": false,
"description": "请求体(字符串或 JSON 序列化后的字符串)"
},
"params": {
"type": "object",
"required": false,
"description": "URL 查询参数"
},
"timeout": {
"type": "integer",
"required": false,
"default": 30,
"description": "超时时间(秒)"
},
"follow_redirects": {
"type": "boolean",
"required": false,
"default": true,
"description": "是否跟随重定向"
}
}使用示例
示例 1:GET 请求获取 JSON 数据
工具调用:
http_request(
url="https://api.github.com/repos/NousResearch/hermes",
headers={"Accept": "application/vnd.github.v3+json"}
)
返回结果:
{
"status": 200,
"headers": { ... },
"body": {
"name": "hermes",
"full_name": "NousResearch/hermes",
"stargazers_count": 5234,
"forks_count": 891,
"open_issues_count": 45
}
}
示例 2:POST 请求提交数据
工具调用:
http_request(
url="https://api.example.com/users",
method="POST",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer sk-123456"
},
body='{"name":"Alice","email":"[email protected]"}'
)
示例 3:带查询参数的搜索请求
工具调用:
http_request(
url="https://api.example.com/search",
params={
"q": "machine learning",
"page": 1,
"limit": 20
}
)
Tips
调用 API 时,建议先用
read_file读取 API 文档(如果有本地文档),或者先用web_search搜索 API 使用说明。错误的请求参数是 API 调用失败的最常见原因。
认证方式示例
| 认证类型 | headers 配置 |
|---|---|
| Bearer Token | {"Authorization": "Bearer YOUR_TOKEN"} |
| Basic Auth | {"Authorization": "Basic base64(user:pass)"} |
| API Key (Header) | {"X-API-Key": "your_key"} |
| API Key (Query) | params={"api_key": "your_key"} |
注意事项
注意
- 敏感信息:不要在
body或headers中硬编码 API Key。建议存储在环境变量中,通过env参数注入。- 响应大小限制:如果响应体超过 1MB,会被截断。对于大文件下载,建议使用
execute_shell配合curl或wget。- SSL 验证:默认开启 SSL 证书验证。如果访问自签名证书的服务器,需要在
~/.hermes/config.yaml中配置tools.http_request.verify_ssl: false。
4.6 rss_fetch —— RSS 订阅获取
功能说明
rss_fetch 用于获取 RSS/Atom 订阅源的内容。这是跟踪博客更新、新闻动态、软件发布的高效方式——不需要手动打开浏览器,Agent 会帮你聚合所有订阅源的更新。
参数详解
{
"url": {
"type": "string",
"required": true,
"description": "RSS/Atom 订阅源 URL"
},
"limit": {
"type": "integer",
"required": false,
"default": 20,
"description": "最多返回多少条条目"
},
"since": {
"type": "string",
"required": false,
"description": "只返回某个时间之后的条目(ISO 8601 格式)"
},
"include_content": {
"type": "boolean",
"required": false,
"default": true,
"description": "是否包含条目的完整内容"
}
}使用示例
示例 1:获取技术博客 RSS
工具调用:
rss_fetch(
url="https://blog.example.com/feed.xml",
limit=5
)
返回结果:
[
{
"title": "Introducing Hermes 2.0",
"link": "https://blog.example.com/hermes-2-0",
"published": "2024-01-10T08:00:00Z",
"author": "Alice Chen",
"summary": "We are excited to announce Hermes 2.0 with...",
"content": "完整文章内容..."
}
]
Tips
rss_fetch+memory_write是构建「个人资讯简报」的经典组合。让 Agent 每天早上拉取你关注的 RSS 源,提取重要信息,写入记忆系统。当你问「最近有什么新闻」时,Agent 就能基于记忆给出个性化回答。
4.7 api_call —— 通用 API 调用
功能说明
api_call 是一个更高级的 API 调用工具,内置了对多种流行 API 的适配器。与 http_request 的「裸 HTTP」不同,api_call 提供了更友好的接口,自动处理认证、分页、错误重试等常见问题。
内置适配器
| 服务 | 适配器名称 | 说明 |
|---|---|---|
| OpenAI | openai | GPT 模型调用 |
| Anthropic | anthropic | Claude 模型调用 |
| GitHub | github | 仓库、Issue、PR 操作 |
| Slack | slack | 消息发送 |
| Discord | discord | Webhook 消息 |
| Notion | notion | 页面、数据库操作 |
| Twitter/X | twitter | 推文操作(需 API Key) |
参数详解
{
"provider": {
"type": "string",
"required": true,
"description": "API 提供商名称"
},
"action": {
"type": "string",
"required": true,
"description": "操作名称,如 send_message、create_issue"
},
"params": {
"type": "object",
"required": false,
"description": "操作参数"
},
"credentials": {
"type": "object",
"required": false,
"description": "认证信息(优先使用配置文件中的凭证)"
}
}使用示例
示例 1:发送 Slack 消息
工具调用:
api_call(
provider="slack",
action="send_message",
params={
"channel": "#alerts",
"text": "部署完成!版本 v1.2.3 已成功上线。"
}
)
示例 2:创建 GitHub Issue
工具调用:
api_call(
provider="github",
action="create_issue",
params={
"owner": "NousResearch",
"repo": "hermes",
"title": "Bug: Memory leak in long-running sessions",
"body": "描述...",
"labels": ["bug", "memory"]
}
)
Tips
api_call的凭证通常在~/.hermes/credentials.yaml中配置,而不是每次调用都传入。配置格式如下:credentials: slack: token: "xoxb-your-bot-token" github: token: "ghp-your-personal-access-token" notion: token: "secret_..."
4.8 web_monitor —— 网页变化监控
功能说明
web_monitor 用于监控网页内容的变化。当指定网页的内容发生变化时,Agent 可以收到通知并执行预设的操作。
这是自动化监控的利器——监控竞争对手的价格页面、监控招聘网站的职位更新、监控文档站的 API 变更等。
参数详解
{
"url": {
"type": "string",
"required": true,
"description": "要监控的网页 URL"
},
"selector": {
"type": "string",
"required": false,
"description": "只监控某个 CSS 选择器选中的区域(而不是整个页面)"
},
"interval": {
"type": "integer",
"required": false,
"default": 3600,
"description": "检查间隔(秒),默认 1 小时"
},
"action": {
"type": "string",
"required": false,
"description": "变化时执行的操作:notify、webhook、script"
},
"name": {
"type": "string",
"required": false,
"description": "监控任务的名称"
}
}使用示例
示例 1:监控文档站的变化
工具调用:
web_monitor(
url="https://docs.hermes.ai/changelog",
selector=".changelog-content",
interval=7200,
name="Hermes Changelog Monitor",
action="notify"
)
示例 2:监控价格页面
工具调用:
web_monitor(
url="https://shop.example.com/product/123",
selector=".price",
interval=3600,
name="Price Monitor - Product 123",
action="webhook"
)
注意事项
注意
- 监控任务持久化:
web_monitor创建的任务会在 Hermes 后台持续运行,即使 Agent 会话结束也不会停止。需要在~/.hermes/monitors/目录下查看和管理所有监控任务。- 频率限制:不要设置过短的检查间隔(如几秒),这会对目标网站造成压力,也可能触发反爬虫机制。建议至少 5 分钟以上的间隔。
- 变化检测算法:默认使用文本相似度算法检测变化。对于动态内容(如时间戳、广告轮播),建议使用
selector限定只监控核心内容区域。
本章小结
本章我们详细讲解了 8 个 Web 交互工具:
web_search:网络搜索,Agent 获取实时信息的主要渠道web_extract:提取网页正文,去除噪音保留核心内容web_browse:控制无头浏览器,处理 JavaScript 动态内容web_screenshot:截取网页截图,支持全屏和元素截图http_request:通用 HTTP 客户端,调用 REST APIrss_fetch:获取 RSS/Atom 订阅源内容api_call:高级 API 调用,内置多种服务适配器web_monitor:监控网页变化,自动化跟踪内容更新
使用建议:
- 信息获取链:
web_search→web_extract→write_file是最常见的信息收集工作流 - API 调用优先用适配器:如果
api_call支持你的目标服务,优先使用它而不是裸http_request - 截图+分析组合:
web_screenshot+image_analyze可以实现「看图说话」 - 监控任务管理:定期检查
~/.hermes/monitors/,清理不再需要的监控任务
5. 第四类:终端命令工具 —— Agent 的「系统管理员」套装
本章你将学到
- 5 个终端命令工具的功能和使用场景
- 危险命令的分级处理机制,理解为什么有些命令需要反复确认
- 后台任务管理和进程控制的完整工作流
- 如何安全地使用系统命令而不破坏环境
run_command与execute_shell的区别和选择策略
终端命令工具让 Agent 能够与你的操作系统直接交互——运行程序、管理进程、获取系统信息。这些工具是 Agent 的「系统管理员」套装,让它从「文件编辑者」升级为「系统操控者」。
5.1 run_command —— 运行系统命令
功能说明
run_command 是 execute_shell 的「轻量版」。它们都执行系统命令,但 run_command 的安全级别更高、审批更轻量。
关键区别:
| 特性 | run_command | execute_shell |
|---|---|---|
| 风险等级 | 中风险 | 高风险 |
| 审批策略 | 可配置为自动允许(白名单内) | 强制每次审批 |
| 命令白名单 | 支持 | 不支持(全部审批) |
| 适用场景 | 日常命令(git、npm、ls) | 复杂/危险操作 |
run_command 的设计思路是:对于常用的、相对安全的命令(如 git status、npm install、python script.py),经过首次确认后可以自动执行,不需要每次都打断用户。
参数详解
{
"command": {
"type": "string",
"required": true,
"description": "要执行的命令"
},
"timeout": {
"type": "integer",
"required": false,
"default": 30,
"description": "超时时间(秒)"
},
"working_dir": {
"type": "string",
"required": false,
"default": ".",
"description": "工作目录"
},
"env": {
"type": "object",
"required": false,
"description": "环境变量"
}
}使用示例
示例 1:查看 Git 日志
工具调用:
run_command(command="git log --oneline -10")
返回结果:
a1b2c3d feat: add memory search
b2c3d4e fix: handle empty results
c3d4e5f docs: update API reference
d4e5f6a test: add unit tests for tools
e5f6a7b chore: bump version to 2.1.0
f6a7b8c refactor: simplify registry logic
g7h8i9d fix: race condition in sandbox
h8i9j0e feat: support custom user agents
i9j0k1f docs: add Chinese translation
j0k1l2g chore: update dependencies
示例 2:运行测试套件
工具调用:
run_command(command="pytest tests/ -v", timeout=120)
返回结果:
============================= test session starts ==============================
platform darwin -- Python 3.11.0
pytest-7.4.0
tests/test_file_tools.py::test_read_file PASSED
tests/test_file_tools.py::test_write_file PASSED
tests/test_web_tools.py::test_web_search PASSED
============================== 3 passed in 2.34s ===============================
示例 3:安装依赖
工具调用:
run_command(command="npm install lodash axios")
返回结果:
added 2 packages in 1.2s
Tips
在日常开发中,优先使用
run_command而不是execute_shell。只有当你需要执行白名单之外的复杂命令时,才使用execute_shell。这样既能享受自动化带来的便利,又能保持较高的安全性。
白名单配置
你可以在配置文件中定义 run_command 的白名单:
# ~/.hermes/config.yaml
tools:
run_command:
whitelist:
- "git"
- "npm"
- "pip"
- "pytest"
- "python"
- "node"
- "ls"
- "cat"
- "echo"
- "mkdir"
# 白名单内命令的策略
whitelist_strategy: "remember" # 首次确认后记住
# 白名单外命令的策略
non_whitelist_strategy: "prompt" # 每次都提示注意事项
注意
- 命令注入风险:不要在
command中拼接用户输入的内容。如果必须拼接,要对特殊字符进行转义。比如command=f"grep {user_input} file.txt"中,如果user_input是"; rm -rf /;",就会导致灾难。- 长命令处理:如果命令输出很长(如
find / -name "*.log"),建议重定向到文件,然后用read_file读取,而不是直接输出。
5.2 background_task —— 后台任务管理
功能说明
background_task 用于在后台启动和管理长时间运行的任务。与同步执行的工具不同,后台任务启动后不会阻塞 Agent,Agent 可以继续执行其他操作,稍后检查任务状态。
典型使用场景:
- 启动一个开发服务器(如
npm run dev) - 运行耗时的数据批处理任务
- 启动日志监控进程
- 执行定时备份脚本
参数详解
{
"action": {
"type": "string",
"required": true,
"description": "操作:start、stop、status、list"
},
"task_id": {
"type": "string",
"required": false,
"description": "任务 ID(start 时自动生成,其他操作需要)"
},
"command": {
"type": "string",
"required": false,
"description": "要启动的命令(action=start 时需要)"
},
"working_dir": {
"type": "string",
"required": false,
"description": "工作目录"
},
"env": {
"type": "object",
"required": false,
"description": "环境变量"
},
"auto_restart": {
"type": "boolean",
"required": false,
"default": false,
"description": "任务崩溃后是否自动重启"
}
}使用示例
示例 1:启动后台开发服务器
工具调用:
background_task(
action="start",
command="npm run dev",
working_dir="./my-app",
task_id="dev-server"
)
返回结果:
任务已启动
任务 ID: dev-server
PID: 12345
状态: running
启动时间: 2024-01-15 10:30:00
示例 2:查看后台任务状态
工具调用:
background_task(action="status", task_id="dev-server")
返回结果:
任务 ID: dev-server
命令: npm run dev
PID: 12345
状态: running
运行时间: 15 分钟
CPU: 2.3%
内存: 128 MB
最近输出: [10:45:00] Compiled successfully in 234ms
示例 3:列出所有后台任务
工具调用:
background_task(action="list")
返回结果:
┌─────────────┬────────────────┬─────────┬──────────┐
│ 任务 ID │ 命令 │ 状态 │ 运行时间 │
├─────────────┼────────────────┼─────────┼──────────┤
│ dev-server │ npm run dev │ running │ 15m │
│ log-monitor │ tail -f app.log│ running │ 2h │
│ backup-job │ python backup.py│ stopped │ - │
└─────────────┴────────────────┴─────────┴──────────┘
示例 4:停止后台任务
工具调用:
background_task(action="stop", task_id="dev-server")
返回结果:
任务 dev-server 已停止(发送 SIGTERM)
退出码: 0
运行总时长: 18 分钟
Tips
后台任务的输出会被保存到
~/.hermes/tasks/<task_id>.log。如果任务输出异常或崩溃,可以用read_file查看日志文件排查问题。
注意事项
注意
- 任务持久性:后台任务在 Hermes 进程退出后不会自动保留。如果需要真正的守护进程,建议使用系统的 systemd、launchd 或 pm2 等工具。
- 资源限制:每个后台任务默认有资源限制(CPU 50%、内存 512MB)。超过限制的任务会被强制终止。
- 端口冲突:如果后台任务需要监听端口(如开发服务器),确保端口没有被其他进程占用。
5.3 process_list —— 进程列表
功能说明
process_list 用于查看当前系统运行的进程列表。它是 ps 或 tasklist 命令的封装,但提供了更友好的输出格式和过滤功能。
参数详解
{
"filter": {
"type": "string",
"required": false,
"description": "按名称过滤进程"
},
"sort_by": {
"type": "string",
"required": false,
"default": "cpu",
"description": "排序方式:cpu、memory、pid、name"
},
"limit": {
"type": "integer",
"required": false,
"default": 50,
"description": "最多返回多少条"
}
}使用示例
示例 1:查看所有进程
工具调用:
process_list()
返回结果:
┌───────┬────────────────┬────────┬──────────┬──────────┐
│ PID │ 名称 │ CPU% │ 内存(MB) │ 用户 │
├───────┼────────────────┼────────┼──────────┼──────────┤
│ 1234 │ hermes-agent │ 5.2 │ 256 │ jwangkun │
│ 5678 │ node │ 12.3 │ 128 │ jwangkun │
│ 9012 │ python │ 2.1 │ 64 │ jwangkun │
└───────┴────────────────┴────────┴──────────┴──────────┘
示例 2:查找特定进程
工具调用:
process_list(filter="hermes")
返回结果:
┌───────┬────────────────┬────────┬──────────┐
│ PID │ 名称 │ CPU% │ 内存(MB) │
├───────┼────────────────┼────────┼──────────┤
│ 1234 │ hermes-agent │ 5.2 │ 256 │
│ 1235 │ hermes-sandbox │ 1.0 │ 64 │
└───────┴────────────────┴────────┴──────────┘
Tips
当你觉得系统卡顿或某个程序无响应时,先用
process_list(sort_by="cpu")查看哪些进程占用了大量 CPU 资源。这是排查系统性能问题的第一步。
5.4 kill_process —— 终止进程
功能说明
kill_process 用于终止指定的进程。这是高风险操作,因为终止错误的进程可能导致数据丢失或系统不稳定。
参数详解
{
"pid": {
"type": "integer",
"required": false,
"description": "进程 PID"
},
"name": {
"type": "string",
"required": false,
"description": "进程名称(会终止所有匹配的进程)"
},
"signal": {
"type": "string",
"required": false,
"default": "SIGTERM",
"description": "发送的信号:SIGTERM(优雅终止)、SIGKILL(强制终止)"
},
"force": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否强制终止(相当于 SIGKILL)"
}
}使用示例
示例 1:通过 PID 终止进程
工具调用:
kill_process(pid=5678)
返回结果:
进程 5678 已发送 SIGTERM 信号
等待进程退出中...
进程已优雅退出
示例 2:强制终止卡死的进程
工具调用:
kill_process(pid=5678, force=true)
返回结果:
进程 5678 已强制终止(SIGKILL)
注意
kill_process默认发送SIGTERM(优雅终止信号),给进程一个清理资源的机会。如果进程无响应,再使用force=true发送SIGKILL(强制终止)。直接强制终止可能导致数据损坏,尤其是数据库进程。
信号说明
| 信号 | 名称 | 作用 |
|---|---|---|
| SIGTERM | 终止 | 请求进程优雅退出(可被捕获) |
| SIGKILL | 强制终止 | 立即终止,无法被捕获或忽略 |
| SIGINT | 中断 | 相当于按 Ctrl+C |
5.5 system_info —— 系统信息获取
功能说明
system_info 用于获取当前系统的硬件和软件信息。这是诊断环境问题、确认系统配置、检查资源使用情况的便捷工具。
参数详解
{
"category": {
"type": "string",
"required": false,
"description": "信息类别:all、os、cpu、memory、disk、network、python"
}
}使用示例
示例 1:获取完整系统信息
工具调用:
system_info()
返回结果:
{
"os": {
"platform": "darwin",
"release": "23.0.0",
"version": "Darwin Kernel Version 23.0.0",
"machine": "arm64",
"node": "MacBook-Pro.local"
},
"cpu": {
"cores": 10,
"threads": 10,
"architecture": "arm64",
"usage_percent": 15.3
},
"memory": {
"total_gb": 32.0,
"available_gb": 18.5,
"used_gb": 13.5,
"usage_percent": 42.2
},
"disk": {
"total_gb": 500.0,
"free_gb": 230.0,
"usage_percent": 54.0
},
"network": {
"hostname": "MacBook-Pro.local",
"interfaces": [
{"name": "en0", "ip": "192.168.1.100"}
]
},
"python": {
"version": "3.11.4",
"executable": "/opt/homebrew/bin/python3",
"pip_packages": 245
}
}
示例 2:只查看内存信息
工具调用:
system_info(category="memory")
返回结果:
内存总量: 32.0 GB
可用内存: 18.5 GB
已用内存: 13.5 GB
使用率: 42.2%
Tips
当你遇到「安装失败」「内存不足」「磁盘满了」等环境问题时,
system_info是最快的诊断工具。几秒钟内就能看到系统的全貌,避免盲目猜测。
注意事项
注意
- 隐私信息:
system_info不会返回敏感信息(如密码、密钥、详细的网络拓扑),但会返回主机名、IP 地址等基本信息。如果你在共享环境中使用,注意这些信息可能暴露你的身份。- 动态数据:CPU 使用率和内存使用率是实时数据,每次调用都会变化。
本章小结
本章我们讲解了 5 个终端命令工具:
run_command:运行系统命令,安全轻量,支持白名单background_task:后台任务管理,启动、停止、监控长时间运行的任务process_list:查看系统进程列表,支持过滤和排序kill_process:终止进程,高风险操作,默认优雅终止system_info:获取系统硬件和软件信息
安全使用原则:
- 优先用 run_command:日常命令用它,只有白名单外的复杂命令才用 execute_shell
- 终止前三思:kill_process 前先用 process_list 确认目标
- 后台任务监控:定期检查 background_task list,防止僵尸任务占用资源
- 环境诊断:遇到问题时,先 system_info 了解全局,再针对性排查
6. 第五类:记忆管理工具 —— Agent 的「笔记本」和「档案馆」
本章你将学到
- 6 个记忆管理工具的完整用法
- 会话记忆与持久记忆的读写区别
- FTS5 全文索引的查询语法和高级用法
- 记忆的隐私保护和清理策略
- 如何构建高效的「记忆-检索-更新」工作流
记忆管理工具让 Agent 能够读写、搜索、管理自己的记忆系统。在第七册中,我们已经深入了解了 Hermes 的三层记忆架构。本章我们将从「工具使用」的角度,讲解如何操作这些记忆。
6.1 memory_read —— 读取记忆
功能说明
memory_read 用于读取 Agent 的记忆内容。它可以读取不同类型的记忆文件,包括:
- 会话记忆(热记忆):当前对话的上下文
- 持久记忆(温记忆):
MEMORY.md和USER.md中的内容 - 检索记忆(冷记忆):SQLite 数据库中的历史记录
参数详解
{
"memory_type": {
"type": "string",
"required": true,
"description": "记忆类型:session、persistent、retrieval、all"
},
"key": {
"type": "string",
"required": false,
"description": "记忆的键名(读取特定条目)"
},
"limit": {
"type": "integer",
"required": false,
"default": 50,
"description": "最多返回多少条"
}
}使用示例
示例 1:读取持久记忆
工具调用:
memory_read(memory_type="persistent")
返回结果:
# MEMORY.md
## 用户偏好
- 编程语言: Python、TypeScript
- 编辑器: VS Code
- 主题: Dark+
## 项目上下文
- 当前项目: Hermes 白皮书编写
- 技术栈: Markdown、Python
- 最近文件: 09-47个内置工具全解.md
示例 2:读取特定键的记忆
工具调用:
memory_read(memory_type="persistent", key="用户偏好")
返回结果:
- 编程语言: Python、TypeScript
- 编辑器: VS Code
- 主题: Dark+
Tips
在长时间对话中,Agent 的上下文可能被新的对话内容挤出。使用
memory_read可以主动回顾之前的记忆,避免「失忆」。比如你可以说:「你还记得我刚才提到的那个想法吗?」Agent 就会用memory_read去查找。
注意事项
注意
- 隐私边界:
memory_read只能读取当前 Agent 实例的记忆,不能访问其他 Agent 或用户的记忆。- 记忆层级:
all会返回所有类型的记忆,但可能会很长。建议指定具体的memory_type。
6.2 memory_write —— 写入记忆
功能说明
memory_write 用于向 Agent 的记忆系统写入新的信息。这是 Agent「学习」用户偏好、记录重要事件、保存中间成果的主要方式。
参数详解
{
"memory_type": {
"type": "string",
"required": true,
"description": "记忆类型:session、persistent、retrieval"
},
"key": {
"type": "string",
"required": true,
"description": "记忆的键名"
},
"value": {
"type": "string",
"required": true,
"description": "记忆的内容"
},
"tags": {
"type": "array",
"required": false,
"description": "标签,用于分类和搜索"
},
"overwrite": {
"type": "boolean",
"required": false,
"default": false,
"description": "如果键已存在,是否覆盖"
}
}使用示例
示例 1:记录用户偏好
工具调用:
memory_write(
memory_type="persistent",
key="用户偏好.编程风格",
value="喜欢使用类型注解,偏好函数式编程风格,注释使用中文",
tags=["preference", "coding"]
)
返回结果:
记忆已写入
位置: ~/.hermes/memories/persistent.json
键: 用户偏好.编程风格
示例 2:保存中间成果到会话记忆
工具调用:
memory_write(
memory_type="session",
key="分析结果.用户画像",
value="用户是后端开发工程师,熟悉 Python 和 Go,对 AI Agent 感兴趣"
)
Tips
memory_write是构建个性化 Agent 体验的核心。每次 Agent 了解到关于你的新信息(喜欢的技术栈、工作习惯、项目背景),都应该写入持久记忆。这样下次对话时,Agent 就能「记得」你是谁,不用每次都重新介绍。
注意事项
注意
- 键名规范:建议使用层级键名(如
用户偏好.编辑器、项目.当前任务),这样便于组织和管理。- 内容长度:单条记忆建议不超过 2000 字符。过长的内容应该拆分成多条记忆,或者保存为文件后只把文件路径记入记忆。
- 敏感信息:不要在记忆中写入密码、API Key 等敏感信息。记忆文件虽然存储在本地,但仍有被意外泄露的风险。
6.3 memory_update —— 更新记忆
功能说明
memory_update 用于修改已有的记忆条目。与 memory_write 的「覆盖」不同,memory_update 提供了更精细的更新能力——可以追加内容、修改特定字段、或者基于旧内容生成新内容。
参数详解
{
"memory_type": {
"type": "string",
"required": true,
"description": "记忆类型"
},
"key": {
"type": "string",
"required": true,
"description": "要更新的键名"
},
"operation": {
"type": "string",
"required": false,
"default": "replace",
"description": "操作类型:replace、append、prepend、merge"
},
"value": {
"type": "string",
"required": true,
"description": "新的值或追加的内容"
}
}使用示例
示例 1:追加内容到现有记忆
工具调用:
memory_update(
memory_type="persistent",
key="用户偏好.编程风格",
operation="append",
value=",不喜欢使用全局变量"
)
返回结果:
更新前: 喜欢使用类型注解,偏好函数式编程风格,注释使用中文
更新后: 喜欢使用类型注解,偏好函数式编程风格,注释使用中文,不喜欢使用全局变量
示例 2:合并结构化数据
工具调用:
memory_update(
memory_type="persistent",
key="项目配置",
operation="merge",
value='{"python_version": "3.11", "framework": "FastAPI"}'
)
Tips
operation="append"特别适合记录「时间线」类的信息。比如记录项目里程碑、学习进度、待办事项列表等。每次有新进展就 append,而不是覆盖整个列表。
6.4 memory_delete —— 删除记忆
功能说明
memory_delete 用于删除记忆系统中的条目。这是需要审批的操作,因为误删记忆可能导致 Agent「遗忘」重要信息。
参数详解
{
"memory_type": {
"type": "string",
"required": true,
"description": "记忆类型"
},
"key": {
"type": "string",
"required": true,
"description": "要删除的键名"
},
"confirm": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否确认删除(防止误操作)"
}
}使用示例
工具调用:
memory_delete(
memory_type="persistent",
key="临时信息.旧项目配置",
confirm=true
)
返回结果:
记忆已删除
键: 临时信息.旧项目配置
注意
删除操作不可逆!建议删除前先
memory_read确认内容。对于不确定是否还需要的内容,可以先把键改为已归档.原键名,而不是直接删除。
6.5 memory_search —— 搜索历史记忆
功能说明
memory_search 是 Agent 的「记忆搜索引擎」。它在 SQLite + FTS5 全文索引上执行搜索,能够快速找到与查询相关的历史记忆。
这是第七册中讲解的「检索记忆(冷记忆)」的主要操作接口。
参数详解
{
"query": {
"type": "string",
"required": true,
"description": "搜索查询词"
},
"memory_type": {
"type": "string",
"required": false,
"description": "限制搜索的记忆类型"
},
"limit": {
"type": "integer",
"required": false,
"default": 10,
"description": "最多返回多少条"
},
"tags": {
"type": "array",
"required": false,
"description": "按标签过滤"
}
}使用示例
示例 1:基础搜索
工具调用:
memory_search(query="Python 项目配置")
返回结果:
[
{
"key": "项目.Hermes配置",
"value": "Python 3.11,使用 Poetry 管理依赖...",
"relevance": 0.92,
"tags": ["project", "python"]
},
{
"key": "用户偏好.编程语言",
"value": "主要使用 Python 和 TypeScript...",
"relevance": 0.78,
"tags": ["preference"]
}
]
示例 2:按标签过滤搜索
工具调用:
memory_search(query="配置", tags=["project"], limit=5)
FTS5 全文索引查询语法
memory_search 底层使用 SQLite 的 FTS5 扩展,支持丰富的查询语法:
| 语法 | 说明 | 示例 |
|---|---|---|
| 普通词 | 包含任意一个词 | python web |
| 短语 | 精确短语匹配 | "machine learning" |
| AND | 同时包含 | python AND web |
| OR | 包含任意一个 | python OR javascript |
| NOT | 排除 | python NOT snake |
| 前缀 | 前缀匹配 | dev* 匹配 developer、development |
| NEAR | 邻近搜索 | python NEAR/5 web(距离5个词以内) |
Tips
当你说「我之前跟你提过……」但记不清具体内容时,Agent 会用
memory_search去查找。为了搜索效果更好,建议在写入记忆时使用清晰、描述性的键名和内容。比如用项目.Hermes部署问题而不是memo_001。
6.6 session_search —— 搜索历史会话
功能说明
session_search 用于搜索历史会话记录。与 memory_search 搜索「记忆条目」不同,session_search 搜索的是「完整的对话历史」。
这是找回「之前某次对话中说过的某句话」的利器。
参数详解
{
"query": {
"type": "string",
"required": true,
"description": "搜索查询词"
},
"time_range": {
"type": "string",
"required": false,
"description": "时间范围:today、week、month、all"
},
"limit": {
"type": "integer",
"required": false,
"default": 10,
"description": "最多返回多少条会话"
}
}使用示例
工具调用:
session_search(query="Docker 部署", time_range="week")
返回结果:
[
{
"session_id": "sess_20240110_143022",
"timestamp": "2024-01-10 14:30:22",
"preview": "用户: 怎么在 Docker 里部署 Hermes?\nAgent: 部署 Hermes 到 Docker 的步骤如下...",
"relevance": 0.95
},
{
"session_id": "sess_20240108_092145",
"timestamp": "2024-01-08 09:21:45",
"preview": "用户: Docker Compose 配置有问题\nAgent: 让我看看你的 docker-compose.yml...",
"relevance": 0.82
}
]
Tips
session_search的结果会显示会话预览,但不会返回完整的对话内容。如果你想回顾完整的某次会话,可以记下session_id,然后使用hermes session show <session_id>命令查看。
本章小结
本章我们讲解了 6 个记忆管理工具:
memory_read:读取记忆,支持会话、持久、检索三种类型memory_write:写入记忆,记录用户偏好和上下文信息memory_update:更新记忆,支持替换、追加、前置、合并四种操作memory_delete:删除记忆,需要确认防止误删memory_search:搜索历史记忆,基于 FTS5 全文索引session_search:搜索历史会话,找回之前的对话内容
记忆管理最佳实践:
- 结构化键名:使用层级键名(如
用户偏好.编辑器)便于组织 - 打标签:写入时添加
tags,搜索时可以通过标签快速过滤 - 定期清理:过期或不再相关的记忆及时删除,保持记忆库精简
- 敏感信息隔离:密码、API Key 等敏感信息不要存入记忆
7. 第六类:技能管理工具 —— Agent 的「技能学院」管理员
本章你将学到
- 6 个技能管理工具的完整用法
- Skill 文件的格式规范和路径约定
- 从 Skills Hub 浏览、安装、更新技能的完整流程
- 技能版本管理和冲突解决
- 自定义技能的创建和调试方法
技能管理工具让 Agent 能够管理自己的「技能库」——创建新技能、查看已有技能、更新技能内容、安装社区技能。这是 Skill 系统的「元操作」工具集。
7.1 skill_create —— 创建技能
功能说明
skill_create 用于创建新的 Skill 文件。在第八册中,我们了解到 Skill 是存放在 ~/.hermes/skills/<name>/SKILL.md 路径下的 Markdown 文件。skill_create 工具就是程序化创建这个文件的方式。
参数详解
{
"name": {
"type": "string",
"required": true,
"description": "技能名称(只能包含字母、数字、连字符、下划线)"
},
"content": {
"type": "string",
"required": true,
"description": "SKILL.md 的完整内容"
},
"overwrite": {
"type": "boolean",
"required": false,
"default": false,
"description": "如果技能已存在,是否覆盖"
}
}使用示例
示例 1:创建一个简单的代码审查技能
工具调用:
skill_create(
name="code-review-helper",
content='''# Code Review Helper
## 触发条件
用户要求审查代码或提到 "review"、"代码审查"、"CR"
## 执行步骤
1. 使用 `read_file` 读取目标文件内容
2. 检查以下方面:
- 代码风格和命名规范
- 潜在的安全问题(如 SQL 注入、XSS)
- 性能问题(如 N+1 查询、不必要的循环)
- 错误处理是否完善
3. 生成审查报告,使用 `write_file` 保存到 `reviews/` 目录
## 输出格式
```markdown
# 代码审查报告
## 文件: {filename}
### 发现的问题
1. **[级别]** 问题描述
- 位置: 第 X 行
- 建议: 修复方案
### 总体评价
(优良中差评级和总结)
示例
输入: "帮我审查一下 src/auth.py" 输出: 生成 src/auth.py 的详细审查报告 ''' )
返回结果: 技能已创建 路径: ~/.hermes/skills/code-review-helper/SKILL.md 大小: 1.2 KB
> **Tips**
>
> 创建技能时,`content` 参数就是 SKILL.md 的完整内容。建议在 Agent 内部先写好内容,确认格式正确后再调用 `skill_create`。你也可以先用 `write_file` 把内容写到临时文件,确认无误后再用 `skill_create` 正式创建。
#### Skill 文件格式要求
一个有效的 SKILL.md 必须包含以下部分:
```markdown
# 技能名称
## 触发条件
(描述什么情况下触发这个技能)
## 执行步骤
(具体的操作步骤,可以包含工具调用)
## 输出格式
(期望的输出格式)
## 示例
(输入输出示例)
注意
- 名称规范:技能名称只能包含小写字母、数字、连字符(-)和下划线(_)。不要包含空格或特殊字符。
- 路径安全:
skill_create只能创建到~/.hermes/skills/目录下,不能写入系统其他位置。- 语法检查:创建后 Hermes 会自动验证 SKILL.md 的格式。如果缺少必要章节,会给出警告。
7.2 skill_read —— 查看技能
功能说明
skill_read 用于读取已安装技能的内容。这在查看技能的触发条件、学习技能的使用方法、调试技能问题时非常有用。
参数详解
{
"name": {
"type": "string",
"required": true,
"description": "技能名称"
}
}使用示例
工具调用:
skill_read(name="code-review-helper")
返回结果:
# Code Review Helper
## 触发条件
用户要求审查代码或提到 "review"、"代码审查"、"CR"
## 执行步骤
...
Tips
当你不确定某个技能具体会做什么时,用
skill_read查看它的完整内容。这比让 Agent 「试试看」更安全——你能提前知道技能会调用哪些工具、会修改哪些文件。
7.3 skill_update —— 更新技能
功能说明
skill_update 用于修改已有技能的内容。与 skill_create 的「全量覆盖」不同,skill_update 支持基于差异的局部更新。
参数详解
{
"name": {
"type": "string",
"required": true,
"description": "技能名称"
},
"content": {
"type": "string",
"required": true,
"description": "新的完整内容(覆盖)或差异片段"
},
"mode": {
"type": "string",
"required": false,
"default": "replace",
"description": "更新模式:replace(全量替换)、patch(差异补丁)"
}
}使用示例
示例 1:全量更新技能
工具调用:
skill_update(
name="code-review-helper",
mode="replace",
content="新的完整 SKILL.md 内容..."
)
示例 2:局部更新(追加执行步骤)
工具调用:
skill_update(
name="code-review-helper",
mode="patch",
content='''--- 原内容
2. 检查以下方面:
- 代码风格和命名规范
- 潜在的安全问题
--- 新内容
2. 检查以下方面:
- 代码风格和命名规范
- 潜在的安全问题
- 类型注解是否完善(Python)
- 测试覆盖率
'''
)
注意
更新技能前,建议先用
skill_read读取当前内容,确认你要修改的部分。更新后,新内容会立即生效——下一次 Agent 匹配到触发条件时,就会使用更新后的版本。
7.4 skill_delete —— 删除技能
功能说明
skill_delete 用于删除已安装的技能。这是需要审批的操作,因为删除后技能无法恢复(除非重新安装或重新创建)。
参数详解
{
"name": {
"type": "string",
"required": true,
"description": "技能名称"
},
"confirm": {
"type": "boolean",
"required": false,
"default": false,
"description": "确认删除"
}
}使用示例
工具调用:
skill_delete(name="old-experiment-skill", confirm=true)
返回结果:
技能已删除
名称: old-experiment-skill
路径: ~/.hermes/skills/old-experiment-skill/
备份: ~/.hermes/skills/.deleted/old-experiment-skill-20240115.bak
注意
删除操作会创建备份(存放在
~/.hermes/skills/.deleted/)。如果你误删了技能,可以从备份恢复。备份保留 30 天后自动清理。
7.5 skill_list —— 列出所有技能
功能说明
skill_list 用于查看当前已安装的所有技能。它会显示技能的名称、来源、信任等级、最近使用时间等信息。
参数详解
{
"filter": {
"type": "string",
"required": false,
"description": "按来源过滤:built-in、official、trusted、community、all"
},
"search": {
"type": "string",
"required": false,
"description": "按名称关键词搜索"
}
}使用示例
示例 1:列出所有技能
工具调用:
skill_list()
返回结果:
┌────────────────────────┬───────────┬──────────┬──────────────┐
│ 技能名称 │ 来源 │ 信任等级 │ 最近使用 │
├────────────────────────┼───────────┼──────────┼──────────────┤
│ web-search-helper │ built-in │ 内置 │ 10 分钟前 │
│ code-review-helper │ local │ 本地 │ 2 小时前 │
│ gstack │ community │ 可信 │ 昨天 │
│ llm-wiki │ community │ 可信 │ 3 天前 │
│ manim │ community │ 官方 │ 上周 │
└────────────────────────┴───────────┴──────────┴──────────────┘
总计: 47 个技能
示例 2:只列出社区技能
工具调用:
skill_list(filter="community")
Tips
定期运行
skill_list清理不再使用的技能。技能文件虽然不大,但过多技能会影响 Agent 的匹配效率——每次用户输入时,Agent 都要在所有技能的触发条件中搜索匹配项。
7.6 skill_install —— 从 Hub 安装技能
功能说明
skill_install 用于从 Skills Hub(技能市场)安装社区技能。Skills Hub 是一个集中的技能仓库,包含 700+ 个社区贡献的技能。
参数详解
{
"name": {
"type": "string",
"required": true,
"description": "技能名称或 Hub ID"
},
"version": {
"type": "string",
"required": false,
"description": "指定版本号,默认安装最新版"
},
"source": {
"type": "string",
"required": false,
"default": "hub",
"description": "安装来源:hub、github、local"
},
"trust_level": {
"type": "string",
"required": false,
"description": "安装后设置的信任等级"
}
}使用示例
示例 1:从 Hub 安装技能
工具调用:
skill_install(name="gstack")
返回结果:
正在从 Skills Hub 安装 gstack...
✓ 下载 SKILL.md
✓ 下载依赖文件
✓ 验证签名
✓ 安装完成
安装路径: ~/.hermes/skills/gstack/
版本: 1.3.2
作者: @alice_dev
信任等级: 可信(已验证签名)
示例 2:从 GitHub 安装技能
工具调用:
skill_install(
name="my-custom-skill",
source="github",
version="v2.0.0"
)
示例 3:安装本地技能包
工具调用:
skill_install(
name="company-internal-skill",
source="local",
version="1.0.0"
)
Tips
安装社区技能前,建议先查看技能的信任等级和评分。Hub 上的技能分为四个等级:内置(built-in)、官方(official)、可信(trusted)、社区(community)。对于「社区」等级的技能,建议先
skill_read查看内容,确认安全后再使用。
信任等级说明
| 等级 | 标识 | 说明 |
|---|---|---|
| 内置 | 🏛️ | Hermes 核心团队维护,随安装包分发 |
| 官方 | ✅ | 经过官方审核,从官方仓库安装 |
| 可信 | 🔒 | 签名验证通过,来自可信作者 |
| 社区 | 👥 | 社区贡献,未经过严格审核 |
注意
- 网络要求:从 Hub 安装需要网络连接。如果处于离线环境,可以手动下载技能文件放到
~/.hermes/skills/目录下。- 依赖安装:某些技能有额外的依赖(如 Python 包、Node.js 包)。
skill_install会自动安装这些依赖,但可能需要你的确认。- 版本冲突:如果已安装同名技能,
skill_install默认会报错。可以使用overwrite=true强制覆盖。
本章小结
本章我们讲解了 6 个技能管理工具:
skill_create:创建新技能,编写 SKILL.md 文件skill_read:查看技能内容,了解触发条件和执行步骤skill_update:更新技能,支持全量替换和差异补丁skill_delete:删除技能,自动创建备份skill_list:列出所有已安装技能,支持过滤和搜索skill_install:从 Skills Hub 安装社区技能
技能管理最佳实践:
- 命名规范:技能名称使用小写字母和连字符,如
code-review-helper - 信任等级:安装社区技能前查看信任等级,不安全的技能不要安装
- 定期清理:删除不再使用的技能,保持技能库精简
- 版本管理:重要技能更新前先用
skill_read备份旧版本
8. 第七类:代理委托工具 —— 多 Agent 协作的「调度中心」
本章你将学到
- 5 个代理委托工具的功能和使用场景
- 多 Agent 并发编排的实际案例
- 最多 3 个子 Agent 并行的限制原因和应对策略
- 子 Agent 间的通信机制和状态同步
- 委托任务的拆分粒度和最佳实践
代理委托工具是 Hermes 最高阶的工具类别。它们让单个 Agent 能够「分身」——创建多个子 Agent,各自执行不同的子任务,最后汇总结果。这是处理复杂任务、实现并行计算、模拟团队协作的核心能力。
8.1 delegate_task —— 委托子任务
功能说明
delegate_task 是代理委托系统的核心工具。它允许当前 Agent(称为「主 Agent」或「Parent」)将一个子任务分配给另一个 Agent(称为「子 Agent」或「Child」)执行。
委托的工作流程:
- 主 Agent 分析任务,决定可以拆分成哪些子任务
- 主 Agent 调用
delegate_task,指定子任务的描述和目标 - Hermes 创建或复用子 Agent,分配任务
- 子 Agent 独立执行,使用自己的工具链
- 子 Agent 完成后,结果返回给主 Agent
- 主 Agent 汇总所有子任务的结果,生成最终输出
参数详解
{
"task": {
"type": "string",
"required": true,
"description": "子任务的详细描述"
},
"context": {
"type": "string",
"required": false,
"description": "传递给子任务的上下文信息"
},
"agent_id": {
"type": "string",
"required": false,
"description": "指定子 Agent ID(不指定则自动创建)"
},
"timeout": {
"type": "integer",
"required": false,
"default": 300,
"description": "子任务超时时间(秒)"
},
"required_tools": {
"type": "array",
"required": false,
"description": "子 Agent 需要的工具列表"
}
}使用示例
示例 1:委托代码审查子任务
主 Agent 思考:
用户要求我审查 5 个文件的代码。我可以并行委托给多个子 Agent,
每个审查一个文件,最后汇总结果。
工具调用:
delegate_task(
task="审查 src/auth.py 的代码质量和安全性",
context="项目使用 Python 3.11 + FastAPI,关注 SQL 注入和 JWT 安全问题",
required_tools=["read_file", "write_file"]
)
delegate_task(
task="审查 src/models.py 的数据模型设计",
context="项目使用 SQLAlchemy ORM,关注模型关系和性能",
required_tools=["read_file", "write_file"]
)
返回结果:
子任务 1 完成:
- 发现 2 个安全问题
- 发现 1 个性能问题
子任务 2 完成:
- 数据模型设计良好
- 建议添加索引优化
Tips
委托任务时,
task描述越详细,子 Agent 的执行效果越好。不要只写「审查代码」,而要写「审查 src/auth.py 的认证逻辑,重点关注 SQL 注入风险和 JWT 令牌处理」。明确的任务边界能减少子 Agent 的困惑。
任务拆分原则
好的任务拆分应该遵循以下原则:
| 原则 | 说明 | 示例 |
|---|---|---|
| 独立性 | 子任务之间尽量独立,减少依赖 | 审查文件 A 和审查文件 B 是独立的 |
| 原子性 | 每个子任务只负责一件事 | 「搜索 + 分析 + 写报告」应拆成三个子任务 |
| 明确边界 | 子任务的输入输出清晰 | 「输出一份 Markdown 格式的审查报告」 |
| 合理粒度 | 不要太细( overhead 高)也不要太粗 | 一个子任务 3-10 分钟完成为宜 |
8.2 agent_spawn —— 创建子 Agent
功能说明
agent_spawn 用于显式创建一个新的子 Agent 实例。与 delegate_task 的「委托即创建」不同,agent_spawn 先创建 Agent,之后可以多次向它委托任务。
这在以下场景很有用:
- 需要一个长期存在的「专家 Agent」(如专门负责代码审查的 Agent)
- 需要预热 Agent 环境(加载特定技能、配置上下文)
- 需要在多个任务之间保持 Agent 状态
参数详解
{
"agent_id": {
"type": "string",
"required": true,
"description": "子 Agent 的唯一标识"
},
"role": {
"type": "string",
"required": false,
"description": "Agent 的角色描述"
},
"skills": {
"type": "array",
"required": false,
"description": "预加载的技能列表"
},
"tools": {
"type": "array",
"required": false,
"description": "可用的工具列表(默认全部)"
},
"model": {
"type": "string",
"required": false,
"description": "指定使用的 LLM 模型"
}
}使用示例
示例 1:创建一个代码审查专家 Agent
工具调用:
agent_spawn(
agent_id="code-reviewer-1",
role="Python 代码审查专家,专注于安全性、性能和可维护性",
skills=["security-audit", "python-best-practices"],
model="claude-sonnet-4"
)
返回结果:
子 Agent 已创建
ID: code-reviewer-1
角色: Python 代码审查专家...
模型: claude-sonnet-4
状态: ready
示例 2:创建一个前端专家 Agent
工具调用:
agent_spawn(
agent_id="frontend-expert",
role="React/TypeScript 前端开发专家",
skills=["react-patterns", "typescript-tips"],
tools=["read_file", "edit_file", "execute_javascript"]
)
Tips
子 Agent 的
agent_id是全局唯一的。如果尝试创建一个已存在的 ID,会报错。如果需要「重置」一个子 Agent,先agent_terminate再重新agent_spawn。
8.3 agent_communicate —— Agent 间通信
功能说明
agent_communicate 用于主 Agent 与子 Agent 之间、或子 Agent 之间的通信。这是多 Agent 协作的「消息总线」。
通信模式:
- 主 → 子:发送指令、提供额外上下文
- 子 → 主:汇报进度、请求澄清、返回中间结果
- 子 → 子:协作任务中的信息交换
参数详解
{
"from": {
"type": "string",
"required": true,
"description": "发送方 Agent ID"
},
"to": {
"type": "string",
"required": true,
"description": "接收方 Agent ID"
},
"message": {
"type": "string",
"required": true,
"description": "消息内容"
},
"message_type": {
"type": "string",
"required": false,
"default": "text",
"description": "消息类型:text、data、request、response"
}
}使用示例
工具调用:
agent_communicate(
from="main-agent",
to="code-reviewer-1",
message="请在审查时特别关注用户输入验证部分",
message_type="request"
)
返回结果:
消息已发送
目标 Agent: code-reviewer-1
状态: 已接收
Tips
Agent 间通信的消息会被记录到
~/.hermes/agents/<agent_id>/messages.log。如果协作过程中出现问题,可以查看日志排查是消息丢失还是处理错误。
8.4 agent_status —— 查看子 Agent 状态
功能说明
agent_status 用于查看子 Agent 的当前状态。在多 Agent 协作时,主 Agent 需要知道哪些子 Agent 还在工作、哪些已完成、哪些遇到了问题。
参数详解
{
"agent_id": {
"type": "string",
"required": false,
"description": "指定 Agent ID(不指定则查看所有子 Agent)"
}
}使用示例
示例 1:查看所有子 Agent 状态
工具调用:
agent_status()
返回结果:
┌──────────────────┬─────────┬──────────────────┬──────────┬──────────────┐
│ Agent ID │ 状态 │ 当前任务 │ 进度 │ 运行时间 │
├──────────────────┼─────────┼──────────────────┼──────────┼──────────────┤
│ code-reviewer-1 │ running │ 审查 src/auth.py │ 60% │ 2 分钟 │
│ frontend-expert │ idle │ - │ - │ 5 分钟 │
│ data-analyst │ done │ 分析销售数据 │ 100% │ 3 分钟 │
└──────────────────┴─────────┴──────────────────┴──────────┴──────────────┘
示例 2:查看特定 Agent 详情
工具调用:
agent_status(agent_id="code-reviewer-1")
返回结果:
Agent ID: code-reviewer-1
状态: running
角色: Python 代码审查专家
当前任务: 审查 src/auth.py
进度: 60%
已执行工具: read_file(3), search_files(1), write_file(0)
最近活动: 2 秒前读取了 src/auth.py 第 120-150 行
内存使用: 45 MB
Token 消耗: 2,340
Tips
当
agent_status显示某个子 Agent 长时间 stuck 在相同进度时,可能遇到了问题。可以用agent_communicate发送消息询问,或者agent_terminate后重新委托。
8.5 agent_terminate —— 终止子 Agent
功能说明
agent_terminate 用于终止子 Agent 的执行。当子 Agent 的任务已经完成、或者子 Agent 陷入死循环、或者需要释放资源时,可以使用这个工具。
参数详解
{
"agent_id": {
"type": "string",
"required": true,
"description": "要终止的 Agent ID"
},
"force": {
"type": "boolean",
"required": false,
"default": false,
"description": "是否强制终止(立即 kill,不等待清理)"
},
"reason": {
"type": "string",
"required": false,
"description": "终止原因(用于日志记录)"
}
}使用示例
工具调用:
agent_terminate(
agent_id="code-reviewer-1",
reason="任务已完成,释放资源"
)
返回结果:
Agent code-reviewer-1 已终止
执行总结:
- 完成任务: 1
- 使用工具: 8 次
- Token 消耗: 4,560
- 运行时间: 5 分钟
注意
- 资源释放:终止 Agent 会释放其占用的内存和上下文资源,但已写入文件或记忆的内容会保留。
- 强制终止:如果 Agent 陷入死循环或无法响应,使用
force=true强制终止。但这可能导致未保存的数据丢失。
多 Agent 并发限制说明
Hermes 对子 Agent 的并行数量有严格限制:最多同时运行 3 个子 Agent。
这个限制的设计原因:
| 原因 | 说明 |
|---|---|
| 资源保护 | 每个子 Agent 都消耗内存和 Token,过多会导致系统卡顿 |
| 质量控制 | 并行太多,主 Agent 的协调成本会超过并行收益 |
| 成本考量 | 每个子 Agent 都独立调用 LLM,过多会快速消耗 API 配额 |
| 调试难度 | 并行 Agent 越多,问题定位和结果汇总越困难 |
应对策略:
- 分批处理:如果任务可以拆成 10 个子任务,分 4 批执行(3+3+3+1)
- 任务合并:将相关性强的子任务合并,减少 Agent 数量
- 串行执行:对于前后依赖的任务,串行执行比并行更合理
本章小结
本章我们讲解了 5 个代理委托工具:
delegate_task:委托子任务给子 Agent 执行agent_spawn:显式创建子 Agent 实例agent_communicate:Agent 间发送消息agent_status:查看子 Agent 状态和进度agent_terminate:终止子 Agent 释放资源
多 Agent 协作最佳实践:
- 任务拆分粒度:每个子任务 3-10 分钟完成为宜,不要太细也不要太粗
- 并行限制:最多 3 个子 Agent 并行,超出需分批
- 通信简洁:Agent 间消息要简洁明了,避免长上下文传递
- 状态监控:定期
agent_status检查子 Agent 状态,及时发现卡死 - 资源释放:任务完成后及时
agent_terminate,避免资源泄漏
9. 其他辅助工具 —— Agent 的「百宝箱」
本章你将学到
- 7 个辅助工具的功能和使用场景
- 剪贴板操作在自动化工作流中的妙用
- 定时任务的创建和管理
- 图像分析和音频转文字的实用案例
- 文本转换工具的各种编码和格式转换能力
除了前面七大类工具之外,Hermes 还提供了一系列小巧但实用的辅助工具。它们就像 Swiss Army Knife(瑞士军刀)上的那些小工具——开瓶器、螺丝刀、指甲锉——单独看都不起眼,但在特定场景下能救急。
9.1 clipboard —— 剪贴板操作
功能说明
clipboard 工具让 Agent 能够读取和写入系统剪贴板。这是连接 Agent 与外部应用的桥梁——Agent 可以把生成的内容放到剪贴板,你直接粘贴到微信、邮件、文档中;你也可以先把内容复制到剪贴板,让 Agent 读取并处理。
参数详解
{
"action": {
"type": "string",
"required": true,
"description": "操作:read(读取)、write(写入)、clear(清空)"
},
"content": {
"type": "string",
"required": false,
"description": "要写入剪贴板的内容(action=write 时需要)"
},
"format": {
"type": "string",
"required": false,
"default": "text",
"description": "内容格式:text、html、rtf"
}
}使用示例
示例 1:读取剪贴板内容
工具调用:
clipboard(action="read")
返回结果:
会议记录:
- 讨论了 Q1 的产品路线图
- 确定了 3 个优先级最高的功能
- 下周五前完成原型设计
示例 2:将生成的内容写入剪贴板
工具调用:
clipboard(
action="write",
content="感谢各位参加今天的会议。会议决议如下:\n1. Q1 优先开发 AI 助手功能\n2. 下周五前提交原型\n3. 下周三安排技术评审"
)
返回结果:
内容已写入剪贴板(256 字符)
Tips
clipboard是「人机协作」的经典工具。比如你在浏览器里看到一段英文,复制到剪贴板,然后对 Agent 说「帮我翻译剪贴板里的内容」,Agent 就会用clipboard(action="read")读取,翻译完再用clipboard(action="write")把中文结果写回剪贴板,你直接粘贴即可。
常见场景
| 场景 | 操作 | 说明 |
|---|---|---|
| 翻译 | read → 翻译 → write | 复制外文,翻译后粘贴 |
| 格式化 | read → 格式化 → write | 粘贴混乱的 JSON,格式化后写回 |
| 提取 | read → 提取关键信息 | 复制长邮件,提取待办事项 |
| 生成摘要 | read → 生成摘要 → write | 复制文章,生成摘要后分享 |
注意事项
注意
- 隐私敏感:剪贴板可能包含密码、银行卡号等敏感信息。Agent 读取剪贴板时,会在日志中记录操作,但不会长期保存剪贴板内容。
- 平台兼容性:
clipboard在 macOS、Linux(需 xclip/xsel)和 Windows 上都可用,但某些远程 SSH 会话中可能无法访问剪贴板。- 大小限制:剪贴板内容超过 1MB 时会被截断。对于大内容,建议保存为文件。
9.2 notification —— 发送通知
功能说明
notification 让 Agent 能够发送系统通知(桌面通知)。当 Agent 完成了一个长时间运行的任务、或者监控到重要事件、或者需要用户注意时,可以弹出一个通知提醒。
参数详解
{
"title": {
"type": "string",
"required": true,
"description": "通知标题"
},
"message": {
"type": "string",
"required": true,
"description": "通知内容"
},
"urgency": {
"type": "string",
"required": false,
"default": "normal",
"description": "紧急程度:low、normal、critical"
},
"timeout": {
"type": "integer",
"required": false,
"default": 5,
"description": "通知显示时间(秒)"
}
}使用示例
示例 1:任务完成通知
工具调用:
notification(
title="Hermes Agent",
message="代码审查已完成,发现 3 个问题",
urgency="normal"
)
示例 2:紧急错误通知
工具调用:
notification(
title="监控告警",
message="检测到网站响应时间超过 5 秒",
urgency="critical",
timeout=10
)
Tips
notification与web_monitor的组合是构建自动化监控系统的经典搭配。当网页监控检测到异常时,立即发送通知,让你第一时间知道问题。
平台支持
| 平台 | 通知方式 | 说明 |
|---|---|---|
| macOS | Notification Center | 显示在屏幕右上角 |
| Linux | notify-send / libnotify | 需要安装通知服务 |
| Windows | Toast Notification | Windows 10+ 原生支持 |
9.3 schedule_task —— 定时任务创建
功能说明
schedule_task 用于创建定时执行的任务。这是 Agent 的「闹钟」——可以设定在未来某个时间点或按某个周期执行特定操作。
参数详解
{
"name": {
"type": "string",
"required": true,
"description": "任务名称"
},
"command": {
"type": "string",
"required": true,
"description": "要执行的命令或工具调用描述"
},
"schedule": {
"type": "string",
"required": true,
"description": "执行计划:cron 表达式或自然语言描述"
},
"enabled": {
"type": "boolean",
"required": false,
"default": true,
"description": "是否启用"
}
}使用示例
示例 1:每天生成日报
工具调用:
schedule_task(
name="daily-report",
command="搜索今日 AI 新闻并生成摘要报告",
schedule="0 9 * * *"
)
返回结果:
定时任务已创建
名称: daily-report
执行计划: 每天 9:00
下次执行: 2024-01-16 09:00:00
示例 2:每周五下午备份项目
工具调用:
schedule_task(
name="weekly-backup",
command="git push backup && tar czf backup.tar.gz project/",
schedule="0 17 * * 5"
)
示例 3:用自然语言描述
工具调用:
schedule_task(
name="reminder",
command="发送通知:该休息了!",
schedule="every 2 hours"
)
Cron 表达式速查
| 表达式 | 含义 |
|---|---|
0 * * * * | 每小时的第 0 分钟 |
0 9 * * * | 每天 9:00 |
0 9 * * 1 | 每周一 9:00 |
0 9 1 * * | 每月 1 日 9:00 |
*/15 * * * * | 每 15 分钟 |
0 9-17 * * 1-5 | 工作日 9:00-17:00 每小时 |
Tips
定时任务创建后会持久化到
~/.hermes/scheduled_tasks/目录。即使 Hermes 重启,任务也会保留。可以用hermes schedule list查看所有定时任务,hermes schedule remove <name>删除任务。
注意事项
注意
- 系统时钟:定时任务依赖系统时钟,确保你的系统时间准确。
- 任务重叠:如果一个任务执行时间超过了执行间隔,下一次执行会在当前执行完成后立即开始。对于耗时任务,建议设置足够的间隔。
- 睡眠唤醒:如果系统在任务执行时间点处于睡眠状态,任务会在系统唤醒后尽快补执行(取决于操作系统调度)。
9.4 image_analyze —— 图像分析
功能说明
image_analyze 让 Agent 能够「看懂」图片。它利用多模态大模型(如 GPT-4V、Claude 3 Vision)分析图像内容,可以:
- 描述图像中的场景和物体
- 识别图像中的文字(OCR)
- 分析图表和数据可视化
- 检测 UI 界面元素
- 评估图像质量
参数详解
{
"image_path": {
"type": "string",
"required": true,
"description": "图像文件路径或 URL"
},
"prompt": {
"type": "string",
"required": false,
"default": "描述这张图片的内容",
"description": "分析提示词"
},
"detail": {
"type": "string",
"required": false,
"default": "auto",
"description": "细节级别:low、auto、high"
}
}使用示例
示例 1:描述图片内容
工具调用:
image_analyze(
image_path="screenshots/dashboard.png",
prompt="描述这个仪表盘的布局和数据"
)
返回结果:
这张图片展示了一个数据分析仪表盘:
- 顶部有 4 个 KPI 卡片:总收入 1.2M、用户数 45K、转化率 3.2%、客单价 $89
- 中间是折线图,显示过去 30 天的日活跃用户趋势
- 右侧是饼图,展示用户来源分布( organic 45%、 paid 30%、 social 25%)
- 底部是最近 10 笔交易的表格
示例 2:提取图片中的文字
工具调用:
image_analyze(
image_path="scanned_document.jpg",
prompt="提取图片中的所有文字,保持原有格式",
detail="high"
)
示例 3:分析错误截图
工具调用:
image_analyze(
image_path="error_screenshot.png",
prompt="分析这个错误截图,解释错误原因和可能的解决方案"
)
Tips
web_screenshot+image_analyze的组合可以实现「网页自动化分析」。比如让 Agent 截图一个电商网站的商品页面,然后分析价格、评价、库存等信息。这比解析 HTML 更稳定,因为不依赖具体的 DOM 结构。
注意事项
注意
- 模型依赖:
image_analyze需要后端 LLM 支持多模态(Vision)。如果使用的是纯文本模型(如某些 GPT-3.5 版本),这个工具会报错。- 图像大小:建议图像不超过 5MB。过大的图像会自动压缩,可能影响分析精度。
- 隐私注意:图像会被发送到 LLM 提供商的服务器。不要上传包含敏感信息(身份证、银行卡)的图片。
9.5 audio_transcribe —— 音频转文字
功能说明
audio_transcribe 用于将音频文件转换为文字。它基于 Whisper 等语音识别模型,支持多种语言和音频格式。
参数详解
{
"audio_path": {
"type": "string",
"required": true,
"description": "音频文件路径"
},
"language": {
"type": "string",
"required": false,
"description": "音频语言(如 zh、en、ja),不指定则自动检测"
},
"model": {
"type": "string",
"required": false,
"default": "base",
"description": "模型大小:tiny、base、small、medium、large"
},
"output_format": {
"type": "string",
"required": false,
"default": "text",
"description": "输出格式:text、srt、vtt、json"
}
}使用示例
示例 1:转写会议录音
工具调用:
audio_transcribe(
audio_path="recordings/meeting_20240115.mp3",
language="zh",
model="medium"
)
返回结果:
参会人 A: 大家好,今天的会议主题是 Q1 的产品规划。
参会人 B: 我先汇报一下目前的进度...
(完整的会议转录文本)
示例 2:生成字幕文件
工具调用:
audio_transcribe(
audio_path="video/audio_track.mp3",
language="en",
output_format="srt"
)
Tips
模型越大(tiny < base < small < medium < large),转写精度越高,但速度越慢。对于中文内容,建议使用
medium或large模型。如果只是快速预览,base模型就够了。
模型选择指南
| 模型 | 速度 | 精度 | 适用场景 |
|---|---|---|---|
| tiny | 最快 | 一般 | 实时预览、低质量音频 |
| base | 快 | 较好 | 快速转写、对精度要求不高 |
| small | 中等 | 好 | 平衡速度和精度 |
| medium | 较慢 | 很好 | 重要会议、出版级内容 |
| large | 最慢 | 最佳 | 专业场景、多语言混合 |
9.6 text_transform —— 文本转换
功能说明
text_transform 是一个通用的文本处理工具,支持各种编码转换、格式转换、文本清理操作。它是「文本瑞士军刀」——JSON 格式化、URL 编解码、Base64 转换、Markdown/HTML 互转等都能搞定。
参数详解
{
"text": {
"type": "string",
"required": true,
"description": "要转换的文本"
},
"operation": {
"type": "string",
"required": true,
"description": "操作类型"
},
"options": {
"type": "object",
"required": false,
"description": "操作相关的额外选项"
}
}使用示例
示例 1:JSON 格式化
工具调用:
text_transform(
text='{"name":"Alice","age":30,"city":"Beijing"}',
operation="json_format"
)
返回结果:
{
"name": "Alice",
"age": 30,
"city": "Beijing"
}
示例 2:Base64 编解码
工具调用:
text_transform(
text="Hello World",
operation="base64_encode"
)
返回结果:
SGVsbG8gV29ybGQ=
示例 3:Markdown 转 HTML
工具调用:
text_transform(
text="# 标题\n\n这是一段**粗体**文字",
operation="markdown_to_html"
)
返回结果:
<h1>标题</h1>
<p>这是一段<strong>粗体</strong>文字</p>
示例 4:URL 编码/解码
工具调用:
text_transform(
text="https://example.com/search?q=Hello World",
operation="url_encode"
)
返回结果:
https://example.com/search?q=Hello%20World
支持的操作类型
| 操作 | 说明 |
|---|---|
| json_format | JSON 格式化 |
| json_minify | JSON 压缩 |
| base64_encode | Base64 编码 |
| base64_decode | Base64 解码 |
| url_encode | URL 编码 |
| url_decode | URL 解码 |
| html_escape | HTML 转义 |
| html_unescape | HTML 反转义 |
| markdown_to_html | Markdown 转 HTML |
| html_to_markdown | HTML 转 Markdown |
| camel_to_snake | 驼峰转下划线 |
| snake_to_camel | 下划线转驼峰 |
| remove_extra_spaces | 去除多余空格 |
| fix_line_endings | 统一换行符 |
| count_words | 统计字数 |
Tips
text_transform是处理「格式混乱数据」的救星。比如从网页复制的内容经常带有奇怪的空格和换行,用remove_extra_spaces和fix_line_endings清理后,再用markdown_to_html转换,就能得到干净的格式。
9.7 calculator —— 计算器
功能说明
calculator 是一个精确的计算工具。虽然 LLM 本身也能做计算,但对于复杂的数学运算,LLM 可能会出现「幻觉」——算错结果。calculator 使用真实的数学引擎(如 Python 的 math 模块或 sympy),确保结果 100% 准确。
参数详解
{
"expression": {
"type": "string",
"required": true,
"description": "数学表达式"
},
"precision": {
"type": "integer",
"required": false,
"default": 10,
"description": "小数精度"
}
}使用示例
示例 1:基础计算
工具调用:
calculator(expression="(10000 * 1.05^10 - 10000) / 10000 * 100")
返回结果:
62.8894626777479
示例 2:科学计算
工具调用:
calculator(expression="sin(pi/4) + cos(pi/4)")
返回结果:
1.4142135624
示例 3:复杂公式
工具调用:
calculator(
expression="sqrt(3^2 + 4^2)",
precision=5
)
返回结果:
5.0
Tips
当你需要 Agent 做涉及金额、统计、工程计算的任务时,明确要求它使用
calculator工具。比如「用计算器精确计算这笔投资的年化收益率」,而不是让它心算。这样能保证结果的准确性。
支持的运算符和函数
| 类型 | 示例 |
|---|---|
| 基础运算 | +, -, *, /, //, %, ** |
| 比较 | ==, !=, <, >, <=, >= |
| 数学函数 | sin, cos, tan, sqrt, log, exp, abs |
| 常量 | pi, e |
| 统计 | mean([1,2,3,4,5]), sum([...]) |
本章小结
本章我们讲解了 7 个辅助工具:
clipboard:剪贴板读写,连接 Agent 与外部应用notification:发送系统通知,任务完成或异常时提醒schedule_task:创建定时任务,自动化周期性工作image_analyze:图像分析,让 Agent 能「看懂」图片audio_transcribe:音频转文字,基于 Whisper 模型text_transform:文本格式转换,编码转换和文本清理calculator:精确计算,避免 LLM 数学幻觉
辅助工具使用建议:
- 剪贴板是桥梁:用 clipboard 实现 Agent 与任意应用的快速交互
- 定时任务自动化:把重复性工作交给 schedule_task,Agent 就是你的 cron 助手
- 精确计算用 calculator:涉及数字的任务不要依赖 LLM 心算
- 图像+分析组合:web_screenshot + image_analyze 是分析网页的利器
10. 工具组合实战案例 —— 从「会用工具」到「善用工具」
本章你将学到
- 4 个完整的多工具组合实战案例
- 每个案例的完整工具调用链和输出说明
- 如何根据任务特点选择合适的工具组合
- 实战中常见问题的排查和解决
单个工具的能力是有限的,但工具组合起来就能产生化学反应。本章通过 4 个完整的实战案例,展示如何将多个工具串联起来,解决真实世界的复杂问题。
案例 1:自动化投研报告(web_search + web_extract + write_file + delegate_task)
场景描述
你是一名投资分析师,每周一早上需要提交一份「AI 行业周报」,内容包括:
- 过去一周 AI 领域的重要新闻(至少 10 条)
- 主要 AI 公司的股价变化
- 热门论文和技术突破摘要
- 行业趋势判断和投资建议
手动完成这份报告需要 2-3 小时。现在,让 Hermes Agent 自动化这个流程。
工具调用链
步骤 1:主 Agent 分析任务并拆分子任务
主 Agent 思考:
这个任务可以拆成 4 个子任务,并行执行:
- 子任务 A:搜索 AI 新闻
- 子任务 B:获取主要 AI 公司股价
- 子任务 C:搜索热门论文
- 子任务 D:分析行业趋势框架
由于最多 3 个并行 Agent,将 A 和 B 合并为一个子任务。
步骤 2:委托子任务
→ delegate_task(
task="搜索过去一周的 AI 领域重要新闻(至少 10 条),
同时获取 NVIDIA、Microsoft、Google、OpenAI 相关公司的最新股价信息",
context="今天是 2024-01-15,搜索范围是 1 月 8 日到 1 月 15 日"
)
→ delegate_task(
task="搜索过去一周 AI 领域的热门论文和技术突破,
重点关注 arXiv 上的高引论文",
context="关注 LLM、多模态、AI Agent 三个方向"
)
→ delegate_task(
task="基于当前 AI 行业发展,分析未来一周的投资趋势,
给出 3-5 条投资建议",
context="面向机构投资者,语言专业严谨"
)
步骤 3:等待子任务完成
→ agent_status() # 检查所有子 Agent 是否完成
步骤 4:读取子任务结果
(子 Agent 的结果通过 delegate_task 的返回值自动传回)
步骤 5:汇总生成报告
主 Agent 将三个子任务的结果整合,生成完整的 Markdown 报告。
步骤 6:写入文件
→ write_file(
file_path="reports/AI_Weekly_2024-01-15.md",
content="(整合后的完整报告内容)"
)
步骤 7:发送通知
→ notification(
title="投研报告生成完成",
message="AI 行业周报已生成,共 15 条新闻、8 篇论文、5 条投资建议",
urgency="normal"
)
完整的子 Agent A 内部调用链
子 Agent A 收到任务后,会执行以下工具调用:
→ web_search(query="AI artificial intelligence news January 2024",
time_range="week", num_results=15)
→ web_search(query="NVIDIA Microsoft Google AI stock price January 2024",
time_range="week")
(对每条重要新闻)
→ web_extract(url="新闻链接", format="text", max_length=2000)
(整理结果后返回给主 Agent)
输出示例
# AI 行业周报
**报告日期**: 2024-01-15
**分析师**: Hermes Agent
**数据来源**: 公开新闻、arXiv、Yahoo Finance
---
## 一、本周重要新闻(15 条)
1. **OpenAI 发布 GPT-4 Turbo 更新**
- 来源: OpenAI Blog
- 摘要: 上下文窗口扩展至 128K,知识截止更新到 2024 年 4 月...
2. **Google 推出 Gemini Ultra**
- 来源: Google DeepMind
- 摘要: 在 MMLU 基准测试上首次超越人类专家水平...
...(更多新闻)
## 二、主要公司股价变化
| 公司 | 代码 | 周初 | 周末 | 变化 |
| --------- | ----- | ---- | ---- | ------ |
| NVIDIA | NVDA | $520 | $548 | +5.4% |
| Microsoft | MSFT | $380 | $395 | +3.9% |
| Google | GOOGL | $140 | $142 | +1.4% |
| C3.ai | AI | $28 | $25 | -10.7% |
## 三、热门论文与技术突破
1. **"Attention Is All You Need" 的继任者?**
- 论文: Mamba: Linear-Time Sequence Modeling
- 机构: CMU、Princeton
- 影响: 可能替代 Transformer 架构...
## 四、趋势判断与投资建议
1. **建议关注**: 边缘 AI 芯片厂商,随着端侧大模型需求增长...
2. **风险提示**: AI 监管政策不确定性增加...
3. **长期看好**: 企业级 AI Agent 平台...Tips
这个案例的核心价值在于并行化。4 个子任务如果串行执行可能需要 20 分钟,但 3 个 Agent 并行只需要 8 分钟。对于每周都要做的重复任务,这种效率提升累计起来非常可观。
案例 2:代码审计流水线(read_file + search_files + execute_python + skill_create)
场景描述
你负责一个 Python Web 项目的安全审计。需要:
- 扫描所有 Python 文件,找出潜在的安全漏洞
- 检查依赖包是否有已知漏洞
- 检查是否使用了危险的函数(如
eval、exec、pickle.loads) - 生成审计报告并保存
- 将审计流程保存为技能,以便以后复用
工具调用链
步骤 1:探索项目结构
→ list_directory(recursive=true)
→ search_files(pattern=".*\\.py$", recursive=true)
步骤 2:扫描危险函数
→ search_files(
pattern="eval\\(|exec\\(|pickle\\.loads\\(|subprocess\\.call\\(|os\\.system\\(",
glob="*.py",
context_lines=3,
max_results=50
)
步骤 3:检查依赖漏洞
→ read_file(file_path="requirements.txt")
→ execute_python(
code="""
import subprocess
result = subprocess.run(['safety', 'check', '-r', 'requirements.txt'],
capture_output=True, text=True)
print(result.stdout)
print(result.stderr)
""",
packages=["safety"]
)
步骤 4:深度分析可疑文件
(对 search_files 找到的可疑文件逐个读取分析)
→ read_file(file_path="src/auth.py", offset=1, limit=100)
→ read_file(file_path="src/utils.py", offset=1, limit=100)
步骤 5:生成审计报告
→ write_file(
file_path="security_audit_report.md",
content="(完整的审计报告)"
)
步骤 6:保存为可复用技能
→ skill_create(
name="python-security-audit",
content='''# Python 安全审计
## 触发条件
用户要求进行安全审计、代码审查或提到 "security audit"
## 执行步骤
1. 使用 search_files 扫描项目中的 Python 文件
2. 搜索危险函数调用(eval、exec、pickle.loads 等)
3. 读取 requirements.txt,使用 safety 检查依赖漏洞
4. 对可疑文件进行深度 read_file 分析
5. 生成 security_audit_report.md 报告
## 输出格式
Markdown 格式的安全审计报告
## 示例
输入: "审计一下这个项目的安全性"
输出: security_audit_report.md
'''
)
审计报告示例
# Python 项目安全审计报告
**审计时间**: 2024-01-15 14:30
**审计范围**: src/ 目录下所有 Python 文件 + requirements.txt
**审计工具**: Hermes Agent + safety + bandit
---
## 高危漏洞(3 个)
### 1. SQL 注入风险
- **位置**: src/auth.py:45
- **代码**: `cursor.execute(f"SELECT * FROM users WHERE name = '{username}'")`
- **风险**: 用户输入直接拼接到 SQL 语句中
- **修复建议**: 使用参数化查询 `cursor.execute("SELECT * FROM users WHERE name = ?", (username,))`
- **严重程度**: 🔴 高危
### 2. 不安全的反序列化
- **位置**: src/cache.py:23
- **代码**: `data = pickle.loads(request.body)`
- **风险**: pickle 反序列化可执行任意代码
- **修复建议**: 使用 JSON 替代 pickle,或严格校验输入
- **严重程度**: 🔴 高危
### 3. 命令注入风险
- **位置**: src/admin.py:67
- **代码**: `os.system(f"ping {ip_address}")`
- **风险**: 用户输入直接传入系统命令
- **修复建议**: 使用 subprocess 模块并校验输入
- **严重程度**: 🟠 中危
## 依赖漏洞
| 包名 | 当前版本 | 漏洞 | 修复版本 |
| -------- | -------- | -------------- | -------- |
| requests | 2.25.1 | CVE-2023-32681 | 2.31.0 |
| urllib3 | 1.26.5 | CVE-2021-33503 | 1.26.18 |
## 建议
1. 立即修复 3 个高危漏洞
2. 升级 requests 和 urllib3 到安全版本
3. 在 CI/CD 中加入安全扫描步骤
4. 使用 bandit 作为静态分析工具Tips
将审计流程保存为
skill_create是这个案例的点睛之笔。下次你再接到类似任务,只需要说一句「审计一下这个项目的安全性」,Agent 就会自动执行整套流程——不需要你再描述每一个步骤。
案例 3:网站监控 + 通知(web_monitor + notification + schedule_task)
场景描述
你运营一个电商网站,需要:
- 监控首页是否正常加载
- 监控商品价格页面是否有异常
- 监控网站响应时间是否超过阈值
- 发现问题时立即发送通知
- 每天生成一份可用性报告
工具调用链
步骤 1:创建监控任务
→ web_monitor(
url="https://myshop.example.com",
selector="body",
interval=300,
name="homepage-monitor",
action="notify"
)
→ web_monitor(
url="https://myshop.example.com/products/123",
selector=".price",
interval=300,
name="price-monitor",
action="notify"
)
步骤 2:创建响应时间监控(使用 http_request + schedule_task)
→ schedule_task(
name="response-time-check",
command="检查 https://myshop.example.com 的响应时间,如果超过 3 秒则发送通知",
schedule="*/5 * * * *"
)
步骤 3:创建每日报告任务
→ schedule_task(
name="daily-uptime-report",
command="生成昨日网站可用性报告并保存到 reports/uptime_YYYYMMDD.md",
schedule="0 9 * * *"
)
监控告警示例
当网站首页加载失败时:
通知标题: 网站监控告警
通知内容: 首页监控检测到异常:
- URL: https://myshop.example.com
- 错误: HTTP 503 Service Unavailable
- 时间: 2024-01-15 15:23:00
- 建议: 检查服务器状态和负载均衡配置
紧急程度: critical
每日报告示例
# 网站可用性报告
**日期**: 2024-01-14
**监控目标**: myshop.example.com
## 可用性统计
| 监控项 | 检查次数 | 成功次数 | 成功率 | 平均响应时间 |
| ------ | -------- | -------- | ------ | ------------ |
| 首页 | 288 | 285 | 98.9% | 1.2s |
| 商品页 | 288 | 288 | 100% | 0.8s |
## 异常事件
- 15:23:00 首页 503 错误,持续 2 分钟
- 原因: 服务器重启
- 恢复: 15:25:00 自动恢复
## 建议
1. 首页成功率低于 99%,建议排查偶发错误原因
2. 考虑增加 CDN 加速以进一步降低响应时间Tips
web_monitor+notification+schedule_task的组合是构建轻量级监控系统的绝佳方案。不需要部署复杂的监控软件(如 Prometheus + Grafana),几行配置就能实现基本的可用性监控。对于个人项目或小型团队,这完全够用。
案例 4:多 Agent 研究团队(agent_spawn + delegate_task + memory_write)
场景描述
你需要在一天内完成一份「2024 年区块链技术趋势」的深度研究报告。这个任务涉及多个专业领域:
- 技术分析师:分析技术发展方向(Layer 2、ZK、跨链等)
- 市场分析师:分析市场数据和投融资情况
- 政策研究员:跟踪各国监管政策变化
- 报告撰写员:整合所有分析,生成最终报告
单个 Agent 难以同时精通这么多领域。解决方案:创建多个专家 Agent,各自负责一块,最后汇总。
工具调用链
步骤 1:创建专家 Agent
→ agent_spawn(
agent_id="tech-analyst",
role="区块链技术专家,专注于协议层和基础设施分析",
skills=["blockchain-tech", "protocol-analysis"]
)
→ agent_spawn(
agent_id="market-analyst",
role="加密市场分析师,关注投融资和市场趋势",
skills=["crypto-market", "fundraising-tracker"]
)
→ agent_spawn(
agent_id="policy-researcher",
role="区块链政策研究员,跟踪全球监管动态",
skills=["regulation-tracker", "policy-analysis"]
)
步骤 2:并行委托研究任务
→ delegate_task(
agent_id="tech-analyst",
task="研究 2024 年区块链技术趋势,重点关注:\n1. Layer 2 扩容方案进展\n2. 零知识证明应用\n3. 跨链互操作性\n4. 新型共识机制",
timeout=600
)
→ delegate_task(
agent_id="market-analyst",
task="分析 2024 年加密市场数据:\n1. 主要币种价格走势\n2. 投融资事件统计\n3. DeFi 和 NFT 市场数据\n4. 机构入场情况",
timeout=600
)
→ delegate_task(
agent_id="policy-researcher",
task="梳理 2024 年全球区块链监管政策:\n1. 美国 SEC 动态\n2. 欧盟 MiCA 法规进展\n3. 亚洲主要国家政策\n4. 央行数字货币(CBDC)发展",
timeout=600
)
步骤 3:监控进度
→ agent_status() # 查看三个 Agent 的进度
(等待所有 Agent 完成...)
步骤 4:将研究结果写入记忆
→ memory_write(
memory_type="session",
key="研究报告.技术分析",
value="(tech-analyst 的完整研究结果)"
)
→ memory_write(
memory_type="session",
key="研究报告.市场分析",
value="(market-analyst 的完整研究结果)"
)
→ memory_write(
memory_type="session",
key="研究报告.政策分析",
value="(policy-researcher 的完整研究结果)"
)
步骤 5:创建报告撰写 Agent 汇总
→ delegate_task(
task="整合技术、市场、政策三个维度的分析结果,\n生成一份结构化的深度研究报告。\n报告应包含:执行摘要、各章节详细分析、趋势预测、投资建议",
context="研究结果已保存在 session 记忆中,键名分别为 研究报告.技术分析、研究报告.市场分析、研究报告.政策分析"
)
步骤 6:保存最终报告
→ write_file(
file_path="reports/Blockchain_Trends_2024.md",
content="(最终整合的报告)"
)
步骤 7:清理资源
→ agent_terminate(agent_id="tech-analyst")
→ agent_terminate(agent_id="market-analyst")
→ agent_terminate(agent_id="policy-researcher")
输出说明
这个案例的最终输出是一份完整的深度研究报告,通常包含:
- 执行摘要(1-2 页):核心观点和建议
- 技术分析(5-8 页):Layer 2、ZK、跨链等技术方向
- 市场分析(5-8 页):价格、投融资、市场份额
- 政策分析(3-5 页):监管框架和合规趋势
- 综合预测(2-3 页):未来 6-12 个月的趋势判断
- 附录:数据来源、术语表、参考文献
Tips
多 Agent 协作的关键在于清晰的职责划分和标准化的输出格式。在委托任务时,明确指定每个 Agent 的专注领域和输出要求。如果输出格式不统一,汇总时会非常困难。建议在任务描述中附上输出模板。
本章小结
本章通过 4 个实战案例,展示了工具组合的强大威力:
| 案例 | 核心工具组合 | 解决的问题 |
|---|---|---|
| 自动化投研报告 | web_search + web_extract + delegate_task | 信息收集与报告生成自动化 |
| 代码审计流水线 | read_file + search_files + skill_create | 安全审计流程化、可复用 |
| 网站监控 + 通知 | web_monitor + notification + schedule_task | 7x24 可用性监控 |
| 多 Agent 研究团队 | agent_spawn + delegate_task + memory_write | 复杂任务的专家分工协作 |
组合设计原则:
- 并行优于串行:能并行的子任务尽量并行(受 3 Agent 限制)
- 记忆是纽带:多 Agent / 多步骤之间通过 memory_write/memory_read 传递信息
- 技能沉淀:将成功的工具组合保存为 Skill,实现一次配置、多次复用
- 通知闭环:耗时任务和监控任务一定要有 notification,避免「石沉大海」
11. 工具开发与扩展 —— 打造你的专属工具
本章你将学到
- 自定义工具的开发方法和完整示例
- ToolRegistry 的注册机制详解
- MCP 协议工具扩展的方法和原理
- 社区工具贡献的流程和规范
- 工具开发的调试和测试技巧
Hermes 的 47 个内置工具覆盖了绝大多数常见场景,但总有一些特定需求需要自定义工具。比如:
- 你的公司有一个内部 API,需要专门的调用工具
- 你经常使用某个特定的 SaaS 服务(如 Jira、Confluence)
- 你需要与本地特定的硬件设备交互
- 你想封装一套常用的数据处理逻辑
本章将教你如何开发和扩展 Hermes 工具。
11.1 自定义工具的开发方法
开发自定义工具的核心步骤:
- 继承 Tool 基类:创建一个新的 Python 类,继承
hermes.core.tools.Tool - 定义元数据:使用
@tool装饰器定义工具名称、描述、参数 - 实现 execute 方法:编写工具的实际执行逻辑
- 注册到 Registry:使用装饰器自动注册,或手动注册
完整示例:开发一个「生成二维码」工具
# ~/.hermes/custom_tools/qr_generator.py
import qrcode
import io
import base64
from hermes.core.tools import tool, Tool, ToolResult
@tool(
name="generate_qr",
description="生成二维码图片",
parameters={
"data": {
"type": "string",
"description": "要编码到二维码中的数据",
"required": True
},
"size": {
"type": "integer",
"description": "二维码尺寸(像素)",
"default": 256
},
"output_path": {
"type": "string",
"description": "保存路径(不指定则返回 base64)",
"required": False
}
},
requires_approval=False
)
class QRGeneratorTool(Tool):
async def execute(self, params: dict) -> ToolResult:
data = params["data"]
size = params.get("size", 256)
output_path = params.get("output_path")
# 生成二维码
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=10,
border=4,
)
qr.add_data(data)
qr.make(fit=True)
# 生成图像
img = qr.make_image(fill_color="black", back_color="white")
img = img.resize((size, size))
if output_path:
# 保存到文件
img.save(output_path)
return ToolResult(
content=f"二维码已保存到 {output_path}",
metadata={"path": output_path, "size": size}
)
else:
# 返回 base64
buffer = io.BytesIO()
img.save(buffer, format='PNG')
img_base64 = base64.b64encode(buffer.getvalue()).decode()
return ToolResult(
content=f"data:image/png;base64,{img_base64}",
metadata={"format": "base64", "size": size}
)工具类结构详解
class Tool:
"""所有工具的基类"""
name: str # 工具名称
description: str # 工具描述(给 LLM 看的)
parameters: dict # 参数定义(用于 JSON Schema 验证)
requires_approval: bool # 是否需要审批
async def execute(self, params: dict) -> ToolResult:
"""核心执行方法,子类必须实现"""
raise NotImplementedError
async def validate(self, params: dict) -> bool:
"""参数校验,可选重写"""
return True
async def before_execute(self, params: dict):
"""执行前钩子,可选重写"""
pass
async def after_execute(self, result: ToolResult):
"""执行后钩子,可选重写"""
passToolResult 结构
class ToolResult:
def __init__(
self,
content: str, # 主要返回内容(给 LLM 看的)
metadata: dict = None, # 元数据(如文件路径、耗时等)
error: str = None, # 错误信息(如果有)
attachments: list = None # 附件(如图片、文件)
):
self.content = content
self.metadata = metadata or {}
self.error = error
self.attachments = attachments or []Tips
content是 LLM 能看到的内容,要尽量简洁明了。metadata可以放一些结构化数据(如文件路径、HTTP 状态码),方便后续工具链使用。error如果不为空,Agent 会知道工具执行失败了。
11.2 工具注册机制详解
装饰器注册(推荐)
@tool(
name="my_tool",
description="...",
parameters={...}
)
class MyTool(Tool):
...装饰器在模块导入时自动执行,将工具注册到全局 ToolRegistry。这是最简单、最推荐的方式。
手动注册
from hermes.core.tools import ToolRegistry
registry = ToolRegistry()
my_tool = MyTool()
registry.register(my_tool)手动注册适用于动态加载的场景——比如从配置文件读取工具定义,然后运行时创建和注册。
配置文件注册
在 ~/.hermes/config.yaml 中指定自定义工具的加载路径:
tools:
custom_paths:
- "~/.hermes/custom_tools/" # 加载此目录下所有 Python 文件
- "~/projects/hermes-tools/" # 也可以指定其他路径
# 禁用某些内置工具
disabled:
- "execute_shell" # 如果你不想允许 Shell 执行注册优先级
当多个工具同名时,Hermes 的加载优先级是:
- 用户自定义工具(最高优先级)
- 插件工具
- 内置工具(最低优先级)
这意味着你可以用自定义工具覆盖内置工具。比如你觉得内置的 calculator 不够用,可以写一个同名工具替换它。
11.3 MCP 协议工具扩展
什么是 MCP
MCP(Model Context Protocol)是 Anthropic 提出的开放协议,用于标准化 AI 模型与外部数据源、工具之间的交互。Hermes 支持通过 MCP 协议集成第三方工具。
MCP 的优势:
- 标准化:统一的接口规范,工具开发一次,多处使用
- 语言无关:MCP 服务器可以用任何语言编写
- 安全隔离:MCP 服务器运行在独立进程中,与主程序隔离
- 动态发现:Hermes 可以自动发现和连接 MCP 服务器
使用 MCP 扩展示例
假设有一个 MCP 服务器提供了「查询公司内部知识库」的能力:
// ~/.hermes/mcp_config.json
{
"mcpServers": {
"company-kb": {
"command": "python",
"args": ["/path/to/company_kb_server.py"],
"env": {
"KB_API_KEY": "your-api-key"
}
}
}
}配置后,Hermes 会自动连接 MCP 服务器,并将其暴露的工具纳入工具调用范围。Agent 可以像调用内置工具一样调用 MCP 工具:
工具调用:
company_kb_search(query="2024 年假政策")
返回结果:
根据公司内部知识库,2024 年假政策如下:
- 年假天数:10-15 天(根据工龄)
- 申请方式:OA 系统提前 3 天申请
- ...
Tips
MCP 协议是工具生态的未来方向。如果你要开发一个长期维护的工具,建议用 MCP 协议封装,而不是直接写 Hermes 原生工具。这样你的工具可以被多个支持 MCP 的 Agent 框架复用。
11.4 社区工具贡献指南
如果你想把开发的工具贡献给社区,可以通过以下渠道:
贡献到 Skills Hub
- 在 GitHub 上 fork
hermes-tools仓库 - 在
tools/目录下创建你的工具目录 - 编写工具代码和 README 文档
- 提交 Pull Request
- 等待审核(通常 3-5 个工作日)
工具贡献检查清单
- [ ] 工具代码完整,包含错误处理
- [ ] 包含完整的参数定义和类型注解
- [ ] 包含单元测试(覆盖率 > 80%)
- [ ] 包含使用示例
- [ ] README 文档包含功能说明、安装方法、使用示例
- [ ] 不包含敏感信息(API Key、密码等)
- [ ] 遵循 Hermes 代码风格
- [ ] 工具名称不与现有工具冲突审核标准
| 等级 | 要求 |
|---|---|
| 官方(Official) | 通过全部检查清单 + 核心团队审核 + 签名验证 |
| 可信(Trusted) | 通过全部检查清单 + 自动化测试通过 |
| 社区(Community) | 基本功能正常 + 有文档 |
本章小结
本章我们讲解了工具开发与扩展的完整流程:
- 自定义工具开发:继承 Tool 基类,实现 execute 方法,使用 @tool 装饰器注册
- 注册机制:装饰器自动注册、手动注册、配置文件指定路径三种方式
- MCP 协议:标准化的工具扩展协议,语言无关,安全隔离
- 社区贡献:通过 GitHub PR 贡献工具,经过审核后进入 Skills Hub
开发建议:
- 从简单开始:先 clone 一个内置工具的代码,在此基础上修改
- 测试驱动:为工具编写单元测试,确保参数校验和边界条件处理正确
- 文档先行:写工具前先写文档,明确工具的输入输出和边界情况
- 考虑 MCP:长期维护的工具建议用 MCP 协议封装
12. 工具使用最佳实践 —— 从新手到高手的进阶之路
本章你将学到
- 工具使用的 5 大核心原则
- 10 个常见工具使用误区和避免方法
- 成本优化技巧:减少不必要的 API 调用
- 错误处理和故障恢复策略
- 工具性能优化和调试技巧
掌握了 47 个工具的用法之后,更重要的是学会「善用」工具。同样的工具,在不同的人手里效果可能天差地别。本章分享我在长期使用 Hermes 过程中总结的最佳实践。
12.1 安全第一:敏感命令必须审批
安全不是可选项,而是必选项。以下是安全使用工具的核心原则:
原则 1:默认不信任
即使是你自己写的 Agent,也要假设它可能犯错。对于任何会修改系统的操作:
- 在配置中启用审批(不要设置
auto_allow) - 定期检查工具调用历史
hermes tools history - 对重要操作开启
backup=true
原则 2:最小权限原则
给 Agent 的权限越小,潜在危害越小:
# 安全配置示例
tools:
execute_shell:
enabled: false # 如果不需要,直接禁用
execute_python:
network: false # 禁止网络访问
memory_limit: 256 # 限制内存
write_file:
allowed_paths:
- "~/projects/" # 只允许写入特定目录
- "~/Documents/"原则 3:审计日志
定期审查工具调用日志:
# 查看最近的工具调用
hermes tools history --limit 50
# 查看高风险操作
hermes tools history --filter "execute_shell,execute_python,kill_process"
# 导出日志用于审计
hermes tools history --export audit_log.json12.2 组合优于单打:多工具配合
一个常见的误区是「一个任务只用一个工具」。实际上,复杂任务往往需要多个工具配合。
反模式:单打独斗
❌ 错误示例:
用户:帮我分析一下这个项目的代码质量
Agent:好的,我用 search_files 搜一下代码文件
→ search_files(pattern=".*", glob="*.py")
(然后就没有然后了——只是列出了文件列表,没有深入分析)
正模式:工具链配合
✅ 正确示例:
用户:帮我分析一下这个项目的代码质量
Agent:
→ list_directory(recursive=true) # 了解项目结构
→ search_files(pattern="def ", glob="*.py") # 找到所有函数
→ read_file(file_path="src/main.py") # 读取核心文件
→ search_files(pattern="TODO|FIXME|XXX", glob="*.py") # 找技术债务
→ execute_python(code="统计代码行数和复杂度") # 量化分析
→ write_file(file_path="code_quality_report.md") # 生成报告
常用工具链组合
| 场景 | 工具链 | 说明 |
|---|---|---|
| 调研报告 | web_search → web_extract → write_file | 搜索、提取、汇总 |
| 代码重构 | search_files → read_file → edit_file → run_command | 定位、确认、修改、测试 |
| 数据分析 | read_file → execute_python → write_file | 读取、分析、输出 |
| 故障排查 | system_info → process_list → read_file(log) → execute_python(分析) | 全面诊断 |
| 批量处理 | list_directory → read_file(模板) → execute_python(批量生成) → write_file | 自动化生成 |
12.3 成本意识:减少不必要的 API 调用
每次工具调用都可能消耗 Token、时间和金钱。养成成本意识,能让你的 Agent 更高效。
成本优化技巧
1. 批量操作优于多次调用
❌ 低效:逐个读取文件
→ read_file(file_path="src/a.py")
→ read_file(file_path="src/b.py")
→ read_file(file_path="src/c.py")
✅ 高效:先搜索,再批量处理
→ search_files(pattern="class ", glob="*.py") # 找到所有类定义
→ read_file(file_path="src/main.py", limit=100) # 只读关键部分
2. 本地计算替代远程调用
❌ 低效:用 web_search 计算简单的数学问题
→ web_search(query="what is 234 * 567")
✅ 高效:用本地计算器
→ calculator(expression="234 * 567")
3. 缓存重复查询
# 在自定义工具中实现缓存
import functools
@functools.lru_cache(maxsize=100)
def fetch_api_data(endpoint):
# 只有第一次调用会发起 HTTP 请求
# 后续相同 endpoint 直接返回缓存
return http_request(url=endpoint)4. 合理设置 limit 和 offset
❌ 低效:读取整个大文件
→ read_file(file_path="app.log") # 100MB 日志
✅ 高效:只读取需要的部分
→ read_file(file_path="app.log", offset=-100) # 只读最后 100 行
成本监控
# 查看工具调用的 Token 消耗统计
hermes tools stats --cost
# 输出示例
┌─────────────┬──────────┬────────────┬──────────────┐
│ 工具 │ 调用次数 │ Token 消耗 │ 预估成本(USD)│
├─────────────┼──────────┼────────────┼──────────────┤
│ web_search │ 45 │ 12,000 │ $0.18 │
│ read_file │ 120 │ 45,000 │ $0.68 │
│ execute_python│ 30 │ 8,000 │ $0.12 │
│ web_browse │ 15 │ 25,000 │ $0.38 │
└─────────────┴──────────┴────────────┴──────────────┘
总计: $1.3612.4 错误处理:工具调用失败的应对
工具调用失败是不可避免的——网络超时、文件不存在、权限不足、API 限流等。良好的错误处理能让 Agent 更健壮。
错误类型和处理策略
| 错误类型 | 常见原因 | 处理策略 |
|---|---|---|
| 文件不存在 | 路径错误、文件被删除 | 先 file_info 检查存在性 |
| 权限不足 | 没有读写权限 | 检查文件权限,或换目录 |
| 网络超时 | 网络不稳定、目标慢 | 增加 timeout,或重试 |
| API 限流 | 请求太频繁 | 增加间隔,或使用缓存 |
| 内存不足 | 处理大数据 | 分块处理,或增加内存限制 |
| 编码错误 | 文件编码不对 | 尝试不同 encoding |
在自定义工具中实现错误处理
class RobustTool(Tool):
async def execute(self, params: dict) -> ToolResult:
try:
result = await self._do_work(params)
return ToolResult(content=result)
except FileNotFoundError as e:
return ToolResult(
content="",
error=f"文件不存在: {e.filename}。请检查路径是否正确。"
)
except PermissionError:
return ToolResult(
content="",
error="权限不足。请检查文件权限或尝试其他目录。"
)
except TimeoutError:
return ToolResult(
content="",
error="操作超时。请稍后重试,或增加 timeout 参数。"
)
except Exception as e:
return ToolResult(
content="",
error=f"未知错误: {str(e)}"
)Tips
当工具返回
error时,Agent 会收到错误信息并决定如何处理。好的错误信息应该:
- 说明发生了什么错误
- 解释可能的原因
- 给出具体的解决建议
这样的错误信息能帮助 Agent 自我修复,或者给用户清晰的指导。
12.5 常见工具使用误区(10 个)
误区 1:用 write_file 做所有文件修改
❌ 错误:
→ write_file(file_path="config.py", content="全新内容")
(覆盖了文件中其他有用的配置)
✅ 正确:
→ read_file(file_path="config.py") # 先读取
→ edit_file(file_path="config.py", old_string="...", new_string="...") # 精确修改
误区 2:忽视 offset 和 limit,读取超大文件
❌ 错误:
→ read_file(file_path="server.log") # 500MB 日志文件
(导致上下文溢出,Token 暴增)
✅ 正确:
→ read_file(file_path="server.log", offset=-50) # 只看最后 50 行
→ search_files(pattern="ERROR", path="logs", glob="*.log") # 只搜错误
误区 3:在 execute_shell 中拼接用户输入
❌ 错误:
→ execute_shell(command=f"grep {user_input} file.txt")
(如果 user_input = "; rm -rf /;" 就完蛋了)
✅ 正确:
→ search_files(pattern=user_input, glob="*.txt") # 用安全的工具替代
→ 或者对输入做转义处理
误区 4:重复安装相同的 Python 包
❌ 错误:
每次 execute_python 都 packages=["pandas", "numpy"]
(每次调用都检查/安装,浪费时间)
✅ 正确:
在 ~/.hermes/config.yaml 中预配置常用包
或者在项目虚拟环境中提前安装
误区 5:用 web_search 查询本地知识
❌ 错误:
→ web_search(query="我上周让 Agent 写的代码在哪里")
(搜索引擎不知道你的本地文件)
✅ 正确:
→ memory_search(query="上周写的代码") # 搜索记忆
→ search_files(pattern="上周写的函数名") # 搜索本地文件
误区 6:创建太多监控任务不清理
❌ 错误:
每次测试都创建新的 web_monitor,从不删除
(导致后台一堆无用监控,浪费资源)
✅ 正确:
定期检查 ~/.hermes/monitors/
测试完成后删除临时监控任务
误区 7:忽略工具的返回值
❌ 错误:
Agent 调用了 edit_file,但文件实际上没有变化
(因为 old_string 匹配失败,但 Agent 没有检查返回结果)
✅ 正确:
关注工具的返回状态
如果 edit_file 返回 "未找到匹配",需要调整策略
误区 8:过度使用 execute_shell 做简单的事情
❌ 错误:
→ execute_shell(command="cat README.md")
(绕过了 read_file 的安全检查和编码处理)
✅ 正确:
→ read_file(file_path="README.md")
(有编码自动检测、大小限制、安全路径检查)
误区 9:不备份就修改重要文件
❌ 错误:
→ write_file(file_path=".env", content="新的配置")
(覆盖了原来的 API Key,可能导致服务中断)
✅ 正确:
→ read_file(file_path=".env") # 先读取备份到记忆
→ write_file(file_path=".env", content="新配置", backup=true)
误区 10:创建 Agent 后不终止,造成资源泄漏
❌ 错误:
→ agent_spawn(agent_id="helper")
→ delegate_task(agent_id="helper", task="...")
(任务完成后不 terminate,内存不释放)
✅ 正确:
→ agent_terminate(agent_id="helper") # 用完后释放
→ 或者在配置中设置自动超时清理
12.6 调试工具问题的技巧
当工具行为不符合预期时,按以下步骤排查:
步骤 1:隔离测试
# 直接用 CLI 测试工具,绕过 Agent 的推理逻辑
hermes tools test read_file --params '{"file_path": "test.txt"}'步骤 2:检查参数
查看工具调用时的实际参数:
- 路径是否正确(相对路径 vs 绝对路径)
- 类型是否匹配(字符串 vs 数字)
- 必需的参数是否都提供了
步骤 3:查看日志
# 查看详细日志
tail -f ~/.hermes/logs/tools.log
# 过滤特定工具的日志
grep "read_file" ~/.hermes/logs/tools.log步骤 4:最小复现
把问题简化为最小的可复现示例:
# 写一个简单的测试脚本
from hermes.tools import read_file_tool
result = read_file_tool.execute({"file_path": "test.txt"})
print(result.content)
print(result.error)
print(result.metadata)步骤 5:检查环境
# 检查 Hermes 版本
hermes --version
# 检查工具加载情况
hermes tools list
# 检查配置文件语法
hermes config validate本章小结
本章总结了工具使用的最佳实践和常见误区:
5 大核心原则:
- 安全第一:敏感操作必须审批,遵循最小权限原则
- 组合优于单打:复杂任务用工具链,而不是单个工具
- 成本意识:减少不必要的 API 调用,批量处理更高效
- 错误处理:工具调用失败时要有应对策略
- 及时清理:用完的 Agent 要终止,临时任务要删除
10 个常见误区回顾:
- 用
write_file做所有修改(应优先用edit_file) - 忽视
offset/limit读取超大文件 - 在 Shell 命令中拼接未转义的用户输入
- 重复安装相同的 Python 包
- 用
web_search查询本地知识 - 创建监控任务不清理
- 忽略工具的返回值和错误信息
- 过度使用
execute_shell做简单的事情 - 不备份就修改重要文件
- 创建 Agent 后不终止造成资源泄漏
进阶建议:
- 定期运行
hermes tools stats分析工具使用模式 - 建立团队的「工具使用规范」文档
- 把常用的工具组合沉淀为 Skill
- 关注 Hermes 更新日志,及时使用新工具
结语:工具是手段,解决问题才是目的
到这里,我们已经走完了 Hermes 47 个内置工具的完整旅程。从文件系统的基础操作,到代码执行的强大能力;从 Web 交互的信息获取,到多 Agent 协作的复杂编排——这些工具构成了 Hermes Agent 的「四肢百骸」,让它从一个只会聊天的「大脑」,变成了能够动手解决问题的「全能助手」。
但请记住,工具永远只是手段,而不是目的。掌握 47 个工具的名字和参数很容易,难的是知道「什么时候该用什么工具」「如何把工具组合起来解决真实问题」。
就像一位经验丰富的工匠,他不需要记住每一种工具的所有规格,但他知道:什么时候该用锤子,什么时候该用凿子,什么时候需要两只手配合。这种「手感」,只能通过大量的实践来培养。
所以,打开你的终端,启动 Hermes,开始动手吧。从简单的「读取一个文件」开始,到复杂的「多 Agent 协作完成研究报告」,每一步都会让你对工具的理解更深一层。
工具在手,天下我有。祝你在 Hermes 的世界里,探索愉快!