Workflow 与 Agent 的区别:从原理到实践的完整指南
原文地址【带图片】:Workflow 与 Agent 的区别:从原理到实践的完整指南
从一场争论说起
最近一年,“AI Agent” 成了技术圈最热门的话题之一。但伴随热度的,是越来越多的困惑——到底什么是 Agent?它和我们一直在用的 Workflow(工作流)有什么区别?为什么 Anthropic 在《Building Effective Agents》博文中强调"大多数场景根本不需要 Agent"?
这篇文章将从控制流归属这一本质区别出发,用图解、代码和实践决策框架,帮你在 Workflow 和 Agent 之间做出正确的选择。
本质区别:谁在控制流程?
Workflow 和 Agent 的根本不同,不在于是否使用了 LLM,而在于**"下一步做什么"这个决策由谁做出**:
- Workflow:流程由代码预先定义。开发者在写代码时就决定好了每一步干什么、什么时候执行。LLM 只负责生成内容,不做流程决策。
- Agent:流程由LLM 在运行时动态决定。LLM 自己选择调用哪个工具、要不要重试、什么时候结束。开发者只设置边界和约束。
这个区别看似简单,但它决定了系统的可预测性、成本和适用范围。
上面这张图展示了从简单 LLM 调用到 Agent 的渐进过程。这不是非黑即白的选择,而是一个连续的光谱。
不要一上来就造 Agent
Anthropic 的工程实践有一条核心原则:从最简单的方案开始,只在确实需要时才增加复杂度。
很多场景用一次 LLM 调用就能完美解决——总结文档、分类邮件、翻译文本。给 LLM 加上检索(RAG)和上下文示例,效果往往已经足够好。
什么时候才需要升级到 Workflow 和 Agent?简单来说:
- 一次调用不够,需要多步处理 → 考虑 Workflow
- 步骤无法预先确定,LLM 必须自己决定做什么 → 考虑 Agent
下面我们通过代码来具体理解两种模式。
Workflow 模式:预定义的确定性流程
Workflow 的思路是:把复杂任务拆解成一系列确定的步骤,每一步由 LLM 或传统代码完成。LLM 参与内容生成,但流程编排由开发者完全控制。
Python 代码示例
下面是一个基于 LangGraph 的 Workflow 实现:它按固定顺序执行"分类意图 → 改写查询 → 检索 → 生成答案"四个步骤。
from langgraph.graph import StateGraph, START, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage
from pydantic import BaseModel
from typing import TypedDict
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 定义结构化状态
class WorkflowState(TypedDict):
question: str
intent: str
rewritten_query: str
retrieval_results: list[str]
final_answer: str
# 步骤 1:分类用户意图
class IntentClassification(BaseModel):
intent: str # "math" | "general_knowledge" | "weather"
def classify_intent(state: WorkflowState) -> dict:
response = llm.with_structured_output(IntentClassification).invoke([
SystemMessage(content="将意图分类为: math, general_knowledge, weather。"),
HumanMessage(content=state["question"])
])
return {"intent": response.intent}
# 步骤 2:改写查询
class RewrittenQuery(BaseModel):
query: str
def rewrite_query(state: WorkflowState) -> dict:
response = llm.with_structured_output(RewrittenQuery).invoke([
SystemMessage(content="改写问题,使其更适合搜索引擎检索。"),
HumanMessage(content=state["question"])
])
return {"rewritten_query": response.query}
# 步骤 3:向量检索(确定性步骤,不使用 LLM)
def retrieve(state: WorkflowState) -> dict:
knowledge_base = {
"weather": "今日天气:晴,22°C。",
"general": "法国的首都是巴黎。"
}
key = "weather" if "weather" in state["intent"] else "general"
return {"retrieval_results": [knowledge_base.get(key, "无结果")]}
# 步骤 4:基于检索结果生成答案
def generate_answer(state: WorkflowState) -> dict:
context = "\n".join(state["retrieval_results"])
response = llm.invoke([
SystemMessage(content=f"使用以下上下文回答问题:\n{context}"),
HumanMessage(content=state["question"])
])
return {"final_answer": response.content}
# 构建固定流程
workflow = StateGraph(WorkflowState)
workflow.add_node("classify_intent", classify_intent)
workflow.add_node("rewrite_query", rewrite_query)
workflow.add_node("retrieve", retrieve)
workflow.add_node("generate_answer", generate_answer)
workflow.add_edge(START, "classify_intent")
# 条件分支:数学问题跳过检索
workflow.add_conditional_edges("classify_intent",
lambda s: "generate_answer" if s["intent"] == "math" else "rewrite_query",
{"rewrite_query": "rewrite_query", "generate_answer": "generate_answer"}
)
workflow.add_edge("rewrite_query", "retrieve")
workflow.add_edge("retrieve", "generate_answer")
workflow.add_edge("generate_answer", END)
pipeline = workflow.compile()
# 运行
result = pipeline.invoke({"question": "今天天气怎么样?"})
print(result["final_answer"])
上面的代码有几个关键特征:
- 每个节点做什么,预先定义得清清楚楚
- 条件分支(数学问题跳过检索)是开发者写死的规则
- LLM 只负责"分类"“改写”"生成"这些内容任务,不做流程决策
这就是 Workflow 的核心特征:控制流在代码里,不在模型里。
Agent 模式:LLM 自主决策的循环推理
Agent 的架构完全不同。它把"下一步做什么"的决定权交给了 LLM。典型的 Agent 采用 ReAct(Reasoning + Acting)循环:LLM 观察当前状态 → 推理需要什么 → 选择工具并执行 → 观察结果 → 继续推理,直到认为任务完成。
Python 代码示例
下面是一个基于 LangGraph 的 ReAct Agent 实现。注意代码量反而比 Workflow 更少,因为 LLM 接管了流程编排。
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode, tools_condition
from langgraph.checkpoint.memory import MemorySaver
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from typing import Annotated
from typing_extensions import TypedDict
import operator
# 定义工具
@tool
def multiply(a: int, b: int) -> int:
"""两个整数相乘。"""
return a * b
@tool
def add(a: int, b: int) -> int:
"""两个整数相加。"""
return a + b
@tool
def subtract(a: int, b: int) -> int:
"""两个整数相减,返回 a - b。"""
return a - b
@tool
def web_search(query: str, max_results: int = 3) -> str:
"""搜索网络获取最新信息。"""
from duckduckgo_search import DDGS
with DDGS() as ddgs:
results = [f"{r['title']}" for r in ddgs.text(query, max_results=max_results)]
return "\n".join(results)
tools = [add, multiply, subtract, web_search]
# 将工具绑定到 LLM
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0).bind_tools(tools)
# 定义状态
class AgentState(TypedDict):
messages: Annotated[list, operator.add]
# Agent 节点:LLM 决定调用工具还是直接回复
def agent_node(state: AgentState) -> dict:
ai_msg = llm.invoke(state["messages"])
return {"messages": [ai_msg]}
# 构建 Agent 图
workflow = StateGraph(AgentState)
workflow.add_node("agent", agent_node)
workflow.add_node("tools", ToolNode(tools))
workflow.add_edge(START, "agent")
# 关键:根据 LLM 输出决定下一步
workflow.add_conditional_edges(
"agent",
tools_condition, # 有 tool_calls → tools,否则 → END
{"tools": "tools", END: END}
)
workflow.add_edge("tools", "agent") # 工具结果返回 Agent 继续推理
agent = workflow.compile(checkpointer=MemorySaver())
# 运行——LLM 自己决定调用哪些工具、调用几次
result = agent.invoke(
{"messages": [{"role": "user", "content": "计算 (15 * 7 + 22) / 11,顺便搜一下今天的科技新闻"}]},
config={"configurable": {"thread_id": "user-1"}}
)
print(result["messages"][-1].content)
注意上面这段代码和 Workflow 的本质区别:
- 没有预定义步骤顺序——LLM 自己决定先算乘法还是先搜索
- tools_condition 是实现自主性的关键——它检查 LLM 的响应中是否包含 tool_calls,有则进入工具节点,没有则结束
- 工具执行完会自动回到 Agent 节点——形成"推理-行动-观察-推理"的循环
- 开发者只定义了能力和边界(有哪些工具可用),不定义执行路径
Workflow vs Agent 对比一览
| 维度 | Workflow | Agent |
|---|---|---|
| 控制流归属 | 代码(开发者预定义) | LLM(运行时动态决策) |
| 执行路径 | 固定或有限分支(DAG) | 动态循环,直到目标达成 |
| 可预测性 | 高——相同输入走相同路径 | 较低——相同输入可能走不同路径 |
| LLM 调用次数 | 可预估(通常固定) | 不可预估(取决于任务复杂度) |
| 延迟 | 低且稳定 | 波动较大 |
| Token 成本 | 可控、预算明确 | 上限难预估 |
| 工具调用 | 开发者在特定节点预设 | LLM 运行时自主选择 |
| 错误处理 | 显式分支或终止 | LLM 可尝试自修复 |
| 代码复杂度 | 节点和边多,路由逻辑多 | 架构简洁,但调试困难 |
| 适用场景 | 结构化、可重复、需审计 | 开放、探索性、需判断 |
混合架构:生产环境的务实选择
现实世界中,纯粹的 Agent 很少单独存在。大多数成功的生产系统采用混合架构:外层是确定性的 Workflow,只在需要动态推理的环节嵌入 Agent。
典型场景
客服系统:Workflow 负责意图分类、权限校验、会话管理;Agent 负责在知识库中动态搜索、调用业务接口、根据客户情绪调整回复策略。
代码审查工具:Workflow 负责拉取 PR、解析 diff、按文件拆分;Agent 负责分析代码逻辑、提出改进建议(因为每个 PR 的问题各不相同)。
数据分析助手:Workflow 负责查询生成、SQL 校验、结果格式化;Agent 负责理解用户的分析意图、决定从哪个角度切入、发现异常时动态调整分析方向。
混合模式的代码结构
# 混合架构示意
from langgraph.graph import StateGraph, START, END
# 外层 Workflow
workflow = StateGraph(HybridState)
# 确定性节点
workflow.add_node("validate_input", validate_input) # 参数校验
workflow.add_node("fetch_context", fetch_context) # 拉取上下文
# Agent 节点(嵌入在 Workflow 中)
workflow.add_node("agent_推理", agent_node) # LLM 自主推理
workflow.add_node("format_output", format_output) # 格式化输出
workflow.add_node("audit_log", audit_log) # 审计日志
# 固定流程
workflow.add_edge(START, "validate_input")
workflow.add_edge("validate_input", "fetch_context")
workflow.add_edge("fetch_context", "agent_推理")
workflow.add_edge("agent_推理", "format_output")
workflow.add_edge("format_output", "audit_log")
workflow.add_edge("audit_log", END)
# Agent 节点内部是自主循环,但输入/输出接口是确定的
混合架构的优势:
- 可靠性:输入校验、输出格式化、审计日志这些环节保持确定性
- 灵活性:Agent 环节可以动态处理多变的任务
- 可观测性:每个节点的输入输出都是确定的数据结构,便于监控和调试
- 安全性:在 Agent 节点的入口和出口设置校验和权限检查
如何选择:一个实用的决策框架
面对具体需求时,可以按下面的流程来判断:
实践建议
优先使用单次 LLM 调用。大多数"AI 功能"用简单的 prompt + RAG 就能做好。先上线,再根据实际效果判断是否需要升级。
需要多步时才考虑 Workflow。写清楚每一步做什么,LLM 只承担内容任务。这样成本可控,出了问题也好排查。
仅当步骤不可预知时才引入 Agent。如果你在写代码时无法确定"做完这一步之后该做什么",那才是 Agent 发挥价值的地方。典型的信号包括:
- 需要根据中间结果动态选择工具
- 任务路径随输入变化很大
- 需要探索性推理(比如调试、研究、复杂分析)
警惕落地风险。Gartner 预测 2027 年超过 40% 的 Agent 项目会因成本失控或价值不明确而被取消。在引入 Agent 之前,先确保:
- 核心子任务模型能可靠执行(不存在致命瓶颈)
- 错误可以被检测且代价可接受
- 任务的业务价值值得付出额外的 token 成本
总结
Workflow 和 Agent 不是"谁更好"的问题,而是"谁更适合当前场景"的问题。如果用一句话总结:
能预先列出所有步骤的,用 Workflow;必须让 LLM 自己想办法的,用 Agent。
从技术演进的角度看,大部分团队的建议路径是:单次 LLM 调用 → Prompt Chaining → Workflow → 混合架构(仅当需要时引入 Agent)。每一步升级都应该由实际需求驱动,而不是技术热情。
希望这篇文章帮你在下一次架构讨论中,能清晰地回答:“我们真的需要 Agent,还是 Workflow 就够了?”
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)