智能体经典范式构建:ReAct、Plan-and-Solve 与 Reflection

智能体经典范式构建:ReAct、Plan-and-Solve 与 Reflection

一句话总览:Agent 的核心不是让模型更会聊天,而是为模型设计三种控制循环:边想边做、先计划再做、做完再改。

这篇文章基于 Datawhale Hello-Agents 第四章整理,但不按原文目录复述。原章用 Python 从零实现 ReAct、Plan-and-Solve 和 Reflection;

快速结论

问题 结论
三种范式分别解决什么问题 ReAct 解决外部信息不确定,Plan-and-Solve 解决复杂任务拆解,Reflection 解决初稿质量不够
什么时候优先用 ReAct 需要搜索、查数据库、调用 API、根据工具反馈调整下一步
什么时候优先用 Plan-and-Solve 任务目标稳定、步骤清楚、多步推理明显
什么时候优先用 Reflection 代码、报告、方案、研究分析等高质量输出
工程上怎么组合 先 Plan 拆任务,中间 ReAct 调工具,最后 Reflection 做质检
最大风险 控制循环越多,成本、延迟、不可控性越高

核心地图

范式 一句话 核心循环 控制权主要来自
ReAct 边想边查 Thought -> Action -> Observation 每一轮环境反馈
Plan-and-Solve 先画路线再走 Plan -> Execute -> Summarize 初始计划
Reflection 先做初稿再评审 Execute -> Reflect -> Refine 事后反馈

#mermaid-svg-1U53lUQUtjgHIg8W{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1U53lUQUtjgHIg8W .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1U53lUQUtjgHIg8W .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1U53lUQUtjgHIg8W .error-icon{fill:#552222;}#mermaid-svg-1U53lUQUtjgHIg8W .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1U53lUQUtjgHIg8W .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1U53lUQUtjgHIg8W .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1U53lUQUtjgHIg8W .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1U53lUQUtjgHIg8W .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1U53lUQUtjgHIg8W .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1U53lUQUtjgHIg8W .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1U53lUQUtjgHIg8W .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1U53lUQUtjgHIg8W .marker.cross{stroke:#333333;}#mermaid-svg-1U53lUQUtjgHIg8W svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1U53lUQUtjgHIg8W p{margin:0;}#mermaid-svg-1U53lUQUtjgHIg8W .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1U53lUQUtjgHIg8W .cluster-label text{fill:#333;}#mermaid-svg-1U53lUQUtjgHIg8W .cluster-label span{color:#333;}#mermaid-svg-1U53lUQUtjgHIg8W .cluster-label span p{background-color:transparent;}#mermaid-svg-1U53lUQUtjgHIg8W .label text,#mermaid-svg-1U53lUQUtjgHIg8W span{fill:#333;color:#333;}#mermaid-svg-1U53lUQUtjgHIg8W .node rect,#mermaid-svg-1U53lUQUtjgHIg8W .node circle,#mermaid-svg-1U53lUQUtjgHIg8W .node ellipse,#mermaid-svg-1U53lUQUtjgHIg8W .node polygon,#mermaid-svg-1U53lUQUtjgHIg8W .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1U53lUQUtjgHIg8W .rough-node .label text,#mermaid-svg-1U53lUQUtjgHIg8W .node .label text,#mermaid-svg-1U53lUQUtjgHIg8W .image-shape .label,#mermaid-svg-1U53lUQUtjgHIg8W .icon-shape .label{text-anchor:middle;}#mermaid-svg-1U53lUQUtjgHIg8W .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1U53lUQUtjgHIg8W .rough-node .label,#mermaid-svg-1U53lUQUtjgHIg8W .node .label,#mermaid-svg-1U53lUQUtjgHIg8W .image-shape .label,#mermaid-svg-1U53lUQUtjgHIg8W .icon-shape .label{text-align:center;}#mermaid-svg-1U53lUQUtjgHIg8W .node.clickable{cursor:pointer;}#mermaid-svg-1U53lUQUtjgHIg8W .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1U53lUQUtjgHIg8W .arrowheadPath{fill:#333333;}#mermaid-svg-1U53lUQUtjgHIg8W .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1U53lUQUtjgHIg8W .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1U53lUQUtjgHIg8W .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1U53lUQUtjgHIg8W .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1U53lUQUtjgHIg8W .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1U53lUQUtjgHIg8W .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1U53lUQUtjgHIg8W .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1U53lUQUtjgHIg8W .cluster text{fill:#333;}#mermaid-svg-1U53lUQUtjgHIg8W .cluster span{color:#333;}#mermaid-svg-1U53lUQUtjgHIg8W div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1U53lUQUtjgHIg8W .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1U53lUQUtjgHIg8W rect.text{fill:none;stroke-width:0;}#mermaid-svg-1U53lUQUtjgHIg8W .icon-shape,#mermaid-svg-1U53lUQUtjgHIg8W .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1U53lUQUtjgHIg8W .icon-shape p,#mermaid-svg-1U53lUQUtjgHIg8W .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1U53lUQUtjgHIg8W .icon-shape .label rect,#mermaid-svg-1U53lUQUtjgHIg8W .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1U53lUQUtjgHIg8W .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1U53lUQUtjgHIg8W .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1U53lUQUtjgHIg8W :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 需要外部反馈
步骤稳定
质量要求高
用户
LLM
判断任务特征
ReAct
Plan-and-Solve
Reflection
候选结果
更可靠的结果

先准备底座:模型客户端和工具执行器

一句话:三种 Agent Loop 的差异在控制流程,底层都需要一个 LLM 客户端和一套工具调用接口。

解决的问题:如果每个范式都自己写模型调用和工具注册,后面会很快失控。先抽底座,可以让 ReAct、Plan-and-Solve、Reflection 复用同一套能力。

适合场景:所有 Agent 原型都应该先做这一步,哪怕只是 demo。

核心机制:LLM 客户端只负责发送消息和返回文本;工具执行器只负责注册、描述和调用工具;Agent Loop 负责决定什么时候调用模型、什么时候调用工具。

最小实现:

bash 复制代码
npm init -y
npm install dotenv

.env

bash 复制代码
LLM_API_KEY="YOUR_API_KEY"
LLM_MODEL_ID="YOUR_MODEL"
LLM_BASE_URL="https://api.openai.com/v1"
SERPAPI_API_KEY="YOUR_SERPAPI_API_KEY"
ts 复制代码
import 'dotenv/config';

export class HelloAgentsLLM {
  constructor({
    model = process.env.LLM_MODEL_ID,
    apiKey = process.env.LLM_API_KEY,
    baseUrl = process.env.LLM_BASE_URL,
    timeoutMs = Number(process.env.LLM_TIMEOUT_MS || 60_000)
  } = {}) {
    if (!model || !apiKey || !baseUrl) {
      throw new Error('LLM_MODEL_ID、LLM_API_KEY、LLM_BASE_URL 必须配置。');
    }

    this.model = model;
    this.apiKey = apiKey;
    this.baseUrl = baseUrl.replace(/\/$/, '');
    this.timeoutMs = timeoutMs;
  }

  async think(messages, { temperature = 0 } = {}) {
    const controller = new AbortController();
    const timer = setTimeout(() => controller.abort(), this.timeoutMs);

    try {
      const response = await fetch(`${this.baseUrl}/chat/completions`, {
        method: 'POST',
        signal: controller.signal,
        headers: {
          'content-type': 'application/json',
          authorization: `Bearer ${this.apiKey}`
        },
        body: JSON.stringify({
          model: this.model,
          messages,
          temperature
        })
      });

      if (!response.ok) {
        throw new Error(`LLM API failed: ${response.status} ${await response.text()}`);
      }

      const data = await response.json();
      return data.choices?.[0]?.message?.content?.trim() ?? '';
    } finally {
      clearTimeout(timer);
    }
  }
}

export class ToolExecutor {
  constructor() {
    this.tools = new Map();
  }

  registerTool(name, description, fn) {
    this.tools.set(name, { description, fn });
  }

  getAvailableToolsText() {
    return [...this.tools.entries()]
      .map(([name, tool]) => `- ${name}: ${tool.description}`)
      .join('\n');
  }

  async execute(name, input) {
    const tool = this.tools.get(name)?.fn;
    if (!tool) return `错误:未找到工具 ${name}`;
    return await tool(input);
  }
}

常见坑:

处理方式
LLM 客户端里混入业务循环 保持客户端只做模型调用
工具描述太含糊 描述清楚何时用、输入是什么、返回什么
所有工具一次性塞给模型 工具多时先做检索或路由

什么时候不要展开这一步:一次性脚本可以直接调用模型;但只要准备复用或组合多个 Agent Loop,就应该抽象底座。

ReAct:适合需要外部反馈的任务

一句话:ReAct 让模型每一步都先想清楚,再调用工具,然后用工具结果修正下一步。

解决的问题:只让模型思考,它可能凭空编;只让模型行动,它可能乱调工具。ReAct 把推理和行动交替起来,让外部世界不断校正模型。

适合场景:

场景 为什么适合
查询实时信息 模型自身知识可能过期
调用 API / 数据库 每次返回会影响下一步
搜索和总结 需要边查边缩小问题
工具链任务 不同工具之间存在依赖

核心机制:
#mermaid-svg-fh0QtszqTrrhD0dW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fh0QtszqTrrhD0dW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fh0QtszqTrrhD0dW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fh0QtszqTrrhD0dW .error-icon{fill:#552222;}#mermaid-svg-fh0QtszqTrrhD0dW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fh0QtszqTrrhD0dW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fh0QtszqTrrhD0dW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fh0QtszqTrrhD0dW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fh0QtszqTrrhD0dW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fh0QtszqTrrhD0dW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fh0QtszqTrrhD0dW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fh0QtszqTrrhD0dW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fh0QtszqTrrhD0dW .marker.cross{stroke:#333333;}#mermaid-svg-fh0QtszqTrrhD0dW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fh0QtszqTrrhD0dW p{margin:0;}#mermaid-svg-fh0QtszqTrrhD0dW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-fh0QtszqTrrhD0dW .cluster-label text{fill:#333;}#mermaid-svg-fh0QtszqTrrhD0dW .cluster-label span{color:#333;}#mermaid-svg-fh0QtszqTrrhD0dW .cluster-label span p{background-color:transparent;}#mermaid-svg-fh0QtszqTrrhD0dW .label text,#mermaid-svg-fh0QtszqTrrhD0dW span{fill:#333;color:#333;}#mermaid-svg-fh0QtszqTrrhD0dW .node rect,#mermaid-svg-fh0QtszqTrrhD0dW .node circle,#mermaid-svg-fh0QtszqTrrhD0dW .node ellipse,#mermaid-svg-fh0QtszqTrrhD0dW .node polygon,#mermaid-svg-fh0QtszqTrrhD0dW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fh0QtszqTrrhD0dW .rough-node .label text,#mermaid-svg-fh0QtszqTrrhD0dW .node .label text,#mermaid-svg-fh0QtszqTrrhD0dW .image-shape .label,#mermaid-svg-fh0QtszqTrrhD0dW .icon-shape .label{text-anchor:middle;}#mermaid-svg-fh0QtszqTrrhD0dW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fh0QtszqTrrhD0dW .rough-node .label,#mermaid-svg-fh0QtszqTrrhD0dW .node .label,#mermaid-svg-fh0QtszqTrrhD0dW .image-shape .label,#mermaid-svg-fh0QtszqTrrhD0dW .icon-shape .label{text-align:center;}#mermaid-svg-fh0QtszqTrrhD0dW .node.clickable{cursor:pointer;}#mermaid-svg-fh0QtszqTrrhD0dW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fh0QtszqTrrhD0dW .arrowheadPath{fill:#333333;}#mermaid-svg-fh0QtszqTrrhD0dW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fh0QtszqTrrhD0dW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fh0QtszqTrrhD0dW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fh0QtszqTrrhD0dW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fh0QtszqTrrhD0dW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fh0QtszqTrrhD0dW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fh0QtszqTrrhD0dW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fh0QtszqTrrhD0dW .cluster text{fill:#333;}#mermaid-svg-fh0QtszqTrrhD0dW .cluster span{color:#333;}#mermaid-svg-fh0QtszqTrrhD0dW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fh0QtszqTrrhD0dW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fh0QtszqTrrhD0dW rect.text{fill:none;stroke-width:0;}#mermaid-svg-fh0QtszqTrrhD0dW .icon-shape,#mermaid-svg-fh0QtszqTrrhD0dW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fh0QtszqTrrhD0dW .icon-shape p,#mermaid-svg-fh0QtszqTrrhD0dW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fh0QtszqTrrhD0dW .icon-shape .label rect,#mermaid-svg-fh0QtszqTrrhD0dW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fh0QtszqTrrhD0dW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fh0QtszqTrrhD0dW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fh0QtszqTrrhD0dW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户
LLM
Thought
Action
Observation
Finish

模型每一轮输出固定格式:

text 复制代码
Thought: 我现在知道什么,还缺什么
Action: Search[要搜索的问题]

如果信息足够:

text 复制代码
Thought: 信息已经足够
Action: Finish[最终答案]

最小实现:

ts 复制代码
const REACT_PROMPT = `
你是一个可以调用外部工具的智能助手。

可用工具:
{tools}

请严格按下面格式输出:
Thought: 你的思考
Action: 工具名[工具输入] 或 Finish[最终答案]

问题:
{question}

历史:
{history}
`;

function parseAction(text) {
  const match = text.match(/Action:\s*([A-Za-z_][\w]*)\[(.*)\]/s);
  if (!match) return null;
  return {
    toolName: match[1],
    toolInput: match[2].trim()
  };
}

export class ReActAgent {
  constructor({ llm, toolExecutor, maxSteps = 5 }) {
    this.llm = llm;
    this.toolExecutor = toolExecutor;
    this.maxSteps = maxSteps;
  }

  async run(question) {
    let history = '';

    for (let step = 1; step <= this.maxSteps; step += 1) {
      const prompt = REACT_PROMPT.replace('{tools}', this.toolExecutor.getAvailableToolsText())
        .replace('{question}', question)
        .replace('{history}', history || '无');

      const output = await this.llm.think([{ role: 'user', content: prompt }]);
      const action = parseAction(output);

      if (!action) {
        history += `\n模型输出无法解析:\n${output}\n`;
        continue;
      }

      if (action.toolName === 'Finish') {
        return action.toolInput;
      }

      const observation = await this.toolExecutor.execute(action.toolName, action.toolInput);
      history += `\n${output}\nObservation: ${observation}\n`;
    }

    return '达到最大步骤数,未得到稳定答案。';
  }
}

常见坑:

说明 工程处理
输出解析脆弱 模型不一定遵守 Action[...] 用 JSON Schema、函数调用或结构化输出
工具选择错误 模型可能搜索不该搜的问题 增强工具描述,加入工具路由
死循环 一直搜索或重复调用 设置最大步数,检测重复动作
上下文膨胀 Observation 越积越多 对历史做摘要,只保留关键证据

什么时候不要用:任务不需要外部信息、步骤很清楚、答案可以一次性推理出来时,ReAct 可能只是增加调用成本。

Plan-and-Solve:适合路径清楚的复杂任务

一句话:Plan-and-Solve 先生成完整路线,再按路线一步步执行。

解决的问题:复杂任务如果直接让模型回答,很容易漏步骤。Plan-and-Solve 先把任务拆开,让模型从一次大跳跃变成多次小推进。

适合场景:

场景 为什么适合
多步数学题 步骤稳定,推理链清楚
报告大纲生成 先定结构,再填内容
稳定流程任务 不需要频繁依赖外部反馈
代码脚手架生成 可先规划模块,再逐个实现

核心机制:
#mermaid-svg-gHgq4neZd9DCpI27{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gHgq4neZd9DCpI27 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gHgq4neZd9DCpI27 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gHgq4neZd9DCpI27 .error-icon{fill:#552222;}#mermaid-svg-gHgq4neZd9DCpI27 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gHgq4neZd9DCpI27 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gHgq4neZd9DCpI27 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gHgq4neZd9DCpI27 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gHgq4neZd9DCpI27 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gHgq4neZd9DCpI27 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gHgq4neZd9DCpI27 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gHgq4neZd9DCpI27 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gHgq4neZd9DCpI27 .marker.cross{stroke:#333333;}#mermaid-svg-gHgq4neZd9DCpI27 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gHgq4neZd9DCpI27 p{margin:0;}#mermaid-svg-gHgq4neZd9DCpI27 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gHgq4neZd9DCpI27 .cluster-label text{fill:#333;}#mermaid-svg-gHgq4neZd9DCpI27 .cluster-label span{color:#333;}#mermaid-svg-gHgq4neZd9DCpI27 .cluster-label span p{background-color:transparent;}#mermaid-svg-gHgq4neZd9DCpI27 .label text,#mermaid-svg-gHgq4neZd9DCpI27 span{fill:#333;color:#333;}#mermaid-svg-gHgq4neZd9DCpI27 .node rect,#mermaid-svg-gHgq4neZd9DCpI27 .node circle,#mermaid-svg-gHgq4neZd9DCpI27 .node ellipse,#mermaid-svg-gHgq4neZd9DCpI27 .node polygon,#mermaid-svg-gHgq4neZd9DCpI27 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gHgq4neZd9DCpI27 .rough-node .label text,#mermaid-svg-gHgq4neZd9DCpI27 .node .label text,#mermaid-svg-gHgq4neZd9DCpI27 .image-shape .label,#mermaid-svg-gHgq4neZd9DCpI27 .icon-shape .label{text-anchor:middle;}#mermaid-svg-gHgq4neZd9DCpI27 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gHgq4neZd9DCpI27 .rough-node .label,#mermaid-svg-gHgq4neZd9DCpI27 .node .label,#mermaid-svg-gHgq4neZd9DCpI27 .image-shape .label,#mermaid-svg-gHgq4neZd9DCpI27 .icon-shape .label{text-align:center;}#mermaid-svg-gHgq4neZd9DCpI27 .node.clickable{cursor:pointer;}#mermaid-svg-gHgq4neZd9DCpI27 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gHgq4neZd9DCpI27 .arrowheadPath{fill:#333333;}#mermaid-svg-gHgq4neZd9DCpI27 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gHgq4neZd9DCpI27 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gHgq4neZd9DCpI27 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gHgq4neZd9DCpI27 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gHgq4neZd9DCpI27 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gHgq4neZd9DCpI27 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gHgq4neZd9DCpI27 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gHgq4neZd9DCpI27 .cluster text{fill:#333;}#mermaid-svg-gHgq4neZd9DCpI27 .cluster span{color:#333;}#mermaid-svg-gHgq4neZd9DCpI27 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gHgq4neZd9DCpI27 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gHgq4neZd9DCpI27 rect.text{fill:none;stroke-width:0;}#mermaid-svg-gHgq4neZd9DCpI27 .icon-shape,#mermaid-svg-gHgq4neZd9DCpI27 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gHgq4neZd9DCpI27 .icon-shape p,#mermaid-svg-gHgq4neZd9DCpI27 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gHgq4neZd9DCpI27 .icon-shape .label rect,#mermaid-svg-gHgq4neZd9DCpI27 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gHgq4neZd9DCpI27 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gHgq4neZd9DCpI27 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gHgq4neZd9DCpI27 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户
LLM
Plan
Step 1
Step 2
Step 3
Answer

最小实现:

ts 复制代码
const PLAN_PROMPT = `
请把用户任务拆成可以依次执行的步骤。

只输出 JSON,不要输出解释。
JSON 格式:
{
  "steps": [
    { "id": 1, "goal": "这一步要完成什么", "instruction": "具体执行说明" }
  ]
}

用户任务:
{task}
`;

function extractJson(text) {
  const start = text.indexOf('{');
  const end = text.lastIndexOf('}');
  if (start === -1 || end === -1 || end <= start) {
    throw new Error('模型没有返回 JSON 对象。');
  }
  return JSON.parse(text.slice(start, end + 1));
}

export class PlanAndSolveAgent {
  constructor({ llm }) {
    this.llm = llm;
  }

  async plan(task) {
    const prompt = PLAN_PROMPT.replace('{task}', task);
    const output = await this.llm.think([{ role: 'user', content: prompt }]);
    return extractJson(output).steps ?? [];
  }

  async execute(task, steps) {
    const results = [];

    for (const step of steps) {
      const prompt = `
原始任务:
${task}

当前步骤:
${JSON.stringify(step, null, 2)}

之前结果:
${results.join('\n\n') || '无'}

请完成当前步骤,只输出本步骤结果。
`;

      const result = await this.llm.think([{ role: 'user', content: prompt }]);
      results.push(`Step ${step.id}: ${result}`);
    }

    return results;
  }

  async run(task) {
    const steps = await this.plan(task);
    const results = await this.execute(task, steps);
    return await this.llm.think([
      {
        role: 'user',
        content: `请根据以下步骤结果汇总最终答案:\n\n${results.join('\n\n')}`
      }
    ]);
  }
}

常见坑:

说明 工程处理
第一版计划错了 后面执行越认真越偏 加检查点和动态重规划
计划太粗 每一步仍然不可执行 要求每步包含目标、输入、输出
计划太细 成本变高,流程拖长 限制步骤数,合并低价值步骤

动态重规划更像真实系统:
#mermaid-svg-O68nVEE8QkQBTCkA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-O68nVEE8QkQBTCkA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-O68nVEE8QkQBTCkA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-O68nVEE8QkQBTCkA .error-icon{fill:#552222;}#mermaid-svg-O68nVEE8QkQBTCkA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-O68nVEE8QkQBTCkA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-O68nVEE8QkQBTCkA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-O68nVEE8QkQBTCkA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-O68nVEE8QkQBTCkA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-O68nVEE8QkQBTCkA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-O68nVEE8QkQBTCkA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-O68nVEE8QkQBTCkA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-O68nVEE8QkQBTCkA .marker.cross{stroke:#333333;}#mermaid-svg-O68nVEE8QkQBTCkA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-O68nVEE8QkQBTCkA p{margin:0;}#mermaid-svg-O68nVEE8QkQBTCkA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-O68nVEE8QkQBTCkA .cluster-label text{fill:#333;}#mermaid-svg-O68nVEE8QkQBTCkA .cluster-label span{color:#333;}#mermaid-svg-O68nVEE8QkQBTCkA .cluster-label span p{background-color:transparent;}#mermaid-svg-O68nVEE8QkQBTCkA .label text,#mermaid-svg-O68nVEE8QkQBTCkA span{fill:#333;color:#333;}#mermaid-svg-O68nVEE8QkQBTCkA .node rect,#mermaid-svg-O68nVEE8QkQBTCkA .node circle,#mermaid-svg-O68nVEE8QkQBTCkA .node ellipse,#mermaid-svg-O68nVEE8QkQBTCkA .node polygon,#mermaid-svg-O68nVEE8QkQBTCkA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-O68nVEE8QkQBTCkA .rough-node .label text,#mermaid-svg-O68nVEE8QkQBTCkA .node .label text,#mermaid-svg-O68nVEE8QkQBTCkA .image-shape .label,#mermaid-svg-O68nVEE8QkQBTCkA .icon-shape .label{text-anchor:middle;}#mermaid-svg-O68nVEE8QkQBTCkA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-O68nVEE8QkQBTCkA .rough-node .label,#mermaid-svg-O68nVEE8QkQBTCkA .node .label,#mermaid-svg-O68nVEE8QkQBTCkA .image-shape .label,#mermaid-svg-O68nVEE8QkQBTCkA .icon-shape .label{text-align:center;}#mermaid-svg-O68nVEE8QkQBTCkA .node.clickable{cursor:pointer;}#mermaid-svg-O68nVEE8QkQBTCkA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-O68nVEE8QkQBTCkA .arrowheadPath{fill:#333333;}#mermaid-svg-O68nVEE8QkQBTCkA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-O68nVEE8QkQBTCkA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-O68nVEE8QkQBTCkA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O68nVEE8QkQBTCkA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-O68nVEE8QkQBTCkA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O68nVEE8QkQBTCkA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-O68nVEE8QkQBTCkA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-O68nVEE8QkQBTCkA .cluster text{fill:#333;}#mermaid-svg-O68nVEE8QkQBTCkA .cluster span{color:#333;}#mermaid-svg-O68nVEE8QkQBTCkA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-O68nVEE8QkQBTCkA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-O68nVEE8QkQBTCkA rect.text{fill:none;stroke-width:0;}#mermaid-svg-O68nVEE8QkQBTCkA .icon-shape,#mermaid-svg-O68nVEE8QkQBTCkA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O68nVEE8QkQBTCkA .icon-shape p,#mermaid-svg-O68nVEE8QkQBTCkA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-O68nVEE8QkQBTCkA .icon-shape .label rect,#mermaid-svg-O68nVEE8QkQBTCkA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O68nVEE8QkQBTCkA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-O68nVEE8QkQBTCkA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-O68nVEE8QkQBTCkA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 正常
失败或偏离
完成
用户
LLM
生成计划
执行一步
检查结果
重规划剩余步骤
最终答案

什么时候不要用:任务高度依赖实时反馈、用户目标不断变化、工具结果会强烈改变后续路径时,单纯的静态计划不够。

Reflection:适合高质量输出

一句话:Reflection 让模型先交初稿,再切换成评审员找问题,最后根据反馈修订。

解决的问题:模型一次生成的结果通常只是合格初稿。代码可能能跑但不高效,报告可能完整但不犀利,方案可能合理但漏掉风险。Reflection 把一次性生成变成迭代优化。

适合场景:

场景 为什么适合
代码生成 可以检查复杂度、边界条件、可读性
技术报告 可以检查逻辑、遗漏和证据
研究分析 可以从多个维度反驳初稿
高风险决策 可以在输出前加一道质量门禁

核心机制:
#mermaid-svg-UY1cdQioI9xCHMhg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UY1cdQioI9xCHMhg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UY1cdQioI9xCHMhg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UY1cdQioI9xCHMhg .error-icon{fill:#552222;}#mermaid-svg-UY1cdQioI9xCHMhg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UY1cdQioI9xCHMhg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UY1cdQioI9xCHMhg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UY1cdQioI9xCHMhg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UY1cdQioI9xCHMhg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UY1cdQioI9xCHMhg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UY1cdQioI9xCHMhg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UY1cdQioI9xCHMhg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UY1cdQioI9xCHMhg .marker.cross{stroke:#333333;}#mermaid-svg-UY1cdQioI9xCHMhg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UY1cdQioI9xCHMhg p{margin:0;}#mermaid-svg-UY1cdQioI9xCHMhg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UY1cdQioI9xCHMhg .cluster-label text{fill:#333;}#mermaid-svg-UY1cdQioI9xCHMhg .cluster-label span{color:#333;}#mermaid-svg-UY1cdQioI9xCHMhg .cluster-label span p{background-color:transparent;}#mermaid-svg-UY1cdQioI9xCHMhg .label text,#mermaid-svg-UY1cdQioI9xCHMhg span{fill:#333;color:#333;}#mermaid-svg-UY1cdQioI9xCHMhg .node rect,#mermaid-svg-UY1cdQioI9xCHMhg .node circle,#mermaid-svg-UY1cdQioI9xCHMhg .node ellipse,#mermaid-svg-UY1cdQioI9xCHMhg .node polygon,#mermaid-svg-UY1cdQioI9xCHMhg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UY1cdQioI9xCHMhg .rough-node .label text,#mermaid-svg-UY1cdQioI9xCHMhg .node .label text,#mermaid-svg-UY1cdQioI9xCHMhg .image-shape .label,#mermaid-svg-UY1cdQioI9xCHMhg .icon-shape .label{text-anchor:middle;}#mermaid-svg-UY1cdQioI9xCHMhg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UY1cdQioI9xCHMhg .rough-node .label,#mermaid-svg-UY1cdQioI9xCHMhg .node .label,#mermaid-svg-UY1cdQioI9xCHMhg .image-shape .label,#mermaid-svg-UY1cdQioI9xCHMhg .icon-shape .label{text-align:center;}#mermaid-svg-UY1cdQioI9xCHMhg .node.clickable{cursor:pointer;}#mermaid-svg-UY1cdQioI9xCHMhg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UY1cdQioI9xCHMhg .arrowheadPath{fill:#333333;}#mermaid-svg-UY1cdQioI9xCHMhg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UY1cdQioI9xCHMhg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UY1cdQioI9xCHMhg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UY1cdQioI9xCHMhg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UY1cdQioI9xCHMhg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UY1cdQioI9xCHMhg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UY1cdQioI9xCHMhg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UY1cdQioI9xCHMhg .cluster text{fill:#333;}#mermaid-svg-UY1cdQioI9xCHMhg .cluster span{color:#333;}#mermaid-svg-UY1cdQioI9xCHMhg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UY1cdQioI9xCHMhg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UY1cdQioI9xCHMhg rect.text{fill:none;stroke-width:0;}#mermaid-svg-UY1cdQioI9xCHMhg .icon-shape,#mermaid-svg-UY1cdQioI9xCHMhg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UY1cdQioI9xCHMhg .icon-shape p,#mermaid-svg-UY1cdQioI9xCHMhg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UY1cdQioI9xCHMhg .icon-shape .label rect,#mermaid-svg-UY1cdQioI9xCHMhg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UY1cdQioI9xCHMhg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UY1cdQioI9xCHMhg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UY1cdQioI9xCHMhg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 无需改进
用户
LLM
Execution
Reflection
Refinement
Final

最小实现:

ts 复制代码
export class Memory {
  constructor() {
    this.records = [];
  }

  addRecord(type, content) {
    this.records.push({ type, content });
  }

  getLastExecution() {
    return [...this.records].reverse().find((record) => record.type === 'execution')?.content ?? '';
  }
}

const INITIAL_PROMPT = `
你是一位资深 Node.js 工程师。请根据要求编写 JavaScript 函数。
请只输出代码。

要求:
{task}
`;

const REFLECT_PROMPT = `
你是一位严格的代码评审专家。
请审查下面的 JavaScript 代码,重点找出算法效率、边界条件和可读性问题。

原始任务:
{task}

代码:
\`\`\`js
{code}
\`\`\`

如果有改进空间,请给出具体反馈。
如果已经足够好,请回答:无需改进。
`;

const REFINE_PROMPT = `
请根据评审反馈优化代码。

原始任务:
{task}

上一版代码:
\`\`\`js
{lastCode}
\`\`\`

评审反馈:
{feedback}

请只输出优化后的 JavaScript 代码。
`;

export class ReflectionAgent {
  constructor({ llm, maxIterations = 3 }) {
    this.llm = llm;
    this.maxIterations = maxIterations;
    this.memory = new Memory();
  }

  async run(task) {
    const firstDraft = await this.llm.think([
      {
        role: 'user',
        content: INITIAL_PROMPT.replace('{task}', task)
      }
    ]);
    this.memory.addRecord('execution', firstDraft);

    for (let i = 0; i < this.maxIterations; i += 1) {
      const lastCode = this.memory.getLastExecution();
      const feedback = await this.llm.think([
        {
          role: 'user',
          content: REFLECT_PROMPT.replace('{task}', task).replace('{code}', lastCode)
        }
      ]);

      this.memory.addRecord('reflection', feedback);
      if (feedback.includes('无需改进')) break;

      const nextDraft = await this.llm.think([
        {
          role: 'user',
          content: REFINE_PROMPT.replace('{task}', task)
            .replace('{lastCode}', lastCode)
            .replace('{feedback}', feedback)
        }
      ]);
      this.memory.addRecord('execution', nextDraft);
    }

    return this.memory.getLastExecution();
  }
}

案例:找出 1n 的所有素数。初版可能逐个试除,复杂度接近 O(n * sqrt(n));Reflection 如果专注算法效率,就会推动它改成埃拉托斯特尼筛法。

ts 复制代码
export function findPrimes(n) {
  if (!Number.isInteger(n) || n < 2) return [];

  const isPrime = Array(n + 1).fill(true);
  isPrime[0] = false;
  isPrime[1] = false;

  for (let p = 2; p * p <= n; p += 1) {
    if (!isPrime[p]) continue;
    for (let current = p * p; current <= n; current += p) {
      isPrime[current] = false;
    }
  }

  return isPrime.map((value, index) => (value ? index : null)).filter((value) => value !== null);
}

常见坑:

说明 工程处理
评审太空泛 只说"可以更好" 给评审明确维度,如复杂度、边界、事实性
终止条件粗糙 只靠"无需改进" 加分数、测试、阈值或人工 gate
成本过高 每轮至少多一次评审和一次修订 只给高价值任务启用

什么时候不要用:实时问答、低风险闲聊、一次性简单任务,不值得为 Reflection 付出额外延迟和成本。

组合策略:真实 Agent 很少只用一种循环

最实用的默认组合是:

任务类型 默认组合 原因
实时搜索问答 ReAct 需要外部观察
复杂报告 Plan-and-Solve + Reflection 先定结构,再做质检
多 API 工作流 Plan-and-Solve + ReAct 先规划接口顺序,再按反馈执行
代码生成 Plan-and-Solve + Reflection 先拆模块,再审查优化
高风险业务决策 ReAct + Reflection + 人工 gate 需要证据、反思和最终审批

一个工程化架构可以这样组织:
#mermaid-svg-HAGxbCd6bcenf1lI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HAGxbCd6bcenf1lI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HAGxbCd6bcenf1lI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HAGxbCd6bcenf1lI .error-icon{fill:#552222;}#mermaid-svg-HAGxbCd6bcenf1lI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HAGxbCd6bcenf1lI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HAGxbCd6bcenf1lI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HAGxbCd6bcenf1lI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HAGxbCd6bcenf1lI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HAGxbCd6bcenf1lI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HAGxbCd6bcenf1lI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HAGxbCd6bcenf1lI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HAGxbCd6bcenf1lI .marker.cross{stroke:#333333;}#mermaid-svg-HAGxbCd6bcenf1lI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HAGxbCd6bcenf1lI p{margin:0;}#mermaid-svg-HAGxbCd6bcenf1lI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-HAGxbCd6bcenf1lI .cluster-label text{fill:#333;}#mermaid-svg-HAGxbCd6bcenf1lI .cluster-label span{color:#333;}#mermaid-svg-HAGxbCd6bcenf1lI .cluster-label span p{background-color:transparent;}#mermaid-svg-HAGxbCd6bcenf1lI .label text,#mermaid-svg-HAGxbCd6bcenf1lI span{fill:#333;color:#333;}#mermaid-svg-HAGxbCd6bcenf1lI .node rect,#mermaid-svg-HAGxbCd6bcenf1lI .node circle,#mermaid-svg-HAGxbCd6bcenf1lI .node ellipse,#mermaid-svg-HAGxbCd6bcenf1lI .node polygon,#mermaid-svg-HAGxbCd6bcenf1lI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HAGxbCd6bcenf1lI .rough-node .label text,#mermaid-svg-HAGxbCd6bcenf1lI .node .label text,#mermaid-svg-HAGxbCd6bcenf1lI .image-shape .label,#mermaid-svg-HAGxbCd6bcenf1lI .icon-shape .label{text-anchor:middle;}#mermaid-svg-HAGxbCd6bcenf1lI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HAGxbCd6bcenf1lI .rough-node .label,#mermaid-svg-HAGxbCd6bcenf1lI .node .label,#mermaid-svg-HAGxbCd6bcenf1lI .image-shape .label,#mermaid-svg-HAGxbCd6bcenf1lI .icon-shape .label{text-align:center;}#mermaid-svg-HAGxbCd6bcenf1lI .node.clickable{cursor:pointer;}#mermaid-svg-HAGxbCd6bcenf1lI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HAGxbCd6bcenf1lI .arrowheadPath{fill:#333333;}#mermaid-svg-HAGxbCd6bcenf1lI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HAGxbCd6bcenf1lI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HAGxbCd6bcenf1lI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HAGxbCd6bcenf1lI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HAGxbCd6bcenf1lI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HAGxbCd6bcenf1lI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HAGxbCd6bcenf1lI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HAGxbCd6bcenf1lI .cluster text{fill:#333;}#mermaid-svg-HAGxbCd6bcenf1lI .cluster span{color:#333;}#mermaid-svg-HAGxbCd6bcenf1lI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HAGxbCd6bcenf1lI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HAGxbCd6bcenf1lI rect.text{fill:none;stroke-width:0;}#mermaid-svg-HAGxbCd6bcenf1lI .icon-shape,#mermaid-svg-HAGxbCd6bcenf1lI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HAGxbCd6bcenf1lI .icon-shape p,#mermaid-svg-HAGxbCd6bcenf1lI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HAGxbCd6bcenf1lI .icon-shape .label rect,#mermaid-svg-HAGxbCd6bcenf1lI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HAGxbCd6bcenf1lI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HAGxbCd6bcenf1lI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HAGxbCd6bcenf1lI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 外部信息
复杂内部任务
简单任务
低风险
高价值或高风险
用户
用户输入
LLM
任务分类
ReAct 工具循环
Plan-and-Solve
直接回答
候选答案
质量门禁
输出
Reflection 反思优化

取舍与风险

这三种范式不是越复杂越好。它们本质上是在不同位置给模型重新判断的机会。

范式 重新判断发生在哪里 代价
ReAct 每次工具返回后 工具调用多,上下文增长快
Plan-and-Solve 初始计划阶段 计划错了会系统性偏离
Reflection 初稿生成之后 延迟和模型调用成本增加

我的判断是:Agent 架构的核心问题不是模型够不够聪明,而是系统允许它在什么时候重新判断。能重新判断的地方越多,系统越灵活,但也越贵、越慢、越难控。

结论

ReAct 解决的是:我不知道外部世界,所以我要边查边想。

Plan-and-Solve 解决的是:任务太复杂,所以我要先拆路线。

Reflection 解决的是:初稿不够好,所以我要让系统学会改。

理解这三种循环,再去看 LangChain、LlamaIndex、AutoGen、CrewAI 或内部 Agent 平台,就不会只看到框架 API,而能看到它们背后的控制结构。

相关推荐
jsonbro1 小时前
手把手带你实现发布订阅模式
前端·vue.js·设计模式
一只猫的梦1 小时前
自动化模块 (Automation Module)
前端·chrome
熊猫钓鱼>_>2 小时前
Electron:当 Web 技术统治桌面
大数据·前端·javascript·人工智能·架构·electron·agent
德福危险2 小时前
从盲打xss到到模板注入:unix靶机渗透之Tempus_fugit4
前端·unix·xss
JavaGuide2 小时前
又一个画图 Skill 开源,再见手动画 draw.io!
前端·后端·github
飞天狗2 小时前
长列表滚动卡顿怎么破:虚拟列表选型 + react-virtuoso 实战调优指南
react.js·性能优化
一只猫的梦2 小时前
AI 适配器架构
前端·chrome
谭光志2 小时前
AI 是怎么操作浏览器的——browser use 实现原理
前端·javascript·ai编程
weixin_471383033 小时前
args,...args与Parameters<T>
开发语言·前端