十一、Spring AI Alibaba · 高级 · 多智能体(Multi-agent)

1. 什么时候该拆成多 Agent

出现以下任一信号,就该考虑 Multi-agent:

信号 说明
工具太多 单个 Agent 挂着十几二十个工具,工具选择准确率下降
上下文膨胀 单个 Agent 难以有效跟踪不断增长的历史与记忆
需要专业化 任务天然可分角色:规划器 / 研究员 / 数学专家 / 评审

拆分的收益不只是「快」,更重要的是每个 Agent 只看它该看的东西------这就是文档强调的「系统质量很大程度上取决于上下文工程」。


2. 两种基础协作模式

模式 工作原理 控制流 场景
Tool Calling(Agent as Tool) Supervisor 把其他 Agent 当工具调用,子 Agent 不直接面对用户,只执行并返回结果 集中式,所有路由经过调用方 任务编排、结构化工作流
Handoffs(交接) 当前 Agent 主动把控制权(和状态)移交给另一个 Agent,活跃 Agent 随之变更,用户接着与新的 Agent 交互 去中心化 跨领域对话、专家接管

怎么选:

问题 Agent Tool Handoffs
需要集中控制工作流程? ✅ ❌
希望 Agent 直接与用户交互? ❌ ✅
专家之间复杂的类人对话? 有限 ✅ 强

两者可以混合:用 Handoffs 做 Agent 切换,同时每个 Agent 又把子 Agent 当工具调用。


3. 上下文工程:四个关键参数

这是 Multi-agent 的实操核心,决定每个子 Agent「看到什么」。

参数 作用 建议
instruction 在当前 Agent 节点插入任务说明,支持 {input} / {outputKey} / {stateKey} 占位符 用占位符引用上游输出,别手动搬状态
outputKey 把本 Agent 输出存进状态,供后续 {key} 引用 起有意义的名字
returnReasoningContents 子 Agent 的中间推理是否回传父流程 默认关/设 false,减少上下文、提效
includeContents 子 Agent 执行时是否带上父流程全部上下文 设 false 让子 Agent 专注自己的任务
java 复制代码
ReactAgent reviewerAgent = ReactAgent.builder()
    .name("reviewer_agent").model(chatModel)
    .instruction("请对文章进行评审修正:\n{article},最终返回评审修正后的文章内容")
    .includeContents(true)            // 带上父流程上下文
    .returnReasoningContents(true)    // 回传推理过程(调试时开,生产建议关)
    .outputKey("reviewed_article")
    .build();

调试期:includeContents=true + returnReasoningContents=true,看清全链路;

生产期:两个都收窄,省 token、降干扰。


4. Instruction 占位符

占位符 含义 场景
{input} 用户原始输入 第一个 Agent / 需要用户输入的 Agent
{outputKey} 引用其他 Agent 通过 outputKey 存的输出 顺序执行中下游引用上游
{stateKey} 状态里的任意键值 访问任何状态数据

机制:执行时从 OverAllState 查值 → 转字符串 → 插入 instruction。

注意:占位符对应值不存在时,系统保留原始占位符文本 (不会报错,但模型会看到 {article} 这种字面量,容易生成怪结果)。

java 复制代码
ReactAgent writerAgent = ReactAgent.builder()
    .name("writer_agent").instruction("你是一个知名作家,请回答:{input}").outputKey("article").build();

ReactAgent reviewerAgent = ReactAgent.builder()
    .name("reviewer_agent").instruction("请评审修正:{article},返回修改后的文章").outputKey("reviewed_article").build();

5. 五种编排 Agent

5.1 SequentialAgent(顺序)

java 复制代码
SequentialAgent blogAgent = SequentialAgent.builder()
    .name("blog_agent")
    .description("先写文章,再交给评论员评论")
    .subAgents(List.of(writerAgent, reviewerAgent))
    .build();

Optional<OverAllState> result = blogAgent.invoke("帮我写一个100字左右的散文");
result.ifPresent(state -> {
    state.value("article");          // 第一个 Agent 的输出
    state.value("reviewed_article"); // 第二个 Agent 的输出
});
  • 按 subAgents 顺序执行,输出经 outputKey 落到状态。
  • 默认共享消息历史 ;用 returnReasoningContents 控制是否包含中间推理。
  • 取出的值是 AssistantMessage,需 instanceof 判断后 getText()。

5.2 ParallelAgent(并行)

java 复制代码
ParallelAgent parallelAgent = ParallelAgent.builder()
    .name("parallel_creative_agent")
    .description("并行写散文、写诗、做总结")
    .subAgents(List.of(proseWriterAgent, poemWriterAgent, summaryAgent))
    .mergeOutputKey("merged_results")
    .mergeStrategy(new ParallelAgent.DefaultMergeStrategy())
    .build();
  • 所有子 Agent 拿到同一份输入 (通常都用 {input}),结果再合并。
  • 各自 outputKey 独立可取,另有 mergeOutputKey 存合并结果。
  • 自定义合并:实现 ParallelAgent.MergeStrategy:
java 复制代码
public class CustomMergeStrategy implements ParallelAgent.MergeStrategy {
    @Override
    public Map<String, Object> merge(Map<String, Object> mergedState, OverAllState state) {
        state.data().forEach((k, v) -> {
            if (k.endsWith("_result")) { /* 累加到 all_results */ }
        });
        return mergedState;
    }
}

5.3 LlmRoutingAgent(单次智能路由)

java 复制代码
LlmRoutingAgent routingAgent = LlmRoutingAgent.builder()
    .name("content_routing_agent")
    .description("根据用户需求智能路由到合适的专家Agent")
    .model(chatModel)
    .subAgents(List.of(writerAgent, reviewerAgent, translatorAgent))
    .build();
  • 每次请求只路由到一个 Agent 就结束。
  • 路由依据是子 Agent 的 description------描述写得含糊,路由就不准。
  • 提升准确率的三个手段:清晰的 description、明确职责边界(写清「不处理什么」)、避免领域重叠。
  • 可用 systemPrompt(SystemMessage,定义角色与决策规则,优先级更高)+ instruction(UserMessage,补充场景指导)。

5.4 SupervisorAgent(多步循环监督)

与 LlmRoutingAgent 的关键区别:子 Agent 执行完回到监督者 ,监督者可以继续路由,直到返回 FINISH。

java 复制代码
SupervisorAgent supervisorAgent = SupervisorAgent.builder()
    .name("content_supervisor").model(chatModel)
    .systemPrompt(SUPERVISOR_SYSTEM_PROMPT)   // 决策规则 + 子Agent职责 + 「只返回名称或FINISH」
    .instruction(SUPERVISOR_INSTRUCTION)      // 可用占位符 {article_content} 读前序输出
    .subAgents(List.of(translatorAgent, reviewerAgent))
    .build();
特性 LlmRoutingAgent SupervisorAgent
路由次数 单次 多步循环
子 Agent 完成后 直接结束 返回监督者继续决策
多步骤任务 ❌ ✅
instruction 占位符 ❌ ✅
重试 --- 内置最多 2 次重试

可嵌套:SequentialAgent(subAgents = [写手Agent, SupervisorAgent]) ------ 先产出内容,再由监督者决定翻译还是评审。

5.5 自定义 FlowAgent

FlowAgent 是 SequentialAgent / ParallelAgent / LlmRoutingAgent 的基类,核心是实现 buildSpecificGraph():

java 复制代码
public abstract class FlowAgent extends Agent {
    protected List<Agent> subAgents;
    protected CompileConfig compileConfig;
    protected abstract StateGraph buildSpecificGraph(FlowGraphBuilder.FlowGraphConfig config) throws GraphStateException;
}

自定义套路:继承 FlowAgent + 继承 FlowAgentBuilder 写 Builder + 用 FlowGraphBuilder 构图。可做出 ConditionalAgent(Predicate 二分支)、CustomLoopAgent(exitCondition + maxIterations,如「质量分 ≥ 8 或最多迭代 5 次」)。


6. 混合模式(实战最常用)

复制代码
ParallelAgent(并行收集:web_data + db_data → research_data)
      ↓
ReactAgent(分析:{research_data} → analysis_result)
      ↓
LlmRoutingAgent(按格式路由:pdf_report / html_report)
      ↓ 包一层
SequentialAgent hybridWorkflow

要点:FlowAgent 本身也是 Agent,所以能互相嵌套 ,subAgents() 里可以放 ReactAgent,也可以放另一个 FlowAgent。


7. 选型决策树

复制代码
任务是固定几步流水线?                    → SequentialAgent
多个独立子任务可同时跑?                   → ParallelAgent(+ mergeStrategy)
需要按用户意图挑一个专家,一次就够?         → LlmRoutingAgent
需要监督者多轮调度、可能反复调用不同专家?    → SupervisorAgent
需要条件分支 / 循环迭代等自定义拓扑?        → 继承 FlowAgent
以上都要?                                → 嵌套组合(Sequential 里放 Parallel / Supervisor)

8. 易混点 & 坑(7 条)

  1. Routing 与 Supervisor 别选错 :只要「一次跳转」用 LlmRoutingAgent;要「写完再翻、翻完再审」这种多步编排才用 SupervisorAgent。反过来用会出现「任务只做了一半就结束」。
  2. description 就是路由的输入:子 Agent 的 description 写得像口号("专业Agent"),LLM 必然乱路由。要写清「能力 + 适用输入 + 不做什么」。
  3. 占位符找不到值时不会报错 ,只会把 {article} 原样塞给模型。上游 outputKey 拼错 = 静默降级。
  4. returnReasoningContent(s) 命名在文档里两种写法都有 (returnReasoningContent / returnReasoningContents),实际编码以你依赖版本的 API 为准。
  5. includeContents=false ≠ 拿不到上游数据 :上游输出仍可通过 {outputKey} 引用,只是不把父流程全部消息历史带进来。这两件事要分开理解。
  6. 并行 Agent 共享同一输入 :子 Agent 的 instruction 通常都用 {input};如果想让它们处理不同东西,得靠各自 instruction 加以区分。
  7. Supervisor 的 systemPrompt 必须写死响应格式(「只返回 Agent 名称或 FINISH,不要解释」),否则模型输出一段分析文本会导致路由解析失败。

9. 本项目(xs-interview-agent)落地建议

现状:单条 ChatModel 直链,四步(解析简历 → 五维评分 → 出题 → 逐题评估)全靠 Service 方法串行拼装,所有上下文一次性塞进 prompt。

9.1 推荐拆法

角色 Agent 类型 说明
简历解析 ReactAgent(Tika 工具) outputKey="resume_profile"
五维评分 ParallelAgent 技术深度/项目STAR/匹配度/表达/潜力 五个子 Agent 并行打分 → mergeOutputKey="scores";天然解决上下文过长
出题 ReactAgent instruction="...{resume_profile}...{scores}",outputKey="questions"
逐题评估 ReactAgent 按 question 循环
面试模式路由 LlmRoutingAgent 技术面 / HR 行为面 / 压力面三个专家,按用户选择或简历特征路由
总装 SequentialAgent [解析, 并行评分, 出题, 评估]

9.2 骨架

java 复制代码
ParallelAgent scoringAgent = ParallelAgent.builder()
    .name("scoring_agent")
    .description("并行完成简历五个维度的评分")
    .subAgents(List.of(techDepthAgent, starAgent, matchAgent, expressionAgent, potentialAgent))
    .mergeOutputKey("scores")
    .mergeStrategy(new ParallelAgent.DefaultMergeStrategy())
    .build();

SequentialAgent interviewFlow = SequentialAgent.builder()
    .name("interview_flow")
    .description("简历解析 → 并行评分 → 出题 → 评估")
    .subAgents(List.of(profileAgent, scoringAgent, questionAgent, evaluationAgent))
    .build();

Optional<OverAllState> state = interviewFlow.invoke(resumeText);

9.3 配套注意

  • 每个子 Agent 设 includeContents=false,只靠 {resume_profile} / {scores} 传数据,避免每一轮都带上整份简历文本。
  • 评分 Agent 用 outputType(见 ReactAgent 笔记)输出结构化分数,避免再手工 cleanJsonResponse() 剥围栏。
  • 之前的 structureScore 分值不一致问题,在「合并策略」处统一收敛:在 CustomMergeStrategy.merge() 里做 min(100, Σ) 兜底。
  • 评分属于「可以并行、互不依赖」的典型场景,是本项目中收益最大的一处改造。

10. 30 秒答辩稿

Multi-agent 是把一个臃肿 Agent 拆成多个小而专的 Agent 协同工作。Spring AI Alibaba 有两种基础协作方式:Tool Calling 是集中式,把子 Agent 当工具调用,子 Agent 不面对用户;Handoffs 是去中心化,Agent 之间直接交棒,活跃 Agent 随之改变,用户可以继续和新 Agent 对话。上层提供了五种编排:SequentialAgent 顺序流水线、ParallelAgent 并行加合并策略、LlmRoutingAgent 单次智能路由、SupervisorAgent 多步循环调度直到 FINISH,以及继承 FlowAgent 自定义图拓扑,而且它们可以互相嵌套。真正决定效果的是上下文工程四个参数:instruction 配合占位符引用上游输出、outputKey 命名输出、returnReasoningContents 控制推理是否回传、includeContents 控制是否带父流程上下文------生产环境后两个都应收窄以省 token 降干扰。


11. 速查表

需求 API
顺序流水线 SequentialAgent.builder().subAgents(List.of(a,b)).build()
并行 + 合并 ParallelAgent.builder().subAgents(...).mergeOutputKey(k).mergeStrategy(s).build()
自定义合并 实现 ParallelAgent.MergeStrategy#merge(Map, OverAllState)
单次路由 LlmRoutingAgent.builder().model(chatModel).subAgents(...).build()
多步监督 SupervisorAgent.builder().model(chatModel).systemPrompt(sp).instruction(i).subAgents(...).build()
自定义拓扑 继承 FlowAgent,实现 buildSpecificGraph(),配合 FlowGraphBuilder
声明输出键 .outputKey("xxx") → 下游用 {xxx} 引用
引用用户输入 {input}
引用任意状态 {stateKey}
控制推理回传 .returnReasoningContents(true/false)
控制父上下文 .includeContents(true/false)
取结果 agent.invoke(x) → Optional<OverAllState> → state.value("key")
结束监督循环 监督者返回 FINISH
相关推荐
2601_955662461 小时前
情感解说视频如何提升感染力?配音细节很关键
人工智能·音视频·语音识别·视频
苏醒的人生1 小时前
电商品牌物料AI生图工具推荐:让品牌调性一套到底
人工智能
lank_M1 小时前
截图OCR预处理在普通屏上翻车,Retina截图却没事
图像处理·人工智能·计算机视觉·ocr
Aloudata2 小时前
LookML 语义模型 vs 企业级独立语义层:BI 建模语言能否承担企业语义底座?
数据库·人工智能·数据分析·数据资产·dataagent
龙亘川2 小时前
AI 协同赋能城市治理:支撑政协数字化履职的技术路径探析
大数据·人工智能·智慧城市·开源软件·数据可视化
通信大模型2 小时前
IEEE TCCN | 面向低空经济网络的Agentic AI驱动多无人机轨迹优化
网络·人工智能·无人机
爱编程的小白L2 小时前
2027 计算机毕业设计选题汇总|深度学习专项(2027最新)
人工智能·深度学习·课程设计
逸模2 小时前
BIM在连锁餐饮装修中的应用:不只是画三维图
大数据·数据库·人工智能·物联网·建模