Hermes Subagent 设计
b1babo
2026年4月19日
2026年4月19日
Hermes Subagent 设计
目录
概述
Hermes Agent 实现了一套完整的子代理委托系统,允许父代理创建隔离的子代理来并行执行任务。
核心特性
- 上下文隔离: 每个子代理拥有全新的对话上下文
- 独立资源: 独立的 terminal session、task_id、文件操作缓存
- 并行执行: 支持多子代理并行工作
- Token 效率: 只有最终摘要进入父代理上下文
关键文件
| 文件 | 行数 | 作用 |
|---|---|---|
tools/delegate_tool.py | 1104 | 子代理创建、管理、通信 |
run_agent.py | 10000+ | AIAgent 类、父代理状态管理 |
environments/agent_loop.py | 535 | 多轮代理引擎 |
tools/mixture_of_agents_tool.py | - | MoA 多模型协作 |
toolsets.py | 703 | 工具集定义 |
核心架构
Subagent 创建流程
用户调用 delegate_task()
│
▼
_build_child_agent() 创建子 AIAgent 实例
│
├── 构建独立 system prompt
├── 隔离工具集(过滤阻塞工具)
├── 独立 terminal session
└── 进度回调注册
│
▼
_run_single_child() 执行子代理对话
│
├── 心跳更新(防止网关超时)
├── 工具调用中继到父代理
└── 结果收集
│
▼
返回结构化结果到父代理上下文隔离机制
# 子代理属性
AIAgent(
base_url=effective_base_url,
api_key=effective_api_key,
model=effective_model,
enabled_toolsets=child_toolsets, # 受限工具集
quiet_mode=True, # 静默模式
ephemeral_system_prompt=child_prompt, # 专用任务提示
log_prefix=f"[subagent-{task_index}]",
skip_context_files=True, # 不加载 SOUL.md/AGENTS.md
skip_memory=True, # 不访问共享记忆
clarify_callback=None, # 无用户交互
tool_progress_callback=child_progress_cb, # 进度中继
)安全限制
# tools/delegate_tool.py
DELEGATE_BLOCKED_TOOLS = frozenset([
"delegate_task", # 禁止递归委托
"clarify", # 禁止用户交互
"memory", # 禁止写入共享记忆
"send_message", # 禁止跨平台副作用
"execute_code", # 强制逐步推理
])
MAX_DEPTH = 2 # 父代理(0) → 子代理(1) → 孙代理(2)被拒绝调用方式
1. delegate_task 工具
单任务模式
delegate_task(
goal="调试为什么测试失败",
context="错误:test_foo.py 第42行断言失败",
toolsets=["terminal", "file"],
max_iterations=50
)批量/并行模式
delegate_task(tasks=[
{"goal": "研究A主题", "toolsets": ["web"]},
{"goal": "研究B主题", "toolsets": ["web"]},
{"goal": "修复构建", "toolsets": ["terminal", "file"]}
])参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
goal | string | 子代理要完成的目标 |
context | string | 背景信息(文件路径、错误消息等) |
toolsets | array[] | 启用的工具集 |
tasks | array[] | 批量模式:并行任务列表 |
max_iterations | int | 每个子代理的最大轮次(默认50) |
acp_command | string | 覆盖子代理的 ACP 命令 |
acp_args | array[] | ACP 命令的参数 |
2. mixture_of_agents 工具
mixture_of_agents(
query="解决这个复杂的数学证明问题...",
reference_models=[
"anthropic/claude-opus-4.6",
"google/gemini-3-pro-preview",
"openai/gpt-5.4-pro",
"deepseek/deepseek-v3.2"
],
aggregator_model="anthropic/claude-opus-4.6"
)工具配置
核心工具列表
所有平台共享的核心工具:
# Web
web_search, web_extract
# Terminal + 进程管理
terminal, process
# 文件操作
read_file, write_file, patch, search_files
# 视觉 + 图像生成
vision_analyze, image_generate
# Skills 管理
skills_list, skill_view, skill_manage
# 浏览器自动化
browser_navigate, browser_snapshot, browser_click,
browser_type, browser_scroll, browser_back,
browser_press, browser_get_images,
browser_vision, browser_console
# 其他
text_to_speech, todo, memory, session_search,
clarify, execute_code, delegate_task, cronjob,
send_message各平台默认工具集
| 平台 | 工具集 | 说明 |
|---|---|---|
| CLI | hermes-cli | 全部核心工具 |
| Telegram | hermes-telegram | 全部核心工具 |
| Discord | hermes-discord | 全部核心工具 |
| 编辑器集成 | hermes-acp | VS Code/Zed/JetBrains(无消息/语音/澄清UI) |
| API 服务器 | hermes-api-server | HTTP API(无交互UI工具) |
基础工具集类别
"web" → web_search, web_extract
"terminal" → terminal, process
"file" → read_file, write_file, patch, search_files
"browser" → 浏览器自动化工具 + web_search
"vision" → vision_analyze
"delegation" → delegate_task
"code_execution"→ execute_code
"clarify" → clarify
"memory" → memory子代理默认配置
# cli-config.yaml.example
delegation:
max_iterations: 50
default_toolsets: ["terminal", "file", "web"]
model: "google/gemini-3-flash-preview"
provider: "openrouter"
max_concurrent_children: 3ACP 协议集成
什么是 ACP?
ACP = Agent Client Protocol,是一个让编辑器与 AI 代理通信的标准协议。
┌─────────────────────────────────────────────────────────────┐
│ 编辑器 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ VS Code │ │ Zed │ │ JetBrains│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └─────────────┴─────────────┘ │
│ ▼ │
│ ACP Protocol (stdio) │
│ ▼ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Hermes Agent (ACP Server) │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘ACP 启动方式
# 方式1: hermes acp
hermes acp
# 方式2: hermes-acp
hermes-acp
# 方式3: Python 模块
python -m acp_adapter编辑器配置
VS Code:
{
"acpClient.agents": [
{
"name": "hermes-agent",
"registryDir": "/path/to/hermes-agent/acp_registry"
}
]
}Zed:
{
"agent_servers": {
"hermes-agent": {
"type": "custom",
"command": "hermes",
"args": ["acp"]
}
}
}传输机制
传输方式决策流程
AIAgent.__init__()
│
▼
┌─────────────────────────────────────────────────────────────┐
│ api_mode 判断 │
├─────────────────────────────────────────────────────────────┤
│ if api_mode == "anthropic_messages": │
│ → Anthropic HTTP SDK │
│ elif api_mode == "bedrock_converse": │
│ → AWS Bedrock SDK │
│ else: │
│ → OpenAI HTTP SDK (默认: chat_completions) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ client_kwargs 构建 │
├─────────────────────────────────────────────────────────────┤
│ if api_key and base_url: │
│ client_kwargs = {"api_key": ..., "base_url": ...} │
│ │
│ if provider == "copilot-acp": ← 只有这种情况 │
│ client_kwargs["command"] = self.acp_command │
│ client_kwargs["args"] = self.acp_args │
└─────────────────────────────────────────────────────────────┘三种传输方式
| api_mode | 客户端类型 | 传输方式 | 示例 |
|---|---|---|---|
chat_completions | OpenAI SDK | HTTP | OpenRouter、OpenAI |
anthropic_messages | Anthropic SDK | HTTP | Anthropic、MiniMax |
bedrock_converse | boto3 | HTTP | AWS Bedrock |
copilot-acp | CopilotACPClient | stdio 子进程 | GitHub Copilot |
默认 HTTP 通信
# 不设置 acp_command 时(默认情况)
AIAgent(
model="claude-opus-4-6",
provider="openrouter",
api_key="sk-or-...",
base_url="https://openrouter.ai/api/v1"
)
# 实际执行:
self.client = OpenAI(
api_key="sk-or-...",
base_url="https://openrouter.ai/api/v1"
)ACP 子进程通信
# 设置 acp_command 时
delegate_task(
goal="修复 bug",
acp_command="claude",
acp_args=["--acp", "--stdio"]
)
# 子代理实际执行:
AIAgent(
model="claude-opus-4-6",
provider="copilot-acp",
acp_command="claude",
acp_args=["--acp", "--stdio"]
)
# 使用 CopilotACPClient:
# → 启动子进程: subprocess.Popen(["claude", "--acp", "--stdio"])
# → 通过 stdin/stdout 进行 JSON-RPC 通信acp_command 的本质
┌─────────────────────────────────────────────────────────────────────┐
│ Hermes 子代理 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 不直接调用 LLM API │ │
│ │ 而是通过 ACP 协议转发请求给另一个 AI 客户端 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ ACP (stdio JSON-RPC) │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 独立的 AI 客户端进程 │ │
│ │ (如 Claude Code、GitHub Copilot) │ │
│ │ 这个客户端有自己的 LLM 访问能力 │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘工作流程对比:
不设置 acp_command(默认):
Hermes 子代理 → OpenAI SDK → HTTP → LLM API
↓
直接获取 LLM 响应设置 acp_command:
Hermes 子代理 → ACP 协议 → stdio → Claude Code 进程
↓
Claude Code 调用自己的 LLM
↓
响应通过 ACP 返回给 Hermes通信模式
delegate_task: 完全隔离
┌─────────────────────────────────────────────────────────────────────┐
│ 父代理 (Parent Agent) │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Subagent 1 │ │ Subagent 2 │ │ Subagent 3 │ │
│ │ 隔离上下文 │ │ 隔离上下文 │ │ 隔离上下文 │ │
│ │ 独立会话 │ │ 独立会话 │ │ 独立会话 │ │
│ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │
│ │ │ │ │
│ └────────────────────┼────────────────────┘ │
│ ▼ │
│ 独立返回结果 │
│ (只返回摘要) │
└─────────────────────────────────────────────────────────────────────┘mixture_of_agents: 两层架构
┌─────────────────────────────────────────────────────────────────────┐
│ 用户问题 (user_prompt) │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 第1层: Reference Models (并行执行) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Claude Opus │ │ Gemini │ │ GPT-5.4 │ │
│ │ │ │ │ │ │ │
│ │ 独立生成响应 │ │ 独立生成响应 │ │ 独立生成响应 │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └──────────────────┼──────────────────┘ │
│ ▼ │
│ 收集所有响应 │
│ (互不知情,不通信) │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 第2层: Aggregator Model │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Claude Opus (Aggregator) │ │
│ │ │ │
│ │ System Prompt: "综合以下模型的响应..." │ │
│ │ - Response 1 from Claude Opus: ... │ │
│ │ - Response 2 from Gemini: ... │ │
│ │ - Response 3 from GPT-5.4: ... │ │
│ │ │ │
│ │ → 生成综合后的最终答案 │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
▼
最终综合答案通信模式对比
| 特性 | delegate_task | mixture_of_agents |
|---|---|---|
| 子代理之间通信? | ❌ 不通信 | ❌ 不通信 |
| 最终综合? | 父代理自己汇总 | Aggregator 模型综合 |
| 综合方式 | 数组返回各结果 | AI 模型智能综合 |
| 层数 | 1 层(并行子任务) | 2 层(参考层 + 聚合层) |
动态工具载入
MCP (Model Context Protocol)
MCP 允许连接外部工具服务器,无需编写原生 Hermes 工具。
Stdio 服务器(本地子进程)
# ~/.hermes/config.yaml
mcp_servers:
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_..."HTTP 服务器(远程端点)
mcp_servers:
company_api:
url: "https://mcp.internal.example.com"
headers:
Authorization: "Bearer sk-..."
timeout: 180工具命名规则
mcp_<server_name>_<tool_name>| 服务器 | MCP 工具 | 注册名称 |
|---|---|---|
filesystem | read_file | mcp_filesystem_read_file |
github | create_issue | mcp_github_create_issue |
工具过滤控制
mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
tools:
include: [create_issue, list_issues] # 白名单
exclude: [delete_repo] # 黑名单
prompts: false # 禁用 prompt 工具
resources: false # 禁用 resource 工具
legacy:
url: "https://mcp.legacy.internal"
enabled: false # 完全禁用动态工具发现
MCP 服务器可以在运行时通知 Hermes 工具变化:
# MCP 服务器发送通知
notifications/tools/list_changed
→ Hermes 自动重新获取工具列表
→ 更新注册表
→ 无需手动 /reload-mcpCLI 命令
hermes mcp add <name> # 交互式添加 MCP 服务器
hermes mcp remove <name> # 移除服务器
hermes mcp list # 列出所有服务器
hermes mcp test <name> # 测试连接
hermes mcp configure # 配置服务器
/reload-mcp # 运行时重载 MCP 工具插件系统
| 插件类型 | 位置 | 用途 |
|---|---|---|
| Memory Provider | plugins/memory/ | 记忆存储后端 |
| Context Engine | plugins/context_engine/ | 上下文压缩 |
| 工具插件 | 动态注册到 tools.registry | 自定义工具 |
hermes plugins list # 列出已安装插件
hermes plugins enable <name> # 启用插件
hermes plugins disable <name> # 禁用插件运行时工具集创建
from toolsets import create_custom_toolset
# 运行时动态创建工具集
create_custom_toolset(
name="my_custom",
description="我的自定义工具集",
tools=["web_search"],
includes=["terminal", "vision"]
)配置方式总结
| 配置层 | 说明 |
|---|---|
| 代码定义 | toolsets.py 中静态定义 |
| MCP 服务器 | ~/.hermes/config.yaml 中配置 |
| 插件注册 | 通过 tools.registry 动态注册 |
| 运行时创建 | 调用 create_custom_toolset() |
总结
| 概念 | 说明 |
|---|---|
| Subagent 本质 | 隔离的 AIAgent 实例 |
| 默认传输 | HTTP(通过 OpenAI SDK) |
| ACP 传输 | stdio 子进程(需要 acp_command) |
| Subagent 通信 | 完全隔离,不直接通信 |
| MoA 通信 | 两层架构,Aggregator 综合结果 |
| 动态载入 | 通过 MCP 协议和插件系统 |
评论