6期|Plan-and-Execute 落地:用 Spring AI 搭一个「维修工单编排 Agent」,让它像售后经理一样「开单→派工→执行→质检」
上一期我用 ReAct 模式搭了一个诊断 Agent,它能像老 SA 一样「听→想→查→下结论」走一步看一步。但售后经理管车间,从来不是走一步看一步——而是先把工单开好、工时配件工位一次规划到位,再派下去执行。今天就把这套「先想好再干」的 Plan-and-Execute 模式写成代码。
一、开篇:ReAct 能诊断,但能管车间吗?
第5期结尾,我的诊断 Agent 给出了一份漂亮的诊断报告:
<span leaf="">主因:制动分泵导向销润滑不良</span>
然后呢?报告生成的那一刻,售后经理老王走过来拍拍我的肩:
「老张,诊断报告是不错。但你现在告诉我——这单子怎么开?派给谁?先干哪步后干哪步?配件什么时候领?质检谁签字?客户什么时候能取车?」
我愣了一下。诊断 Agent 只回答了**「车怎么了」,但没回答「怎么修」**。
「怎么修」不是推理问题,是编排问题。售后经理脑子里想的是:
<span leaf="">开单(维修项目+工时+配件)→ 派工(哪个技师+哪个工位)→ 执行(领料→施工→进度跟踪)→ 质检(完工检查→路试验证)→ 交车</span>
这是一条有先后依赖、有资源约束、有并行可能的执行链。走一步看一步?不行。你得先把这个链条规划出来,再一步步执行。
这就是第2期讲的第二种架构模式:Plan-and-Execute(先规划后执行)。
今天的目标:用 Spring AI 把 Plan-and-Execute 模式写成代码,让 Agent 像一个干了 10 年的售后经理一样,把一份诊断报告编排成一张可执行的维修工单。
二、ReAct vs Plan-and-Execute:两种模式到底差在哪?
在写代码之前,先把这两个模式的本质区别彻底讲透。我在第2期画过理论对比图,今天从代码执行逻辑的角度再拆一遍。
2.1 执行流程对比
<span leaf="">ReAct 模式(第<span>5</span>期·诊断 Agent)</span>
2.2 核心差异对照表
| 维度
|
ReAct(诊断 Agent)
|
Plan-and-Execute(工单编排 Agent)
核心思路
|
走一步看一步,每步结果决定下一步
|
先出完整计划,再逐步执行
| |
规划时机
|
不预先规划,边走边调
|
先一次性规划,再执行
| |
执行路径
|
动态,可能 3 步也可能 8 步
|
固定,按计划清单走
| |
工具调用
|
每轮 LLM 决定调什么工具
|
规划阶段确定步骤,执行阶段按步骤调工具
| |
LLM 调用次数
|
每步 1 次(Thought+Action)
|
规划 1 次 + 每步执行各 1 次
| |
失败处理
|
LLM 自主调整方向
|
执行器报错 → 可重试 / 可重新规划
| |
适合场景
|
诊断、排查、开放式问题
|
工单编排、流程自动化、项目管理
| |
类比
|
急诊医生问诊排查
|
外科手术方案制定后执行
| |
售后角色
|
SA / 诊断技师
|
售后经理 / 车间调度
|
2.3 一句话总结
ReAct 是「不知道答案,一步步找」;Plan-and-Execute 是「知道要做哪些事,先列清单再逐个干」。
诊断不知道病因在哪,所以用 ReAct 逐步排查;维修工单知道要做哪些项目(换刹车盘、换导向销、路试),所以用 Plan-and-Execute 先排好顺序再执行。
三、场景还原:售后经理是怎么开单派工的?
还是那辆 2022 款奥迪 Q5。第5期的诊断 Agent 给出了维修方案:
<span leaf="">维修项目:</span>
如果我是售后经理,拿到这个方案后脑子里是这样转的:
<span leaf="">第<span>1</span>步·开单</span>
注意看:这些步骤之间有明确的先后依赖——你必须先开单才能查配件(因为配件清单在工单里),必须先查配件才能派工(缺件就不用派工了),必须先派工才能领料(要知道派给谁、送到哪个工位)。
这就是 Plan-and-Execute 的精髓:先把所有步骤和依赖关系想清楚,列成一张计划清单,再逐步执行。
四、系统架构:Plan-and-Execute 的代码结构
<span leaf="">┌─────────────────────────────────────────────────────────────────────────┐</span>
关键设计:
-
Planner:调一次 LLM,输入诊断报告 + 维修方案,输出一个结构化的 Plan(JSON 格式的步骤清单)
-
Step Executor:遍历 Plan 的每个步骤,每步调对应的后端工具(不是每步都调 LLM)
-
Replan Trigger:执行中发现计划不可行(比如缺件、技师请假),触发重新规划
-
Result Collector:收集每步执行结果,最终生成工单执行报告
五、核心代码实现
5.1 项目依赖(pom.xml)
<span leaf=""><span><!-- Spring Boot Web --></span></span>
5.2 配置文件(application.yml)
<span leaf=""><span>spring</span>:</span>
注意:诊断 Agent 我用 temperature 0.2,这里用 0.1。因为规划输出的结构化要求更高——步骤的顺序、依赖关系、并行标记不能有随机性。差 0.1 可能就差在某个步骤被 LLM 漏掉。
5.3 数据模型:Plan 与 Step
这是 Plan-and-Execute 模式最核心的数据结构。Plan 是一张有序的步骤清单,每个 Step 有自己的类型、依赖和执行参数。
<span leaf="">package com.<span>aftersales</span>.<span>orch</span>.<span>model</span>;</span>
5.4 执行结果模型
<span leaf="">package com.<span>aftersales</span>.<span>orch</span>.<span>model</span>;</span>
<span leaf="">package com.<span>aftersales</span>.<span>orch</span>.<span>model</span>;</span>
5.5 Planner:让 LLM 一次性生成完整计划
这是 Plan-and-Execute 的灵魂。Planner 接收诊断报告,输出一个结构化的 Plan JSON。
<span leaf="">package com.<span>aftersales</span>.<span>orch</span>.<span>planner</span>;</span>
关键点:
.entity(WorkOrderPlan.class)是 Spring AI 的结构化输出能力。LLM 返回 JSON,Spring AI 自动反序列化成 Java Record。这比手动解析 JSON 安全得多——类型不对编译就报错。
5.6 六个执行工具
Plan-and-Execute 模式下,工具不是由 LLM 在循环中自主选择调用的(那是 ReAct),而是在规划阶段就确定了「第几步调什么工具」,执行阶段按计划调用。
<span leaf=""><span>package</span> com.aftersales.orch.tools;</span>
5.7 Orchestrator:编排主控(Executor)
这是 Plan-and-Execute 的执行引擎。它接收 Plan,逐步骤执行,收集结果,处理异常。
<span leaf=""><span>package</span> com.aftersales.orch.agent;</span>
架构师视角:注意这个 Orchestrator 和第5期 ReAct 诊断 Agent 的根本区别——
ReAct Agent:LLM 在循环里每步决定「调什么工具」,工具列表由 Spring AI 的
.tools(...)注册,LLM 自主选择Plan-and-Execute Orchestrator:LLM 只在规划阶段决定「第几步调什么工具」,执行阶段是 Java 的
switch-case按计划分发,LLM 不参与每步的工具选择这意味着执行阶段更快(不调 LLM)、更可控(Java 代码决定调用路径)、更省钱(LLM 只调 2 次:规划 + 报告)。
六、REST 接口与运行效果
6.1 Controller
<span leaf=""><span>package</span> com.aftersales.orch.controller;</span>
6.2 调用示例
<span leaf="">curl -X POST http://localhost:8080/api/workorder/orchestrate \</span>
6.3 运行日志
<span leaf="">═══════ 阶段<span>1</span>:Planner 生成执行计划 ═══════</span>
6.4 最终执行报告
<span leaf="">══════════════════════════════════════════════════════</span>
七、Plan-and-Execute 的关键设计:Replan 机制
Plan-and-Execute 有一个 ReAct 不需要面对的问题:计划执行到一半发现走不通了怎么办?
比如配件缺货、技师请假、施工中发现额外问题——这些都需要重新规划。
7.1 Replan 的三种触发策略
| 策略
|
触发条件
|
处理方式
跳过+继续
|
非关键步骤失败
|
标记跳过,继续执行后续步骤
| |
终止+人工
|
关键步骤失败
|
终止编排,通知售后经理介入
| |
重新规划
|
计划不可行(如缺件)
|
把已执行结果 + 失败原因喂给 Planner,重新生成 Plan
|
7.2 Replan 代码实现
<span leaf=""><span>/**</span></span>
实际场景举例:
<span leaf="">原计划:开单→查件→派工→领料→施工→质检</span>
架构师视角:Replan 是 Plan-and-Execute 模式最复杂的部分。ReAct 不需要 Replan,因为它每步都在重新决策。但 Plan-and-Execute 一旦计划错了,就需要一个明确的「重新规划」机制来纠正。这也是为什么 Plan-and-Execute 的代码量通常比 ReAct 多 30%~50%。
八、ReAct vs Plan-and-Execute:什么时候用哪个?
这是全文最重要的一张表。我在第2期给过理论版,现在补充实战版。
8.1 选型决策矩阵
| 判断维度
|
选 ReAct
|
选 Plan-and-Execute
路径是否已知
|
❌ 未知,需要逐步探索
|
✅ 已知大概步骤,只是参数待定
| |
步骤间依赖
|
弱依赖,每步相对独立
|
强依赖,A 完成才能 B
| |
并行可能性
|
基本串行
|
有并行/合并空间
| |
LLM 调用成本
|
每步 1 次,N 步 N 次
|
规划 1 次 + 执行 0 次(Java 调工具)+ 报告 1 次
| |
执行速度
|
慢(每步等 LLM)
|
快(执行阶段不调 LLM)
| |
可控性
|
低(LLM 自主决策)
|
高(Java 代码控制执行路径)
| |
失败处理
|
LLM 自主调整
|
需要 Replan 机制
| |
输出可预测性
|
低(路径动态)
|
高(路径预设)
| |
售后场景类比
|
诊断(不知道病因)
|
工单编排(知道做什么)
|
8.2 售后场景选型速查表
| 售后场景
|
推荐模式
|
理由
故障诊断
|
ReAct
|
病因未知,需逐步排查
| |
工单编排
|
Plan-and-Execute
|
步骤固定,依赖明确
| |
客服问答
|
ReAct(轻量)
|
单轮或少量工具调用
| |
保险理赔流程
|
Plan-and-Execute
|
理赔步骤固定:报案→定损→报价→审批→赔付
| |
首保邀约
|
ReAct
|
客户反应不确定,需动态调整话术
| |
配件采购调度
|
Plan-and-Execute
|
采购流程固定:需求→询价→比价→下单→到货
| |
投诉处理
|
ReAct
|
客户情绪和诉求不确定,需动态应对
| |
月度结算风控
|
Plan-and-Execute
|
结算流程固定:对账→校验→预警→审批
|
8.3 一句话决策法则
路径不确定 → ReAct;路径确定但步骤多 → Plan-and-Execute。
更精确的说法:如果你能在写代码之前画出流程图,用 Plan-and-Execute;如果画不出来、得靠 LLM 自己决定下一步,用 ReAct。
九、ReAct + Plan-and-Execute 混合模式(进阶预告)
实际项目中,你很少只用一种模式。售后全流程其实是两种模式的嵌套:
<span leaf="">接车 → 诊断 → 工单编排 → 维修执行 → 质检 → 交车</span>
-
诊断阶段用 ReAct(逐步排查病因)
-
诊断结果输入给 Planner,生成工单 Plan
-
工单执行用 Plan-and-Execute(按计划逐步执行)
-
施工中如果发现意外(拆开发现还有其他问题),切回 ReAct(排查新问题),排查完再 Replan(更新工单)
这就是第2期讲过的「模式不是二选一,而是可以嵌套组合」。后面的期数我会用一个完整的混合模式 Demo 把整个售后流程串起来。
十、踩坑清单:Plan-and-Execute 的 5 个暗坑
坑1:Planner 生成的步骤遗漏关键环节
LLM 规划时可能漏掉某个步骤。比如只规划了「开单→施工→质检」,漏掉了「查配件」和「派工」。
<span leaf="">解决方案:</span>
<span leaf=""><span>@Component</span></span>
坑2:步骤间的数据传递断裂
第3步派工需要第1步的工单号,第4步领料需要第3步的工位号——如果 Orchestrator 没有正确地从上一步结果中取数据传给下一步,整个链条就断了。
<span leaf="">解决方案:</span>
坑3:Planner 输出的 JSON 格式不稳定
LLM 偶尔会在 JSON 前后加 markdown 标记(json … ),或者多输出一句话,导致反序列化失败。
<span leaf="">解决方案:</span>
坑4:没有设置执行超时
某个工具调用卡住(比如 DMS 系统响应慢),整个编排链路就挂在那里。
<span leaf=""><span>// 每步执行加超时</span></span>
坑5:Replan 死循环
重新规划后执行又失败,又触发 Replan,又失败……无限循环。
<span leaf="">解决方案:</span>
<span leaf=""><span>private</span> <span>static</span> <span>final</span> <span>int</span> MAX_REPLAN_ATTEMPTS = <span>2</span>;</span>
十一、诊断 Agent(ReAct)vs 工单编排 Agent(Plan-and-Execute):一图看懂
<span leaf="">诊断 Agent(第<span>5</span>期·ReAct) 工单编排 Agent(第<span>6</span>期·Plan<span>-</span><span>and</span><span>-</span><span>Execute</span>)</span>
十二、项目结构
<span leaf="">aftersales<span>-</span>workorder<span>-</span>agent<span>/</span></span>
十三、总结 & 下期预告
今天我从第2期的 Plan-and-Execute 理论走到了代码实现,用 Spring AI 搭建了一个完整的维修工单编排 Agent:
-
Planner:调一次 LLM,把诊断报告变成结构化的 6 步执行计划
-
Step Executor:Java 代码按计划逐步执行,每步调对应后端工具,不调 LLM
-
Replan 机制:执行中遇到异常(缺件/技师请假),触发重新规划
-
Plan Validator:校验 LLM 生成的计划是否包含所有必要步骤
-
5 个实战踩坑:步骤遗漏、数据传递断裂、JSON 不稳定、执行超时、Replan 死循环
核心认知:
ReAct 的难点在于「让 LLM 学会推理」,Plan-and-Execute 的难点在于「让 LLM 学会规划」+「让 Java 代码学会执行」。前者考验 Prompt 功力,后者考验架构设计。
一句话选型法则:路径不确定 → ReAct;路径确定但步骤多 → Plan-and-Execute。如果你能在写代码前画出流程图,用 Plan-and-Execute;画不出来,用 ReAct。
| 模式
|
LLM 角色
|
Java 代码角色
|
适合场景
ReAct
|
每步决策调什么工具
|
注册工具、返回结果
|
诊断、排查、探索
| |
Plan-and-Execute
|
规划一次 + 报告一次
|
按计划执行、管理依赖、处理异常
|
工单编排、流程自动化
|
第7期预告:前面几期都是 Single-Agent——一个 Agent 从头干到尾。但售后全流程这么长,一个 Agent 真的扛得住吗?第7期我们进入 Multi-Agent 多智能体——客服 Agent、诊断 Agent、工单编排 Agent、质检 Agent 如何分工协作?它们之间怎么通信?谁来当「总调度」?Spring AI 的多智能体编排怎么写?下期代码见。
互动话题:你店里的售后流程,哪些环节适合 ReAct(走一步看一步),哪些适合 Plan-and-Execute(先规划再执行)?把你觉得最难编排的流程发在评论区,下期我可能会用 Multi-Agent 帮你拆成多个 Agent 协作。
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/ai002/post/20260822/6%E6%9C%9FPlan-and-Execute-%E8%90%BD%E5%9C%B0%E7%94%A8-Spring-AI-%E6%90%AD%E4%B8%80%E4%B8%AA%E7%BB%B4%E4%BF%AE%E5%B7%A5%E5%8D%95%E7%BC%96%E6%8E%92-Agent%E8%AE%A9%E5%AE%83%E5%83%8F%E5%94%AE%E5%90%8E%E7%BB%8F%E7%90%86%E4%B8%80%E6%A0%B7%E5%BC%80%E5%8D%95%E6%B4%BE%E5%B7%A5%E6%89%A7%E8%A1%8C%E8%B4%A8%E6%A3%80/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com