Agent 构建模式

LLM GEN

为什么需要特殊的"架构"?

要回答这个问题,首先要理解一个核心矛盾:

LLM 是"一次对话"式的——你问一句,它答一句,上下文用完就结束。
现实任务是多步骤的——需要查资料、算数据、写文件、反复修正。

Agent 架构本质上解决的是:如何让 LLM 突破"单次对话"的局限,在一个循环中自主完成复杂任务。

底层涉及几个关键能力:

  1. 工具调用(Tool Use)——模型输出结构化指令来调用外部函数
  2. 多步推理(Multi-step Reasoning)——不靠一次生成,靠"想一步、做一步、再看结果"的迭代
  3. 状态管理(State Management)——在多次调用间维护上下文、记忆中间结果
  4. 自我修正(Self-correction)——发现错误后调整策略而非直接放弃

不同架构的区别,归根结底是在以上四个维度上做了不同的权衡。


第一种:ReAct(Reasoning + Acting)

底层原理

ReAct 是 2022 年由谷歌提出的论文方法,核心思想极其简单:让模型在每一步同时输出"思考"和"动作",而不是直接输出答案。

循环体(每次调用 LLM):
  ├── Thought: 模型当前的想法(自然语言推理)
  ├── Action:  决定调用的工具和参数
  └── Observation: 工具返回的结果
       ↓
  把 thought + action + observation 追加到上下文
  进入下一次循环

论文中的经典例子是问"除了 Apple Remote,还有什么设备能控制它?"

模式 结果
直接回答(Standard) 幻觉,回答 iPod ❌
只推理(Reason Only) 思考很多但没法验证 ❌
只调用工具(Act Only) 搜了多次但不会关联结果 ❌
ReAct 搜索 Apple Remote → 发现是 Front Row 用的 → 搜索 Front Row → 找到 Keyboard ✅

ReAct 的三种实现形态

graph LR
    subgraph "1. 原始 ReAct(文本解析)"
        A1[LLM 输出文本] --> B1[暴力 split 关键词] --> C1[提取 thought/action]
    end
    subgraph "2. ReAct + Function Calling"
        A2[LLM 输出 JSON] --> B2[原生解析 tool_calls] --> C2[稳定可靠]
    end
    subgraph "3. ReAct + MCP Tools"
        A3[MCP 协议] --> B3[动态发现工具] --> C3[标准化工具生态]
    end
  1. 原始 ReAct(2022):模型输出 Thought: ... Action: Search[xxx] 这样的文本,靠正则或字符串 split 解析。不稳定,对弱模型几乎不可用。
  2. ReAct + Function Calling(2023+):OpenAI 发布 function calling 后,模型原生支持输出结构化 JSON tool_calls,解析成功率接近 100%。这是如今最普遍的形式——你实际上每天都在用,只不过没人叫它 ReAct 了。
  3. ReAct + MCP(2025+):通过 MCP 协议,工具不再硬编码在代码里,而是由 MCP Server 动态提供,模型在运行时发现可用工具。

核心特点

维度 说明
工具 必须提前全部定义好,无法动态生成
组合能力 弱——每次只能调一个工具,不能嵌套
稳定性 高(搭配 Function Calling)——JSON 结构化输出保证了解析
调用次数 O(n)——每个子任务都需要一次完整的 LLM 调用
适合场景 调用外部 API(搜索、查 DB、发邮件)

优势

劣势


第二种:CodeAct(Coding + Acting)

底层原理

CodeAct 的核心洞察极其锐利:大模型已经会写代码了,为什么不直接让它写代码?

循环体(每次调用 LLM):
  ├── Thought: 模型思考需要做什么
  ├── Code:   模型直接输出代码片段(Python / JavaScript)
  └── Execution Result: 沙箱运行代码后的输出或报错
       ↓
  把结果追加到上下文,进入下一次循环
graph LR
    A[LLM] -->|输出代码| B[沙箱环境]
    B -->|运行结果 / 报错| C{是否还有代码?}
    C -->|是| A
    C -->|否| D[输出最终答案]

和 ReAct 的本质区别

维度 ReAct CodeAct
工具来源 预定义的有限工具集 语言标准库 + 任意第三方库
组合能力 不能嵌套 可以任意嵌套、循环、条件
一次调用的信息量 一个工具结果 一次完整计算的输出
对模型要求 较低 较高——需要模型能写出正确代码
安全风险 低——工具是你定义的 ——代码可能做危险操作,需要沙箱

为什么 CodeAct 效率更高?

回到之前的复杂表达式:(15 - 9) × 8 + 48 ÷ 6

ReAct 需要 5 次 LLM 调用(减法 → 乘法 → 除法 → 加法 → 总结答案)。

CodeAct 只需要 2 次甚至 1 次

// 第一次调用:模型直接输出完整代码
const result = (15 - 9) * 8 + 48 / 6;
console.log(result);  // → 65

两者的时间复杂度差距随着任务复杂度增长而放大。CodeAct 论文中的数据表明,在复杂任务上 CodeAct 的调用次数减少约 60-80%任务成功率提升 20-40%

CodeAct 的关键设计问题

沙箱安全

模型生成的代码必须在一个隔离环境中运行,不能访问文件系统、网络等。最简单的沙箱使用 eval() / exec()(仅限演示),生产环境需使用:

错误处理

CodeAct 有一个 ReAct 不具备的优势:错误信息本身就是有效的反馈

用户:画一个正弦波

模型第一次输出:
```python
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.show()

沙箱报错:plt.show() 在非交互环境中不工作

模型第二次输出:

import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.savefig('/tmp/sine_wave.png')
print("图片已保存")

#### 对模型能力的要求
CodeAct 要求模型具备较强的代码生成和调试能力。2022 年(ReAct 提出时)模型写代码能力不够,CodeAct 不现实。2024-2026 年(GPT-4、Claude 3/4 时代)模型写代码能力已经足够,CodeAct 成为可行且强大的选择。

### 优势

- **效率极高**——用代码代替多次工具调用,大幅减少 LLM 调用次数
- **表达力无限**——可以写循环、条件、递归,调用任何标准库
- **组合自然**——嵌套调用是代码基本功,不需要额外设计
- **自修正**——报错本身就是反馈,模型可以自己 debug

### 劣势

- **对模型要求高**——代码能力弱的模型不适用
- **安全风险大**——需要可靠的沙箱隔离
- **不适合纯 API 调用**——如果任务是"搜索网页、查数据库",写代码反而绕弯路
- **结果解析有额外开销**——需要从代码输出中提取有用信息

---

## 第三种:Plan-and-Execute(先规划再执行)

### 底层原理

ReAct 和 CodeAct 都是"边想边做"。Plan-and-Execute 反过来:**先制定完整计划,再按计划执行。**

这其实模拟了人类处理复杂任务的方式——先想清楚怎么做,再动手。

阶段一:规划
LLM 接收任务 → 输出完整步骤列表(每一步的依赖关系)

阶段二:执行
按计划逐步执行(可以结合 ReAct 或 CodeAct)
如果某一步失败 → 回到规划阶段重新调整


### 示例

用户:分析这篇论文的主要内容,做一个摘要,再用中文翻译

规划阶段输出:

  1. 读取论文 PDF(工具:read_file)
  2. 提取关键段落(工具:llm_extract)
  3. 生成英文摘要(工具:llm_summarize)
  4. 翻译为中文(工具:llm_translate)
  5. 保存到文件(工具:write_file)

执行阶段:
[第1步] read_file → 成功
[第2步] llm_extract → 成功
[第3步] llm_summarize → 成功
[第4步] llm_translate → 成功
[第5步] write_file → 成功 → 完成


```mermaid
graph TD
    A[用户输入] --> B[规划器: 制定步骤]
    B --> C[执行步骤 1]
    C --> D{成功?}
    D -->|是| E[执行步骤 2]
    D -->|否| B
    E --> F{全部完成?}
    F -->|否| G[执行下一步]
    G --> D
    F -->|是| H[输出最终结果]

Plan-and-Execute vs ReAct

ReAct Plan-and-Execute
规划时机 边走边看 先想好再走
灵活性 高——随时可以调整 中——计划可能过时
可预测性 低——不知道会走多少步 高——一开始就知道总步骤
适合任务 探索性、不确定性高的任务 流程明确、确定性高的任务

优势

劣势


第四种:Multi-Agent(多智能体协作)

底层原理

核心思想:用一个模型解决所有事情是低效的,让多个专业模型各司其职。

每个 Agent 有自己的:

                   ┌─────────────────┐
                   │  Orchestrator    │
                   │  (协调者 Agent)  │
                   └────────┬────────┘
                            │
               ┌────────────┼────────────┐
               ▼            ▼            ▼
        ┌──────────┐ ┌──────────┐ ┌──────────┐
        │ 研究员   │ │ 程序员   │ │ 审查员   │
        │ Agent    │ │ Agent    │ │ Agent    │
        └──────────┘ └──────────┘ └──────────┘

经典架构类型

  1. Supervisor / Worker(主管 + 工人)

    • 一个主管 Agent 负责任务拆解和分配
    • 多个 Worker Agent 各司其职
    • 结果汇总给主管做最终输出
  2. Debate(辩论式)

    • 多个 Agent 就同一个问题各自输出
    • 互相审查、质疑、反驳
    • 最终达成共识或由裁决者决定
  3. Pipeline(流水线式)

    • Agent A 的输出 → Agent B 的输入 → Agent C 的输入
    • 适用于有明确前后依赖的任务

为什么 Multi-Agent 现在很火?

核心原因:一个 prompt 不可能同时擅长所有事。

"你是一个擅长写代码、做研究、写文档、测试、部署的全栈工程师。"

→ 实际上模型会在多个角色间摇摆,哪个都做不精。
Agent A: "你是一个严谨的代码审查员,只关注代码质量和安全性。"
Agent B: "你是一个富有创造力的产品设计师,专注于用户体验。"
Agent C: "你是一个高效的工程师,专注于快速实现功能。"

→ 每个 Agent 聚焦一个角色,输出质量明显更高。

代表框架

框架 特点
CrewAI Python 原生,最易上手,定义 Role + Goal + Task 即可
AutoGen (Microsoft) 支持复杂对话模式,适合研究场景
LangGraph 最灵活,可以定义任意拓扑结构
OpenAI Swarm 轻量级实验框架,手写逻辑,透明可控

关键挑战

Multi-Agent 不是"Agent 越多越好"。每增加一个 Agent 意味着:

Multi-Agent 的常见误区

并不是所有任务都需要多 Agent。对于简单任务,一个 Agent 加好 prompt 就足够了。多 Agent 只有在任务需要多个不同专业视角协作时才真正发挥价值。

优势

劣势


第五种:Workflow / DAG(有向无环图工作流)

底层原理

这个模式在理念上和前几种完全不同:不是让模型自己决定下一步做什么,而是开发者预先画好流程图,模型按图执行。

graph LR
    A[用户输入] --> B[分类器]
    B -->|技术问题| C[搜索知识库]
    B -->|账户问题| D[查询用户信息]
    B -->|投诉| E[转人工]
    C --> F[生成回答]
    D --> F
    F --> G[输出]

和 Agentic Loop 的关键区别

Agentic Loop Workflow / DAG
决策者 模型自己决定下一步 开发者预先决定
灵活性 高——模型可以自由选择路径 低——路径固定
可预测性 高——行为完全确定
控制粒度 粗——模型决定一切 细——可以精确控制每个节点
适用场景 开放式探索任务 确定性业务流程

为什么 Workflow 模式在企业级很流行?

因为企业不喜欢"黑箱"。

一个自由发挥的 Agent 可能今天走这条路,明天走那条路,QA 没法覆盖所有路径。而 Workflow 的路径是确定的,每个分支都可以单独测试。

代表产品

优势

劣势


最佳实践:推荐范式

当前(2026年)的最佳实践

不需要在以上模式中"选一个"。 现代生产级 Agent 都是多种模式的混合体

推荐架构:分层混合模式

┌─────────────────────────────────────────────┐
│           Orchestrator Layer                │
│          Plan-and-Execute 风格              │
│     (先规划,再按计划调度子任务)           │
└──────────────────┬──────────────────────────┘
                   │
      ┌────────────┼────────────┐
      ▼            ▼            ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 工具调用  │ │ 代码执行  │ │ 子Agent  │
│ ReAct 风格│ │CodeAct 风格│ │ 多 Agent │
│(API 类) │ │(计算/处理)│ │(复杂协作)│
└──────────┘ └──────────┘ └──────────┘

具体建议

场景 推荐方式 原因
简单工具调用(搜网页、查天气) ReAct + Function Calling 简单直接,几乎零开销
数据处理/计算/绘图 CodeAct 一次代码顶 N 次工具调用
复杂多步任务 Plan-and-Execute + ReAct 先规划稳定大方向,再灵活执行
多角色协作(代码生成+审查) Multi-Agent(2-3 个 Agent) 专业角色分工提升质量
生产环境业务流(客服、审批) Workflow / DAG 确定性优先,每条路径可测试
需要调用外部工具生态 MCP 协议 标准化工具接入,不绑定特定实现

避免反模式

反模式 1:把所有能力写在同一个 prompt 里

"你是一个可以写代码、上网搜索、查数据库、发送邮件、做数据分析的全能助手。"
→ 模型会迷失方向,什么都做不精。
应该:用 Orchestrator + 专用 Agent / Tool 的架构,每个能力独立管理。

反模式 2:无条件堆 Agent

"这个任务太复杂了,我们上 10 个 Agent 吧。"
→ 每个 Agent 都是额外的成本和故障点。大部分任务 1-3 个 Agent 足够了。
应该:从单个 Agent 开始,只有确实需要多个视角时才拆分。

反模式 3:让 Workflow 处理所有意外

"用户可能说任何话,所以我的流程图覆盖所有分支。"
→ 分支数量会指数级膨胀,最终无法维护。
应该:Workflow 只处理确定路径,意外情况交给 Agentic Loop 兜底。


底层原理总结

所有 Agent 架构的本质都可以概括为:

Agent = LLM + 循环 + 工具 + 状态管理
维度 说明
LLM 推理引擎,负责"思考"
循环 突破单次对话限制,让任务可以多步完成
工具 扩展 LLM 的能力边界(搜索、计算、操作文件)
状态管理 在多次调用间维护上下文、记忆、中间结果

不同的架构只是对这四要素的组合方式不同

架构 LLM 任务 循环驱动力 工具形式 状态管理
ReAct 思考+决策 Tool calls 触发 预定义函数 上下文累积
CodeAct 写代码 代码执行结果触发 编程语言+标准库 上下文累积
Plan-and-Execute 先规划后执行 计划步骤触发 任意 计划+上下文
Multi-Agent 专业化分工 Agent 间通信 各 Agent 自有 独立+共享
Workflow/DAG 按图执行 图的边触发 各节点自有 图引擎管理

写在最后

Quote

没有银弹。最好的架构取决于你具体要解决什么问题。

  • 做一个聊天机器人 + 简单工具调用?ReAct + Function Calling 就够了
  • 做一个数据分析助手?CodeAct 是核心
  • 做一个企业级客服系统?Workflow / DAG
  • 做一个 AI 编程助手?ReAct(工具)+ CodeAct(代码)的混合
  • 做一个复杂的自动化系统?Plan-and-Execute + Multi-Agent

最关键的是理解底层原理,然后根据实际需求灵活组合,而不是盲目追随某种"流行模式"。


参考

claude code 的一个典型代表:

graph TD
    A[用户输入] --> B[Agentic Loop]
    B --> C{模型决定方式}
    C -->|调工具| D[ReAct: Read / Write / Bash / Grep]
    C -->|写代码| E[CodeAct: 写代码 → 终端执行 → 看结果]
    C -->|查资料| F[ReAct: WebSearch / MCP工具]
    D --> G{还有更多?}
    E --> G
    F --> G
    G -->|是| B
    G -->|否| H[输出答案]

curcor:

graph TD
    A[用户输入] --> B{Agent 模式}
    B --> C[写/改代码]
    B --> D[执行终端命令]
    B --> E[读取上下文]
    C --> F[感知结果]
    D --> F
    E --> F
    F --> G{还需要改?}
    G -->|是| B
    G -->|否| H[提交更改]