为什么你的 Multi-Agent 跑不起来?因为你还没理解 State
一、为什么学 Multi-Agent 一定会遇到 State?
刚开始学 Multi-Agent 的时候,我们很容易把注意力放在“Agent 角色”上。
比如一个典型的多 Agent 系统可能会有:
Planner Agent:负责拆解任务
Executor Agent:负责执行任务
Tool Agent:负责调用工具
Reviewer Agent:负责检查结果
Replanner Agent:负责重新规划
Supervisor Agent:负责调度整体流程
看起来好像只要把这些 Agent 都写出来,一个 Multi-Agent 系统就完成了。
但真正落到代码里,你马上会遇到一堆问题:
用户原始问题存在哪里?
Planner 生成的计划存在哪里?
Executor 执行到第几步了?
工具调用结果要怎么传给下一个 Agent?
某一步执行失败了,错误信息谁保存?
Replanner 根据什么判断是否需要重新规划?
最终回答从哪里汇总?
这时候你会发现:
Multi-Agent 的难点不是“有几个 Agent”,而是这些 Agent 之间如何共享信息、传递上下文、更新任务进度。
这就是 State 的作用。
在单 Agent 场景中,我们可能只需要把用户问题和历史对话拼成 Prompt,然后发给大模型就行。
但是在 Multi-Agent 场景中,一次用户请求可能会经过多个节点:
用户输入
↓
Planner 生成计划
↓
Executor 执行步骤
↓
Tool 调用外部系统
↓
Replanner 判断是否重新规划
↓
Final Agent 汇总答案
这个过程中,每一步都会产生新的中间结果。
这些中间结果不能只存在模型的“脑子里”,因为大模型本身并不会真正帮你维护程序状态。
所以我们需要一个统一的状态对象,把整个任务执行过程记录下来。
这个东西,在很多 Agent 框架里会被称为:
State
GraphState
AgentState
WorkflowState
OverallState
名字可以不同,但本质都是一样的:
它是一次 Agent 工作流运行过程中的全局上下文对象。
二、OverallState 到底是什么?
可以先用一句话理解:
OverallState 就是整个 Multi-Agent 工作流运行过程中的“任务档案袋”。
它不是大模型自动保存的,也不是 ChatMemory 那种单纯的聊天记录,而是程序主动维护的一份任务状态。
比如用户输入:
帮我分析一下最近服务报错的原因,并生成一份排障报告。
这个请求进入系统后,不能只是简单丢给大模型。
更合理的做法是,把它变成一个任务状态:
public class OverallState {
private String userInput;
private List<String> plan;
private String currentStep;
private Map<String, Object> toolResults;
private List<String> observations;
private String errorMessage;
private Boolean needReplan;
private String finalAnswer;
}
这个对象里可以保存:
用户原始输入
任务拆解计划
当前执行步骤
工具调用结果
Agent 中间输出
错误信息
是否需要重新规划
最终回答
所以,OverallState 不是某个神秘的 AI 概念。
它本质上就是:
后端程序为了管理 Agent 工作流,设计出来的一个上下文状态对象。
你可以把它类比成一次请求的“全局变量”,但它比普通全局变量更有边界。
它通常只属于一次任务执行过程。
比如:
用户 A 发起一次告警分析任务 → 创建一个 OverallState
用户 B 发起一次知识库问答任务 → 创建另一个 OverallState
每个任务都有自己的 State,互不干扰。
这也是为什么 Multi-Agent 系统必须考虑 sessionId、conversationId、taskId 这些东西。
因为你不能让不同用户、不同任务的状态混在一起。
三、State 和 Prompt 是一回事吗?
这是学习 Agent 时非常容易混淆的地方。
很多人会觉得:
既然最后都是发给大模型,那 State 不就是 Prompt 吗?
其实不是。
它们的关系应该这样理解:
State 是程序中保存的上下文数据。
Prompt 是每次调用大模型时临时组装出来的输入。
也就是说,State 是“原材料仓库”,Prompt 是“这一次喂给模型的材料包”。
举个例子。
假设当前 State 是这样的:
{
"userInput": "分析订单服务异常",
"plan": [
"查询最近 10 分钟错误日志",
"检索相关故障知识库",
"分析可能原因",
"生成排障报告"
],
"currentStep": "查询最近 10 分钟错误日志",
"toolResults": {
"logSearch": "出现大量 Redis connection timeout"
},
"needReplan": false
}
当 Executor Agent 要工作时,程序可能会根据 State 组装一个 Prompt:
你是一个执行 Agent。
用户问题:
分析订单服务异常
当前执行步骤:
查询最近 10 分钟错误日志
已有计划:
1. 查询最近 10 分钟错误日志
2. 检索相关故障知识库
3. 分析可能原因
4. 生成排障报告
已有工具结果:
出现大量 Redis connection timeout
请基于当前步骤继续执行,并返回观察结果。
这个 Prompt 是临时生成的。
但是 State 会继续存在,并且会被后续节点继续读取和修改。
所以两者关系是:
State 负责保存完整任务上下文。
Prompt 负责把其中一部分上下文组织成模型能理解的输入。
这就是为什么我觉得 Agent 工程里不能只盯着 Prompt。
Prompt 很重要,但 Prompt 只是某一次模型调用的输入。
真正贯穿整个工作流的是 State。
四、State、Prompt、Memory 三者有什么区别?
在 Agent 系统里,这三个概念经常放在一起:
State
Prompt
Memory
但它们不是一个东西。
可以这样区分:
| 概念 | 作用 | 生命周期 | 典型内容 |
|---|---|---|---|
| Prompt | 本次模型调用的输入 | 一次 LLM 调用 | system、user input、历史片段、工具说明 |
| State | 当前任务执行状态 | 一次任务或一次工作流 | 计划、步骤、工具结果、错误、最终答案 |
| Memory | 跨轮次或长期保存的信息 | 多轮对话甚至长期存在 | 用户偏好、历史摘要、长期记忆、知识经验 |
举个更直观的例子。
用户说:
帮我分析订单服务为什么一直报错。
系统可能会这样处理:
Prompt:
这一次发给模型看的内容。
State:
这次排障任务执行过程中的所有中间状态。
Memory:
之前用户说过他项目里订单服务依赖 Redis、MySQL、RabbitMQ,这些长期信息可以被检索出来辅助分析。
所以三者的关系可以总结为:
Memory 提供历史经验
State 管理当前任务过程
Prompt 组织本次模型输入
在一个复杂 Agent 系统里,三者通常会一起工作:
用户输入
↓
读取 Memory 中的相关历史信息
↓
创建当前任务 State
↓
根据 State + Memory 组装 Prompt
↓
调用模型或工具
↓
把结果写回 State
↓
必要时再更新 Memory
这就比单纯的“用户输入 → 大模型回答”复杂很多了。
也正是因为多了这些工程层,Agent 才能真正从 Demo 走向项目。
五、多 Agent 是怎么围绕 State 协作的?
理解了 State 之后,再看 Multi-Agent,就会清楚很多。
多个 Agent 不是各说各的,而是围绕同一个 State 工作。
可以抽象成:
Agent = 读取 State → 执行自己的职责 → 更新 State
例如 Planner Agent:
public class PlannerAgent {
public void run(OverallState state) {
String userInput = state.getUserInput();
List<String> plan = callLLMToMakePlan(userInput);
state.setPlan(plan);
state.setCurrentStep(plan.get(0));
}
}
Executor Agent:
public class ExecutorAgent {
public void run(OverallState state) {
String currentStep = state.getCurrentStep();
Object result = executeStep(currentStep);
state.getToolResults().put(currentStep, result);
}
}
Replanner Agent:
public class ReplannerAgent {
public void run(OverallState state) {
boolean needReplan = judgeNeedReplan(state);
state.setNeedReplan(needReplan);
if (needReplan) {
List<String> newPlan = callLLMToReplan(state);
state.setPlan(newPlan);
}
}
}
Final Agent:
public class FinalAgent {
public void run(OverallState state) {
String answer = summarizeFinalAnswer(state);
state.setFinalAnswer(answer);
}
}
从这个角度看,多 Agent 并不是玄学。
它其实就是不同职责的处理节点,共同操作一个任务状态。
Planner 负责写入 plan
Executor 负责写入 toolResults
Replanner 负责写入 needReplan 和 newPlan
Final Agent 负责写入 finalAnswer
每个 Agent 都只负责自己那一部分。
这就像后端项目里的业务流程:
Controller 接收请求
Service 编排业务逻辑
Repository 查询数据
DTO 传递数据
Response 返回结果
只不过在 Agent 系统里,某些节点的逻辑不是传统代码写死的,而是通过大模型推理、工具调用、RAG 检索来完成。
六、DAG 固定了,为什么还能 Replan?
这个问题也很关键。
很多人看到 DAG 或 Workflow,会有一个误解:
既然流程图已经固定了,那它不就是死流程吗?
那还怎么体现 Agent 的动态性?
其实不是。
DAG 固定的是流程结构,不是每次执行的具体内容。
比如我们可以设计这样一个流程:
Start
↓
Planner
↓
Executor
↓
Check
↓
是否完成?
├── 是 → Final
└── 否 → Replanner → Executor
这个图的结构是固定的。
但是每次任务执行时,具体怎么走,要看 State。
比如:
如果 Executor 执行成功:
needReplan = false
进入 Final
如果 Executor 执行失败:
needReplan = true
进入 Replanner
如果工具结果不完整:
needReplan = true
重新补充计划
如果发现问题已经解决:
needReplan = false
直接生成最终结果
也就是说:
DAG 定义的是“可能的路径”,State 决定的是“这一次走哪条路径”。
这就像后端代码里的 if else。
代码结构是固定的,但不同输入会走不同分支。
Agent Workflow 也是一样。
if (state.getNeedReplan()) {
replanner.run(state);
executor.run(state);
} else {
finalAgent.run(state);
}
所以,DAG 和动态规划并不矛盾。
真正让流程动态起来的,不是 DAG 本身,而是 State 中不断变化的数据。
七、结合 Spring AI Alibaba 怎么理解?
在 Spring AI Alibaba 或类似 Agent 框架里,我们看到的一些概念,比如:
Graph
Node
Edge
State
OverAllState
Agent
ToolCallback
ChatClient
Advisor
其实可以放到同一张图里理解。
Graph / Workflow:
定义任务流程结构。
Node:
流程中的一个执行节点,可以是 Agent,也可以是普通函数。
Agent:
具有模型调用能力的节点。
ToolCallback:
Agent 可以调用的外部工具。
State / OverallState:
整个流程运行时共享的上下文。
ChatClient:
真正和大模型交互的客户端。
Advisor:
在模型调用前后增强上下文,比如记忆、RAG、日志等。
如果用一句话串起来:
Workflow 定义流程,Node 执行步骤,Agent 调用模型,ToolCallback 调用工具,OverallState 负责在这些节点之间传递上下文。
比如一次智能运维任务可以这样理解:
用户输入告警问题
↓
创建 OverallState
↓
Planner Node 读取 userInput,生成 plan,写入 State
↓
Log Tool Node 查询日志,写入 toolResult
↓
Knowledge Agent 检索知识库,写入 ragResult
↓
Diagnosis Agent 分析原因,写入 diagnosis
↓
Replanner Node 判断信息是否足够
↓
Final Node 汇总最终报告
在这个过程中,最重要的不是某一个 Agent 有多聪明,而是:
每一步产生的信息能不能被正确保存;
每一个 Agent 能不能拿到自己需要的上下文;
失败后能不能根据状态重新规划;
最终答案能不能基于完整状态汇总。
这就是 State 的价值。
八、结合 SuperBizAgent:一个智能运维场景
假设在 SuperBizAgent 里,用户输入:
订单服务最近 10 分钟大量报错,帮我分析原因。
这个时候可以创建一个任务状态:
OverallState state = new OverallState();
state.setUserInput("订单服务最近 10 分钟大量报错,帮我分析原因。");
state.setTaskType("AIOps");
state.setNeedReplan(false);
然后 Planner Agent 先生成计划:
1. 查询订单服务最近 10 分钟错误日志
2. 分析日志中的异常关键词
3. 检索知识库中类似故障案例
4. 判断是否和 Redis、MySQL、MQ 等依赖有关
5. 生成排障结论和处理建议
此时 State 变成:
{
"userInput": "订单服务最近 10 分钟大量报错,帮我分析原因。",
"taskType": "AIOps",
"plan": [
"查询订单服务最近 10 分钟错误日志",
"分析日志中的异常关键词",
"检索知识库中类似故障案例",
"判断是否和 Redis、MySQL、MQ 等依赖有关",
"生成排障结论和处理建议"
],
"currentStep": "查询订单服务最近 10 分钟错误日志",
"needReplan": false
}
接着 Executor 调用日志查询工具,发现:
Redis connection timeout
于是写回 State:
{
"toolResults": {
"logSearch": "订单服务出现大量 Redis connection timeout"
}
}
然后 Knowledge Agent 检索知识库,找到类似案例:
当 Redis 连接池耗尽或网络抖动时,订单服务可能出现接口超时和下单失败。
继续写回 State:
{
"ragResult": "Redis 连接池耗尽可能导致订单服务接口超时。"
}
Diagnosis Agent 再根据日志和知识库结果生成诊断:
{
"diagnosis": "初步判断订单服务异常与 Redis 连接超时有关,可能原因包括连接池配置过小、Redis 服务负载过高、网络抖动。"
}
如果此时 Replanner 判断信息不足,比如没有 Redis 监控指标,就可以设置:
{
"needReplan": true,
"missingInfo": "缺少 Redis 当前连接数、CPU、内存、慢查询等指标。"
}
然后重新生成补充计划:
1. 查询 Redis 当前连接数
2. 查询 Redis CPU 和内存使用率
3. 查询 Redis 慢查询日志
4. 结合订单服务错误日志重新分析
这就是 Replan。
它不是模型突然“灵光一现”,而是根据 State 中已有信息和缺失信息进行判断。
最终,如果信息足够,Final Agent 就可以基于 State 汇总报告:
问题现象:
订单服务最近 10 分钟大量报错。
关键日志:
出现 Redis connection timeout。
可能原因:
Redis 连接池耗尽、Redis 服务负载过高、网络抖动。
建议排查:
1. 检查 Redis 当前连接数和最大连接数配置。
2. 检查订单服务连接池配置。
3. 查看 Redis CPU、内存、慢查询指标。
4. 如果连接数打满,可临时扩容连接池或优化热点访问。
整个过程看起来像是多个 Agent 在协作。
但底层本质是:
多个 Agent 在不断读取和更新同一个任务状态。
九、为什么说 State 是 Agent 工程化的核心?
如果没有 State,多 Agent 很容易变成下面这种情况:
Planner 生成了计划,但 Executor 不知道。
Executor 调用了工具,但 Replanner 不知道结果。
Replanner 觉得要重试,但不知道之前失败在哪。
Final Agent 想总结,但拿不到完整过程。
这就会导致系统看起来有很多 Agent,但实际上每个 Agent 都是割裂的。
真正可用的 Multi-Agent 系统,一定要解决这几个问题:
1. 状态怎么创建?
2. 状态怎么传递?
3. 状态怎么更新?
4. 状态怎么隔离?
5. 状态怎么持久化?
6. 状态怎么参与 Prompt 组装?
7. 状态怎么决定流程分支?
这些问题,才是 Multi-Agent 工程化真正绕不开的地方。
如果只是写几个 Agent 类,然后每个类里面调用一次大模型,这还只是 Demo。
如果能把 State 管起来,才开始接近真正的 Agent 系统。
十、面向项目开发的设计建议
如果要在自己的项目里设计 Multi-Agent,我建议不要一上来就写很多 Agent。
应该先设计 State。
比如可以先问自己:
这个任务的输入是什么?
中间过程会产生哪些结果?
哪些信息需要被后续 Agent 使用?
哪些状态决定流程分支?
哪些错误需要记录?
最终答案需要哪些字段?
然后再设计一个状态对象:
@Data
public class AgentTaskState {
private String taskId;
private String sessionId;
private String userInput;
private String taskType;
private List<String> plan;
private Integer currentStepIndex;
private Map<String, Object> toolResults = new HashMap<>();
private Map<String, Object> agentResults = new HashMap<>();
private List<String> observations = new ArrayList<>();
private List<String> errors = new ArrayList<>();
private Boolean needReplan = false;
private String finalAnswer;
}
然后每个 Agent 都遵守一个统一规则:
只读取自己需要的状态;
只写入自己负责的结果;
不要随便覆盖其他 Agent 的输出;
每次关键变化都记录 observation;
失败信息写入 errors;
是否需要 Replan 写入 needReplan。
这样整个系统才会清晰。
你甚至可以把 Agent 抽象成统一接口:
public interface AgentNode {
void run(AgentTaskState state);
}
然后每个 Agent 实现这个接口:
public class PlannerNode implements AgentNode {
@Override
public void run(AgentTaskState state) {
// 读取 userInput
// 调用大模型生成 plan
// 写回 state
}
}
public class ExecutorNode implements AgentNode {
@Override
public void run(AgentTaskState state) {
// 读取 currentStep
// 调用工具或模型执行
// 写回 toolResults / agentResults
}
}
public class ReplannerNode implements AgentNode {
@Override
public void run(AgentTaskState state) {
// 读取已有执行结果
// 判断是否需要重新规划
// 更新 needReplan / plan
}
}
这样设计之后,Multi-Agent 就不再是几个大模型调用的堆叠,而是一个有结构、有状态、有流程控制的系统。
十一、总结
今天这篇文章主要想表达一个观点:
Multi-Agent 的核心不是“多个 Agent”,而是“多个 Agent 如何围绕 State 协作”。
Planner、Executor、Replanner、Supervisor 这些名字都很重要,但如果没有 State,它们之间就无法真正协作。
可以把整个关系总结成一句话:
Prompt 决定这一次模型怎么看问题;
Memory 决定系统能记住什么历史;
State 决定整个任务怎么推进。
在 Spring AI Alibaba 或其他 Agent 框架里,我们看到的 OverallState,本质上就是一次工作流执行过程中的全局任务上下文。
它负责保存用户输入、任务计划、执行步骤、工具结果、错误信息、重规划标记和最终答案。
理解了 State,再去看 DAG、Workflow、Replan、Supervisor,就会清楚很多。
DAG 不是死流程。
它只是定义了可能的执行路径。
真正决定流程怎么走的,是 State 中不断变化的数据。
所以,想把 Multi-Agent 从 Demo 写成项目,第一步不是疯狂加 Agent,而是先问自己:
我的 State 设计清楚了吗?
如果 State 设计不清楚,Agent 越多,系统越乱。
如果 State 设计清楚,Agent 才能真正协作起来。
这也是我最近学习 Multi-Agent 最大的感受:
Agent 工程化,表面是在调模型,本质是在管理上下文。
更多推荐



所有评论(0)