第九册: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 单例中。

这个过程就像是:

  1. Hermes 启动 → 扫描工具目录
  2. 发现 read_file_tool.py → 导入模块
  3. 装饰器 @tool(...) 执行 → 调用 registry.register(read_file_tool)
  4. 工具进入全局注册表 → 可供 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.yaml

hermes 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 tools CLI 命令提供了便捷的工具管理和调试手段

接下来的章节,我们将逐一深入讲解 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_fileoffsetlimit 参数精确读取。这比一次性读取整个文件高效得多,特别是对于几千行的大文件。

示例 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"自动检测编码

注意事项

注意

  1. 路径安全read_file 默认被限制在当前工作目录及其子目录内。尝试读取 /etc/passwd../../secret.txt 这样的路径会被拒绝。
  2. 大文件保护:如果文件超过 10MB,Agent 会收到警告,建议使用 offsetlimit 分段读取。
  3. 敏感文件:以 .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.jsonpyproject.toml)时,强烈建议设置 backup=true。这样如果修改出了问题,你可以随时用 read_file 查看 .bak 文件恢复原始内容。

常见场景

场景参数组合说明
生成报告file_path="report.md"Agent 最常用的输出方式
保存代码file_path="src/utils.py"生成新模块或修改现有模块
追加日志append=true不覆盖已有内容
创建多级目录create_dirs=true自动创建不存在的父目录

注意事项

注意

  1. 覆盖警告:如果目标文件已存在且 append=false(默认值),工具会提示「文件已存在,是否覆盖?」这是防止意外丢失数据的重要保护。
  2. 空内容保护:如果 content 为空字符串,工具会拒绝执行,防止误删文件内容。
  3. 二进制文件:虽然 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 替换为空即可删除

注意事项

注意

  1. 匹配唯一性old_string 必须在文件中能唯一标识要修改的位置。如果匹配到多处,工具会拒绝执行,防止误改。
  2. 空白字符敏感old_string 的匹配是精确的,包括空格和换行。如果文件中使用的是 Tab 缩进,而你的 old_string 用的是空格,匹配会失败。
  3. 备份默认开启edit_filebackup 默认为 true,因为编辑操作通常比写入更危险——你可能只改了一行,却影响了整个文件的功能。

常见问题

Q: edit_file 匹配失败,但我确定文本是对的,怎么办?

A: 最常见的原因是不可见字符(如 BOM、不同换行符 \r\n vs \n、尾部空格)。解决方法:

  1. 先用 read_file 精确读取目标区域
  2. 直接复制工具返回的文本作为 old_string
  3. 如果还是失败,检查是否有混合缩进(Tab + 空格)

Q: 如何一次性进行多处修改?

A: edit_file 一次调用只能修改一处。如果需要多处修改,可以:

  1. 连续调用多次 edit_file
  2. 或者使用 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"按修改时间排序

注意事项

注意

  1. 递归深度限制recursive=true 时,默认最大递归深度为 5 层。这是为了防止在包含大量子目录的项目(如 node_modules)中卡死。
  2. 权限过滤:没有读取权限的目录会被跳过,并在结果中标注 [权限不足]
  3. 符号链接:默认会跟随符号链接,但最多跟随 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 文件

注意事项

注意

  1. 二进制文件跳过search_files 会自动跳过二进制文件(图片、视频、压缩包等),避免无意义的匹配。
  2. 大文件处理:超过 100MB 的文件会被标记为 [文件过大,仅搜索前 1000 行]
  3. 忽略目录:默认会跳过 .gitnode_modules__pycache__vendor 等常见依赖目录。如果需要搜索这些目录,可以显式指定 path

常见问题

Q: 搜索太慢怎么办?

A: 优化搜索速度的几种方法:

  1. 缩小 path 范围,不要从根目录开始搜
  2. 使用更精确的 glob 过滤,如 src/**/*.py
  3. 减小 max_results,如果只需要前几个结果
  4. 避免使用过于宽泛的正则,如 .*

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% 相同(忽略哈希碰撞这种极特殊情况)。

常见场景

场景用法说明
排查文件访问问题检查 permissionsowner确认当前用户有读取权限
判断文件类型查看 mime_type决定后续处理方式
检查文件新鲜度对比 modified 时间确认文件是否是最新版本
验证下载完整性compute_hash=true对比官方提供的哈希值

注意事项

注意

  1. 符号链接:如果目标文件是符号链接,file_info 默认返回链接目标的信息。如果你想获取链接本身的信息,目前需要配合 execute_shell 使用 ls -la
  2. 不存在的文件:如果文件不存在,工具不会报错,而是返回 "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_directorysearch_files 探索,用 read_file 确认细节,最后用 edit_filewrite_file 执行修改。不要跳过「探索」和「确认」步骤直接修改——这就像不看路就开车,很容易出问题。

本章小结

本章我们详细讲解了 6 个文件系统工具:

  • read_file:读取文件内容,支持分段读取和编码自动检测
  • write_file:创建或覆盖文件,支持追加模式和自动备份
  • edit_file:精确替换文件中的特定文本片段,默认自动备份
  • list_directory:列出目录内容,支持递归和过滤
  • search_files:grep 风格的文件搜索,支持正则和上下文显示
  • file_info:获取文件元数据,包括大小、时间、权限、哈希值

核心原则

  1. 先读再写:修改文件前先 read_file 确认内容
  2. 搜索定位:用 search_files 找到精确位置,再用 edit_file 修改
  3. 备份保护:重要文件操作开启 backup=true
  4. 分段读取:大文件使用 offsetlimit,避免上下文溢出

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, numpyCSV/Excel 数据清洗和分析
数据可视化matplotlib, seaborn生成统计图表
文本处理re, json, csv正则匹配、JSON 解析
网络请求requests调用 API 获取数据
文件操作os, shutil, pathlib批量文件处理
科学计算scipy, numpy数值计算和算法

注意事项

注意

  1. 不要假设包已安装:Hermes 的基础 Python 环境只包含标准库。使用第三方库时,务必在 packages 中声明。如果执行时 import 失败,工具会给出清晰的错误提示。
  2. 输出长度限制print() 的输出如果超过 10,000 字符,会被截断。对于大量数据,建议保存到文件,再用 read_file 读取。
  3. 状态不持久:每次 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 /:()&#123; : | :& &#125;;: 等危险命令直接拒绝 | | 沙箱层 | 文件系统隔离 | 默认只能在当前工作目录操作 | | 超时层 | 执行时间限制 | 默认 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 的安全过滤器采用「宁可错杀,不可放过」的策略。如果命令包含危险关键字(如 mkfsdd if=/dev),即使上下文是安全的,也会被拒绝。遇到这种情况,可以:

  1. 尝试用更安全的替代命令
  2. 或者手动在终端执行,然后把结果告诉 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_javascriptexecute_python 的选择原则:如果项目主要是 Node.js 生态(前端、npm 包),用 JavaScript 更自然;如果是数据科学、后端脚本,用 Python 更合适。对于纯 JSON 处理,两者都可以。

注意事项

注意

  1. Node.js 版本:Hermes 使用系统默认的 Node.js 版本。如果你需要特定版本,可以在 ~/.hermes/config.yaml 中配置 tools.javascript.node_path
  2. TypeScript 支持:如果代码以 .ts 语法编写(包含类型注解),Hermes 会自动调用 ts-nodetsx 执行。确保这些工具已全局安装。

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 MB64-2048 MB超过会被 OOM Kill
CPU1 核1-4 核限制 CPU 使用率
磁盘100 MB10-1000 MB沙箱内可写空间
网络禁用可开启默认完全隔离
执行时间60 秒10-300 秒超时强制终止

注意

  1. 沙箱需要 Dockersandbox_run 依赖 Docker 容器技术。如果你的系统没有安装 Docker,这个工具会报错。在 macOS 和 Linux 上,Docker Desktop 或 Docker Engine 都可以。
  2. 首次启动较慢:创建沙箱容器需要几秒钟。如果需要频繁执行,可以考虑批量提交多个任务。
  3. 文件持久化:沙箱执行结束后,容器被销毁,内部文件也一并消失。如果需要保留输出,请确保代码将结果写入挂载的宿主机目录。

本章小结

本章我们深入讲解了 4 个代码执行工具:

  • execute_python:执行 Python 代码,适合数据分析、自动化脚本
  • execute_shell:执行 Shell 命令,功能最强但风险最高,强制审批
  • execute_javascript:执行 JavaScript/TypeScript,适合前端和 Node.js 项目
  • sandbox_run:在隔离沙箱中执行代码,运行不可信代码的首选

安全使用原则

  1. 默认用沙箱:不确定安全性的代码,先用 sandbox_run
  2. 最小权限:只给代码执行所需的最小权限(网络、文件访问)
  3. 超时保护:对于可能死循环的代码,设置合理的 timeout
  4. 审计日志:所有代码执行都有日志记录,定期审查

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

搜索查询的质量直接影响结果质量。几个提升搜索效果的小技巧:

  1. 用英文搜索:技术类内容英文搜索结果通常更好
  2. 加关键词限定:如 Python asyncio best practices 2024Python async 更精准
  3. 用 site: 限定来源error solution site:stackoverflow.com
  4. 用引号精确匹配"Hermes Agent" framework

搜索语法速查表

技巧语法示例
精确短语"exact phrase""machine learning"
排除关键词-keywordPython -snake
限定网站site:domainsite:github.com
文件类型filetype:extfiletype:pdf
时间范围after:YYYY-MM-DDafter:2024-01-01
OR 条件A OR BReact OR Vue
通配符*best * framework

注意事项

注意

  1. 结果不保证实时:搜索引擎的索引有延迟,最新发布的内容可能需要几小时甚至几天才能被收录。
  2. API 配额:如果使用 Google 或 Bing 后端,注意 API 调用配额。DuckDuckGo 没有硬配额限制,但频繁请求可能触发反爬虫。
  3. 结果去重:Hermes 会自动对搜索结果进行去重和排序,优先返回权威来源(如官方文档、知名技术博客)。

常见问题

Q: 搜索返回空结果怎么办?

A: 尝试以下方法:

  1. 简化查询词,去掉过于具体的关键词
  2. 换用不同的搜索引擎(如从 DuckDuckGo 换到 Bing)
  3. 检查网络连接,确认能正常访问搜索引擎
  4. 如果是中文搜索,尝试用英文关键词

Q: 如何搜索学术论文?

A: 推荐使用 site:arxiv.orgsite: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 文件,你就得到了一份完整的离线学习资料。

注意事项

注意

  1. 动态内容限制:如果网页内容是通过 JavaScript 动态加载的(如 React/Vue 单页应用),web_extract 可能只能获取到初始 HTML 骨架,看不到动态内容。这种情况下需要使用 web_browse 工具。
  2. 反爬虫机制:某些网站会检测并阻止自动化访问。如果遇到 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 代码)

注意事项

注意

  1. 资源消耗:无头浏览器比普通 HTTP 请求消耗更多内存和 CPU。不要同时打开太多浏览器实例。
  2. 超时设置:某些网页加载很慢(特别是有大量 JavaScript 的页面)。如果 wait_for 的元素一直没出现,工具会超时。可以适当增加 timeout 参数。
  3. 人机验证:对于需要 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&#123;"Authorization": "Bearer YOUR_TOKEN"&#125;
Basic Auth&#123;"Authorization": "Basic base64(user:pass)"&#125;
API Key (Header)&#123;"X-API-Key": "your_key"&#125;
API Key (Query)params=&#123;"api_key": "your_key"&#125;

注意事项

注意

  1. 敏感信息:不要在 bodyheaders 中硬编码 API Key。建议存储在环境变量中,通过 env 参数注入。
  2. 响应大小限制:如果响应体超过 1MB,会被截断。对于大文件下载,建议使用 execute_shell 配合 curlwget
  3. 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 提供了更友好的接口,自动处理认证、分页、错误重试等常见问题。

内置适配器

服务适配器名称说明
OpenAIopenaiGPT 模型调用
AnthropicanthropicClaude 模型调用
GitHubgithub仓库、Issue、PR 操作
Slackslack消息发送
DiscorddiscordWebhook 消息
Notionnotion页面、数据库操作
Twitter/Xtwitter推文操作(需 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"
)

注意事项

注意

  1. 监控任务持久化web_monitor 创建的任务会在 Hermes 后台持续运行,即使 Agent 会话结束也不会停止。需要在 ~/.hermes/monitors/ 目录下查看和管理所有监控任务。
  2. 频率限制:不要设置过短的检查间隔(如几秒),这会对目标网站造成压力,也可能触发反爬虫机制。建议至少 5 分钟以上的间隔。
  3. 变化检测算法:默认使用文本相似度算法检测变化。对于动态内容(如时间戳、广告轮播),建议使用 selector 限定只监控核心内容区域。

本章小结

本章我们详细讲解了 8 个 Web 交互工具:

  • web_search:网络搜索,Agent 获取实时信息的主要渠道
  • web_extract:提取网页正文,去除噪音保留核心内容
  • web_browse:控制无头浏览器,处理 JavaScript 动态内容
  • web_screenshot:截取网页截图,支持全屏和元素截图
  • http_request:通用 HTTP 客户端,调用 REST API
  • rss_fetch:获取 RSS/Atom 订阅源内容
  • api_call:高级 API 调用,内置多种服务适配器
  • web_monitor:监控网页变化,自动化跟踪内容更新

使用建议

  1. 信息获取链web_searchweb_extractwrite_file 是最常见的信息收集工作流
  2. API 调用优先用适配器:如果 api_call 支持你的目标服务,优先使用它而不是裸 http_request
  3. 截图+分析组合web_screenshot + image_analyze 可以实现「看图说话」
  4. 监控任务管理:定期检查 ~/.hermes/monitors/,清理不再需要的监控任务

5. 第四类:终端命令工具 —— Agent 的「系统管理员」套装

本章你将学到

  • 5 个终端命令工具的功能和使用场景
  • 危险命令的分级处理机制,理解为什么有些命令需要反复确认
  • 后台任务管理和进程控制的完整工作流
  • 如何安全地使用系统命令而不破坏环境
  • run_commandexecute_shell 的区别和选择策略

终端命令工具让 Agent 能够与你的操作系统直接交互——运行程序、管理进程、获取系统信息。这些工具是 Agent 的「系统管理员」套装,让它从「文件编辑者」升级为「系统操控者」。

5.1 run_command —— 运行系统命令

功能说明

run_commandexecute_shell 的「轻量版」。它们都执行系统命令,但 run_command 的安全级别更高、审批更轻量。

关键区别:

特性run_commandexecute_shell
风险等级中风险高风险
审批策略可配置为自动允许(白名单内)强制每次审批
命令白名单支持不支持(全部审批)
适用场景日常命令(git、npm、ls)复杂/危险操作

run_command 的设计思路是:对于常用的、相对安全的命令(如 git statusnpm installpython 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" # 每次都提示

注意事项

注意

  1. 命令注入风险:不要在 command 中拼接用户输入的内容。如果必须拼接,要对特殊字符进行转义。比如 command=f"grep &#123;user_input&#125; file.txt" 中,如果 user_input"; rm -rf /;",就会导致灾难。
  2. 长命令处理:如果命令输出很长(如 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/&lt;task_id&gt;.log。如果任务输出异常或崩溃,可以用 read_file 查看日志文件排查问题。

注意事项

注意

  1. 任务持久性:后台任务在 Hermes 进程退出后不会自动保留。如果需要真正的守护进程,建议使用系统的 systemd、launchd 或 pm2 等工具。
  2. 资源限制:每个后台任务默认有资源限制(CPU 50%、内存 512MB)。超过限制的任务会被强制终止。
  3. 端口冲突:如果后台任务需要监听端口(如开发服务器),确保端口没有被其他进程占用。

5.3 process_list —— 进程列表

功能说明

process_list 用于查看当前系统运行的进程列表。它是 pstasklist 命令的封装,但提供了更友好的输出格式和过滤功能。

参数详解

{
  "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 是最快的诊断工具。几秒钟内就能看到系统的全貌,避免盲目猜测。

注意事项

注意

  1. 隐私信息system_info 不会返回敏感信息(如密码、密钥、详细的网络拓扑),但会返回主机名、IP 地址等基本信息。如果你在共享环境中使用,注意这些信息可能暴露你的身份。
  2. 动态数据:CPU 使用率和内存使用率是实时数据,每次调用都会变化。

本章小结

本章我们讲解了 5 个终端命令工具:

  • run_command:运行系统命令,安全轻量,支持白名单
  • background_task:后台任务管理,启动、停止、监控长时间运行的任务
  • process_list:查看系统进程列表,支持过滤和排序
  • kill_process:终止进程,高风险操作,默认优雅终止
  • system_info:获取系统硬件和软件信息

安全使用原则

  1. 优先用 run_command:日常命令用它,只有白名单外的复杂命令才用 execute_shell
  2. 终止前三思:kill_process 前先用 process_list 确认目标
  3. 后台任务监控:定期检查 background_task list,防止僵尸任务占用资源
  4. 环境诊断:遇到问题时,先 system_info 了解全局,再针对性排查

6. 第五类:记忆管理工具 —— Agent 的「笔记本」和「档案馆」

本章你将学到

  • 6 个记忆管理工具的完整用法
  • 会话记忆与持久记忆的读写区别
  • FTS5 全文索引的查询语法和高级用法
  • 记忆的隐私保护和清理策略
  • 如何构建高效的「记忆-检索-更新」工作流

记忆管理工具让 Agent 能够读写、搜索、管理自己的记忆系统。在第七册中,我们已经深入了解了 Hermes 的三层记忆架构。本章我们将从「工具使用」的角度,讲解如何操作这些记忆。

6.1 memory_read —— 读取记忆

功能说明

memory_read 用于读取 Agent 的记忆内容。它可以读取不同类型的记忆文件,包括:

  • 会话记忆(热记忆):当前对话的上下文
  • 持久记忆(温记忆)MEMORY.mdUSER.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 去查找。

注意事项

注意

  1. 隐私边界memory_read 只能读取当前 Agent 实例的记忆,不能访问其他 Agent 或用户的记忆。
  2. 记忆层级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 就能「记得」你是谁,不用每次都重新介绍。

注意事项

注意

  1. 键名规范:建议使用层级键名(如 用户偏好.编辑器项目.当前任务),这样便于组织和管理。
  2. 内容长度:单条记忆建议不超过 2000 字符。过长的内容应该拆分成多条记忆,或者保存为文件后只把文件路径记入记忆。
  3. 敏感信息:不要在记忆中写入密码、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 &lt;session_id&gt; 命令查看。

本章小结

本章我们讲解了 6 个记忆管理工具:

  • memory_read:读取记忆,支持会话、持久、检索三种类型
  • memory_write:写入记忆,记录用户偏好和上下文信息
  • memory_update:更新记忆,支持替换、追加、前置、合并四种操作
  • memory_delete:删除记忆,需要确认防止误删
  • memory_search:搜索历史记忆,基于 FTS5 全文索引
  • session_search:搜索历史会话,找回之前的对话内容

记忆管理最佳实践

  1. 结构化键名:使用层级键名(如 用户偏好.编辑器)便于组织
  2. 打标签:写入时添加 tags,搜索时可以通过标签快速过滤
  3. 定期清理:过期或不再相关的记忆及时删除,保持记忆库精简
  4. 敏感信息隔离:密码、API Key 等敏感信息不要存入记忆

7. 第六类:技能管理工具 —— Agent 的「技能学院」管理员

本章你将学到

  • 6 个技能管理工具的完整用法
  • Skill 文件的格式规范和路径约定
  • 从 Skills Hub 浏览、安装、更新技能的完整流程
  • 技能版本管理和冲突解决
  • 自定义技能的创建和调试方法

技能管理工具让 Agent 能够管理自己的「技能库」——创建新技能、查看已有技能、更新技能内容、安装社区技能。这是 Skill 系统的「元操作」工具集。

7.1 skill_create —— 创建技能

功能说明

skill_create 用于创建新的 Skill 文件。在第八册中,我们了解到 Skill 是存放在 ~/.hermes/skills/&lt;name&gt;/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
# 代码审查报告

## 文件: &#123;filename&#125;

### 发现的问题

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
# 技能名称

## 触发条件
(描述什么情况下触发这个技能)

## 执行步骤
(具体的操作步骤,可以包含工具调用)

## 输出格式
(期望的输出格式)

## 示例
(输入输出示例)

注意

  1. 名称规范:技能名称只能包含小写字母、数字、连字符(-)和下划线(_)。不要包含空格或特殊字符。
  2. 路径安全skill_create 只能创建到 ~/.hermes/skills/ 目录下,不能写入系统其他位置。
  3. 语法检查:创建后 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 核心团队维护,随安装包分发
官方经过官方审核,从官方仓库安装
可信🔒签名验证通过,来自可信作者
社区👥社区贡献,未经过严格审核

注意

  1. 网络要求:从 Hub 安装需要网络连接。如果处于离线环境,可以手动下载技能文件放到 ~/.hermes/skills/ 目录下。
  2. 依赖安装:某些技能有额外的依赖(如 Python 包、Node.js 包)。skill_install 会自动安装这些依赖,但可能需要你的确认。
  3. 版本冲突:如果已安装同名技能,skill_install 默认会报错。可以使用 overwrite=true 强制覆盖。

本章小结

本章我们讲解了 6 个技能管理工具:

  • skill_create:创建新技能,编写 SKILL.md 文件
  • skill_read:查看技能内容,了解触发条件和执行步骤
  • skill_update:更新技能,支持全量替换和差异补丁
  • skill_delete:删除技能,自动创建备份
  • skill_list:列出所有已安装技能,支持过滤和搜索
  • skill_install:从 Skills Hub 安装社区技能

技能管理最佳实践

  1. 命名规范:技能名称使用小写字母和连字符,如 code-review-helper
  2. 信任等级:安装社区技能前查看信任等级,不安全的技能不要安装
  3. 定期清理:删除不再使用的技能,保持技能库精简
  4. 版本管理:重要技能更新前先用 skill_read 备份旧版本

8. 第七类:代理委托工具 —— 多 Agent 协作的「调度中心」

本章你将学到

  • 5 个代理委托工具的功能和使用场景
  • 多 Agent 并发编排的实际案例
  • 最多 3 个子 Agent 并行的限制原因和应对策略
  • 子 Agent 间的通信机制和状态同步
  • 委托任务的拆分粒度和最佳实践

代理委托工具是 Hermes 最高阶的工具类别。它们让单个 Agent 能够「分身」——创建多个子 Agent,各自执行不同的子任务,最后汇总结果。这是处理复杂任务、实现并行计算、模拟团队协作的核心能力。

8.1 delegate_task —— 委托子任务

功能说明

delegate_task 是代理委托系统的核心工具。它允许当前 Agent(称为「主 Agent」或「Parent」)将一个子任务分配给另一个 Agent(称为「子 Agent」或「Child」)执行。

委托的工作流程:

  1. 主 Agent 分析任务,决定可以拆分成哪些子任务
  2. 主 Agent 调用 delegate_task,指定子任务的描述和目标
  3. Hermes 创建或复用子 Agent,分配任务
  4. 子 Agent 独立执行,使用自己的工具链
  5. 子 Agent 完成后,结果返回给主 Agent
  6. 主 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/&lt;agent_id&gt;/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 分钟

注意

  1. 资源释放:终止 Agent 会释放其占用的内存和上下文资源,但已写入文件或记忆的内容会保留。
  2. 强制终止:如果 Agent 陷入死循环或无法响应,使用 force=true 强制终止。但这可能导致未保存的数据丢失。

多 Agent 并发限制说明

Hermes 对子 Agent 的并行数量有严格限制:最多同时运行 3 个子 Agent

这个限制的设计原因:

原因说明
资源保护每个子 Agent 都消耗内存和 Token,过多会导致系统卡顿
质量控制并行太多,主 Agent 的协调成本会超过并行收益
成本考量每个子 Agent 都独立调用 LLM,过多会快速消耗 API 配额
调试难度并行 Agent 越多,问题定位和结果汇总越困难

应对策略

  1. 分批处理:如果任务可以拆成 10 个子任务,分 4 批执行(3+3+3+1)
  2. 任务合并:将相关性强的子任务合并,减少 Agent 数量
  3. 串行执行:对于前后依赖的任务,串行执行比并行更合理

本章小结

本章我们讲解了 5 个代理委托工具:

  • delegate_task:委托子任务给子 Agent 执行
  • agent_spawn:显式创建子 Agent 实例
  • agent_communicate:Agent 间发送消息
  • agent_status:查看子 Agent 状态和进度
  • agent_terminate:终止子 Agent 释放资源

多 Agent 协作最佳实践

  1. 任务拆分粒度:每个子任务 3-10 分钟完成为宜,不要太细也不要太粗
  2. 并行限制:最多 3 个子 Agent 并行,超出需分批
  3. 通信简洁:Agent 间消息要简洁明了,避免长上下文传递
  4. 状态监控:定期 agent_status 检查子 Agent 状态,及时发现卡死
  5. 资源释放:任务完成后及时 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复制文章,生成摘要后分享

注意事项

注意

  1. 隐私敏感:剪贴板可能包含密码、银行卡号等敏感信息。Agent 读取剪贴板时,会在日志中记录操作,但不会长期保存剪贴板内容。
  2. 平台兼容性clipboard 在 macOS、Linux(需 xclip/xsel)和 Windows 上都可用,但某些远程 SSH 会话中可能无法访问剪贴板。
  3. 大小限制:剪贴板内容超过 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

notificationweb_monitor 的组合是构建自动化监控系统的经典搭配。当网页监控检测到异常时,立即发送通知,让你第一时间知道问题。

平台支持

平台通知方式说明
macOSNotification Center显示在屏幕右上角
Linuxnotify-send / libnotify需要安装通知服务
WindowsToast NotificationWindows 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 &lt;name&gt; 删除任务。

注意事项

注意

  1. 系统时钟:定时任务依赖系统时钟,确保你的系统时间准确。
  2. 任务重叠:如果一个任务执行时间超过了执行间隔,下一次执行会在当前执行完成后立即开始。对于耗时任务,建议设置足够的间隔。
  3. 睡眠唤醒:如果系统在任务执行时间点处于睡眠状态,任务会在系统唤醒后尽快补执行(取决于操作系统调度)。

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 结构。

注意事项

注意

  1. 模型依赖image_analyze 需要后端 LLM 支持多模态(Vision)。如果使用的是纯文本模型(如某些 GPT-3.5 版本),这个工具会报错。
  2. 图像大小:建议图像不超过 5MB。过大的图像会自动压缩,可能影响分析精度。
  3. 隐私注意:图像会被发送到 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),转写精度越高,但速度越慢。对于中文内容,建议使用 mediumlarge 模型。如果只是快速预览,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_formatJSON 格式化
json_minifyJSON 压缩
base64_encodeBase64 编码
base64_decodeBase64 解码
url_encodeURL 编码
url_decodeURL 解码
html_escapeHTML 转义
html_unescapeHTML 反转义
markdown_to_htmlMarkdown 转 HTML
html_to_markdownHTML 转 Markdown
camel_to_snake驼峰转下划线
snake_to_camel下划线转驼峰
remove_extra_spaces去除多余空格
fix_line_endings统一换行符
count_words统计字数

Tips

text_transform 是处理「格式混乱数据」的救星。比如从网页复制的内容经常带有奇怪的空格和换行,用 remove_extra_spacesfix_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 工具。比如「用计算器精确计算这笔投资的年化收益率」,而不是让它心算。这样能保证结果的准确性。

支持的运算符和函数

类型示例
基础运算+, -, *, /, //, %, **
比较==, !=, &lt;, &gt;, &lt;=, &gt;=
数学函数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 数学幻觉

辅助工具使用建议

  1. 剪贴板是桥梁:用 clipboard 实现 Agent 与任意应用的快速交互
  2. 定时任务自动化:把重复性工作交给 schedule_task,Agent 就是你的 cron 助手
  3. 精确计算用 calculator:涉及数字的任务不要依赖 LLM 心算
  4. 图像+分析组合:web_screenshot + image_analyze 是分析网页的利器

10. 工具组合实战案例 —— 从「会用工具」到「善用工具」

本章你将学到

  • 4 个完整的多工具组合实战案例
  • 每个案例的完整工具调用链和输出说明
  • 如何根据任务特点选择合适的工具组合
  • 实战中常见问题的排查和解决

单个工具的能力是有限的,但工具组合起来就能产生化学反应。本章通过 4 个完整的实战案例,展示如何将多个工具串联起来,解决真实世界的复杂问题。

案例 1:自动化投研报告(web_search + web_extract + write_file + delegate_task)

场景描述

你是一名投资分析师,每周一早上需要提交一份「AI 行业周报」,内容包括:

  1. 过去一周 AI 领域的重要新闻(至少 10 条)
  2. 主要 AI 公司的股价变化
  3. 热门论文和技术突破摘要
  4. 行业趋势判断和投资建议

手动完成这份报告需要 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 项目的安全审计。需要:

  1. 扫描所有 Python 文件,找出潜在的安全漏洞
  2. 检查依赖包是否有已知漏洞
  3. 检查是否使用了危险的函数(如 evalexecpickle.loads
  4. 生成审计报告并保存
  5. 将审计流程保存为技能,以便以后复用

工具调用链

步骤 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. 监控首页是否正常加载
  2. 监控商品价格页面是否有异常
  3. 监控网站响应时间是否超过阈值
  4. 发现问题时立即发送通知
  5. 每天生成一份可用性报告

工具调用链

步骤 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. 执行摘要(1-2 页):核心观点和建议
  2. 技术分析(5-8 页):Layer 2、ZK、跨链等技术方向
  3. 市场分析(5-8 页):价格、投融资、市场份额
  4. 政策分析(3-5 页):监管框架和合规趋势
  5. 综合预测(2-3 页):未来 6-12 个月的趋势判断
  6. 附录:数据来源、术语表、参考文献

Tips

多 Agent 协作的关键在于清晰的职责划分标准化的输出格式。在委托任务时,明确指定每个 Agent 的专注领域和输出要求。如果输出格式不统一,汇总时会非常困难。建议在任务描述中附上输出模板。

本章小结

本章通过 4 个实战案例,展示了工具组合的强大威力:

案例核心工具组合解决的问题
自动化投研报告web_search + web_extract + delegate_task信息收集与报告生成自动化
代码审计流水线read_file + search_files + skill_create安全审计流程化、可复用
网站监控 + 通知web_monitor + notification + schedule_task7x24 可用性监控
多 Agent 研究团队agent_spawn + delegate_task + memory_write复杂任务的专家分工协作

组合设计原则

  1. 并行优于串行:能并行的子任务尽量并行(受 3 Agent 限制)
  2. 记忆是纽带:多 Agent / 多步骤之间通过 memory_write/memory_read 传递信息
  3. 技能沉淀:将成功的工具组合保存为 Skill,实现一次配置、多次复用
  4. 通知闭环:耗时任务和监控任务一定要有 notification,避免「石沉大海」

11. 工具开发与扩展 —— 打造你的专属工具

本章你将学到

  • 自定义工具的开发方法和完整示例
  • ToolRegistry 的注册机制详解
  • MCP 协议工具扩展的方法和原理
  • 社区工具贡献的流程和规范
  • 工具开发的调试和测试技巧

Hermes 的 47 个内置工具覆盖了绝大多数常见场景,但总有一些特定需求需要自定义工具。比如:

  • 你的公司有一个内部 API,需要专门的调用工具
  • 你经常使用某个特定的 SaaS 服务(如 Jira、Confluence)
  • 你需要与本地特定的硬件设备交互
  • 你想封装一套常用的数据处理逻辑

本章将教你如何开发和扩展 Hermes 工具。

11.1 自定义工具的开发方法

开发自定义工具的核心步骤:

  1. 继承 Tool 基类:创建一个新的 Python 类,继承 hermes.core.tools.Tool
  2. 定义元数据:使用 @tool 装饰器定义工具名称、描述、参数
  3. 实现 execute 方法:编写工具的实际执行逻辑
  4. 注册到 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):
        """执行后钩子,可选重写"""
        pass

ToolResult 结构

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 的加载优先级是:

  1. 用户自定义工具(最高优先级)
  2. 插件工具
  3. 内置工具(最低优先级)

这意味着你可以用自定义工具覆盖内置工具。比如你觉得内置的 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

  1. 在 GitHub 上 fork hermes-tools 仓库
  2. tools/ 目录下创建你的工具目录
  3. 编写工具代码和 README 文档
  4. 提交 Pull Request
  5. 等待审核(通常 3-5 个工作日)

工具贡献检查清单

- [ ] 工具代码完整,包含错误处理
- [ ] 包含完整的参数定义和类型注解
- [ ] 包含单元测试(覆盖率 > 80%)
- [ ] 包含使用示例
- [ ] README 文档包含功能说明、安装方法、使用示例
- [ ] 不包含敏感信息(API Key、密码等)
- [ ] 遵循 Hermes 代码风格
- [ ] 工具名称不与现有工具冲突

审核标准

等级要求
官方(Official)通过全部检查清单 + 核心团队审核 + 签名验证
可信(Trusted)通过全部检查清单 + 自动化测试通过
社区(Community)基本功能正常 + 有文档

本章小结

本章我们讲解了工具开发与扩展的完整流程:

  • 自定义工具开发:继承 Tool 基类,实现 execute 方法,使用 @tool 装饰器注册
  • 注册机制:装饰器自动注册、手动注册、配置文件指定路径三种方式
  • MCP 协议:标准化的工具扩展协议,语言无关,安全隔离
  • 社区贡献:通过 GitHub PR 贡献工具,经过审核后进入 Skills Hub

开发建议

  1. 从简单开始:先 clone 一个内置工具的代码,在此基础上修改
  2. 测试驱动:为工具编写单元测试,确保参数校验和边界条件处理正确
  3. 文档先行:写工具前先写文档,明确工具的输入输出和边界情况
  4. 考虑 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.json

12.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.36

12.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 会收到错误信息并决定如何处理。好的错误信息应该:

  1. 说明发生了什么错误
  2. 解释可能的原因
  3. 给出具体的解决建议

这样的错误信息能帮助 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:忽视 offsetlimit,读取超大文件

❌ 错误:
→ 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 大核心原则

  1. 安全第一:敏感操作必须审批,遵循最小权限原则
  2. 组合优于单打:复杂任务用工具链,而不是单个工具
  3. 成本意识:减少不必要的 API 调用,批量处理更高效
  4. 错误处理:工具调用失败时要有应对策略
  5. 及时清理:用完的 Agent 要终止,临时任务要删除

10 个常见误区回顾

  1. write_file 做所有修改(应优先用 edit_file
  2. 忽视 offset/limit 读取超大文件
  3. 在 Shell 命令中拼接未转义的用户输入
  4. 重复安装相同的 Python 包
  5. web_search 查询本地知识
  6. 创建监控任务不清理
  7. 忽略工具的返回值和错误信息
  8. 过度使用 execute_shell 做简单的事情
  9. 不备份就修改重要文件
  10. 创建 Agent 后不终止造成资源泄漏

进阶建议

  • 定期运行 hermes tools stats 分析工具使用模式
  • 建立团队的「工具使用规范」文档
  • 把常用的工具组合沉淀为 Skill
  • 关注 Hermes 更新日志,及时使用新工具

结语:工具是手段,解决问题才是目的

到这里,我们已经走完了 Hermes 47 个内置工具的完整旅程。从文件系统的基础操作,到代码执行的强大能力;从 Web 交互的信息获取,到多 Agent 协作的复杂编排——这些工具构成了 Hermes Agent 的「四肢百骸」,让它从一个只会聊天的「大脑」,变成了能够动手解决问题的「全能助手」。

但请记住,工具永远只是手段,而不是目的。掌握 47 个工具的名字和参数很容易,难的是知道「什么时候该用什么工具」「如何把工具组合起来解决真实问题」。

就像一位经验丰富的工匠,他不需要记住每一种工具的所有规格,但他知道:什么时候该用锤子,什么时候该用凿子,什么时候需要两只手配合。这种「手感」,只能通过大量的实践来培养。

所以,打开你的终端,启动 Hermes,开始动手吧。从简单的「读取一个文件」开始,到复杂的「多 Agent 协作完成研究报告」,每一步都会让你对工具的理解更深一层。

工具在手,天下我有。祝你在 Hermes 的世界里,探索愉快!