Sub-Agent委派系统:从task工具到舱壁隔离的多Agent可治理设计
多Agent协作的本质不是"增加人手",而是明确职责边界、隔离执行域、标准化协作流程。边界模糊的多Agent系统,规模越大越混乱。
一、传统多Agent架构的四大致命缺陷
一个看起来很聪明的多Agent Demo:主Agent负责搜索、读文件、写代码、整理计划、跑测试、做审稿。演示效果不错。但一到真实任务,问题立刻暴露:
缺陷一:上下文污染(Context Bloat)
主Agent需承载规划、工具调用、子任务结果等全量信息。搜索带回几万字材料、文件读取返回大段代码——这些中间结果快速耗尽上下文窗口,关键信息淹没、推理漂移、Token成本激增。
缺陷二:职责边界模糊
主Agent同时承担"决策指挥"与"任务执行"双重角色。路由逻辑与业务逻辑高度耦合,主循环代码越来越臃肿,迭代风险极高——没人敢改,因为改了不知道哪里会炸。
缺陷三:故障无隔离(Single Point of Failure)
子Agent执行报错、工具调用异常、输出格式错误时,错误直接扩散至主Agent状态。一个子任务崩了,主线程跟着迷路。
缺陷四:调度不可控
子Agent生命周期、并发数、执行状态无统一管理。容易出现"无限派生"(子Agent递归创建孙Agent)、资源耗尽、任务追踪困难。
核心根因:主Agent又当指挥又干杂活。多Agent协作的本质不是堆更多Agent,而是明确职责边界、隔离执行域、标准化协作流程。
二、DeepAgents的核心对策:主Agent只决策,子Agent只执行
DeepAgents摒弃"Agent间自由通信"的网状模式,采用“Sub Agent委派 + 工具化封装 + 中间件接管 + 状态隔离”的极简架构:
三条铁律:
- 主Agent不直接操作子图,只通过
task工具委派 - 子Agent不能把内部消息、待办、技能元数据一股脑塞回主Agent
- 子Agent之间不直接通信,所有协作通过主Agent中转
这就是整个架构的核心思想:
主Agent只做决策与委派,子Agent只做隔离执行与结果交付;多Agent协作收敛为一套可治理的委派系统,而非无规则的聊天网络。
三、子Agent是什么:被裁剪过的独立执行单元
先把概念说清楚。
子Agent不是主Agent的缩小版,也不是一个带独立Prompt的LLM调用。它是一个被裁剪过的独立执行单元。
| 属性 | 说明 |
|---|---|
| 身份 | 有自己的名字(name)和职责描述(description),主Agent靠description匹配 |
| 指令 | 有自己的系统提示词,不和主Agent共用同一套 |
| 工具 | 可独立配置工具集,不配就继承主Agent |
| 模型 | 可独立配置模型,不配就继承主Agent |
| 中间件 | 可独立配置中间件栈,默认不加载SubAgentMiddleware(禁止子派生) |
| 权限 | 可独立配置权限,不配就继承主Agent |
每一项都在构建期定死,运行期改不了。
子Agent的职责一句话:替主Agent干杂活,失败了自己扛,不连累主线程。
四、环节一:子Agent创建——声明式 + 动态 + 兜底
DeepAgents支持三种子Agent定义方式:
静态声明(推荐)
在中间件初始化时预定义子Agent池,指定名称、能力、工具、权限。主Agent直接匹配调用,避免重复创建开销。这是生产环境的主流用法——子Agent池像"部门编制",任务来了按描述匹配最合适的执行者。
动态创建
主Agent根据任务类型,通过task工具临时生成专属子Agent(如临时数据清洗子Agent),任务完成后销毁,节省资源。
默认兜底(通用子Agent)
未匹配到专属子Agent时,自动调用通用子Agent处理杂项任务,避免主Agent过载。调用方可以显式关闭,也可以自己定义一个同名子Agent覆盖默认。
五、环节二:任务委派——task工具,唯一的合法通道
在DeepAgents工程里,task不只是一个工具,它是委派动作的唯一合法通道。模型可以建议怎么协作,但通道只能走这一条。
主Agent不直接操作子图,只调一个task工具。这个工具收两个参数:
description:任务描述——要干什么subagent_type:执行者类型——交给哪个子Agent
中间件根据这两个参数找到对应子Agent、准备上下文、启动执行。整个过程对主Agent透明——调task跟调read_file没区别。
委派的三不原则
委派权严格集中于主Agent。具体体现为三条刚性约束:
- 子Agent不可自行派生——Sub-Agent的
task工具被直接移除,单层委派 - 子Agent不可越权访问主状态——
_EXCLUDED_STATE_KEYS阻断私有状态传播 - 子Agent不可直接与用户交互——所有输出走主Agent中转
标准化契约思维
整个委派体系是标准化契约思维的极致体现:
- 定义契约化:
SubAgentTypedDict明确名称、描述、工具、权限等字段,所有子Agent结构统一 - 委派契约化:
TaskToolSchema定义两个参数(description + subagent_type),规范委派方式 - 结果契约化:同步走
ToolMessage格式,异步走async_tasks结构化字典
新增子Agent时,只需遵循契约定义,无需修改主Agent代码。组件交互可校验、可排障。
六、环节三:隔离执行——四重安全舱
每个子Agent均运行于独立安全舱,实现四重隔离:
上下文隔离
子Agent仅接收主Agent传递的任务必要信息,不含主Agent历史对话、临时变量等私有数据。执行过程中的中间结果仅存在于自身上下文,不回传主Agent。
技术实现:_EXCLUDED_STATE_KEYS常量严格阻断主Agent的对话历史、待办列表、长期记忆等私有状态传递给子Agent。子Agent启动时只收到一条干净的HumanMessage——任务描述。
工具隔离
子Agent使用专属工具集,与主Agent、其他子Agent完全隔离。避免工具冲突与权限滥用。
模型隔离
支持为不同子Agent配置差异化模型。复杂推理子Agent用强模型,简单摘要子Agent用轻量模型——优化成本与性能。
故障隔离
子Agent执行失败仅影响自身。中间件捕获异常后返回标准化错误结果,不破坏主Agent状态。一个子Agent调用工具报错,主Agent仍可正常委派其他任务。
舱壁隔离思维
这套设计是舱壁隔离思维(Bulkhead)的经典落地。源自船舶设计的"隔舱板"理念——每个舱室拥有独立的资源和故障域,一个舱进水不沉整条船。
在软件架构中,舱壁隔离解决三个问题:故障扩散、资源竞争、上下文污染。DeepAgents的子Agent隔离设计,让每个子Agent成为独立执行单元,边界清晰、风险可控——这也是子Agent能支撑生产级场景的关键前提。
七、环节四&五:同步 vs 异步调度
主Agent调度子Agent干活分两条路:
| 对比项 | 同步task | 异步任务 |
|---|---|---|
| 适合任务 | 短任务、独立分析、上下文隔离 | 长任务、远端执行、后台处理 |
| 返回方式 | 等子Agent完成后返回一条ToolMessage | 先返回task_id,后续再查 |
| 状态管理 | 双向过滤,避免污染主图 | async_tasks账本登记任务索引 |
| 架构模式 | 命令模式 + 舱壁隔离 | 先开工单,后面按需查 |
| 失败处理 | 错误回到工具结果或抛出明确异常 | 通过状态查询看到running/success/error/cancelled |
同步路径
主Agent调用task工具 →SubAgentMiddleware过滤主状态 → 创建子Agent实例 → 执行任务 → 过滤中间过程 → 仅回传结构化最终结果 → 主Agent收到ToolMessage→ 继续执行。
全流程阻塞式,适合秒级短任务。
异步路径
主Agent发起任务 →AsyncSubAgentMiddleware登记到后台 → 立即返回task_id→ 主Agent继续干别的 → 随时通过list_async_tasks查询进度。
异步任务支持五大操作:状态查询、结果更新、任务取消、列表查看、按需重试。
怎么选
任务能在一个回合里干完 → 同步task。任务跨时间、跨远端服务、跨多轮查询 → 异步任务。不是二选一,是覆盖不同场景的两条路。
八、环节六:结果回传——同步走ToolMessage,异步走账本
同步结果:一条干净ToolMessage交回
子Agent内部的所有消息被_EXCLUDED_STATE_KEYS拦下,只把最后一条AI消息包装成ToolMessage,通过Command(update=...)写回主Agent的消息历史。
主Agent看到的是一个干净的"工具调用结果",而不是子Agent几十轮的内部对话。这个设计至关重要——它让主Agent的上下文窗口不被子Agent的中间产物撑爆。
异步结果:任务账本随时查
异步任务的结果不能靠"等",因为它可能跑很久。DeepAgents把异步任务登记到async_tasks字段里,用Reducer合并更新。主Agent可以随时通过list_async_tasks查询任务状态,不必等到任务完成。
为什么要专门搞一个async_tasks字段?因为异步任务不能靠聊天历史记住。聊天历史是给模型读的,模型一忘,任务就丢了。async_tasks是结构化状态,不受模型遗忘影响。
九、环节七:故障处理与状态闭环
DeepAgents构建了“执行→监控→恢复→审计”全链路状态闭环:
- 实时监控:中间件实时采集子Agent执行状态(运行中/成功/失败)、资源占用、工具调用日志
- 故障隔离:子Agent报错时中间件捕获异常,返回标准化错误信息,不扩散至主Agent
- 自动恢复:异步任务支持失败重试(可配置重试次数与间隔)
- 审计追溯:
async_tasks账本永久保存任务元数据与执行结果
十、最小权限与默认收紧
子Agent的权限设计遵循最小权限与默认收紧原则:
- 默认继承主Agent权限——无需显式配置时,仅拥有与主Agent一致的最小权限
- 显式声明才生效——若需调整权限,必须在配置中显式声明,调用点可直接审查
- 子Agent禁止派生——默认不加载
SubAgentMiddleware,杜绝"无限派生"
这套设计让子Agent的操作始终处于可控范围,是能落地生产的关键保障。
十一、小结:多Agent系统的本质是边界治理
DeepAgents的子Agent不是"多个Agent凑一起聊天"的花架子,而是主Agent发工单、子Agent干完交差的受控派工系统。
源码层面的职责分配:
| 模块 | 架构角色 | 设计模式 | 工程价值 |
|---|---|---|---|
SubAgentMiddleware | 同步委派网关 | Middleware/Proxy | 主Agent不直接接触子图 |
_build_task_tool() | 命令入口 | Command/Strategy | 工具空间稳定,扩展成本低 |
_EXCLUDED_STATE_KEYS | 舱壁规则 | Bulkhead/State Isolation | 防止上下文和私有状态污染 |
GENERAL_PURPOSE_SUBAGENT | 泄压阀 | Convention over Configuration | 杂项任务不压主线程 |
子Agentpermissions/interrupt_on | 策略门禁 | Policy Gate | 委派不能绕过安全审查 |
AsyncSubAgentMiddleware | 后台任务网关 | Lifecycle Manager | 长任务不阻塞主Agent |
AsyncSubAgentState.async_tasks | 状态账本 | Reducer/Memento | 任务可追踪,可恢复查询 |
打一个比方:
主Agent像调度员,同步子Agent像短工单执行者,异步子Agent像远端后台工单,
async_tasks像工单台账。每个人各管一摊,边界清楚。
在企业级AI Agent落地中,智能度不是第一优先级,可控性、稳定性、可维护性才是。DeepAgents的Sub-Agent委派与隔离机制,正是解决这一核心痛点的关键方案。