Spring AI Alibaba 1.x 系列【42】多智能体 - 顺序执行、并行执行
文章目录
1. 串行执行
SequentialAgent 关键特性:
- 按顺序执行:
Agent按照subAgents列表中定义的顺序执行 - 状态传递:每个
Agent的输出通过outputKey存储在状态中,可被后续Agent访问 - 消息历史:默认情况下,所有
Agent共享消息历史 - 推理内容控制:使用
returnReasoningContents控制是否在消息历史中包含中间推理
设计一个企业【合同标准化串行审核流程】,固定审核顺序(强串行,必须 1→2→3→4):
- 子
Agent1:合同基础内容校验(格式、缺失字段、必填项检查) - 子
Agent2:商务风险审核(付款周期、违约金、金额条款) - 子
Agent3:合规风控审核(违法条款、敏感用语、合规红线) - 子
Agent4:汇总生成审核报告(整合前三步结果,输出最终结论)
1.1 构建子智能体
依次创建四个子智能体:
// 节点1:合同基础格式校验 Agent
ReactAgent basicCheckAgent = ReactAgent.builder()
.model(dashscopeChatModel)
.name("合同基础校验-Agent")
.description("负责检查合同缺失字段、格式错误、甲乙双方信息完整性")
.systemPrompt("你是行政专员,只做基础校验:检查合同是否缺少甲方、乙方、有效期、签字位置,只输出问题清单。")
.build();
// 节点2:商务条款风控 Agent
ReactAgent businessRiskAgent = ReactAgent.builder()
.model(dashscopeChatModel)
.name("商务条款审核-Agent")
.description("审核付款方式、账期、违约金、报价合理性等商务风险")
.systemPrompt("你是商务经理,专注审核付款周期、结算方式、违约赔偿条款,标记不合理商务条款。")
.build();
// 节点3:合规法律审核 Agent
ReactAgent legalComplianceAgent = ReactAgent.builder()
.model(dashscopeChatModel)
.name("合规法务审核-Agent")
.description("排查违法违规、霸王条款、法律禁止性内容")
.systemPrompt("你是法务专员,排查合同中的无效条款、霸王条款、不合规表述,给出合规修改建议。")
.build();
// 节点4:最终报告汇总 Agent
ReactAgent reportSummaryAgent = ReactAgent.builder()
.model(dashscopeChatModel)
.name("审核报告汇总-Agent")
.description("整合前面所有审核结果,输出结构化审核结论:通过/整改/驳回")
.systemPrompt("整合前面所有环节的审核结果,输出结构化报告,明确给出:审核结论、风险等级、修改建议。")
.build();
1.2 串行编排
按照实际执行顺序构建子智能体集合,执行链路(完全串行):
- 基础校验
Agent→ 识别:乙方缺失、无有效期、信息不全 - 商务风控
Agent→ 识别:账期模糊、无违约约束、金额不明确 - 合规法务
Agent→ 识别:单方霸王条款、合同无效风险 - 汇总
Agent→ 输出完整审核报告 + 风险等级:驳回,需全面整改
构建 SequentialAgent 传入列表:
// 关键:List 顺序 = 实际执行顺序,强串行
List<Agent> subAgents = List.of(
basicCheckAgent,
businessRiskAgent,
legalComplianceAgent,
reportSummaryAgent
);
// 传入子智能体列表 构建 SequentialAgent
return SequentialAgent.builder()
.name("企业合同串行审核工作流")
.description("基于顺序智能体,完成合同四步标准化审核")
.subAgents(subAgents)
.build();
1.3 单元测试
模拟一份简易商务合同,进行对话:
甲方:XX科技 乙方:
合作有效期:无固定期限
付款条款:项目完工后随意付款,无违约处罚
服务费用:暂定,后期口头协商
双方权责:甲方拥有无条件单方解约权,乙方不得提出任何异议
首先进入第一个:

依次进入第二个:

进入第三个时的消息列表:
- 当前子智能体的系统提示词
- 用户输入消息
- 第一个智能体返回的消息
- 第二个智能体返回的消息

1.4 指令占位符
在上面的案例中,我们没有使用不用占位符,框架只是把完整的消息列表(messages)丢给大模型,本质是多轮对话历史,依赖大模型自主解析历史,极易跑偏。在实际开发中,我们应该将使用占位符将内容嵌入到指令中,确保精准执行任务,零误解。
核心区别:
| 维度 | 仅传递消息列表(不使用占位符) | 占位符嵌入指令(使用 {xx}) |
|---|---|---|
| 本质 | 多轮对话历史 | 单轮结构化任务指令 |
| 大模型理解 | 自主解析历史,极易跑偏 | 明确输入 + 任务,100% 精准 |
| 数据传递 | 非结构化、无固定参数 | 结构化、outputKey=固定参数 |
| 适用场景 | 闲聊、对话、记忆历史 | 工作流 / Agent 串行、业务任务 |
| 串行业务效果 | 流程隐式依赖上下文,易失效、结果不可控 | 强绑定上下游数据,流程通畅、执行稳定 |
优化,使用 outputKey 定义当前子智能体的输出键,下游智能体通过【占位符】填充结果到指令中:
// 节点1:合同基础格式校验 Agent
ReactAgent basicCheckAgent = ReactAgent.builder()
.model(dashscopeChatModel)
.name("contract_basic_check")
.description("校验合同必填字段、格式完整性、甲乙双方主体信息")
// 结构化输出KEY,供下游Agent精准调用
.outputKey("basic_check_result")
// 保留推理过程,便于日志追踪+上下文传递
.returnReasoningContents(true)
// 强指令约束:输出格式固定,无冗余内容
.instruction("""
你是企业行政审核专员,仅执行【合同基础格式校验】任务:
1. 检查:甲方信息、乙方信息、合同有效期、签章位置、合同标的是否完整
2. 仅输出【缺失/错误】清单,无问题则输出【基础校验通过】
3. 禁止输出无关内容,格式简洁规范
""")
.build();
// 节点2:商务条款风控 Agent
ReactAgent businessRiskAgent = ReactAgent.builder()
.model(dashscopeChatModel)
.name("contract_business_check")
.description("审核付款、账期、违约金、报价等商务条款风险")
.outputKey("business_check_result")
.returnReasoningContents(true)
// 占位符显式引用上游校验结果,杜绝上下文误解
.instruction("""
你是企业商务经理,基于基础校验结果执行【商务条款审核】:
上游基础校验结果:{basic_check_result}
审核范围:付款方式、结算周期、违约金、报价合理性、权责对等性
输出要求:标记风险条款 + 风险等级 + 修改建议,无风险则输出【商务审核通过】
""")
.build();
// 节点3:合规法律审核 Agent
ReactAgent legalComplianceAgent = ReactAgent.builder()
.model(dashscopeChatModel)
.name("contract_legal_check")
.description("法务合规审核,排查违法、霸王、无效条款")
.outputKey("legal_check_result")
.returnReasoningContents(true)
.includeContents(true)
.instruction("""
你是企业专职法务,基于前序审核结果执行【合规性审核】:
基础校验结果:{basic_check_result}
商务审核结果:{business_check_result}
审核范围:无效条款、霸王条款、违法违规表述、法律风险点
输出要求:列出违规条款 + 法律风险 + 强制修改建议,无风险则输出【合规审核通过】
""")
.build();
// 节点4:最终报告汇总 Agent
ReactAgent reportSummaryAgent = ReactAgent.builder()
.model(dashscopeChatModel)
.name("contract_report_summary")
.description("整合全流程审核结果,生成最终合同审核报告")
// 最终输出KEY,业务层直接获取
.outputKey("final_audit_report")
.returnReasoningContents(true)
// 结构化指令,强制输出企业标准格式
.instruction("""
你是合同审核汇总专员,整合全部审核结果,生成【最终审核报告】:
基础校验:{basic_check_result}
商务校验:{business_check_result}
合规校验:{legal_check_result}
必须输出固定结构:
1. 审核结论:通过/整改/驳回
2. 风险等级:低/中/高
3. 问题汇总:精简罗列所有问题
4. 处理意见:明确修改要求
""")
.build();
可以看到,输入内容被填充到了指令中:


1.5 完整执行状态
获取完整执行状态:
Optional<OverAllState> result = sequentialAgent.invoke("帮我写一个100字左右的散文");
if (result.isPresent()) {
// 消息历史将包含所有工具调用和推理过程
List<Message> messages = (List<Message>) result.get().value("messages").orElse(List.of());
System.out.println("消息数量: " + messages.size()); // 包含所有中间步骤
}
可以看到每个子智能体的输出内容:

messages 消息列表,如果是显示 AssistantMessage 的话,将会输出每个子智能体的响应内容:

2. 并行执行
在并行执行模式中,多个 Agent 同时处理相同的输入。它们的结果被收集并合并。
核心流程:
- 输入同时发送给所有
Agent - 所有
Agent并行处理 - 结果被合并成单一输出
设计一个【主题写作智能体】:
- 根据用户输入【主题】
- 同时执行:写散文、写现代诗、主题总结
- 合并结果,返回给用户
2.1 构建子智能体
// 创建多个专业化Agent
ReactAgent proseWriterAgent = ReactAgent.builder()
.name("prose_writer_agent")
.model(dashscopeChatModel)
.description("专门写散文的AI助手")
.instruction("你是一个知名的散文作家,擅长写优美的散文。" +
"用户会给你一个主题:{input},你只需要创作一篇100字左右的散文。")
.outputKey("prose_result")
.build();
ReactAgent poemWriterAgent = ReactAgent.builder()
.name("poem_writer_agent")
.model(dashscopeChatModel)
.description("专门写现代诗的AI助手")
.instruction("你是一个知名的现代诗人,擅长写现代诗。" +
"用户会给你的主题是:{input},你只需要创作一首现代诗。")
.outputKey("poem_result")
.build();
ReactAgent summaryAgent = ReactAgent.builder()
.name("summary_agent")
.model(dashscopeChatModel)
.description("专门做内容总结的AI助手")
.instruction("你是一个专业的内容分析师,擅长对主题进行总结和提炼。" +
"用户会给你一个主题:{input},你只需要对这个主题进行简要总结。")
.outputKey("summary_result")
.build();
2.2 合并策略
MergeStrategy 「并行结果合并」策略接口,定义如何执行结果的合并规则能力:
/**
* 用于合并并行执行结果的策略接口
*/
public interface MergeStrategy {
/**
* 合并所有并行子代理的执行结果
* @param subAgentResults 子代理输出键与其对应执行结果的映射集合
* @param overallState 包含所有上下文信息的全局状态对象
* @return 合并后的最终结果
*/
Object merge(Map<String, Object> subAgentResults, OverAllState overallState);
}
默认提供了三种合并策略:
| 策略类 | 输出结果 | 适用场景 |
|---|---|---|
| ConcatenationMergeStrategy | 拼接字符串 | 文本汇总、日志输出、最终展示 |
| ListMergeStrategy | 不可变 List | 遍历结果、二次处理、数据聚合 |
| DefaultMergeStrategy | 新 HashMap | 保留键值映射、框架默认兜底 |
可以实现自定义的合并策略来控制如何组合多个 Agent 的输出,示例,分批计算结果然后输出累加值:
// 求和合并策略实现
public class SumMergeStrategy implements MergeStrategy {
@Override
public Object merge(Map<String, Object> subAgentResults, OverAllState overallState) {
int total = 0;
// 遍历所有子代理结果,累加数值
for (Object result : subAgentResults.values()) {
if (result instanceof Integer) {
total += (Integer) result;
}
}
return total;
}
}
2.3 串行编排
并行中无需考虑子智能体的位置,全部传入即可,这里使用默认的合并策略:
// 创建并行Agent
ParallelAgent parallelAgent = ParallelAgent.builder()
.name("parallel_creative_agent")
.description("并行执行多个创作任务,包括写散文、写诗和做总结")
.mergeOutputKey("merged_results")
.subAgents(List.of(proseWriterAgent, poemWriterAgent, summaryAgent))
.mergeStrategy(new ParallelAgent.DefaultMergeStrategy())
.build();
2.4 查看完整执行状态
查看完整执行状态:
Optional<OverAllState> result = parallelAgent.invoke("AI");
注意:messages 消息列表中只有输入消息,输出需要从 merged_results 中获取:

3. 构建流程(SequentialAgent)

3.1 构建入口
所有 FlowAgent 建造器的 build() 方法,调用的都是抽象父类 FlowAgentBuilder,再调用子类实现的 doBuild() 创建具体智能体:
/**
* 【模板方法】构建具体的 FlowAgent 实例
* @return 构建完成的 FlowAgent 实例
* @throws GraphStateException 智能体创建失败时抛出异常
*/
public T build() {
// ====================== 公共逻辑:统一处理状态持久化配置 ======================
// 如果配置了状态持久化器(saver,用于智能体状态保存/恢复)
if (this.saver != null) {
// 场景1:若编译配置(CompileConfig)为空,创建新的编译配置,并注册持久化器
if (this.compileConfig == null) {
this.compileConfig = CompileConfig.builder()
.saverConfig(SaverConfig.builder()
.register(saver) // 注册状态持久化器
.build())
.build();
}
// 场景2:若编译配置已存在,基于原有配置,覆盖/注入持久化配置
else {
this.compileConfig = CompileConfig.builder(compileConfig)
.saverConfig(SaverConfig.builder()
.register(saver)
.build())
.build();
}
}
// ====================== 调用子类实现:创建具体智能体实例 ======================
return doBuild();
}
doBuild() 会先进行校验,再调用 SequentialAgent 构造函数:
/**
* 重写:抽象构建方法
* 完成校验后,创建并返回 SequentialAgent 具体实例
* @return 构建完成的顺序执行智能体
*/
@Override
public SequentialAgent doBuild() {
// 执行参数校验(确保所有配置合法)
validate();
// 通过构造方法创建 SequentialAgent,传入当前建造器的所有配置
return new SequentialAgent(this);
}
/**
* 重写:参数校验方法
* 先执行父类通用校验,再扩展顺序智能体专属校验(可扩展)
*/
@Override
protected void validate() {
// 1. 执行父类 FlowAgentBuilder 的基础校验(必填项:名称、子智能体非空等)
super.validate();
// 2. 扩展点:此处可添加 SequentialAgent 专属的参数校验规则(当前无额外校验)
}
校验智能体名称 name 非空,智能体列表 subAgents 非空
protected void validate() {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("Name must be provided");
}
if (subAgents == null || subAgents.isEmpty()) {
throw new IllegalArgumentException("At least one sub-agent must be provided for flow");
}
}
3.2 构造函数
SequentialAgent 构造函数中都是调用的父类的构造进行初始化:
protected SequentialAgent(SequentialAgentBuilder builder) {
super(builder.name, builder.description, builder.compileConfig, builder.subAgents, builder.stateSerializer, builder.executor, builder.hooks);
}
protected FlowAgent(String name, String description, CompileConfig compileConfig, List<Agent> subAgents,
StateSerializer stateSerializer, Executor executor, List<Hook> hooks) {
super(name, description);
this.compileConfig = compileConfig;
this.subAgents = subAgents;
this.stateSerializer = stateSerializer;
this.executor = executor;
this.hooks = hooks;
}
protected Agent(String name, String description) {
this.name = name;
this.description = description;
}
3.3 初始化状态图
图在第一次执行时,会调用 FlowAgent #initGraph() 进行初始化,统一为所有子类(顺序 / 并行 / 循环 / 路由智能体)初始化状态图(StateGraph):
/**
* 重写父类方法:初始化状态图(StateGraph)
* 所有 FlowAgent 子类(顺序/并行/循环/路由)统一复用此模板方法
* @return 构建完成的状态图对象
* @throws GraphStateException 状态图构建失败时抛出异常
*/
@Override
protected StateGraph initGraph() throws GraphStateException {
// ====================== 1. 构建流图基础配置 ======================
// 使用 FlowGraphBuilder 构建工作流配置,封装智能体核心属性
FlowGraphBuilder.FlowGraphConfig config = FlowGraphBuilder.FlowGraphConfig.builder()
.name(this.name()) // 设置智能体名称
.rootAgent(this) // 设置当前智能体为【根智能体】(工作流入口)
.subAgents(this.subAgents()); // 设置子智能体列表
// ====================== 2. 注入可选配置 ======================
// 如果配置了状态序列化器(用于状态持久化/断点续跑),则注入配置
if (this.stateSerializer != null) {
config.stateSerializer(this.stateSerializer);
}
// 如果配置了钩子函数(日志/裁剪/权限/工具扩展),则注入配置
if (this.hooks != null && !this.hooks.isEmpty()) {
config.hooks(this.hooks);
}
// ====================== 3. 子类实现具体图构建逻辑 ======================
// 调用抽象方法 buildSpecificGraph,由子类实现【顺序/并行/循环/路由】的具体图构建
return buildSpecificGraph(config);
}
接着进入到子类中的具体构建【顺序执行】类型的状态图方法:
/**
* 重写父类抽象方法:构建【顺序执行】类型的状态图
* @param config 流图通用配置(名称、子智能体、钩子、序列化器等)
* @return 构建完成的顺序执行状态图
* @throws GraphStateException 图构建失败异常
*/
@Override
protected StateGraph buildSpecificGraph(FlowGraphBuilder.FlowGraphConfig config) throws GraphStateException {
// 调用统一的流图构建器,传入【顺序类型】和通用配置,生成StateGraph
return FlowGraphBuilder.buildGraph(FlowAgentEnum.SEQUENTIAL.getType(), config);
}
3.4 图构建器
使用策略模式 ,从【策略注册器】中,根据类型创建对应的图构建策略,再调用具体策略,执行图构建逻辑:
/**
* 流图构建器(统一调度器)
* 所有FlowAgent的状态图构建,最终都会走到这个静态方法
*/
public class FlowGraphBuilder {
/**
* 通用图构建方法:根据策略类型,分发到对应的具体构建逻辑
* @param strategyType 策略类型(对应FlowAgentEnum:SEQUENTIAL/PARALLEL/LOOP/ROUTING)
* @param config 图构建的所有配置参数
* @return 最终构建完成的StateGraph(状态图)
* @throws GraphStateException 图构建失败抛出异常
*/
public static StateGraph buildGraph(String strategyType, FlowGraphConfig config) throws GraphStateException {
// 1. 从【策略注册器】中,根据类型创建对应的图构建策略
FlowGraphBuildingStrategy strategy = FlowGraphBuildingStrategyRegistry.getInstance().createStrategy(strategyType);
// 2. 执行策略专属的配置校验
strategy.validateConfig(config);
// 3. 调用具体策略,执行图构建逻辑
return strategy.buildGraph(config);
}
}
3.4.1 FlowGraphBuildingStrategyRegistry
【流图构建策略注册中心】负责所有 FlowGraphBuildingStrategy(图构建策略)的注册、查询、创建。
核心能力:
- 动态注册新的图构建策略,无需修改框架核心代码(符合开闭原则)
- 线程安全设计,支持多线程环境下的策略注册与获取
- 单例全局唯一,统一管理所有策略
/**
* 【流图构建策略注册中心】
* 负责所有 FlowGraphBuildingStrategy(图构建策略)的注册、查询、创建
*
* 核心能力:
* 1. 动态注册新的图构建策略,无需修改框架核心代码(符合开闭原则)
* 2. 线程安全设计,支持多线程环境下的策略注册与获取
* 3. 单例全局唯一,统一管理所有策略
*
* 所有 FlowAgent(顺序/并行/循环/路由)的图构建策略,都由此类管理
*/
public class FlowGraphBuildingStrategyRegistry {
/** 单例实例:全局唯一的注册中心对象 */
private static final FlowGraphBuildingStrategyRegistry INSTANCE = new FlowGraphBuildingStrategyRegistry();
/**
* 策略工厂容器:线程安全的 ConcurrentHashMap
* Key:策略类型(如 sequential/parallel/loop/routing)
* Value:策略工厂(Supplier 函数式接口,用于创建策略实例)
*/
private final Map<String, Supplier<FlowGraphBuildingStrategy>> strategyFactories = new ConcurrentHashMap<>();
/**
* 私有构造方法:禁止外部实例化,保证单例
* 构造时自动注册框架内置的默认策略
*/
private FlowGraphBuildingStrategyRegistry() {
registerDefaultStrategies();
}
/**
* 获取单例实例:全局唯一入口
*/
public static FlowGraphBuildingStrategyRegistry getInstance() {
return INSTANCE;
}
/**
* 注册策略实例:每次获取返回同一个对象(单例策略)
* @param strategy 具体的图构建策略
*/
public void registerStrategy(FlowGraphBuildingStrategy strategy) {
if (strategy == null) {
throw new IllegalArgumentException("策略实例不能为空");
}
String type = strategy.getStrategyType();
if (type == null || type.trim().isEmpty()) {
throw new IllegalArgumentException("策略类型不能为空");
}
if (strategyFactories.containsKey(type)) {
throw new IllegalArgumentException("策略类型 '" + type + "' 已注册,不可重复注册");
}
// 存入工厂:固定返回当前策略实例
strategyFactories.put(type, () -> strategy);
}
/**
* 注册策略工厂:每次获取创建新实例(原型策略)
* 适用于每次构建都需要新策略对象的场景
* @param type 策略类型
* @param factory 策略工厂(创建新实例)
*/
public void registerStrategy(String type, Supplier<FlowGraphBuildingStrategy> factory) {
if (type == null || type.trim().isEmpty()) {
throw new IllegalArgumentException("策略类型不能为空");
}
if (factory == null) {
throw new IllegalArgumentException("策略工厂不能为空");
}
if (strategyFactories.containsKey(type)) {
throw new IllegalArgumentException("策略类型 '" + type + "' 已注册");
}
strategyFactories.put(type, factory);
}
/**
* 创建策略实例:调用工厂生成新的策略对象
* 内置策略:每次返回新实例
* 手动注册实例:每次返回同一实例
*/
public FlowGraphBuildingStrategy createStrategy(String type) {
if (type == null || type.trim().isEmpty()) {
throw new IllegalArgumentException("策略类型不能为空");
}
Supplier<FlowGraphBuildingStrategy> factory = strategyFactories.get(type);
if (factory == null) {
throw new IllegalArgumentException("未找到策略类型: " + type);
}
// 执行工厂方法,创建/获取策略实例
return factory.get();
}
/**
* 获取策略实例(别名方法,底层调用 createStrategy)
*/
public FlowGraphBuildingStrategy getStrategy(String type) {
return createStrategy(type);
}
/**
* 判断指定类型的策略是否已注册
*/
public boolean hasStrategy(String type) {
return type != null && strategyFactories.containsKey(type);
}
/**
* 获取所有已注册的策略类型
*/
public Set<String> getRegisteredTypes() {
return Set.copyOf(strategyFactories.keySet());
}
/**
* 注销指定策略(主要用于测试)
*/
public Supplier<FlowGraphBuildingStrategy> unregisterStrategy(String type) {
return strategyFactories.remove(type);
}
/**
* 清空所有策略(主要用于测试)
*/
public void clear() {
strategyFactories.clear();
}
/**
* 注册框架【内置默认策略】
* 所有官方 FlowAgent 对应的图构建策略,都在这里初始化
* 采用 工厂方法::new 模式,每次创建新实例
*/
private void registerDefaultStrategies() {
registerStrategy(FlowAgentEnum.SEQUENTIAL.getType(), SequentialGraphBuildingStrategy::new);
registerStrategy(FlowAgentEnum.ROUTING.getType(), RoutingGraphBuildingStrategy::new);
registerStrategy(FlowAgentEnum.PARALLEL.getType(), ParallelGraphBuildingStrategy::new);
registerStrategy(FlowAgentEnum.CONDITIONAL.getType(), ConditionalGraphBuildingStrategy::new);
registerStrategy(FlowAgentEnum.LOOP.getType(), LoopGraphBuildingStrategy::new);
}
}
注册中心初始化时,自动注册 5 种官方策略:
SEQUENTIAL→SequentialGraphBuildingStrategy(顺序)ROUTING→RoutingGraphBuildingStrategy(路由)PARALLEL→ParallelGraphBuildingStrategy(并行)LOOP→LoopGraphBuildingStrategy(循环)CONDITIONAL→ConditionalGraphBuildingStrategy(条件分支)
3.4.2 SequentialGraphBuildingStrategy
【顺序执行图构建策略】实现线性顺序执行流程,子智能体按添加顺序串联,前一个执行完成 → 后一个执行。
public class SequentialGraphBuildingStrategy extends AbstractFlowGraphBuildingStrategy {
/**
* 【核心】构建顺序图的核心逻辑
*/
@Override
protected void buildCoreGraph(FlowGraphBuilder.FlowGraphConfig config)
throws GraphStateException {
// 1. 专属校验:至少1个子智能体
validateSequentialConfig(config);
// 2. 定义顺序流程入口:根智能体名称
String sequentialStartNode = getRootAgent().name();
// 3. 添加【透明节点】作为流程入口(无业务逻辑,仅做流转)
this.graph.addNode(sequentialStartNode, node_async(new TransparentNode()));
// 4. 连接前置钩子(如果有)到入口节点
if (!this.beforeModelHooks.isEmpty()) {
connectBeforeModelHookEdges(this.graph, sequentialStartNode, this.beforeModelHooks);
}
// 5. 🌟 核心:线性串联所有子智能体
Agent currentAgent = getRootAgent();
for (Agent subAgent : config.getSubAgents()) {
// 添加子智能体节点
FlowGraphBuildingStrategy.addSubAgentNode(subAgent, this.graph);
// 建立边:前一个节点 → 当前子节点
this.graph.addEdge(currentAgent.name(), subAgent.name());
// 移动指针,继续串联
currentAgent = subAgent;
}
// 6. 连接后置钩子(如果有)
String finalNode;
if (!this.afterModelHooks.isEmpty()) {
finalNode = connectAfterModelHookEdges(this.graph, currentAgent.name(), this.afterModelHooks);
} else {
finalNode = currentAgent.name();
}
// 7. 最后一个节点连接到出口节点,结束流程
this.graph.addEdge(finalNode, this.exitNode);
}
/**
* 重写:空实现(顺序策略已在核心方法中处理钩子,避免重复连接)
*/
@Override
protected void connectBeforeModelHooks() throws GraphStateException {
}
/**
* 重写:空实现(顺序策略已在核心方法中处理钩子,避免重复连接)
*/
@Override
protected void connectAfterModelHooks() throws GraphStateException {
}
/**
* 返回策略类型:sequential
*/
@Override
public String getStrategyType() {
return FlowAgentEnum.SEQUENTIAL.getType();
}
/**
* 扩展校验:父类通用校验 + 顺序专属校验
*/
@Override
public void validateConfig(FlowGraphBuilder.FlowGraphConfig config) {
super.validateConfig(config);
validateSequentialConfig(config);
}
/**
* 顺序流程专属校验规则
*/
private void validateSequentialConfig(FlowGraphBuilder.FlowGraphConfig config) {
// 必须至少有一个子智能体
if (config.getSubAgents() == null || config.getSubAgents().isEmpty()) {
throw new IllegalArgumentException("顺序流程至少需要一个子智能体");
}
// 根节点必须是 FlowAgent
if (!(config.getRootAgent() instanceof FlowAgent)) {
throw new IllegalArgumentException("顺序流程的根节点必须是 FlowAgent");
}
}
}
3.5 构建完成
所有智能体都是通过对应的 GraphBuildingStrategy 策略类进行构建,SequentialGraphBuildingStrategy 中的核心流程:
- 专属校验:至少
1个子智能体 - 定义顺序流程入口:根智能体名称
- 添加【透明节点】作为流程入口(无业务逻辑,仅做流转)
- 连接前置钩子(如果有)到入口节点
- 🌟 核心:线性串联所有子智能体
- 连接后置钩子(如果有)
- 最后一个节点连接到出口节点,结束流程
/**
* 【核心】构建顺序图的核心逻辑
*/
@Override
protected void buildCoreGraph(FlowGraphBuilder.FlowGraphConfig config)
throws GraphStateException {
// 1. 专属校验:至少1个子智能体
validateSequentialConfig(config);
// 2. 定义顺序流程入口:根智能体名称
String sequentialStartNode = getRootAgent().name();
// 3. 添加【透明节点】作为流程入口(无业务逻辑,仅做流转)
this.graph.addNode(sequentialStartNode, node_async(new TransparentNode()));
// 4. 连接前置钩子(如果有)到入口节点
if (!this.beforeModelHooks.isEmpty()) {
connectBeforeModelHookEdges(this.graph, sequentialStartNode, this.beforeModelHooks);
}
// 5. 🌟 核心:线性串联所有子智能体
Agent currentAgent = getRootAgent();
for (Agent subAgent : config.getSubAgents()) {
// 添加子智能体节点
FlowGraphBuildingStrategy.addSubAgentNode(subAgent, this.graph);
// 建立边:前一个节点 → 当前子节点
this.graph.addEdge(currentAgent.name(), subAgent.name());
// 移动指针,继续串联
currentAgent = subAgent;
}
// 6. 连接后置钩子(如果有)
String finalNode;
if (!this.afterModelHooks.isEmpty()) {
finalNode = connectAfterModelHookEdges(this.graph, currentAgent.name(), this.afterModelHooks);
} else {
finalNode = currentAgent.name();
}
// 7. 最后一个节点连接到出口节点,结束流程
this.graph.addEdge(finalNode, this.exitNode);
}
最终图可视化如下:

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)