Skip to content

子代理

delegate_task 工具可以生成子 AIAgent 实例,具有隔离的上下文、受限的工具集和独立的终端会话。每个子代理获得全新的对话并独立工作 - 只有最终摘要会进入父代理的上下文。

子代理(Sub-agent)是 Hermes Agent 的核心功能之一,允许你将复杂任务分解为多个并行执行的子任务。每个子代理:

  • 拥有完全独立的对话上下文 - 不了解父代理的历史对话
  • 可以使用受限的工具集 - 只获得完成任务所需的工具
  • 拥有独立的终端会话 - 与父代理和其他子代理隔离
  • 返回结构化摘要 - 只有最终结果进入父代理上下文
  • 并行执行 - 最多 3 个并发子代理(可配置,无硬性上限)
  • 上下文隔离 - 子代理从零开始,只接收你提供的 goalcontext
  • 工具集控制 - 精确控制每个子代理可以访问的工具
  • 深度限制 - 默认扁平结构,可选嵌套编排(最多 3 层)
  • 中断传播 - 中断父代理会自动中断所有活动子代理
  • 成本优化 - 可以为子代理配置更便宜的模型

~/.hermes/config.yaml 中配置子代理:

delegation:
max_iterations: 50 # 每个子代理的最大轮数(默认:50)
max_concurrent_children: 3 # 每批并行子代理数(默认:3)
max_spawn_depth: 1 # 树深度(1-3,默认 1 = 扁平)
orchestrator_enabled: true # 禁用则强制所有子代理为叶子角色
child_timeout_seconds: 600 # 子代理超时时间(秒,默认:600)
# 可选:为子代理使用不同的模型
model: "google/gemini-flash-2.0" # 更便宜的模型用于子代理
provider: "openrouter" # 可选:将子代理路由到不同的提供商
delegation:
model: "qwen2.5-coder"
base_url: "http://localhost:1234/v1"
api_key: "local-key"
# api_mode: "anthropic_messages" # 可选,用于 Anthropic 兼容端点

base_url 指向 Anthropic 兼容端点时,api_mode 会自动检测。

delegate_task(
goal="调试测试失败的原因",
context="错误:test_foo.py 第 42 行的断言失败",
toolsets=["terminal", "file"]
)
delegate_task(tasks=[
{"goal": "研究主题 A", "toolsets": ["web"]},
{"goal": "研究主题 B", "toolsets": ["web"]},
{"goal": "修复构建", "toolsets": ["terminal", "file"]}
])

同时研究多个主题并收集摘要:

delegate_task(tasks=[
{
"goal": "研究 2025 年 WebAssembly 的当前状态",
"context": "关注:浏览器支持、非浏览器运行时、语言支持",
"toolsets": ["web"]
},
{
"goal": "研究 2025 年 RISC-V 的采用情况",
"context": "关注:服务器芯片、嵌入式系统、软件生态系统",
"toolsets": ["web"]
},
{
"goal": "研究 2025 年量子计算进展",
"context": "关注:纠错突破、实际应用、主要参与者",
"toolsets": ["web"]
}
])

将审查和修复工作流委托给新的上下文:

delegate_task(
goal="审查认证模块的安全问题并修复发现的任何问题",
context="""项目位于 /home/user/webapp。
认证模块文件:src/auth/login.py、src/auth/jwt.py、src/auth/middleware.py。
项目使用 Flask、PyJWT 和 bcrypt。
关注:SQL 注入、JWT 验证、密码处理、会话管理。
修复发现的任何问题并运行测试套件(pytest tests/auth/)。""",
toolsets=["terminal", "file"]
)

委托大型重构任务,避免淹没父代理的上下文:

delegate_task(
goal="重构 src/ 中的所有 Python 文件,将 print() 替换为适当的日志记录",
context="""项目位于 /home/user/myproject。
使用 'logging' 模块,logger = logging.getLogger(__name__)。
将 print() 调用替换为适当的日志级别:
- print(f"Error: ...") -> logger.error(...)
- print(f"Warning: ...") -> logger.warning(...)
- print(f"Debug: ...") -> logger.debug(...)
- 其他 prints -> logger.info(...)
不要更改测试文件或 CLI 输出中的 print()。
之后运行 pytest 验证没有破坏任何东西。""",
toolsets=["terminal", "file"]
)

对于多阶段工作流,可以生成可以委托自己的工作人员的编排器子代理:

delegate_task(
goal="调研三种代码审查方法并推荐一种",
role="orchestrator", # 允许此子代理生成自己的工作人员
context="...",
)
  • role="leaf"(默认):子代理不能进一步委托
  • role="orchestrator":子代理保留 delegation 工具集

注意max_spawn_depth 默认为 1(扁平),需要将其提高到 2 才能允许编排器子代理生成叶子孙代理。

关键:子代理一无所知

子代理以完全全新的对话开始。它们对父代理的对话历史、先前的工具调用或委托之前讨论的任何内容一无所知。父代理必须在调用中传递所有子代理需要的信息:

# 错误 - 子代理不知道"错误"是什么
delegate_task(goal="修复错误")
# 正确 - 子代理拥有所需的所有上下文
delegate_task(
goal="修复 api/handlers.py 中的 TypeError",
context="""api/handlers.py 第 47 行有 TypeError:
'NoneType' 对象没有 'get' 属性。
process_request() 函数从 parse_body() 接收一个 dict,
但 parse_body() 在 Content-Type 缺失时返回 None。
项目位于 /home/user/myproject,使用 Python 3.11。"""
)

toolsets 参数控制子代理可以访问的工具。根据任务选择:

工具集模式使用场景
["terminal", "file"]代码工作、调试、文件编辑、构建
["web"]研究、事实核查、文档查找
["terminal", "file", "web"]全栈任务(默认)
["file"]只读分析,不执行的代码审查
["terminal"]系统管理、进程管理

子代理被阻止的工具

  • delegation - 叶子子代理默认被阻止
  • clarify - 子代理无法与用户交互
  • memory - 不写入共享持久内存
  • code_execution - 子代理应该逐步推理
  • send_message - 无跨平台副作用

每个子代理都有迭代限制(默认:50),控制它可以进行多少次工具调用轮次:

delegate_task(
goal="快速文件检查",
context="检查 /etc/nginx/nginx.conf 是否存在并打印前 10 行",
max_iterations=10 # 简单任务,不需要很多轮次
)

如果子代理在 child_timeout_seconds 秒内没有响应,会被视为卡住并被终止。默认是 600 秒(10 分钟)。

delegation:
child_timeout_seconds: 600 # 默认值

对于快速本地模型可以降低;对于复杂问题上的慢速推理模型可以提高。

TUI 提供 /agents 覆盖层(别名 /tasks):

  • 实时树状视图显示运行中和最近完成的子代理
  • 每个分支的成本、令牌和文件触摸汇总
  • 终止和暂停控制
  • 事后审查:逐步查看每个子代理的历史

经典 CLI 只打印 /agents 作为文本摘要;TUI 是覆盖层真正发挥作用的地方。

因素delegate_taskexecute_code
推理完整的 LLM 推理循环仅 Python 代码执行
上下文全新隔离对话无对话,仅脚本
工具访问所有非阻止工具带推理通过 RPC 的 7 个工具,无推理
并行性默认 3 个并发子代理(可配置)单脚本
最适合需要判断的复杂任务机械多步骤管道
令牌成本更高(完整 LLM 循环)更低(仅返回 stdout)
用户交互无(子代理无法澄清)

经验法则:当子任务需要推理、判断或多步骤问题解决时使用 delegate_task。当你需要机械数据处理或脚本化工作流时使用 execute_code

使用 max_spawn_depth: 3max_concurrent_children: 3 时,树可以达到 3×3×3 = 27 个并发叶子代理。每增加一层都会成倍增加花费 - 有意识地提高 max_spawn_depth

delegate_task 是同步的 - 不是持久的:

  • 在父代理的当前回合内运行
  • 阻塞父代理直到每个子代理完成(或被取消)
  • 如果父代理被中断,所有活动子代理被取消
  • 子代理在父代理回合结束后不会继续运行

对于持久的长时间运行工作,使用:

  • cronjob(action=create)- 安排单独的 Agent 运行
  • terminal(background=True, notify_on_complete=True) - 长时间运行的 shell 命令

如果子代理在次 API 调用后超时(通常是:提供商不可达、认证失败或工具模式拒绝),delegate_task 会将结构化诊断写入 ~/.hermes/logs/subagent-timeout-<session>-<timestamp>.log,包含子代理的配置快照、凭证解析跟踪和任何早期错误消息。