看完这篇,你再也不会把Workflow和Agent搞混了
开篇:AI圈的第一大悬案
作为一个在AI圈摸爬滚打多年的老兵,我见过最离谱的事情是什么?
是产品经理和研发吵架,吵了半天发现:俩人说的"Agent"根本不是一个东西。
产品经理说的Agent:能自主决策、能调用工具、能自己完成任务的智能体。
研发说的Agent:一个工作流里串了三个Prompt节点,号称"智能客服Agent"。
然后产品经理急了:"你这个Workflow跟Agent有什么关系?"
研发也急了:"我这就是Agent啊!我调用了大模型!"
啪!巴别塔塌了。
今天这篇文章,就是来给你们"统一度量衡"的。看完之后,保证你对AI应用开发的四种架构范式门儿清,再也不会被忽悠。
一、先搞清楚:我们为什么要学"设计模式"?
先问一个问题:你学设计模式是为了什么?
是为了面试能背出来?"单例模式、工厂模式、观察者模式"念得滚瓜烂熟,结果实际写代码的时候还是CRUD一把梭?
错!设计模式是为了让你"少踩坑"。
前人花了几十年时间,总结出一套"特定场景下的最佳实践"。当你遇到相似的问题时,直接套用这些已经被验证的成熟方案,就能事半功倍。
在AI应用开发领域,这套逻辑同样成立。
可惜的是,很多AI开发者还处于"野路子"阶段。拿到一个需求,上来就问:"用LangChain还是CrewAI?"、"要不要上RAG?"
兄弟,你连问题是什么都没搞清楚,上什么框架?
真正的架构师思维是:先分析业务本质,再选择合适的范式,最后才是具体框架和工具。
二、AI应用开发的"四大门派"
让我们先上一张图,建立整体认知:
flowchart TD
subgraph AI应用四大门派
A["🧘 Prompt派<br/>一切交给模型"]
B["🏭 Workflow派<br/>代码预先编排"]
C["🤖 Agent派<br/>模型决定下一步"]
D["👥 Multi-Agent派<br/>组织的力量"]
end
A -->|"自主性低"| A1["复杂度:低"]
B -->|"自主性中"| B1["复杂度:中"]
C -->|"自主性高"| C1["复杂度:高"]
D -->|"自主性最高"| D1["复杂度:最高"]
style A fill:#e1f5fe,color:#000
style B fill:#fff3e0,color:#000
style C fill:#f3e5f5,color:#000
style D fill:#e8f5e9,color:#000
一句话总结:
- Prompt派:你说什么,模型做什么,简单直接
- Workflow派:我设计好流程,模型按部就班执行
- Agent派:我只告诉你目标,模型自己想办法
- Multi-Agent派:我一个不够用,那就一群来干!
接下来,我们用"生成竞品分析报告"这个任务,带你逐一拆解每个门派。
三、第一派:Prompt Engineering(提示词工程)
核心理念:一切交给模型。
这是最简单的模式,也是大多数人的起点。
flowchart LR
A["📄 竞品数据"] --> B["🤖 大模型"]
C["📋 任务要求"] --> B
B --> D["📊 分析报告"]
什么是Prompt Engineering?
简单来说,就是你构建一个"超级Prompt",把所有东西都塞进去,然后让模型一次性给你输出结果。
核心工作就一件事:写好那个Prompt。
代码示例
# ============================================
# Prompt Engineering 的"精髓"
# 就是把你想说的全塞进一个Prompt里
# 然后祈祷模型能理解 😅
# ============================================
class PromptEngineer:
"""
提示词工程师
工作内容:
1. 写系统提示词(定义角色)
2. 写上下文(塞数据)
3. 写任务要求(告诉模型要什么)
理想场景:
- 数据量不大(<3万字)
- 任务简单明确
- 输出格式固定
"""
def generate_report(self, data: str, requirement: str) -> str:
"""
生成报告
参数说明:
- data: 竞品数据(静态文本)
- requirement: 你的要求(目标+格式+风格)
典型用法:
"""
# 构建"超级Prompt"
# 把数据、要求、格式全塞进去
prompt = f"""
# 系统提示:定义你的角色
你是一位资深行业分析师,擅长从数据中提炼洞察。
# 背景数据
{data}
# 任务要求
{requirement}
# 输出格式
请按以下格式输出:
1. 竞品概览
2. 核心洞察
3. 趋势分析
4. 建议
"""
# 调用模型,一次性输出
return self.model.complete(prompt)
Prompt派的"三大原罪"
| 罪状 | 症状 | 后果 |
|---|---|---|
| 上下文膨胀 | 数据一多,模型就开始"选择性失忆" | 关键信息被忽略 |
| 效果不稳定 | 换个大模型,Prompt要重写 | 维护成本爆炸 |
| 无法应对意外 | 用户问了个Prompt里没覆盖的 | 系统直接崩溃 |
什么时候用Prompt派?
简单场景,数据量可控,边界明确。比如:
- 写一封邮件润色
- 翻译一段文字
- 按模板生成文案
什么时候不用Prompt派?
长链路任务、数据量大、边界不确定的任务。硬上的结果就是:Debug到怀疑人生。
四、第二派:Workflow / Chain(代码驱动的流水线)
核心理念:预先编排,稳定执行。
这是目前工业界落地最多的模式。扣子(Coze)、Dify 这些平台,本质上都是Workflow模式。
什么是Workflow?
简单来说,就是你设计好流程图,模型按照你设计的步骤一步一步执行。
核心理念:程序员决定下一步,模型只是在特定节点"打工"。
flowchart TB
A["📥 输入"] --> B["🔍 爬虫"]
B --> C["🧹 清洗"]
C --> D["🧠 LLM分析"]
D --> E["📝 LLM总结"]
E --> F["✅ LLM审核"]
F --> G["💾 输出PDF"]
style A fill:#e1f5fe
style B fill:#fff8e1
style C fill:#fff8e1
style D fill:#e8f5e9
style E fill:#e8f5e9
style F fill:#e8f5e9
style G fill:#fce4ec
代码示例
# ============================================
# Workflow 模式:程序员是导演,模型是演员
# ============================================
class WorkflowEngine:
"""
工作流引擎
核心思路:
1. 定义好处理节点(节点是固定的)
2. 定义好执行顺序(顺序是硬编码的)
3. 模型只在特定节点被调用
优势:
- 极其稳定(代码写死了,不会乱来)
- 易于调试(哪个节点出问题,一目了然)
- 适合工程落地(生产环境首选)
局限:
- 不灵活(遇到没设计过的场景就抓瞎)
- 枚举成本高(异常分支太多,代码写不下)
"""
def __init__(self):
# 定义处理流程(顺序是死的)
self.nodes = [
CrawlerNode(), # 节点1:爬虫
CleanerNode(), # 节点2:清洗
AnalyzerNode(), # 节点3:分析(调用LLM)
SummarizerNode(), # 节点4:总结(调用LLM)
ReviewerNode(), # 节点5:审核(调用LLM)
WriterNode() # 节点6:输出
]
def run(self, input_data):
"""
按顺序执行
执行逻辑:
1. 从节点1开始
2. 每个节点处理后传给下一个
3. 直到最后一个节点输出结果
"""
result = input_data
for node in self.nodes:
result = node.execute(result)
return result
# 节点基类
class WorkflowNode:
"""
每个节点都要实现 execute 方法
输入 -> 处理 -> 输出
"""
def execute(self, input_data):
# 子类实现具体逻辑
pass
Workflow vs Agent:傻傻分不清?
很多人搞不清Workflow和Agent的区别。我来给你画个重点:
flowchart LR
subgraph Workflow
A["程序员"] -->|"决定|下一步"| B["执行节点"]
end
subgraph Agent
C["程序员"] -->|"给目标|工具"| D["模型自主"]
D -->|"自己决定|下一步"| E["执行动作"]
end
style A fill:#fff3e0
style D fill:#e8f5e9
判断标准:
- Workflow:LLM只是决定"调什么工具",整个流程是程序员设计好的
- Agent:LLM决定"下一步做什么",模型有真正的自主决策权
一个经典的误区:
"我用扣子搭了一个工作流,里面有LLM节点,这算不算Agent?"
不算。 你这个叫Workflow,不叫Agent。因为下一步做什么,是你设计好的,不是模型决定的。
五、第三派:Single Agent(五脏俱全的数字生命)
核心理念:模型决定下一步。
这是真正让程序员"失业"的模式——不是让你失业,而是让你从"写代码"变成"设计系统"。
什么是Agent?
简单来说,就是你给模型一个目标,加上工具箱和记忆,然后模型自己想办法完成。
核心变化:从"程序员控制流程"变成"模型自主决策"。
flowchart TB
A["🎯 目标"] --> B["🧠 规划器"]
B -->|"调用工具"| C["🔧 工具箱"]
B -->|"查询记忆"| D["💾 记忆"]
C -->|"结果"| E["👁️ 观察"]
E --> B
D -->|"历史"| B
ReAct范式:Agent的"大脑"
ReAct = Reasoning + Acting,即"思考 + 行动"。
这是目前最主流的Agent实现范式。让我用图解的方式解释:
flowchart TB
subgraph ReAct循环
A["🧠 Thought<br/>思考"] -->|"下一步行动"| B["🎬 Action<br/>执行"]
B -->|"观察结果"| C["👁️ Observation<br/>观察"]
C -->|"更新推理"| A
end
A -."|反思|改进".-> A
循环执行,直到任务完成。
ReAct的数学公式
这是本文的核心公式,看懂了这个,你就真正理解了Agent:
公式变量详解:
| 符号 | 定义 | 类比 |
|---|---|---|
| 时刻t的完整记忆 | Agent的"经验簿" | |
| 时刻t的推理/思考 | Agent的"脑子" | |
| 时刻t要执行的动作 | Agent的"决定" | |
| 时刻t的观察结果 | Agent的"收获" | |
| 大语言模型 | Agent的"大脑" | |
| 解析动作类型 | 判断要做什么 | |
| 执行工具 | 真正干活 |
代码实现
# ============================================
# ReAct Agent:从零实现一个会"思考"的Agent
# ====================================
class ReActAgent:
"""
ReAct智能体
核心理念:
- 思考(Reasoning):我当前知道什么,下一步该做什么?
- 行动(Acting):执行工具,获取结果
- 观察(Observation):根据结果更新认知
循环执行,直到输出最终答案
"""
def __init__(self, model, tools: dict, max_loops: int = 10):
"""
初始化
参数:
model: 大语言模型(GPT-4、Claude等)
tools: 可用工具字典 {工具名: 工具函数}
max_loops: 最大循环次数(防止无限循环)
"""
self.model = model
self.tools = tools
self.max_loops = max_loops
# 记忆:存储(思考, 动作, 结果)元组
self.memory = []
def run(self, task: str) -> str:
"""
执行任务
执行流程:
1. 根据记忆生成提示词
2. 调用LLM获取思考
3. 解析动作类型
4. 执行工具或输出答案
5. 更新记忆
6. 重复直到完成
"""
loop_count = 0
while loop_count < self.max_loops:
# Step 1: 生成思考
# 这是公式中 τ_t = LLM(format(M_{t-1}))
prompt = self._build_prompt(task)
thought = self.model.think(prompt)
# Step 2: 解析动作
# 这是公式中 a_t = parse_action(τ_t)
action_type, action_data = self._parse_action(thought)
# 如果是最终答案,直接返回
if action_type == "final_answer":
return action_data
# 如果是工具调用,执行工具
# 这是公式中 o_t = ToolExec(a_t)
observation = self._execute_tool(action_data)
# Step 3: 更新记忆
# 这是公式中 M_t = M_{t-1} ∪ {(τ_t, a_t, o_t)}
self.memory.append({
"thought": thought,
"action": action_data,
"observation": observation
})
loop_count += 1
return "超出最大循环次数,任务失败"
def _build_prompt(self, task: str) -> str:
"""
构建提示词
提示词结构:
1. 原始任务
2. 可用工具
3. 历史记录(思考-动作-结果)
4. 输出格式要求
"""
prompt_parts = [f"任务:{task}\n"]
prompt_parts.append("可用工具:")
for name, tool in self.tools.items():
prompt_parts.append(f"- {name}: {tool.description}")
prompt_parts.append("\n格式要求:")
prompt_parts.append("Thought: [你的思考]")
prompt_parts.append("Action: [工具名[参数]] 或 Answer: [最终答案]")
# 添加历史记录
if self.memory:
prompt_parts.append("\n历史记录:")
for i, record in enumerate(self.memory):
prompt_parts.append(f"第{i+1}轮:")
prompt_parts.append(f" 思考:{record['thought']}")
prompt_parts.append(f" 动作:{record['action']}")
prompt_parts.append(f" 结果:{record['observation']}")
return "\n".join(prompt_parts)
def _parse_action(self, thought: str) -> tuple:
"""
解析动作
判断逻辑:
- 如果包含"Answer:" -> 最终答案
- 如果包含"Action:" -> 工具调用
"""
if "Answer:" in thought:
answer = thought.split("Answer:")[1].strip()
return ("final_answer", answer)
if "Action:" in thought:
action_str = thought.split("Action:")[1].strip()
# 解析 tool_name[params] 格式
if "[" in action_str:
tool_name = action_str.split("[")[0].strip()
params = action_str.split("[")[1].split("]")[0].strip()
return ("tool_call", (tool_name, params))
# 无法解析,按最终答案处理
return ("final_answer", thought)
def _execute_tool(self, tool_call: tuple) -> str:
"""
执行工具
参数:
tool_call: (工具名, 参数) 元组
"""
tool_name, params = tool_call
if tool_name not in self.tools:
return f"错误:未找到工具 {tool_name}"
tool = self.tools[tool_name]
result = tool.execute(params)
return str(result)
Agent的痛点
很多人用Agent会遇到一个问题:上下文爆炸。
flowchart LR
A["搜索1"] -->|"塞入|上下文"| B["🧠 上下文"]
C["搜索2"] -->|"塞入|上下文"| B
D["搜索3"] -->|"塞入|上下文"| B
E["分析结果"] -->|"塞入|上下文"| B
F["...几十个|调用..."] -->|"塞入|上下文"| B
B -->|"太长|爆炸"| G["💥 上下文爆炸<br/>模型开始幻觉"]
症状:
- Agent执行任务时,越来越慢
- 输出质量越来越差
- 开始出现明显的逻辑错误
根本原因: 每次工具调用的结果都会积累在上下文中,长链路任务会把上下文塞满。
解决方案: 上下文压缩、摘要,或者——Multi-Agent。
六、第四派:Multi-Agent System(组织的力量)
核心理念:一个不够用,一群来干!
什么是Multi-Agent?
简单来说,就是多个Agent协同工作,每个Agent负责一部分任务,通过分工合作完成复杂目标。
核心价值:上下文隔离 + 专业分工
flowchart TB
A["🎯 任务"] --> B["👔 Manager<br/>主管"]
B -->|"分派|研究"| C["🔍 Researcher<br/>研究员"]
B -->|"分派|分析"| D["📊 Analyst<br/>分析师"]
B -->|"分派|审核"| E["✅ Reviewer<br/>审核员"]
C -->|"精炼数据"| D
D -->|"分析结论"| E
E -->|"通过|输出"| F["📄 最终报告"]
E -.->|"不通过|回退"| B
style A fill:#e1f5fe
style B fill:#fff3e0
style C fill:#e8f5e9
style D fill:#e8f5e9
style E fill:#e8f5e9
Multi-Agent的四大架构
根据不同的协作模式,Multi-Agent可以分为四种架构:
flowchart LR
subgraph 四大架构
A["🏭 串行架构"]
B["👔 分层架构"]
C["⚡ 并行架构"]
D["🔗 网络架构"]
end
A -->|"顺序执行<br/>A→B→C"| A1["流水线模式"]
B -->|"中央协调<br/>Manager分配"| B1["主管-员工模式"]
C -->|"并行执行<br/>同时干活"| C1["Map-Reduce模式"]
D -->|"对等协作<br/>自由通信"| D1["点对点模式<br/>⚠️慎用"]
代码实现:分层架构
# ============================================
# Multi-Agent:分层架构实现
# 核心思想:专业化分工 + 上下文隔离
# ====================================
class MultiAgentSystem:
"""
多智能体系统
为什么需要Multi-Agent?
1. 上下文隔离:每个Agent只处理一部分
2. 专业分工:研究员只搜索,分析师只分析
3. 质量保证:审核员负责质检,不合格就回退
"""
def __init__(self):
# 主管:负责协调,不干具体活
self.manager = ManagerAgent()
# 研究员:只负责搜索
self.researcher = SpecialistAgent(
role="研究员",
tools=[SearchTool(), CrawlerTool()]
)
# 分析师:只负责分析
self.analyst = SpecialistAgent(
role="分析师",
tools=[AnalysisTool(), ChartTool()]
)
# 审核员:只负责判断
self.reviewer = ReviewerAgent()
def run(self, task: str) -> str:
"""
多Agent协作执行
执行流程:
1. Manager分析任务,决定下一步
2. Researcher收集数据(独立的上下文)
3. Analyst分析数据(独立的上下文)
4. Reviewer审核结果
5. 不合格则回退给Manager重新分配
"""
state = {"phase": "start", "task": task}
while True:
decision = self.manager.decide(state)
if decision["type"] == "research":
# 研究员独立工作(上下文隔离)
data = self.researcher.research(task)
# 精炼数据传给下一个Agent
refined_data = self._refine(data)
state = {"phase": "analyze", "data": refined_data}
elif decision["type"] == "analyze":
# 分析师独立工作(上下文隔离)
analysis = self.analyst.analyze(state["data"])
refined_analysis = self._refine(analysis)
state = {"phase": "review", "analysis": refined_analysis}
elif decision["type"] == "review":
# 审核员判断
verdict = self.reviewer.judge(state["analysis"])
if verdict["pass"]:
return verdict["report"]
else:
# 不合格,回退!
state = {"phase": "retry", "feedback": verdict["feedback"]}
def _refine(self, data: Any) -> str:
"""
跨Agent数据精炼
关键设计:不在Agent间传递完整上下文
而是精炼后只传递下一个Agent需要的信息
"""
# 用LLM摘要,精简数据
return self.manager.llm.summarize(data)
Multi-Agent vs 工作流:有什么区别?
| 维度 | Workflow | Multi-Agent |
|---|---|---|
| 决策者 | 程序员(硬编码) | 模型(自主决策) |
| 节点类型 | 固定功能节点 | 具备自主能力的Agent |
| 上下文 | 共享上下文 | 每个Agent独立上下文 |
| 灵活性 | 低(流程固定) | 高(动态决策) |
| 复杂度 | 低 | 高 |
| 适用场景 | 边界清晰 | 复杂长链路 |
一句话区分:
- Workflow:你设计好剧本,演员按剧本来
- Multi-Agent:你请了一群各有专长的演员,让他们自己商量着来
七、架构选型指南:别把洗衣机当冰箱用
终于到了最关键的问题:我该用哪种范式?
这里要引入一个核心概念:阿什比定律
"Only variety can destroy variety." —— 只有多样性才能对抗多样性。
翻译成人话:业务有多复杂,系统就得有多复杂。
业务不确定性分析
业务的不确定性来自三个方面:
flowchart TB
A["业务不确定性"] --> B["输入不确定性"]
A --> C["过程不确定性"]
A --> D["结果不确定性"]
B -->|"用户说什么不确定"| E["智能客服"]
C -->|"如何解决不确定"| F["代码调试"]
D -->|"输出什么不确定"| G["创意写作"]
熵-架构匹配矩阵
选型决策表
| 业务特征 | 推荐范式 | 典型场景 |
|---|---|---|
| 规则固定、数据简单 | Prompt | 邮件润色、翻译、模板生成 |
| 流程固定、边界清晰 | Workflow | 扣子工作流、内容处理流水线 |
| 开放问题、需要决策 | Single Agent | 智能客服、代码调试 |
| 超长链路、复杂协作 | Multi-Agent | 竞品分析、研究报告 |
常见误区
| 误区 | 真相 |
|---|---|
| "我用了LangChain,就是Agent了" | 不一定,可能是Workflow |
| "Agent一定比Workflow好" | 看场景!杀鸡焉用牛刀 |
| "Multi-Agent就是多个LLM节点" | 错!每个节点都得是能自主决策的Agent |
| "AI越贵越好" | 不一定,适合最重要 |
八、总结:一张图记住四种范式
mindmap
root((AI应用开发<br/>四大范式))
Prompt Engineering
你说啥我做啥
简单直接
上下文是瓶颈
Workflow
流程我设计
模型按部就班
稳定可靠
Single Agent
目标给你
工具给你
模型自己想办法
Multi-Agent
一群Agent协作
分工专业
上下文隔离
记住四句话:
- Prompt:简单够用,不要over engineering
- Workflow:工程落地首选,稳定压倒一切
- Agent:模型当大脑,程序员当设计师
- Multi-Agent:组织的力量,给模型减负