返回博客列表

Agent 设计模式不是 Prompt 套路,而是控制系统

2026-07-07
6 min read
aiagentAI工程

Agent 设计模式不是把 Prompt 写得更花,而是在给不稳定的模型补一套可控的工程结构。Plan 解决目标分解,ReAct 解决边行动边观察,Reflection 解决失败复盘,Tree of Thoughts 解决多路径搜索。真正的难点不是记住这些名字,而是知道什么时候该让模型想、什么时候该让工具做、什么时候必须刹车。

导读:很多人聊 Agent 设计模式,喜欢把 Plan、ReAct、Reflection、Tree of Thoughts 这些词排成一张表。小编一开始也这么看,后来真把 Agent 放进业务流程里才发现:这些模式不是 Prompt 技巧,而是在给模型补一套控制系统。

说白了,模型本身像一个很聪明但状态不稳定的实习生。你不能只跟他说“好好干”,你得给他目标、步骤、工具、日志、检查点、复盘机制和安全边界。Agent 设计模式解决的正是这些东西。

一、先说结论:Agent 模式不是让模型更聪明,而是让系统更可控

小编先把结论放前面:Agent 设计模式的本质,不是提升模型智商,而是管理模型的不确定性。

一个普通 LLM 调用,大概像这样:

text
1用户输入 -> 模型生成 -> 返回结果

这条链路适合问答、总结、改写、生成一段代码。但只要任务变成下面这些情况,单次调用就开始吃力:

  • 目标不是一步能完成,需要分解。
  • 中间要调用工具,比如搜索、数据库、代码执行、文件读写。
  • 执行结果会改变下一步策略。
  • 有副作用,比如发消息、下单、改配置、创建工单。
  • 失败后不能直接重来,需要知道错在哪里。

这时 Agent 就不是“一个会调用工具的聊天机器人”了,而更像一个小型运行时:

工程对象在 Agent 里的对应物解决的问题
控制面计划、路由、状态机、策略选择下一步该做什么
执行面工具调用、函数执行、外部系统交互真正把事情办掉
数据面上下文、记忆、检索结果、任务输入Agent 基于什么信息行动
观测面日志、轨迹、评估、告警怎么知道它跑偏了
安全面权限、确认、回滚、限流、人工介入怎么防止它乱来

所以小编更愿意把 Agent 设计模式理解成一组“控制结构”:

  • Plan:先想清楚路线。
  • ReAct:边想边做,边做边看。
  • Reflection:失败后复盘,把经验写回系统。
  • Tree of Thoughts:不是只走一条路,而是试几条路再选。
  • Plan-and-Execute / LLMCompiler:把计划和执行拆开,甚至并行执行。

名字很多,但核心问题只有一个:当模型不能一次性稳定解决任务时,我们怎么把它变成一个可观察、可约束、可迭代的系统。

Agent 设计模式是一套控制系统

二、为什么 Demo 能跑,业务跑不远

很多 Agent Demo 看起来很惊艳:输入一个目标,它自己搜索、分析、调用工具,最后给你一个结果。

但一进业务,小编见过最多的问题不是“模型不会回答”,而是下面这些:

2.1 它会做事,但不知道什么时候该停

比如你让 Agent 分析一个线上问题,它可能查日志、查监控、查代码、再查一遍日志,然后继续查。

人类工程师会在心里有个判断:

  • 证据够不够?
  • 继续查的收益大不大?
  • 现在应该先止血,还是继续定位根因?
  • 这个动作有没有风险?

模型没有天然的“工程刹车”。如果系统层不设计停止条件,它就会把“继续努力”理解成“继续调用工具”。

2.2 它会调用工具,但不理解副作用

读文档、查数据库、跑测试,这些是低风险动作。

但发通知、改配置、重启服务、创建 Issue、提交 PR,这些就有副作用了。副作用一旦发生,就不是生成文本那么简单。

这里小编有个判断:所有带副作用的 Agent 行为,都应该先当成生产变更来设计,而不是当成模型能力展示。

最少也要有:

  • 权限边界。
  • dry run。
  • 人工确认。
  • 操作日志。
  • 回滚方案。

2.3 它会解释错误,但不一定真的学到了

Reflection 很容易被误用。

很多人让模型失败后写一段“反思”,然后下一轮把反思塞回 Prompt。看起来很合理,但问题是:这段反思到底有没有被结构化?有没有绑定到任务类型?有没有进入后续决策?有没有被验证?

如果没有,那它只是“失败后的作文”。

真正有用的反思,应该像事故复盘一样:

复盘字段应该回答的问题
失败现象哪一步失败了
失败原因是信息不足、工具错误、计划错误,还是约束缺失
可迁移经验下次遇到同类任务应该怎么改
触发条件什么情况下启用这条经验
验证方式怎么知道改进真的有效

这才是 Reflection 从“自我感动”变成工程资产的关键。

三、Plan:先计划,不是为了慢,而是为了少走冤枉路

Plan 模式最直观:先让模型生成一个计划,再按计划执行。

它适合什么任务?

  • 目标明确,但步骤较多。
  • 中间依赖顺序明显。
  • 每一步可以被检查。
  • 失败成本不低,需要提前识别风险。

比如让 Agent 帮你改一个项目里的 bug,比较靠谱的流程不是直接开写,而是:

text
11. 复现问题 22. 定位相关模块 33. 阅读现有测试 44. 提出修改方案 55. 实现最小改动 66. 跑测试 77. 总结影响范围

这背后不是仪式感,而是把任务拆成可观察的检查点。

Plan 模式可以写成一个很简单的控制结构:

ts
1type Step = { 2 id: string 3 goal: string 4 action: string 5 doneWhen: string 6 risk?: string 7} 8 9type Plan = { 10 objective: string 11 steps: Step[] 12 stopConditions: string[] 13}

小编建议,Plan 不要只写“步骤”,还要写 doneWhenstopConditions

因为 Agent 里最值钱的不是“它知道要做什么”,而是“它知道做到什么程度算够了”。

Plan 的坑也很明显:计划可能一开始就错。

所以 Plan 不适合写死成瀑布流。更好的方式是:

text
1生成计划 -> 执行一步 -> 观察结果 -> 必要时修订计划 -> 继续执行

也就是说,Plan 最后往往会走向 ReAct。

四、ReAct:真正关键的是 Observation,不是 Action

ReAct 来自 “Reasoning + Acting” 这个思路。它的核心不是让模型一边碎碎念一边调用工具,而是把任务过程拆成循环:

text
1Thought -> Action -> Observation -> Thought -> Action -> Observation...

翻译成白话:

  • Thought:我现在怎么看这个问题。
  • Action:我要调用什么工具。
  • Observation:工具返回了什么事实。
  • 下一轮 Thought:根据新事实修正判断。

小编觉得 ReAct 最大的价值,是把模型从“闭门造车”拉回到环境里。

比如一个知识问答 Agent,如果只靠模型内部知识,就容易编;如果它能搜索、读取文档、观察返回结果,再继续推理,幻觉会少很多。ReAct 论文里也强调了这种交错方式:推理轨迹帮助模型跟踪和更新行动计划,行动则让模型从外部环境拿到信息。

但工程里用 ReAct,有三个关键点。

4.1 工具结果要短,不要把垃圾塞回上下文

很多 Agent 失败,不是因为工具少,而是工具返回太多。

搜索返回十几页,数据库返回几百行,日志返回几万字,全部塞给模型,模型当然会迷路。

工具层应该做预处理:

ts
1type ToolResult = { 2 summary: string 3 evidence: Array<{ 4 source: string 5 quote?: string 6 value?: string 7 }> 8 nextHints?: string[] 9}

给模型的是“可推理的证据”,不是“原始垃圾桶”。

4.2 每个 Action 都要有权限等级

小编建议把工具分成三类:

工具类型例子策略
只读工具搜索、读文件、查日志可自动执行
可逆写工具创建草稿、生成临时文件、dry run可自动执行但要记录
不可逆/高风险工具发布、删除、支付、改生产配置必须人工确认

这不是保守,这是生产系统基本礼貌。

4.3 Observation 必须进入日志

Agent 的每一次行动都应该能复盘:

json
1{ 2 "step": 3, 3 "thoughtSummary": "怀疑配置读取顺序有问题", 4 "action": "read_file", 5 "input": "src/config.ts", 6 "observation": "发现 env 覆盖默认配置", 7 "decision": "继续检查测试覆盖" 8}

注意,小编这里写的是 thoughtSummary,不是把完整隐式思维链暴露出来。工程系统需要的是可审计的决策摘要,不是让模型把所有脑内过程倒出来。

五、Reflection:反思不是再想一遍,而是把失败变成资产

Reflection 模式很诱人,因为它听起来像人:做错了,反思一下,下次变好。

Reflexion 这类方法的核心,是让 Agent 根据任务反馈生成语言形式的经验,并放进记忆里,影响后续尝试。这个方向很有价值,但工程落地时要小心一个问题:反思必须绑定反馈信号。

没有反馈的反思,可信度很低。

比如下面这段就没什么用:

text
1我应该更加仔细地分析需求,并在执行前充分考虑边界情况。

这是正确废话。

更好的反思应该长这样:

json
1{ 2 "taskType": "修改前端表单校验", 3 "failure": "只改了 submit 校验,遗漏了 blur 校验", 4 "rootCause": "没有先搜索同字段的所有校验入口", 5 "lesson": "修改字段规则前,必须搜索 schema、submit、blur、server validation 四类入口", 6 "trigger": "当任务包含 表单/校验/字段规则 时启用", 7 "nextCheck": "提交前列出所有入口和覆盖情况" 8}

这就可以进入经验库。

小编更建议把 Reflection 用在三类场景:

场景是否适合 Reflection原因
单次问答不太适合反馈弱,复盘价值低
编码任务适合测试结果能提供明确反馈
多轮工具任务很适合每一步都有轨迹,可定位失败点
高风险业务动作谨慎使用反思不能替代权限和人工确认

Reflection 最怕变成“失败后让模型安慰自己”。真正要做的是把失败归因结构化,然后让下一次计划发生变化。

六、Tree of Thoughts:不是更复杂,而是承认第一条路可能不对

Chain of Thought 是一条线。

Tree of Thoughts 是多条线。

它解决的是另一类问题:有些任务不是按步骤推进就行,而是需要探索、比较、回退。

比如:

  • 设计一个复杂架构方案。
  • 写一篇有观点的文章。
  • 做一道需要尝试路径的推理题。
  • 规划多约束下的执行策略。

这类任务如果只让模型生成一条思路,很容易早早押错方向。Tree of Thoughts 的思路是让模型生成多个中间思路,再评估、选择、扩展,必要时回溯。

白话一点:

text
1不要只问“下一步是什么” 2而要问“可能有哪几种下一步,哪一种更值得继续”

工程上可以简化成:

ts
1type Candidate = { 2 idea: string 3 score: number 4 risk: string 5 reason: string 6} 7 8function chooseNext(candidates: Candidate[]) { 9 return candidates 10 .filter(item => item.score >= 7) 11 .sort((a, b) => b.score - a.score)[0] 12}

当然,真实系统不会这么粗糙,但思想是这个思想:把模型从“单线程自信”改成“多路径比较”。

Tree of Thoughts 的代价也很明显:贵、慢、复杂。

所以小编不建议普通业务流程一上来就搞搜索树。它更适合:

  • 高价值任务。
  • 创造性任务。
  • 难以一次判断对错的任务。
  • 错了会导致大量返工的任务。

如果只是把用户输入转成 SQL,或者总结一段日志,用 Tree of Thoughts 就像骑车去楼下拿快递还带了导航仪。

七、Plan-and-Execute / LLMCompiler:当工具变多,就要像调度系统一样设计

Plan 和 ReAct 都有一个问题:很多时候它们是串行的。

text
1想一步 -> 调工具 -> 看结果 -> 再想一步 -> 再调工具

这很直观,但慢。

如果任务里有很多互不依赖的工具调用,比如:

  • 同时查三个服务的日志。
  • 同时读取几个配置文件。
  • 同时跑多个静态检查。
  • 同时查询多个数据源。

那就没必要一条一条等。

LLMCompiler 这类思路,就是把模型生成的计划变成更像执行图的东西:

text
1Planner -> Task Graph -> Dispatcher -> Parallel Executors -> Join Results

这时 Agent 更像一个小型工作流引擎。

小编觉得这类模式特别适合“工具多、延迟敏感、依赖关系清楚”的任务。比如代码仓库分析、运维诊断、资料收集、数据比对。

但这里有一个工程提醒:计划和执行一拆开,状态管理就更重要了。

你需要知道:

  • 哪些任务可以并行。
  • 哪些任务依赖前置结果。
  • 哪个任务失败会影响整体。
  • 多个结果回来后如何合并。
  • 合并后的结论是否需要模型再判断。

否则并行只会把错误放大得更快。

按不确定性和副作用选择 Agent 模式

八、到底怎么选:看不确定性和副作用

Agent 模式不用背,按两个维度选就行:

text
1不确定性:任务执行过程中,是否需要根据新信息调整策略 2副作用:工具调用会不会改变外部世界

可以粗略放进这张表:

任务类型推荐模式小编的判断
输入输出清楚、低风险Prompt Chain别过度设计,简单链路就够
步骤多但目标明确Plan / Plan-and-Execute先拆步骤,再逐步检查
需要边查边改策略ReAct工具结果必须反过来影响下一步
失败可反馈、可重试Reflection / Reflexion把失败归因写成可复用经验
多方案探索、难以一次判断Tree of Thoughts生成候选路径,评估后再走
工具多且可并行LLMCompiler / DAG Executor把计划变成任务图
高副作用动作状态机 + 人工确认不要把安全交给模型自觉

小编自己的选择顺序一般是:

  1. 能不用 Agent,就不用 Agent。
  2. 能用 Prompt Chain,就别上复杂循环。
  3. 需要外部信息,再考虑 ReAct。
  4. 需要失败学习,再加 Reflection。
  5. 需要方案搜索,再用 Tree of Thoughts。
  6. 需要稳定上线,就补状态机、权限、日志、评估和兜底。

这套顺序听起来不酷,但很工程。

九、一个可落地的 Agent 骨架

如果让我从零设计一个业务 Agent,小编不会先问“用什么模式”,我会先画这个骨架:

text
1User Goal 2 | 3 v 4Task Router --------------+ 5 | | 6 v | 7Planner | 8 | | 9 v | 10Policy / Permission Check | 11 | | 12 v | 13Executor -> Tools -> Observation 14 | | 15 v | 16Evaluator | 17 | | 18 +--> Reflector -> Memory 19 | 20 v 21Final Answer / Human Confirm / Rollback

对应到代码,最小也应该有这些对象:

ts
1type AgentState = { 2 goal: string 3 plan: Step[] 4 currentStep: number 5 observations: Observation[] 6 decisions: DecisionLog[] 7 permissions: Permission[] 8 memoryHints: string[] 9} 10 11type AgentRuntime = { 12 plan(state: AgentState): Promise<Step[]> 13 act(step: Step, state: AgentState): Promise<Observation> 14 evaluate(state: AgentState): Promise<"continue" | "revise" | "stop" | "human_review"> 15 reflect(state: AgentState): Promise<MemoryHint[]> 16}

这里最重要的是 evaluate

很多 Agent 框架喜欢强调 planact,但小编觉得真正决定系统质量的是评估层:

  • 当前结果够不够?
  • 有没有偏离目标?
  • 是否触发风险?
  • 是否需要人确认?
  • 是否要修订计划?
  • 是否要停止?

没有评估层,Agent 就是一个会调用工具的 while 循环。

十、几个容易踩的坑

10.1 把模式当银弹

ReAct 不是所有任务都比普通 Prompt 好。

Reflection 也不是加了就会进化。

Tree of Thoughts 更不是免费的深度思考。

模式解决的是结构问题,不是替你解决需求理解、数据质量、工具可靠性和权限治理。

10.2 只看最终答案,不看过程轨迹

Agent 的过程比结果更重要。

因为结果错了,你要知道它错在哪里:

  • 目标理解错了?
  • 计划错了?
  • 工具选错了?
  • 工具结果读错了?
  • 中间判断错了?
  • 安全策略漏了?

如果没有轨迹,你只能说“模型又抽风了”。这句话对排障没有任何帮助。

10.3 让模型自己决定所有边界

高风险系统里,边界不能靠模型“自觉遵守”。

比如:

  • 最多调用多少次工具。
  • 最多花多少钱。
  • 哪些工具需要确认。
  • 哪些字段不能输出。
  • 哪些动作必须 dry run。
  • 哪些异常必须升级给人。

这些应该写在程序里,而不是写在 Prompt 里祈祷模型听话。

10.4 没有离线评估集

如果一个 Agent 每次改 Prompt 都靠肉眼试两条样例,那迟早会变成玄学。

至少要有一批离线任务:

text
1输入任务 -> 期望轨迹 -> 允许工具 -> 关键断言 -> 风险检查 -> 最终结果

Agent 的评估,不应该只看最终回答像不像,还要看:

  • 有没有调用不该调用的工具。
  • 有没有漏掉关键证据。
  • 有没有在信息不足时强行下结论。
  • 有没有在高风险动作前请求确认。
  • 有没有把失败经验写进正确位置。

十一、最后的判断:Agent 工程不是让模型自由发挥,而是设计可控自由

小编最后想说一句有点绕、但很重要的话:

Agent 的价值,不是让模型想干嘛就干嘛,而是在可控边界里,让模型拥有足够的行动空间。

Plan 给它路线。

ReAct 给它眼睛和手。

Reflection 给它复盘能力。

Tree of Thoughts 给它多路径探索。

状态机、权限、日志、评估、人工确认,给它边界。

所以真正的 Agent 设计,不是把一堆模式名塞进 Prompt,也不是迷信某个框架。它更像搭一台机器:哪里需要齿轮,哪里需要传感器,哪里需要刹车,哪里需要人站在旁边确认。

当你从这个角度看 Agent,很多问题就清楚了。

不是“我要不要用 ReAct”。

而是“这个任务的不确定性在哪里,副作用在哪里,我准备用什么结构把它管住”。

这才是 Agent 设计模式真正有价值的地方。

参考资料

返回博客列表
最后更新于 2026-07-07
想法或问题?在 GitHub Issue 下方参与讨论
去评论