工具运行时
Hermes Agent 的工具系统是其核心能力之一。本页详细介绍工具从注册到执行的完整生命周期。
核心概念
工具是 AIAgent 可以调用以执行动作的函数。它们:
- 由 LLM 通过
function_callAPI 调用 - 在隔离的沙箱中执行(Docker、Modal 或本地)
- 返回结构化结果回到 LLM 上下文
主要组件:
agent/tool_manager.py— 工具注册和分发agent/tool_parser.py— 解析 LLM 函数调用sandbox/— 各种沙箱执行后端
工具调用生命周期
1. LLM 返回 function_call → 2. tool_parser 解析 → 3. tool_manager 分发 → 4. 沙箱执行 → 5. 结果返回
1. 工具注册
工具在启动时注册到 AIAgent:
# 每个工具集贡献工具
self.tool_manager.register(terminal)
self.tool_manager.register(read_file)
self.tool_manager.register(write_file)
# ... 等等
每个工具都有:
name— 函数名description— LLM 可见的描述parameters— JSON Schema 参数定义handler— 实际执行函数
2. 解析 function_call
LLM 返回的 function_call 格式:
{
"name": "terminal",
"arguments": "{\"command\": \"ls -la\"}"
}
tool_parser.py 负责:
- 解析参数字符串为字典
- 验证必需参数
- 处理参数类型转换
- 错误处理
3. 参数验证
工具参数通过 JSON Schema 验证:
def validate_parameters(tool_schema, args):
"""验证参数是否符合 schema"""
for required in tool_schema.get('required', []):
if required not in args:
raise MissingRequiredArg(f"Missing required: {required}")
# 类型检查等等
4. 沙箱执行
工具在隔离环境中执行:
| 后端 | 使用场景 | 隔离级别 |
|---|---|---|
local | 开发/调试 | 无(同一进程) |
docker | 生产,默认 | 容器隔离 |
modal | 远程计算 | 远程容器 |
执行流程:
async def execute_tool(name, args, sandbox='docker'):
if sandbox == 'docker':
return await docker_sandbox.execute(name, args)
elif sandbox == 'modal':
return await modal_sandbox.execute(name, args)
else:
return await local_execute(name, args)
5. 结果处理
工具结果格式:
{
"success": true,
"output": "file1.txt\nfile2.txt\n...",
"error": null,
"metadata": {
"duration_ms": 45,
"sandbox": "docker"
}
}
工具定义格式
每个工具定义遵循此结构:
class Tool:
name: str # 函数名
description: str # 描述(LLM 使用)
parameters: dict # JSON Schema
requiresApproval: bool # 是否需要用户审批
sandbox: str # 'local', 'docker', 'modal'
async def execute(self, args: dict, context: dict) -> dict:
"""执行工具逻辑"""
pass
内置工具集
文件工具
| 工具 | 描述 | 沙箱 |
|---|---|---|
read_file | 读取文件内容 | docker |
write_file | 写入文件 | docker |
edit_file | 编辑文件(行级别) | docker |
list_dir | 列出目录 | docker |
glob | 文件模式匹配 | docker |
grep | 文本搜索 | docker |
终端工具
| 工具 | 描述 | 沙箱 |
|---|---|---|
terminal | 执行 shell 命令 | docker |
execute_code | 执行 Python/JS 代码 | docker/modal |
网络工具
| 工具 | 描述 | 沙箱 |
|---|---|---|
web_search | 网络搜索 | docker |
web_extract | 从 URL 提取内容 | docker |
http_request | 发起 HTTP 请求 | docker |
记忆工具
| 工具 | 描述 | 沙箱 |
|---|---|---|
memory_read | 读取记忆 | local |
memory_write | 写入记忆 | local |
session_search | 搜索会话历史 | local |
沙箱安全
Docker 沙箱
# 最小权限容器
FROM python:3.11-slim
USER nonroot
# 无网络访问(除非工具需要)
# 只读文件系统(除了工作目录)
关键安全措施:
- 非 root 用户运行
- 网络隔离(可配置)
- 资源限制(CPU/内存)
- 只读文件系统(工作目录除外)
环境变量隔离
敏感环境变量不会传递给沙箱:
# 注入到沙箱的环境变量(已清理)
safe_env = {
'PATH': os.environ['PATH'],
'HOME': '/root', # 沙箱内的主目录
# 不包含 API 密钥!
}
工具错误处理
工具错误被分类处理:
class ToolError(Exception):
"""工具执行中的错误"""
pass
class NetworkError(ToolError):
"""网络相关错误"""
pass
class PermissionError(ToolError):
"""权限不足"""
pass
class TimeoutError(ToolError):
"""执行超时"""
pass
LLM 接收结构化错误消息以从中恢复:
{
"success": false,
"error": "File not found: /path/to/file.txt",
"error_type": "FileNotFoundError",
"recoverable": true
}