子代理委派
delegate_task 工具会创建拥有隔离上下文、受限工具集和独立终端会话的子 AIAgent 实例。每个子代理都会在全新的对话中独立运行,只有最终摘要才会回到父代理的上下文里。
单任务委派
delegate_task(
goal="Debug why tests fail",
context="Error: assertion in test_foo.py line 42",
toolsets=["terminal", "file"]
)
并行批量委派
最多支持 3 个并发子代理:
delegate_task(tasks=[
{"goal": "Research topic A", "toolsets": ["web"]},
{"goal": "Research topic B", "toolsets": ["web"]},
{"goal": "Fix the build", "toolsets": ["terminal", "file"]}
])
子代理上下文机制说明
重要:子代理一无所知
子代理会从一个完全全新的对话开始。它不知道父代理之前聊了什么、调用过哪些工具,也不知道任何你们已经讨论过的背景信息。子代理唯一能依赖的上下文,就只有你传入的 goal 和 context。
这意味着你必须提供子代理完成任务所需的全部信息:
# BAD - subagent has no idea what "the error" is
delegate_task(goal="Fix the error")
# GOOD - subagent has all context it needs
delegate_task(
goal="Fix the TypeError in api/handlers.py",
context="""The file api/handlers.py has a TypeError on line 47:
'NoneType' object has no attribute 'get'.
The function process_request() receives a dict from parse_body(),
but parse_body() returns None when Content-Type is missing.
The project is at /home/user/myproject and uses Python 3.11."""
)
子代理会收到一段围绕目标和上下文构建的专注型系统提示,要求它完成任务,并最终返回结构化摘要,包括:
- 它执行了什么操作
- 发现了哪些内容
- 修改了哪些文件
- 遇到的任何问题
实际示例
并行研究
同时研究多个主题并收集摘要:
delegate_task(tasks=[
{
"goal": "Research the current state of WebAssembly in 2025",
"context": "Focus on: browser support, non-browser runtimes, language support",
"toolsets": ["web"]
},
{
"goal": "Research the current state of RISC-V adoption in 2025",
"context": "Focus on: server chips, embedded systems, software ecosystem",
"toolsets": ["web"]
},
{
"goal": "Research quantum computing progress in 2025",
"context": "Focus on: error correction breakthroughs, practical applications, key players",
"toolsets": ["web"]
}
])
代码审查 + 修复
将审查与修复流程委派给一个全新上下文:
delegate_task(
goal="Review the authentication module for security issues and fix any found",
context="""Project at /home/user/webapp.
Auth module files: src/auth/login.py, src/auth/jwt.py, src/auth/middleware.py.
The project uses Flask, PyJWT, and bcrypt.
Focus on: SQL injection, JWT validation, password handling, session management.
Fix any issues found and run the test suite (pytest tests/auth/).""",
toolsets=["terminal", "file"]
)
多文件重构
将大型重构任务委派给子代理,避免污染父代理的上下文:
delegate_task(
goal="Refactor all Python files in src/ to replace print() with proper logging",
context="""Project at /home/user/myproject.
Use the 'logging' module with logger = logging.getLogger(__name__).
Replace print() calls with appropriate log levels:
- print(f"Error: ...") -> logger.error(...)
- print(f"Warning: ...") -> logger.warning(...)
- print(f"Debug: ...") -> logger.debug(...)
- Other prints -> logger.info(...)
Don't change print() in test files or CLI output.
Run pytest after to verify nothing broke.""",
toolsets=["terminal", "file"]
)
批量模式细节
当你传入一个 tasks 数组时,子代理会通过线程池以并行方式运行:
- 最大并发数: 3 个任务(若数组长度超过 3,则自动截断为 3)
- 线程池配置: 使用
ThreadPoolExecutor,配备MAX_CONCURRENT_CHILDREN = 3个工作线程 - 进度显示: 在 CLI 模式下,以树形视图实时展示每个子代理的工具调用;在网关模式下,进度将分批传递给父代理的进度回调函数
- 结果排序: 结果按任务索引排序,确保与输入顺序一致,无论完成顺序如何
- 中断传播: 中断父代理(例如发送新消息)会立即中断所有活跃的子代理
单任务委派直接运行,无需线程池开销。
模型覆盖
你可以在 config.yaml 中为子代理指定不同的模型,这很适合把一些简单任务分配给更便宜或更快的模型:
# In ~/.hermes/config.yaml
delegation:
model: "google/gemini-flash-2.0" # Cheaper model for subagents
provider: "openrouter" # Optional: route subagents to a different provider
如果没有单独指定,子代理会继承父代理当前使用的模型。
工具集选择建议
toolsets 参数控制子代理可访问的工具集。请根据任务类型选择:
| 工具集模式 | 使用场景 |
|---|---|
["terminal", "file"] | 代码工作、调试、文件编辑、构建 |
["web"] | 研究、事实核查、文档查询 |
["terminal", "file", "web"] | 全栈任务(默认) |
["file"] | 只读分析、代码审查但不执行 |
["terminal"] | 系统管理、进程控制 |
有些工具集无论如何都不会开放给子代理:
delegation— 禁止递归委派(防止无限生成)clarify— 子代理无法与用户交互memory— 禁止写入共享持久内存code_execution— 子代理应逐步推理send_message— 禁止跨平台副作用(如发送 Telegram 消息)
最大迭代次数
每个子代理都有迭代限制(默认值:50),控制其可进行的工具调用轮次:
delegate_task(
goal="Quick file check",
context="Check if /etc/nginx/nginx.conf exists and print its first 10 lines",
max_iterations=10 # Simple task, don't need many turns
)
深度限制
委派的最大深度是 2。父代理(深度 0)可以创建子代理(深度 1),但子代理不能继续向下再委派。这个限制是为了防止递归委派失控。
关键特性
- 每个子代理拥有独立的终端会话(与父代理分离)
- 无嵌套委派 —— 子代理无法继续委派(无孙代理)
- 子代理不可调用:
delegate_task,clarify,memory,send_message,execute_code - 中断传播 —— 中断父代理会立即中断所有活跃子代理
- 仅最终摘要进入父代理上下文,有效控制 token 使用
- 子代理继承父代理的API 密钥、提供商配置和凭证池(支持在限流时自动轮换密钥)
委派 vs execute_code 对比
| 因素 | delegate_task | execute_code |
|---|---|---|
| 推理能力 | 完整的 LLM 推理循环 | 仅 Python 代码执行 |
| 上下文 | 完全隔离的新对话 | 无对话,仅脚本执行 |
| 工具访问 | 所有非禁用工具 + 推理能力 | 7 个工具通过 RPC 调用,无推理 |
| 并行性 | 最多 3 个并发子代理 | 单一脚本 |
| 适用场景 | 需要判断力、多步决策的复杂任务 | 机械式多步骤流水线 |
| Token 成本 | 较高(完整 LLM 循环) | 较低(仅返回 stdout) |
| 用户交互 | 无(子代理无法澄清) | 无 |
经验法则: 如果子任务需要推理、判断或多步决策,用 delegate_task;如果只是机械式数据处理或脚本化流水线,则更适合 execute_code。
配置说明
# In ~/.hermes/config.yaml
delegation:
max_iterations: 50 # Max turns per child (default: 50)
default_toolsets: ["terminal", "file", "web"] # Default toolsets
model: "google/gemini-3-flash-preview" # Optional provider/model override
provider: "openrouter" # Optional built-in provider
# Or use a direct custom endpoint instead of provider:
delegation:
model: "qwen2.5-coder"
base_url: "http://localhost:1234/v1"
api_key: "local-key"
tip
代理会根据任务复杂度自动处理委派。你无需显式要求它委派——它会在合适时机自行决定。