# 《WaLiSSH - AI Shell 智能终端》第2-10节:子Agent派发
作者:小傅哥
博客:https://bugstack.cn (opens new window)
视频:https://t.zsxq.com/cNahM (opens new window)
沉淀、分享、成长,让自己和他人都能有所收获!😄
大家好,我是技术UP主小傅哥。
回顾上一节,我们已经把 AI 对话链路的“成本和稳定性”问题处理了:缓存命中、推理强度、标准协议。到这里,WaLiSSH 的 ReAct 引擎已经具备了意图识别、长期记忆、数据召回、上下文治理这一整套能力。
但如果你真的拿这套系统去干活,还是会撞上一个天花板(也是面试高频问题) —— 所有事情都是一个智能体在干。
啥意思呢?
你回头看看 ssh-agent.yml 就会发现:不管用户是让它“看下日志”,还是“重启服务”,甚至“删除一个目录”,接活的都是同一个 sshOperator。它的 instruction 越写越长,既要教它怎么诊断、又要教它怎么变更、还要教它哪些命令危险不能碰。工具也一样,一把 executeCommand 既干只读的活,也干破坏性的活。(抛开面试,其实有时候一个智能体的稳定性更高。但你需要了解更多,解决更复杂问题)
这就是典型的“一个智能体干所有事”模式,它有三个绕不开的问题:
- 权责不清。只读诊断和破坏性变更之间没有天然边界,全靠提示词里的“安全规则”自觉。提示词一长,模型的服从性就开始波动。
- 上下文污染。诊断时执行了十几条命令,失败的、无关的输出全堆在主会话上下文里。等真正要执行变更时,模型已经被一堆噪音淹了。
- 提示词膨胀。所有场景的规则都塞进一个 instruction,越写越长,改一个场景的规则还要担心影响别的场景。
这一节我们就来解决这个问题:把“单打独斗”升级为“父子协作”,再从“一次派一个”升级为“规划一批、并行执行”。这里会需要把智能体作为 Tool 工具使用, 一切皆插件是模块安装,一些皆工具是抽象调用。
核心思路其实很像一个公司组织:父智能体是“老板”,它不写代码、不碰服务器,只负责理解需求、拆解任务、派活、看结果;子智能体是“专家”,诊断专家只收集证据,变更专家只执行操作,每个专家在自己的会话里干活,干完只汇报结论。而遇到复杂任务时,老板还可以先做一轮“项目规划”——拆成几个子任务、标好依赖关系,然后并行派发。
这一节我们分 2 步来走:
- 先搞懂多智能体协作的两种模式:ADK 提供了什么,我们为什么选 Agent-as-Tool。
- 再看课程代码怎么实现:
SubAgentDispatchTool单任务派发、BatchSubAgentDispatchTool批量派发、DynamicPlanDispatchTool动态规划编排,以及AgentNode二段式装配、sub-agents配置化编排,是怎么串成一条完整链路的。
# 一、本章诉求
本章的目标,是在 walissh-server 工程里,把“单智能体”升级为“父子智能体协作”,并父智能体配上“规划与并行派发”的能力,落到代码上包括:
- 理解 Agent-as-Tool:把子智能体包装成一个标准 Function Tool,交给父智能体按需调用,而不是用固定流程编排。
- 配置化编排:在
ssh-agent.yml里通过sub-agents字段声明父子关系,父子关系是配置,不是写死的代码。 - 单任务派发
SubAgentDispatchTool:父智能体的每一次派发,都是一次独立会话里的完整子智能体运行,最后收敛成一个结果返回。 - 批量派发
BatchSubAgentDispatchTool:父智能体一次工具调用就能派发一组任务,声明依赖关系(dependsOn),无依赖的任务并行执行,有依赖的按 DAG(Directed Acyclic Graph)有向无环图的拓扑顺序串行(如,t1、t2、t3 都执行完,进入收尾的 t4)。 - 动态规划派发
DynamicPlanDispatchTool:对复杂任务,先由一个临时构建的“规划器智能体”输出 JSON 任务计划,经过解析和校验(去重、依赖存在性、环检测),再交给编排器执行。父智能体只需要说“这个任务复杂,帮我规划派发”,不需要自己拆任务。 - 职责分离:父智能体不再持有
executeCommand,诊断类任务派给sshDiagnosisAgent,变更类任务派给sshChangeAgent,各自只执行职责范围内的命令。 - 会话隔离:子智能体跑在独立
invocationId的会话里,中间执行过程不污染父智能体的上下文;同时终端会话 ID 通过AgentExecutionContext显式传递,子智能体在正确的 SSH 连接上执行命令。 - 可观测:插件识别
AgentTool类型工具,输出专属的派发日志,让“谁派发了谁、结果是什么”一目了然。
别忘记,我们一路以来都在干啥。
如果说 2-7 是“让 AI 理解用户想干什么”,2-8 是“让 AI 记住发生过什么”,2-9 是“让 AI 又省又稳地跑”,那么 2-10 就是“让 AI 像一个团队一样干活”——老板不写代码,专家各司其职,复杂任务先规划再并行推进。
# 二、多智能体协作设计
这玩意吧,不能一上来就写代码,你得先搞懂多智能体协作的“世界观”(给人放松下,乔杉)。包括:
- 多智能体到底解决了什么问题
- ADK 的两种协作方式分别是什么
- 为什么本节选 Agent-as-Tool,而不是流程编排
# 1. 为什么要拆父子智能体
先看一个直观的对比。
单智能体模式,所有能力长在一个身体上:
用户请求 → sshOperator(一个 LlmAgent)
├── instruction:诊断规则 + 变更规则 + 安全规则(越来越长)
└── tools:executeCommand(一把梭)
2
3
父子智能体模式,按职责拆成团队:
用户请求 → sshOperator(父智能体,老板)
└── 派发 → sshDiagnosisAgent(诊断专家)
│ └── tools: executeCommand(只读)
└── 派发 → sshChangeAgent(变更专家)
└── tools: executeCommand(变更)
2
3
4
5
拆开之后有三个直接收益:
一是权责边界清晰了。诊断子智能体的 instruction 里只有一条铁律:“不执行安装、重启、删除、写入或任何变更类命令”。变更子智能体的 instruction 里也只有一条:“不扩大任务范围,不执行派发内容之外的危险命令”。这比在同一个 instruction 里写十几次“你要小心”有效得多——给一个角色的规则越少、越聚焦,模型执行得越稳定。
二是上下文干净了。诊断子智能体在自己的会话里执行 journalctl、nginx -t、netstat,十几条命令的中间输出全部留在它自己的会话里。父智能体最后只拿到一段收敛过的诊断结论。主会话的上下文始终保持“用户说了什么 + 派发了什么 + 专家结论是什么”的干净结构,这不仅让模型决策更准,对 2-9 讲的 Prompt Cache 命中也更友好。
三是编排灵活了。以后要加“回滚子智能体”“发布子智能体”,只需要在配置里加一个 agent 定义,再在父智能体的` 列表里加一行,装配层自动完成包装。代码零改动。

