Agent 的设计模式总结:ReAct、Plan-Execute 和 Reflexion 工程对比
Agent 的设计模式总结ReAct、Plan-Execute 和 Reflexion 工程对比一、深度引言与场景痛点大家好我是赵咕咕一名每天都在跟 AI Agent 较劲的工程师。不知道你有没有这种体验你给 Agent 一个看起来挺简单的任务——比如帮我汇总一下上周的销售数据并生成周报——结果它要么开始无休止地调工具、把 Token 花到天荒地老要么草草执行一步就交差了质量让人血压飙升。这背后其实是 Agent 设计模式选的锅。Agent 的执行策略不是一刀切的。不同的任务类型、不同的时效要求、不同的成本约束都需要匹配不同的设计模式。今天我们聊聊三种最主流的 Agent 设计模式ReAct、Plan-Execute和Reflexion。这三种模式像三大流派各有千秋。理解它们的差异和适用场景是做好 Agent 工程化的第一步。二、底层机制与原理深度剖析2.1 ReAct边想边干的行动派ReAct 全称是 Reasoning Acting核心思想是让模型在每一步都交替进行推理和行动。它不自顶向下做全局规划而是根据每步观察动态决策下一步做什么。它的执行流程可以用下面这张图表示flowchart TD A[接收用户任务] -- B[LLM 推理分析当前状态] B -- C{是否需要调用工具?} C --|是| D[选择工具并执行] C --|否| E[生成最终回答] D -- F[获取工具返回结果] F -- G[将结果追加到上下文] G -- B E -- H[返回用户]ReAct 的优势是灵活每一步都在最新信息基础上决策不会走冤枉路。但问题是缺少全局视野容易在小问题上纠结太久。比如我让它查三次天气然后对比它每查一次都要重新推理上下文越来越长、成本越来越高。2.2 Plan-Execute先画地图再走路Plan-Execute 模式则完全不同。它先让 LLM 出一份完整计划然后按计划逐步执行sequenceDiagram participant U as 用户 participant P as Planner participant E as Executor participant T as 工具集 U-P: 提交任务 P-P: 生成执行计划 P-U: 返回计划供确认可选 P-E: 下发第一步任务 E-T: 调用工具 T--E: 返回结果 E-P: 汇报执行结果 P-P: 检查计划是否需调整 P-E: 下发下一步任务 E-T: 调用工具 T--E: 返回结果 E-P: 汇报最终结果 P-U: 整理输出这种模式的好处是可预测你甚至可以在 Planner 出计划后让用户确认再执行。对步骤多、依赖复杂的任务特别合适。代价也很明显——如果中间环境变化最初的计划就不准了。你得在 Planner 里加检查点、允许动态调整。2.3 Reflexion会自我批评的学霸Reflexion 是我个人觉得最有意思的模式。它在 ReAct 基础上加了一个反思组件Agent 执行完一轮后会把结果交给一个反思模型评估。反思模型会给反馈比如你第三步的搜索关键词选错了应该用更精确的术语。这段反馈会存入长期记忆供后续轮次参考。核心流程是这样的flowchart LR A[任务输入] -- B[Actor 执行] B -- C{得到结果} C -- D[Evaluator 评估] D -- E{通过?} E --|否| F[生成反思文本] F -- G[存入 Episodic Memory] G -- B E --|是| H[输出最终结果]Reflexion 最大的价值在于它让 Agent具备了从错误中学习的能力。传统 Agent 的上下文窗口一旦被截断之前的教训就全丢了。Reflexion 通过显式存储反思让经验得以累积。三、生产级代码实现下面给出一个基于 asyncio 的 ReAct Agent 实现骨架核心是循环中的think → act → observe流程import asyncio from typing import Any from dataclasses import dataclass, field dataclass class ToolResult: tool_name: str output: str success: bool error: str | None None class ReActAgent: def __init__(self, llm, tools: dict, max_steps: int 10): self.llm llm self.tools tools self.max_steps max_steps self.history: list[dict] [] async def run(self, task: str) - str: self.history [{role: user, content: task}] step 0 while step self.max_steps: step 1 # 1. Think让模型决定下一步 thought await self._think() if thought[action] finish: return thought[answer] # 2. Act执行工具调用 result await self._act( thought[action], thought.get(action_input, ) ) # 3. Observe将结果注入上下文 self.history.append({ role: system, content: f工具 {thought[action]} 返回: {result.output} }) raise RuntimeError(fAgent 在 {self.max_steps} 步内未完成任务) async def _think(self) - dict[str, Any]: prompt self._build_prompt() try: response await self.llm.generate(prompt) return self._parse_action(response) except Exception as e: return {action: finish, answer: f推理失败: {e}} async def _act(self, action: str, action_input: str) - ToolResult: if action not in self.tools: return ToolResult(action, 未知工具, False, f工具 {action} 不存在) try: output await self.tools[action](action_input) return ToolResult(action, str(output), True) except Exception as e: return ToolResult(action, , False, str(e)) def _build_prompt(self) - str: history_text \n.join( f{h[role]}: {h[content]} for h in self.history ) return f你是一个任务执行助手。根据以下对话历史决定下一步动作。 {history_text} 可用工具: {list(self.tools.keys())} 请以 JSON 格式回复 {{action: 工具名或finish, action_input: 参数, thought: 你的推理}} def _parse_action(self, text: str) - dict[str, Any]: import json import re match re.search(r\{[\s\S]*\}, text) if not match: raise ValueError(f无法从回复中解析 JSON: {text[:200]}) return json.loads(match.group())这个骨架虽然简洁但包含了生产级 Agent 的核心循环。接入真实的 LLM 和工具就立即可用。四、边界分析与架构权衡三种模式并非谁更先进而是各有适配场景维度ReActPlan-ExecuteReflexion适用任务工具调用少、动态性强步骤多、依赖明确需多轮迭代优化Token 消耗较高每步都推理中等计划复用最高多轮反思延迟步步为营总延迟不确定计划固定可预测多轮重试最长错误恢复靠 LLM 临场发挥靠计划调整靠反思显式纠偏实现复杂度低中等高几点工程建议不要只用一种模式。实际项目中可以让 Planner 先用 Plan-Execute 做任务分解然后每一步用 ReAct 来执行失败后用 Reflexion 反思。ReAct 一定要设 max_steps。我已经见过太多次 Agent 在第 47 步还在跑Token 账单飞出天际。Reflexion 的反思不要过长。反思文本也是 Prompt 的一部分太长会吃掉大量上下文窗口。工具调用要做超时控制。外部 API 调用必须设asyncio.wait_for不然一个卡住的工具调用会阻塞整个 Agent。最好的 Agent 架构是按需组合模式而不是死守某一种。五、总结Agent 设计模式的选择本质上是在灵活性与可控性之间做权衡。ReAct 给了你最大的灵活性但可能让成本失控。Plan-Execute 让你对流程有掌控力但碰上变化快的场景就捉襟见肘。Reflexion 让 Agent 能自我进化代价是更高的延迟和更复杂的系统设计。实际工程中我的建议是从 ReAct 起步、用 max_steps 兜底。当任务复杂度上来后再加入 Plan-Execute 做任务分解。最后引入 Reflexion 的反思机制让 Agent 在长时间运行中持续自我优化。Agent 架构没有银弹但理解这三板斧你就有了 80% 工程场景的应对方案。希望这篇文章帮你省下几笔不必要的 Token 账单——省下来的钱请自己喝杯奶茶不用谢我。下一篇预告LlamaIndex 与 LangChain 混合使用敬请期待。