Workflow vs Agent:别再搞混了,这是两个完全不同的东西

如果你分不清 Workflow 和 Agent,你设计的 AI 系统会既不可控,又不可预测。

更糟的是,你甚至可能不知道自己用错了


一、先说清楚:什么是 Workflow?什么是 Agent?

1.1 一句话定义

Workflow(工作流)定义每一步做什么,LLM 只负责执行。

Agent(智能体)LLM 决定下一步做什么,只定义它能用的工具。

看出来区别了吗?

  • Workflow:在驾驶
  • Agent:LLM 在驾驶,你只给了它方向盘和地图

1.2 代码层面的直观对比

Workflow 示例(用 LangGraph 实现):

from langgraph.graph import StateGraph, END

# Workflow:你定义每一步
def step1(state):
    """步骤 1:提取关键词"""
    keywords = llm.invoke(f"提取关键词:{state['query']}")
    state["keywords"] = keywords
    return state

def step2(state):
    """步骤 2:检索文档"""
    docs = vector_db.search(state["keywords"])
    state["docs"] = docs
    return state

def step3(state):
    """步骤 3:生成回答"""
    answer = llm.invoke(f"基于{docs},回答问题:{state['query']}")
    state["answer"] = answer
    return state

# 构建 Workflow(你定义流程)
graph = StateGraph()
graph.add_node("extract_keywords", step1)
graph.add_node("retrieve_docs", step2)
graph.add_node("generate_answer", step3)

graph.add_edge("extract_keywords", "retrieve_docs")
graph.add_edge("retrieve_docs", "generate_answer")
graph.add_edge("generate_answer", END)

workflow = graph.compile()

关键点:流程是固定的step1 → step2 → step3,永远不会变。


Agent 示例(用 LangGraph 实现):

from langgraph.graph import StateGraph, END
from langchain.tools import Tool

# Agent:LLM 决定下一步调用哪个工具
def should_retrieve(state):
    """LLM 判断:需要检索吗?"""
    decision = llm.invoke(f"需要检索知识库吗?问题:{state['query']}")
    return decision  # "yes" or "no"

def retrieve_tool(state):
    """检索工具"""
    docs = vector_db.search(state["query"])
    state["docs"] = docs
    return state

def answer_tool(state):
    """回答工具"""
    answer = llm.invoke(f"基于{state.get('docs', '')},回答:{state['query']}")
    state["answer"] = answer
    return state

# 构建 Agent(LLM 决定流程)
tools = [
    Tool(name="Retrieve", func=retrieve_tool, description="检索知识库"),
    Tool(name="Answer", func=answer_tool, description="生成回答"),
]

# Agent 循环:LLM 每次决定调用哪个工具
def agent_loop(state):
    """LLM 选择下一个动作"""
    action = llm.invoke(
        f"问题:{state['query']}\n可选工具:{tools}\n选择下一个工具:"
    )
    return action  # 返回 "Retrieve" 或 "Answer"

graph = StateGraph()
graph.add_node("agent", agent_loop)
graph.add_node("retrieve", retrieve_tool)
graph.add_node("answer", answer_tool)

# 关键区别:边是动态的,由 LLM 决定
graph.add_conditional_edges(
    "agent",
    lambda state: should_retrieve(state),
    {"yes": "retrieve", "no": "answer"}
)
graph.add_edge("retrieve", "agent")  # 检索完,回到 agent 决策
graph.add_edge("answer", END)

agent = graph.compile()

关键点:流程是动态的。LLM 每次决定"下一步调哪个工具"。


二、核心区别:5 个维度深度对比

维度 Workflow Agent
控制权 你(开发者)完全控制流程 LLM 控制流程,你只定义工具
可预测性 高(流程固定,每次执行路径相同) 低(LLM 决策,每次可能不同)
适用场景 流程明确、步骤固定、可枚举 流程不确定、需要动态决策、开放性问题
成本 低(LLM 调用次数固定) 高(可能多轮调用,甚至死循环)
调试难度 低(流程固定,容易复现) 高(LLM 决策不确定,难以复现)

2.1 控制权:谁在驾驶?

Workflow:你在驾驶。

  • 你定义:step1 → step2 → step3
  • LLM 只是执行者,不决定流程
  • 适合:你知道"正确流程"是什么

Agent:LLM 在驾驶。

  • LLM 决定:下一步调哪个工具?需要几次检索?什么时候输出答案?
  • 你只定义:LLM 能用的工具列表
  • 适合:你不知道"正确流程"是什么(或者不固定)
一个具体例子

任务:回答用户的技术问题。

Workflow 方案

用户输入 → 提取关键词 → 检索文档 → 生成回答 → 输出

流程是固定的,永远不会变。

Agent 方案

用户输入 → LLM 决策:
  - 如果简单问题 → 直接回答
  - 如果需要查文档 → 调用检索工具 → 再决策:需要查更多信息吗?
  - 如果需要计算 → 调用计算器工具 → 再决策:结果合理吗?
  - ...(LLM 动态决定)

流程是动态的,每次可能不同。

2.2 可预测性:每次执行路径相同吗?

Workflow

  • 输入相同 → 执行路径相同 → 输出相同(如果 LLM 确定性输出)
  • 优点:容易测试、容易调试、容易保证质量
  • 缺点:不够灵活,无法处理意外情况

Agent不一定

  • 输入相同 → 执行路径可能不同(LLM 决策有随机性)
  • 优点:灵活,能处理复杂、开放性任务
  • 缺点:难以测试、难以调试、可能失控
一个真实案例

场景:客服机器人处理退货请求。

Workflow 方案

接收请求 → 检查订单状态 → 如果已发货 → 拒绝退货 → 如果未发货 → 同意退货

问题:如果用户说"我收到的商品有质量问题,但订单显示已发货",Workflow 会直接拒绝,因为它只检查"订单状态",不理解"质量问题"这个例外。

Agent 方案

接收请求 → LLM 分析:
  - 如果订单未发货 → 同意退货
  - 如果订单已发货 → LLM 进一步检查:"用户理由是什么?"
    - 如果是"质量问题" → 转人工处理
    - 如果是"不想要了" → 拒绝退货

区别:Agent 能处理例外情况,Workflow 只能处理预设情况

2.3 适用场景:什么时候用哪个?

Workflow 适合

  1. 流程明确:你知道每一步应该做什么
  2. 步骤固定:流程不会根据输入变化
  3. 可枚举:所有可能的路径都能提前定义
  4. 要求可预测:每次输出必须一致(比如金融、医疗)

例子

  • 文档摘要(固定流程:分割 → 摘要 → 合并)
  • 数据 ETL(固定流程:抽取 → 转换 → 加载)
  • 报表生成(固定流程:查询数据 → 格式化 → 生成图表)

Agent 适合

  1. 流程不明确:你不知道"正确流程"是什么
  2. 需要动态决策:根据输入,每一步的决策可能不同
  3. 开放性问题:无法枚举所有可能的路径
  4. 容错率高:偶尔出错可以接受(比如聊天机器人)

例子

  • 智能客服(需要根据用户问题动态决定:查订单?查物流?转人工?)
  • 代码助手(需要根据需求动态决定:写代码?改代码?解释代码?)
  • 研究助手(需要动态决定:搜哪些论文?读哪些章节?怎么总结?)

2.4 成本:LLM 调用次数可控吗?

Workflow可控

  • 你定义了 3 步 → 每次执行恰好 3 次 LLM 调用
  • 成本可预测,容易做预算

Agent不可控

  • LLM 可能调用 1 次就给出答案,也可能调用 10 次还在循环
  • 成本不可预测,可能失控
代码示例:成本控制

Workflow(成本固定)

# Workflow:固定 3 次 LLM 调用
def workflow(query):
    step1 = llm.invoke(f"提取关键词:{query}")      # 第 1 次调用
    step2 = llm.invoke(f"检索文档:{step1}")         # 第 2 次调用
    step3 = llm.invoke(f"生成回答:{query}{step2}") # 第 3 次调用
    return step3

# 每次调用 workflow(query),恰好 3 次 LLM 调用
# 成本 = 3 × (input_tokens + output_tokens) × 单价

Agent(成本不可控)

# Agent:LLM 决定调用次数
def agent(query, max_steps=10):
    state = {"query": query, "history": []}
    
    for i in range(max_steps):
        # LLM 决策:下一步做什么?
        action = llm.invoke(f"选择动作:{state}")  # 每次循环都调用 LLM
        
        if action == "answer":
            return llm.invoke(f"生成回答:{state}")  # 再调用 1 次
        elif action == "retrieve":
            state["docs"] = retrieve(state["query"])
        elif action == "calculate":
            state["result"] = calculate(state["query"])
        # ... 可能还有很多其他动作
        
        # 问题:如果 LLM 一直不选择 "answer",会循环到 max_steps
    
    return "超时,未得到答案"

# 每次调用 agent(query),LLM 调用次数可能是 1-10 次
# 成本不可预测

关键区别

  • Workflow 的成本是 O(1)(常数次 LLM 调用)
  • Agent 的成本是 O(n)(n 由 LLM 决策决定,可能很大)

2.5 调试难度:出错了怎么排查?

Workflow容易

  • 流程固定 → 出错时,你能精确定位是哪一步的问题
  • 可以单独测试每一步
  • 可以复现错误(输入相同 → 错误必现)

Agent困难

  • 流程动态 → 出错时,你可能不知道 LLM 为什么做了某个决策
  • 难以单独测试(因为 LLM 决策有随机性)
  • 难以复现错误(输入相同,LLM 决策可能不同)
代码示例:调试

Workflow 调试

# Workflow:可以单独测试每一步
def test_workflow():
    # 测试 step1
    state = {"query": "什么是 Agent?"}
    state = step1(state)
    assert "Agent" in state["keywords"]  # 如果失败,精确定位到 step1
    
    # 测试 step2
    state = step2(state)
    assert len(state["docs"]) > 0  # 如果失败,精确定位到 step2
    
    # 测试 step3
    state = step3(state)
    assert "Agent" in state["answer"]  # 如果失败,精确定位到 step3

Agent 调试

# Agent:难以单独测试,因为 LLM 决策有随机性
def test_agent():
    # 第一次运行
    result1 = agent("什么是 Agent?")
    
    # 第二次运行(相同输入)
    result2 = agent("什么是 Agent?")
    
    # 问题:result1 和 result2 的执行路径可能不同!
    # LLM 第一次可能调用 3 次工具,第二次可能调用 5 次
    # 如果 result1 正确,result2 错误,你怎么调试?

调试 Agent 的方法(比 Workflow 复杂):

  1. 记录 LLM 的每次决策(用 LangSmith 或自定义日志)
  2. 设置最大步数(防止死循环)
  3. 用更确定的模型(降低 temperature)
  4. 人工审查边界案例

三、代码示例:同一个任务,两种实现

为了让你更直观地理解,我用同一个任务,分别用 Workflow 和 Agent 实现。

任务:智能客服处理用户问题。

要求

  1. 如果用户问"订单状态",调用订单查询工具
  2. 如果用户问"退货政策",检索知识库
  3. 如果问题复杂,转人工

3.1 Workflow 实现

from langgraph.graph import StateGraph, END

# Workflow:你定义所有路径
def route_query(state):
    """路由:根据关键词,决定下一步"""
    query = state["query"]
    
    if "订单" in query or "物流" in query:
        return "check_order"
    elif "退货" in query or "退款" in query:
        return "check_policy"
    else:
        return "transfer_human"

def check_order(state):
    """查询订单"""
    order_id = extract_order_id(state["query"])
    order_status = order_api.get_status(order_id)
    state["response"] = f"订单状态:{order_status}"
    return state

def check_policy(state):
    """检索退货政策"""
    docs = vector_db.search("退货政策")
    state["response"] = summarize(docs)
    return state

def transfer_human(state):
    """转人工"""
    state["response"] = "正在为您转接人工客服..."
    return state

# 构建 Workflow
graph = StateGraph()
graph.add_node("route", route_query)
graph.add_node("check_order", check_order)
graph.add_node("check_policy", check_policy)
graph.add_node("transfer_human", transfer_human)

# 你定义所有路径
graph.add_conditional_edges(
    "route",
    lambda s: route_query(s),  # 返回 "check_order" / "check_policy" / "transfer_human"
)
graph.add_edge("check_order", END)
graph.add_edge("check_policy", END)
graph.add_edge("transfer_human", END)

workflow = graph.compile()

# 测试
print(workflow.invoke({"query": "我的订单什么时候到?"}))  
# → 走到 check_order

print(workflow.invoke({"query": "怎么退货?"}))           
# → 走到 check_policy

print(workflow.invoke({"query": "你们公司怎么样?"}))     
# → 走到 transfer_human

关键点

  • ✅ 流程完全可控
  • ✅ 每次执行路径完全相同
  • 不够灵活:如果用户输入"订单号 12345 到哪了?",Workflow 可能识别不出"订单"关键词

3.2 Agent 实现

from langgraph.graph import StateGraph, END
from langchain.tools import Tool

# Agent:LLM 决定调用哪个工具
def order_tool(state):
    """订单查询工具"""
    order_id = state.get("order_id")
    if not order_id:
        # LLM 先从用户消息中提取 order_id
        order_id = llm.invoke(f"提取订单号:{state['query']}")
        state["order_id"] = order_id
    
    order_status = order_api.get_status(order_id)
    state["response"] = f"订单状态:{order_status}"
    return state

def policy_tool(state):
    """退货政策工具"""
    docs = vector_db.search("退货政策")
    state["response"] = summarize(docs)
    return state

def human_tool(state):
    """转人工工具"""
    state["response"] = "正在为您转接人工客服..."
    return state

# LLM 决策:下一步调用哪个工具?
def agent_decide(state):
    """LLM 选择工具"""
    tools = [
        "OrderTool(查询订单)",
        "PolicyTool(查询退货政策)",
        "HumanTool(转人工)"
    ]
    
    decision = llm.invoke(f"""
    用户问题:{state['query']}
    可选工具:{tools}
    选择最合适的工具:
    """)
    
    return decision  # 返回 "OrderTool" / "PolicyTool" / "HumanTool"

# 构建 Agent
graph = StateGraph()
graph.add_node("agent", agent_decide)
graph.add_node("order_tool", order_tool)
graph.add_node("policy_tool", policy_tool)
graph.add_node("human_tool", human_tool)

# 动态边:LLM 决定下一步
graph.add_conditional_edges(
    "agent",
    lambda s: agent_decide(s),
    {
        "OrderTool": "order_tool",
        "PolicyTool": "policy_tool",
        "HumanTool": "human_tool",
    }
)

graph.add_edge("order_tool", END)
graph.add_edge("policy_tool", END)
graph.add_edge("human_tool", END)

agent = graph.compile()

# 测试
print(agent.invoke({"query": "我的订单什么时候到?"}))  
# → LLM 决策:调用 OrderTool

print(agent.invoke({"query": "怎么退货?"}))           
# → LLM 决策:调用 PolicyTool

print(agent.invoke({"query": "你们公司怎么样?"}))     
# → LLM 决策:调用 HumanTool

关键点

  • 灵活:LLM 能理解"订单号 12345 到哪了?"中的"订单"意图
  • 不可控:LLM 可能决策错误(比如把"退货"问题路由到 OrderTool)
  • 成本不可控:每次都至少 2 次 LLM 调用(1 次决策 + 1 次工具执行)

四、决策框架:什么时候用哪个?

为了帮你做决策,我总结了一个决策树

你的任务流程是否固定?
│
├─ 是 → 用 Workflow
│   │
│   └─ 是否要求可预测性?(每次输出必须一致)
│       │
│       ├─ 是 → 必须用 Workflow
│       └─ 否 → 仍推荐 Workflow(成本低、易调试)
│
└─ 否 → 考虑用 Agent
    │
    ├─ 是否容错率高?(偶尔出错可以接受)
    │   │
    │   ├─ 是 → 可以用 Agent
    │   └─ 否 → 用 Workflow + 人工审核(混合架构)
    │
    └─ 成本是否敏感?
        │
        ├─ 是 → 谨慎用 Agent(设置 max_steps 限制)
        └─ 否 → 可以用 Agent

4.1 用 Workflow 的场景(80% 的情况)

场景 1:文档处理

  • 任务:把 100 个 PDF 转换成结构化数据
  • 流程:读取 PDF → 提取文本 → 结构化 → 写入数据库
  • 为什么用 Workflow:流程固定,不需要 LLM 决策

场景 2:日报生成

  • 任务:每天早上生成昨日数据报告
  • 流程:查询数据库 → 计算指标 → 生成图表 → 发送邮件
  • 为什么用 Workflow:流程固定,成本低

场景 3:数据 ETL

  • 任务:从多个数据源抽取数据,转换后加载到数据仓库
  • 流程:抽取 → 清洗 → 转换 → 加载
  • 为什么用 Workflow:流程固定,要求可预测性(数据不能错)

4.2 用 Agent 的场景(20% 的情况)

场景 1:智能客服

  • 任务:回答用户的各种问题(订单、物流、退货、产品咨询…)
  • 为什么用 Agent:问题类型不确定,需要根据用户问题动态决策

场景 2:代码助手

  • 任务:根据用户需求,写代码、改代码、解释代码、调试代码
  • 为什么用 Agent:用户需求不确定,需要动态决定下一步

场景 3:研究助手

  • 任务:根据用户研究主题,搜索论文、阅读、总结、回答
  • 为什么用 Agent:研究路径不确定,需要动态决定搜索哪些论文、读哪些章节

4.3 混合架构:Workflow + Agent(推荐)

核心思路:用 Workflow 定义主干流程,在需要动态决策的地方,插入 Agent。

示例:智能客服系统

# 混合架构:Workflow 主干 + Agent 节点
graph = StateGraph()

# Workflow 部分(固定流程)
graph.add_node("receive_query", receive_query)  # 接收用户问题
graph.add_node("classify_intent", classify_intent)  # 分类意图(简单/复杂)

# Agent 部分(动态决策)
graph.add_node("simple_agent", simple_agent)  # 处理简单问题(Agent)
graph.add_node("complex_agent", complex_agent)  # 处理复杂问题(Agent)

# Workflow 部分(固定流程)
graph.add_node("log_interaction", log_interaction)  # 记录对话
graph.add_node("send_response", send_response)  # 发送回复

# 主干流程(Workflow)
graph.add_edge("receive_query", "classify_intent")

# 分支:简单问题 → simple_agent,复杂问题 → complex_agent
graph.add_conditional_edges(
    "classify_intent",
    lambda s: "simple" if is_simple(s) else "complex"
)

graph.add_edge("simple_agent", "log_interaction")
graph.add_edge("complex_agent", "log_interaction")
graph.add_edge("log_interaction", "send_response")
graph.add_edge("send_response", END)

优点

  • ✅ 主干流程可控(Workflow)
  • ✅ 需要灵活的地方灵活(Agent)
  • ✅ 成本可控(Agent 只在需要时调用)

五、真实案例:用错了会导致什么问题?

案例 1:用 Agent 做 ETL(错误)

背景:某团队用 Agent 做数据 ETL(抽取 → 转换 → 加载)。

问题

  1. 成本失控:ETL 任务每天运行 1000 次,每次 Agent 调用 5-10 次 LLM,成本是从 0.5 元/次飙升到 5 元/次
  2. 不可预测:有时候 ETL 成功,有时候失败(LLM 决策错误)
  3. 难以调试:数据错误时,无法复现(因为 LLM 决策有随机性)

正确做法:用 Workflow。ETL 流程是固定的,不需要 LLM 决策。

案例 2:用 Workflow 做智能客服(错误)

背景:某团队用 Workflow 做智能客服。

问题

  1. 不够灵活:只能处理预设的问题类型,无法处理用户的新问题
  2. 用户体验差:用户问"订单号 12345 到哪了?“,Workflow 识别不出"订单"关键词(因为用户没说"订单状态”),直接转人工

正确做法:用 Agent。客服问题类型不确定,需要 LLM 理解用户意图。

案例 3:混合架构(正确)

背景:某电商公司做智能客服系统。

架构

  1. Workflow 主干:接收问题 → 分类意图 → 简单问题 → Agent1,复杂问题 → Agent2 → 记录 → 发送
  2. Agent1(简单问题):处理订单查询、物流查询(2-3 个工具)
  3. Agent2(复杂问题):处理退货、换货、投诉(5-10 个工具,可能需要多轮对话)

效果

  • ✅ 成本可控(简单问题用 Agent1,成本低;复杂问题用 Agent2,成本高但有价值)
  • ✅ 灵活(Agent 能处理各种问题)
  • ✅ 可维护(Workflow 主干固定,容易调试)

六、常见误区:你可能在用的错误认知

误区 1:“Agent 比 Workflow 更先进”

错误。Agent 和 Workflow 是不同的工具,适合不同的场景。

正确认知

  • 流程固定 → Workflow
  • 流程不确定 → Agent
  • 大部分情况 → Workflow(80%),因为只有 20% 的任务需要动态决策

误区 2:“用 Agent 才能体现 AI 的能力”

错误。Workflow 也能体现 AI 的能力(比如用 LLM 做摘要、提取、分类)。

正确认知

  • Workflow + LLM = 自动化固定流程
  • Agent + LLM = 自动化动态决策
  • 两者都有价值,取决于你的任务

误区 3:“Agent 一定能处理更复杂的问题”

错误。Agent 能处理更多样化的问题,但不一定能处理更复杂的问题。

例子

  • 复杂但固定:财务报告生成(需要多个步骤,但流程固定)→ Workflow 更合适
  • 简单但多样:客服问答(步骤少,但问题类型多)→ Agent 更合适

误区 4:“用了 Agent,就不需要定义流程了”

错误。Agent 也需要你定义:

  1. 工具列表:Agent 能调用哪些工具?
  2. 工具描述:每个工具是做什么的?(LLM 根据描述选择工具)
  3. 终止条件:什么时候停止调用工具?(比如"用户满意"或"达到最大步数")

你没有"不需要定义流程",你只是把流程定义成了"工具 + LLM 决策规则"。


七、总结:怎么选?

你的任务 推荐方案
流程固定、步骤明确 Workflow
流程不确定、需要动态决策 Agent
要求可预测性(每次输出必须一致) Workflow(必须)
容错率高(偶尔出错可以接受) Agent(可以用)
成本敏感 Workflow(优先)或 Agent + max_steps
需要灵活性 Agent混合架构

一句话总结

如果你能提前画出流程图,用 Workflow。如果你画不出,用 Agent。


八、实践建议

8.1 从 Workflow 开始

大部分任务都能用 Workflow 解决。只有当你发现 Workflow 不够灵活时,才考虑引入 Agent。

8.2 用混合架构

在 Workflow 的某些节点,如果需要动态决策,插入一个 Agent 节点。

8.3 设置安全边界

如果用 Agent:

  1. 设置 max_steps(防止死循环)
  2. 记录 LLM 的每次决策(方便调试)
  3. 人工审核边界案例(比如"不确定"的情况)

九、结语

Workflow 和 Agent 不是"谁更先进"的问题,而是"谁更适合你的任务"的问题。

记住

  • Workflow:你驾驶,LLM 执行
  • Agent:LLM 驾驶,你给地图和工具

选对了,你的系统既可控又灵活。选错了,你的系统既不可控又不可预测。

别再搞混了。


如果你觉得这篇文章有帮助,欢迎分享给你的团队。大部分 AI 项目的失败,都是因为用错了 Workflow 和 Agent。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐