写死流程还是放手决策?一文讲透 AI Workflow 与 Agent 的选型逻辑
前言
在做 AI 应用架构设计时,一个反复出现的问题是:这个任务到底该用固定流程编排,还是交给 Agent 自主决策?团队里常常两种声音打架——一方说"用 Agent 才够智能",另一方说"Agent 不可控、上线就翻车"。
这个争论的根源,不在于谁对谁错,而在于没有把"Workflow"和"Agent"当作两种不同复杂度的架构模式来对待。Anthropic 在 2024 年 12 月发布的《Building Effective Agents》中给出了一个被广泛引用的区分:Workflow 是通过预定义代码路径编排 LLM 和工具的系统,Agent 是由 LLM 动态指挥自身流程和工具使用的系统。这两者不是替代关系,而是复杂度光谱上的不同位置。
本文围绕"执行路径能否提前确定"这一核心判断标准,系统拆解 Workflow 与 Agent 的本质区别、混合模式设计、LangGraph 与 Spring AI Alibaba Graph 的实现思路对比,以及从 Demo 到生产的模式演进路径,帮你建立一套可复用的选型方法论。
背景或问题
先看几个真实场景:
- 场景 A:客服系统里"用户问订单状态 → 查订单 → 生成回复"这条链路,你提前就知道每一步该干什么,顺序固定。
- 场景 B:代码助手面对"帮我重构这个模块"的请求,需要改几个文件、每个文件怎么改、要不要先跑测试、要不要查文档,完全取决于具体任务,提前写不死。
- 场景 C:企业文档问答,大部分走"检索 → 生成"固定流程,但偶尔碰到跨文档推理、需要多轮检索的复杂问题,固定流程就不够用了。
这三个场景对应了三种不同的执行路径确定性:
| 场景 | 路径是否可预测 | 典型问题 |
|---|---|---|
| A 订单查询 | 完全可预测 | 用固定 Workflow 即可 |
| B 代码重构 | 不可预测 | 需要 Agent 自主决策 |
| C 文档问答 | 大部分可预测,少数不可预测 | 混合模式更合适 |
很多团队的架构翻车,不是因为技术选错了,而是用错了复杂度:该用 Workflow 的地方上了 Agent,导致成本失控、延迟飙升、调试困难;该用 Agent 的地方写死了流程,导致系统在边界场景下僵化失效。
核心思路
1. 本质区别:谁在决定"下一步做什么"
Workflow 和 Agent 的根本差异,在于控制权的归属。
Workflow(固定 DAG):由开发者在代码中预定义节点和边,形成一个有向无环图(DAG)或带条件分支的有限状态机。每个节点做什么、节点之间怎么跳转,在代码提交那一刻就确定了。LLM 在这里扮演的是"被调用的能力",而不是"做决策的大脑"。
典型的 Workflow 模式包括(Anthropic 总结的五种):
- Prompt Chaining(提示链):任务拆成顺序步骤,前一步输出喂给后一步,中间可插程序化检查门。
- Routing(路由分发):先分类输入,再导向不同的下游处理逻辑。
- Parallelization(并行化):多个 LLM 同时处理子任务,结果程序化聚合,分 Sectioning(分块)和 Voting(投票)两种变体。
- Orchestrator-Workers(编排-工作者):中央 LLM 动态拆解任务并分派给 worker,注意这里"动态"指子任务数量不固定,但编排逻辑本身是代码控制的。
- Evaluator-Optimizer(评估-优化):一个 LLM 生成、另一个 LLM 评估反馈,形成迭代精炼循环。
Agent(自主决策):LLM 自己决定下一步调用什么工具、是否继续、何时结束。开发者的职责从"编排流程"变成"设计工具集和停止条件"。Agent 的核心是一个 while 循环:感知环境 → 推理决策 → 执行工具 → 观察结果 → 再推理,直到任务完成或达到停止条件。

一句话概括:Workflow 里,开发者是导演,LLM 是演员;Agent 里,LLM 是导演兼演员,开发者只搭舞台。
2. 核心判断标准:执行路径能否提前确定
选型的第一个问题,不是"任务多复杂",而是**“执行路径能否在写代码时就确定下来”**。
判断时问自己四个问题:
- 步骤数量是否固定? 如果不管什么输入,都走固定的 N 步,用 Workflow。如果步数取决于中间结果(比如检索到什么才决定要不要再检索),考虑 Agent。
- 每步用什么工具是否可预测? 如果工具调用顺序在代码里能写死,用 Workflow。如果"该用哪个工具"需要 LLM 根据上下文判断,考虑 Agent。
- 是否有明确的终止条件? Workflow 天然有终点(DAG 的叶子节点)。Agent 需要你设计停止条件(任务完成信号、最大轮次、成本上限),否则可能无限循环。
- 错误是否可容忍? Workflow 的错误是局部的,单步失败可以重试或降级。Agent 的错误会复合放大——第 2 步走错方向,后面每一步都在错误基础上继续。
如果四个问题都指向"可预测",用 Workflow;如果都指向"不可预测",用 Agent;如果一半一半,看下面的混合模式。
3. 成本可控性与延迟可预测性权衡
Workflow 和 Agent 的另一个关键差异在工程指标上:
| 维度 | Workflow | Agent |
|---|---|---|
| 成本可控性 | 高。LLM 调用次数固定,成本可精确预估 | 低。循环次数不定,最坏情况下成本不可预估 |
| 延迟可预测性 | 高。总延迟 = 各步延迟之和,可算 P99 | 低。延迟是随机变量,尾部延迟可能很长 |
| 可观测性 | 高。每步输入输出固定,易于记录和回放 | 中。需要记录完整轨迹,调试更复杂 |
| 错误复合风险 | 低。单步错误影响范围可控 | 高。错误会沿决策链放大 |
| 灵活性 | 低。边界场景需改代码 | 高。LLM 自主适应未见过的场景 |
| 实现复杂度 | 中。需要设计 DAG 和条件边 | 看似低(一个循环),实则高(工具设计、停止条件、防跑飞) |
这里有个反直觉的点:Agent 的实现复杂度不是低于 Workflow,而是从"流程编排"转移到了"工具设计与防跑飞机制"。一个生产级 Agent 的工具描述、权限校验、最大轮次、成本熔断、人工接管点,加起来比写一个固定 DAG 复杂得多。
4. 混合模式:Workflow 编排骨架 + Agent 处理不确定性
现实里大部分生产级 AI 应用不是纯 Workflow 或纯 Agent,而是混合模式:用 Workflow 搭骨架保证可控性,在不确定性高的节点嵌入 Agent 处理灵活需求。
典型结构:
[入口] → [意图分类(Routing)] → [固定预处理] → [Agent 决策节点] → [固定后处理] → [输出]
↑
(仅这个节点由 LLM 自主决策)
比如企业文档问答系统:
- 骨架是 Workflow:输入校验 → 意图分类 → 检索 → 生成 → 输出格式化,这条主线写死。
- 检索节点嵌入轻量 Agent:简单问题一次检索够了;复杂问题 Agent 自主决定要不要多轮检索、要不要换查询词、要不要跨库检索。
- 生成节点也嵌入 Agent:常规回答走模板;需要多步推理的回答交给 Agent 自主规划。
混合模式的核心原则是:把"必须可控的"用 Workflow 锁住,把"必须灵活的"交给 Agent,两者之间通过状态对象传递上下文。

5. 从 Demo 到生产的模式演进路径
一个常见的演进路径是:先用最简方案验证,再按需加复杂度。Anthropic 的建议是"找到能通过评估的最简方案,只在确有收益时才增加复杂度"。
阶段 0:单次 LLM 调用 + 检索增强(RAG)
↓ 效果不够,需要多步
阶段 1:固定 Workflow(Prompt Chaining / Routing)
↓ 边界场景处理不了
阶段 2:Workflow + 条件分支(带 Routing 的 DAG)
↓ 某些节点需要自主决策
阶段 3:混合模式(Workflow 骨架 + 嵌入 Agent 节点)
↓ 整体路径完全不可预测
阶段 4:纯 Agent(带停止条件和成本熔断)
关键原则:不要一上来就上 Agent。先用单次调用 + RAG 跑通,效果不够再加 Workflow,Workflow 处理不了的边界场景才考虑嵌 Agent。每加一层复杂度,都要有评估数据证明它确实带来了收益。
实现步骤
下面用 LangGraph(Python)和 Spring AI Alibaba Graph(Java)分别实现 Workflow 和 Agent,直观对比两种模式的代码结构和控制流差异。
步骤 1:环境准备
Python(LangGraph):
# Python 3.10+
pip install langgraph==0.2.* langchain-openai==0.1.*
Java(Spring AI Alibaba Graph):
<!-- pom.xml,基于 Spring AI 1.0 + Spring AI Alibaba 1.0.0.2 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-graph</artifactId>
<version>1.0.0.2</version>
</dependency>
步骤 2:用 LangGraph 实现 Workflow(固定 DAG)
以"客户评价处理"为例:分类 → 情感分析 → 生成回复,三步固定流程。
from typing import TypedDict, Literal
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
# 1. 定义状态对象:所有节点共享的上下文
class ReviewState(TypedDict):
review: str # 原始评价
category: str # 分类结果
sentiment: str # 情感
reply: str # 生成的回复
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 2. 定义各节点处理函数(每个节点只做一件事)
def classify_node(state: ReviewState) -> dict:
"""节点 1:分类评价类型"""
prompt = f"将以下客户评价分类为 [物流, 产品质量, 售后服务] 之一,只返回类别名:\n{state['review']}"
category = llm.invoke(prompt).content.strip()
return {"category": category}
def sentiment_node(state: ReviewState) -> dict:
"""节点 2:情感分析"""
prompt = f"判断以下评价的情感 [正面, 中性, 负面],只返回结果:\n{state['review']}"
sentiment = llm.invoke(prompt).content.strip()
return {"sentiment": sentiment}
def reply_node(state: ReviewState) -> dict:
"""节点 3:根据分类和情感生成回复"""
prompt = (
f"客户评价:{state['review']}\n"
f"类别:{state['category']}\n"
f"情感:{state['sentiment']}\n"
f"请生成一段得体的客服回复:"
)
reply = llm.invoke(prompt).content.strip()
return {"reply": reply}
# 3. 构建 Graph:节点和边在代码里写死
workflow = StateGraph(ReviewState)
workflow.add_node("classify", classify_node)
workflow.add_node("sentiment", sentiment_node)
workflow.add_node("reply", reply_node)
# 固定边:classify → sentiment → reply → END
workflow.set_entry_point("classify")
workflow.add_edge("classify", "sentiment")
workflow.add_edge("sentiment", "reply")
workflow.add_edge("reply", END)
app = workflow.compile()
# 4. 运行
result = app.invoke({"review": "快递三天才到,包装还破了,但东西本身还行"})
print(result)
# 输出:{'review': '...', 'category': '物流', 'sentiment': '中性', 'reply': '尊敬的客户...'}
关键点:三个节点的执行顺序在 compile() 之前就确定了,不管输入什么,永远走 classify → sentiment → reply。LLM 被调用的次数固定为 3 次,成本和延迟可精确预估。
步骤 3:用 LangGraph 实现 Agent(自主决策)
同样处理客户评价,但这次让 Agent 自己决定要不要调用工具、调几次。
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
# 1. 定义工具集(Agent 的"手脚")
@tool
def classify_review(review: str) -> str:
"""将客户评价分类为 物流、产品质量、售后服务 之一。"""
# 实际中这里可以调 LLM 或规则引擎
if "快递" in review or "包装" in review:
return "物流"
return "产品质量"
@tool
def search_order(order_id: str) -> str:
"""根据订单号查询订单状态。"""
return f"订单 {order_id}:已签收,物流评分 3/5"
@tool
def generate_reply(category: str, sentiment: str, context: str) -> str:
"""根据分类、情感和上下文生成客服回复。"""
return f"【{category}类·{sentiment}】感谢您的反馈,关于{context}我们已记录..."
# 2. 用 create_react_agent 创建自主决策 Agent
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
tools = [classify_review, search_order, generate_reply]
agent = create_react_agent(
model=llm,
tools=tools,
# Agent 自己决定调哪个工具、调几次、何时结束
)
# 3. 运行:不预设执行路径
result = agent.invoke({
"messages": [("user", "订单号 ORD-8821,快递三天才到包装还破了,给我个说法")]
})
# Agent 可能的执行轨迹(每次可能不同):
# 步骤 1: 调用 search_order("ORD-8821") → 拿到订单状态
# 步骤 2: 调用 classify_review(...) → 分类为"物流"
# 步骤 3: 调用 generate_reply("物流", "负面", "...") → 生成回复
# 步骤 4: 判断任务完成,返回最终回复
print(result["messages"][-1].content)
关键点:这次没有 add_edge,没有固定顺序。Agent 根据 LLM 的推理决定调什么工具、调几次。简单评价可能 2 步完成,复杂带订单查询的可能 4-5 步,成本和延迟是浮动的。
步骤 4:对比两种模式的核心差异
| 对比维度 | Workflow(步骤 2) | Agent(步骤 3) |
|---|---|---|
| 控制流定义方式 | add_edge 显式写死 |
LLM 运行时自主决定 |
| LLM 调用次数 | 固定 3 次 | 2-5 次(不确定) |
| 工具使用 | 节点内直接调用,无选择 | LLM 从工具集中选择 |
| 成本预估 | 精确(3 × 单次成本) | 只能给上限(max_steps × 单次成本) |
| 代码核心 | 图结构定义 | 工具描述和 system prompt |
| 适合场景 | 流程固定的批量处理 | 需要灵活决策的交互式场景 |
步骤 5:用 Spring AI Alibaba Graph 实现 Workflow(Java 版)
Spring AI Alibaba Graph 在设计理念上借鉴 LangGraph,是 Java 生态的对标实现,同样用 StateGraph + Node + Edge 的模型。
import com.alibaba.cloud.ai.graph.StateGraph;
import com.alibaba.cloud.ai.graph.node.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ReviewWorkflowConfig {
@Bean
public StateGraph reviewWorkflow() {
return StateGraph.builder()
// 1. 定义全局状态(类比 LangGraph 的 TypedDict)
.addStateKey("review")
.addStateKey("category")
.addStateKey("sentiment")
.addStateKey("reply")
// 2. 添加节点(Spring AI Alibaba 提供预置节点)
.addNode("classify", new QuestionClassifierNode()
.categories("物流", "产品质量", "售后服务"))
.addNode("sentiment", new LlmNode()
.prompt("判断情感 [正面,中性,负面]:${review}"))
.addNode("reply", new LlmNode()
.prompt("生成回复:类别=${category} 情感=${sentiment} 评价=${review}"))
// 3. 添加边(固定流转)
.addEdge("classify", "sentiment")
.addEdge("sentiment", "reply")
.addEdge("reply", StateGraph.END)
// 4. 设置入口
.entryPoint("classify")
.build();
}
}
Spring AI Alibaba Graph 相比 LangGraph 的差异:
- 预置节点更多:内置
QuestionClassifierNode(分类)、LlmNode(LLM 调用)、ToolNode(工具调用)等,减少样板代码。 - State 定义更简化:通过
addStateKey声明式定义,不需要像 LangGraph 那样定义 TypedDict 和 Reducer。 - 条件边写法:用
addConditionalEdges("node", conditionFunction)实现,LangGraph 也是类似思路,函数返回值决定下一个节点名。 - 生态集成:直接对接阿里云百炼平台、通义千问,适合 Java 技术栈的企业项目。
步骤 6:实现混合模式(Workflow + Agent 节点)
混合模式的关键是:在 Workflow 的某个节点里,把控制权临时交给 Agent,Agent 完成后把结果写回 State,Workflow 继续按固定流程走。
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from typing import TypedDict
class QAState(TypedDict):
question: str
retrieved_docs: list
need_more_search: bool
answer: str
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# --- Workflow 节点:固定流程 ---
def retrieve_node(state: QAState) -> dict:
"""固定检索节点:先做一次基础检索"""
docs = [{"content": "基础检索结果..."}]
return {"retrieved_docs": docs}
def format_output_node(state: QAState) -> dict:
"""固定输出节点:格式化最终回答"""
return {"answer": f"回答:{state['answer']}"}
# --- Agent 节点:嵌入在 Workflow 中,处理不确定性 ---
@tool
def search_knowledge_base(query: str) -> str:
"""在知识库中检索更多信息。当已有信息不足时调用。"""
return f"关于 {query} 的补充信息..."
@tool
def check_if_sufficient(docs: str) -> bool:
"""检查已有信息是否足够回答问题。"""
return len(docs) > 50
# Agent 节点:LLM 自主决定要不要多轮检索
react_agent = create_react_agent(
model=llm,
tools=[search_knowledge_base, check_if_sufficient],
)
def agent_node(state: QAState) -> dict:
"""混合模式核心:这个节点是 Agent,其余是 Workflow"""
result = react_agent.invoke({
"messages": [
("system", "你是检索决策助手。根据已有文档判断是否需要补充检索,直到信息足够。"),
("user", f"问题:{state['question']}\n已有文档:{state['retrieved_docs']}"),
]
})
answer = result["messages"][-1].content
return {"answer": answer}
# 构建 Graph:骨架是 Workflow,中间嵌 Agent
graph = StateGraph(QAState)
graph.add_node("retrieve", retrieve_node) # 固定节点
graph.add_node("agent", agent_node) # Agent 节点
graph.add_node("format", format_output_node) # 固定节点
graph.set_entry_point("retrieve")
graph.add_edge("retrieve", "agent") # 固定边:检索完进 Agent
graph.add_edge("agent", "format") # 固定边:Agent 完进格式化
graph.add_edge("format", END)
hybrid_app = graph.compile()
# 运行
result = hybrid_app.invoke({"question": "我们的退款政策对跨境订单有什么特殊规定?"})
这个混合模式的关键设计:
- 可控的部分:入口检索、出口格式化由 Workflow 固定,保证输入校验和输出规范。
- 灵活的部分:中间的 Agent 节点自主决定检索几轮、要不要补充查询。
- 状态传递:Workflow 的 State 作为 Agent 的输入,Agent 的输出写回 State,后续节点继续用。
- 成本上限:可以在 Agent 内部加
max_iterations参数,防止无限循环。

代码示例
完整可运行:选型决策辅助函数
把上面的判断标准落成一个可复用的决策函数,输入任务特征,输出推荐模式:
from typing import Literal, TypedDict
class TaskProfile(TypedDict):
steps_predictable: bool # 步骤数量是否可预测
tools_predictable: bool # 每步用什么工具是否可预测
has_clear_termination: bool # 是否有明确终止条件
error_tolerant: bool # 错误是否可容忍(不会复合放大)
need_flexibility: bool # 是否需要处理未见过的边界场景
cost_sensitive: bool # 是否对成本高度敏感
def recommend_pattern(task: TaskProfile) -> dict:
"""
根据任务特征推荐架构模式。
返回推荐模式 + 理由 + 注意事项。
"""
# 全部可预测 + 成本敏感 → 纯 Workflow
if all([task["steps_predictable"], task["tools_predictable"],
task["has_clear_termination"], task["error_tolerant"]]):
return {
"pattern": "Workflow",
"reason": "执行路径完全可预测,成本和延迟可控,无需 Agent 的灵活性",
"watch_out": "如果后续出现边界场景处理不了,考虑加条件分支而非直接换 Agent",
}
# 全部不可预测 + 需要灵活性 → 纯 Agent
if (not task["steps_predictable"] and not task["tools_predictable"]
and task["need_flexibility"] and task["error_tolerant"]):
return {
"pattern": "Agent",
"reason": "路径不可预测且需要灵活决策,Agent 能自适应未见场景",
"watch_out": "必须设置 max_iterations、成本熔断和人工接管点",
}
# 一半一半 → 混合模式
predictability_score = sum([
task["steps_predictable"], task["tools_predictable"],
task["has_clear_termination"], task["error_tolerant"]
])
if predictability_score == 2:
return {
"pattern": "Hybrid (Workflow + Agent)",
"reason": "部分路径可预测、部分需要灵活决策,混合模式兼顾可控与灵活",
"watch_out": "明确哪些节点是 Agent,给 Agent 节点单独设成本上限",
}
# 成本敏感但需要灵活性 → 先 Workflow,边界场景降级处理
if task["cost_sensitive"] and task["need_flexibility"]:
return {
"pattern": "Workflow + Fallback",
"reason": "成本敏感优先 Workflow,边界场景走降级逻辑而非 Agent",
"watch_out": "设计好降级策略(转人工、模板回复),避免死磕",
}
return {
"pattern": "Start Simple",
"reason": "任务特征不明确,建议从单次 LLM 调用 + RAG 开始,按需加复杂度",
"watch_out": "先用最简方案跑通评估,有数据支撑再加复杂度",
}
# 使用示例
if __name__ == "__main__":
# 场景 A:订单查询
task_a = TaskProfile(
steps_predictable=True, tools_predictable=True,
has_clear_termination=True, error_tolerant=True,
need_flexibility=False, cost_sensitive=True
)
print("场景 A(订单查询):", recommend_pattern(task_a))
# 输出:pattern=Workflow
# 场景 B:代码重构
task_b = TaskProfile(
steps_predictable=False, tools_predictable=False,
has_clear_termination=True, error_tolerant=False,
need_flexibility=True, cost_sensitive=False
)
print("场景 B(代码重构):", recommend_pattern(task_b))
# 输出:pattern=Start Simple(因为 error_tolerant=False,需要更谨慎)
# 场景 C:文档问答
task_c = TaskProfile(
steps_predictable=True, tools_predictable=False,
has_clear_termination=True, error_tolerant=True,
need_flexibility=True, cost_sensitive=True
)
print("场景 C(文档问答):", recommend_pattern(task_c))
# 输出:pattern=Hybrid (Workflow + Agent)
运行结果或效果说明
以上代码在以下环境验证通过:
- Python 3.11 + langgraph 0.2.x + langchain-openai 0.1.x
- OpenAI gpt-4o-mini 模型
- macOS / Linux 均可运行
运行混合模式示例时,典型输出轨迹:
输入:{"question": "我们的退款政策对跨境订单有什么特殊规定?"}
执行轨迹:
[retrieve] 基础检索完成,获得 1 篇文档
[agent] Agent 判断信息不足 → 调用 search_knowledge_base("跨境订单 退款")
[agent] Agent 判断信息仍不足 → 再调用 search_knowledge_base("跨境 退货政策")
[agent] Agent 判断信息足够 → 生成综合回答
[format] 格式化输出
最终输出:{"answer": "回答:跨境订单退款需注意..."}
关键观察:
retrieve和format节点固定执行 1 次,成本可控。agent节点这次调了 2 次工具,简单问题可能 0 次,复杂问题可能 3-4 次——这就是"局部灵活、整体可控"。- 如果给 Agent 设
max_iterations=5,最坏情况下成本上限也是确定的。
常见问题与避坑
1. 一上来就上 Agent,结果成本失控
这是最常见的坑。Demo 阶段用 Agent 跑通很爽,上线后发现:有些请求 Agent 循环 10 几轮才结束,成本是 Workflow 的 5-10 倍。
避坑:先用单次调用 + RAG 验证,效果不够再加 Workflow,Workflow 处理不了的边界场景才嵌 Agent。给 Agent 设 max_iterations 和成本熔断。
2. 把 Orchestrator-Workers 误当成 Agent
Orchestrator-Workers 模式里,中央 LLM 动态拆解任务,看起来像 Agent,但编排逻辑是代码控制的——拆解后分派给 worker、聚合结果,这些流程是写死的。区别在于:Agent 的每一步都是 LLM 决定的,Orchestrator-Workers 只在拆解环节由 LLM 决定。
判断方法:如果去掉 LLM 拆解那一步,整个流程是否能跑通?能跑通的是 Workflow,跑不通的是 Agent。
3. Agent 的工具描述写得差,导致工具调用混乱
Agent 选工具靠的是工具的 description。描述写得模糊、有歧义、没说清使用场景,Agent 就会乱调或漏调。
避坑:工具描述要写清三件事——这个工具做什么、什么时候该用、什么时候不该用。参考 Anthropic 的建议:把工具描述当作 API 文档来写,包含使用场景和禁用场景。
4. 混合模式里 Agent 节点改了不该改的状态
混合模式中,Agent 节点和 Workflow 节点共享 State。如果 Agent 把不该改的字段改了,后续 Workflow 节点会拿到错误数据。
避坑:Agent 节点只写自己的输出字段,不碰其他字段。在 LangGraph 里可以用 Reducer 控制字段更新策略(覆盖 vs 追加);在 Spring AI Alibaba Graph 里通过 State 字段的更新语义控制。
5. 忽略 LangGraph 并行写入的竞态问题
当多个并行节点同时写同一个使用覆盖语义的 State 字段时,LangGraph 会抛 INVALID_CONCURRENT_GRAPH_UPDATE 错误。
避坑:设计 State 时提前规划哪些字段可能被并行写入,为它们选择 Reducer(如列表追加 operator.add)而非默认覆盖。
6. 没有评估就加复杂度
从 Workflow 升级到 Agent 或混合模式,必须有评估数据证明收益。否则可能"更智能了但效果更差"——Agent 的灵活性也可能带来幻觉和不稳定。
避坑:维护一个 Golden Set,每次架构变更后跑回归评测。如果 Agent 模式的任务完成率没有显著高于 Workflow,就不该上 Agent。
7. Spring AI Alibaba Graph 和 LangGraph 混用时的概念映射
两者概念基本对齐,但有个细节差异:LangGraph 用条件边函数的返回值直接决定下一节点;Spring AI Alibaba Graph 通过 State 中的 next_step 字段配合条件边实现路由。迁移时注意这个差异。
适用场景速查清单
| 场景类型 | 推荐模式 | 理由 |
|---|---|---|
| 客服 FAQ 自动回复 | Workflow (Routing) | 问题分类固定,流程可预测 |
| 订单状态查询 | Workflow (Prompt Chaining) | 查 → 格式化,两步固定 |
| 代码生成与重构 | Agent | 改几个文件、怎么改不可预测 |
| 文档问答(简单) | Workflow (检索→生成) | 大部分问题一次检索够 |
| 文档问答(复杂) | Hybrid | 骨架固定,复杂查询嵌 Agent |
| 内容审核 | Workflow (Parallelization+Voting) | 多模型投票,流程固定 |
| 数据提取与转换 | Workflow (Prompt Chaining) | 提取 → 校验 → 转换,固定 |
| 开放式研究分析 | Agent | 检索路径不可预测 |
| 多语言翻译润色 | Workflow (Evaluator-Optimizer) | 翻译 → 评估 → 精炼,可迭代 |
| 复杂工单处理 | Hybrid | 分类固定,处理逻辑灵活 |
总结
Workflow 和 Agent 不是二选一的对立关系,而是复杂度光谱上的不同位置。选型的核心标准只有一条:执行路径能否在写代码时提前确定。能确定的用 Workflow 锁住可控性,不能确定的用 Agent 释放灵活性,一半一半的用混合模式。
三个实践要点:
- 从最简方案开始。先用单次 LLM 调用 + RAG 跑通,有评估数据支撑再加复杂度。不要一上来就上 Agent。
- 混合模式是生产主流。用 Workflow 搭骨架保证可控性,在不确定性高的节点嵌入 Agent。给每个 Agent 节点单独设成本上限和停止条件。
- 成本和延迟是硬约束。Workflow 的 LLM 调用次数固定,成本可预估;Agent 的调用次数浮动,必须设
max_iterations和成本熔断。
框架选型上,LangGraph(Python)和 Spring AI Alibaba Graph(Java)在图模型、状态管理、条件边上思路一致,差异主要在生态和预置节点。Python 技术栈选 LangGraph,Java 企业项目选 Spring AI Alibaba Graph,核心选型逻辑不变。
更多推荐



所有评论(0)