第 2 篇:Agent 的三种工作模式,选错了事倍功半

2 阅读7分钟

系列简介:从零搭建一个多 Agent AI 助手,覆盖原理、实现、部署全链路。不讲空话,每篇都有可运行的代码。
项目地址github.com/CodeMomentY…
本篇目标:理解 Agent 的三种工作模式,知道什么场景用哪种。

IMG_7505.JPG

前言

  大家好,我是一名前端工程师。都说前端“已死”,那与其担心被 AI 替代,不如打入敌人内部,于是我开始折腾 Agent 开发。

  折腾下来发现,Agent 的核心不是算法,而是“工程能力”(怎么设计架构、怎么串联服务、怎么把 LLM 的能力落地成产品)。这些恰好是我们擅长的事。

  这个系列记录我从零搭建多 Agent 系统的完整过程。只聊技术知识和设计思路,代码交给 AI 写。如果你也想从应用层切入 AI,希望这个系列对你有帮助。

读完本篇你将学到:

  • Agent 的三种经典工作模式(范式);
  • 每种范式的核心思想和适用场景;
  • 三种范式的代码实现对比;
  • 什么时候该用哪种,什么时候组合使用;

背景与动机

  上一篇我们搞清楚了 Agent 的本质:LLM + 工具 + 循环。但“循环”具体怎么循环,其实有不同的策略。

打个比方:你接到一个任务“帮我规划一次北京三日游”

  • 方式 A:边想边做。先查天气,看到晴天,那就安排户外景点,再查景点,发现故宫周一闭馆,那换一个...一步步推进。
  • 方式 B:先规划再执行。先列出三天的大纲(Day1 历史、Day2 自然、Day3 美食),然后逐个填充细节。
  • 方式 C:做完检查一遍。先生成一版计划,然后自己审视“有没有遗漏?时间安排合理吗?”,不满意就修改。

这三种方式对应 Agent 的三大范式:ReAct、Plan-and-Solve、Reflection

核心概念

  我们对比一下这三种范式的流程:

image.png

  用一张表来总结一下:

ReActPlan-and-SolveReflection
核心思想边想边做先规划后执行做完自检
循环方式思考→行动→观察→思考...规划→执行步骤1→执行步骤2...生成→反思→修改→再反思...
优势灵活,能应对意外有条理,不遗漏质量高,能自我修正
劣势可能跑偏规划错了全盘皆输慢(多次 LLM 调用)
适合场景简单查询、工具调用复杂多步任务写作、代码生成
类比即兴发挥写提纲再写文章写完改稿

动手实现

ReAct 范式:边想边做

  ReAct 是最常用的范式,上一篇我们其实已经实现了。核心就是 Thought → Action → Observation 的循环:

"""
ReAct 范式:边想边做
适合:需要调用工具获取信息的场景
"""

REACT_PROMPT = """你是一个助手,请按以下格式思考和行动:

Thought: 我需要做什么
Action: 工具名(参数)
Observation: 工具返回的结果
... (重复直到有足够信息)
Thought: 我现在可以回答了
Answer: 最终回答
"""

def react_agent(user_input):
    messages = [{"role": "system", "content": REACT_PROMPT}]
    messages.append({"role": "user", "content": user_input})

    for _ in range(5):  # 最多 5 轮
        response = call_llm(messages)

        if "Action:" in response:
            # 解析并执行工具
            tool_result = execute_tool(response)
            messages.append({"role": "assistant", "content": response})
            messages.append({"role": "user", "content": f"Observation: {tool_result}"})
        elif "Answer:" in response:
            return response.split("Answer:")[-1].strip()

    return "处理超时"

  特点:每一步都能看到中间过程,灵活应对意外情况。但如果任务复杂(比如需要 10 个步骤),可能会跑偏。

Plan-and-Solve 范式:先规划后执行

  先让 LLM 列出计划,再逐步执行。适合复杂的多步任务:

"""
Plan-and-Solve 范式:先规划后执行
适合:复杂多步任务(旅行规划、研究报告)
"""

PLAN_PROMPT = """请先制定计划,再逐步执行。

格式:
Plan:
1. 第一步做什么
2. 第二步做什么
3. 第三步做什么

然后逐步执行每一步。
"""

def plan_and_solve_agent(user_input):
    # 阶段 1:生成计划
    plan_response = call_llm([
        {"role": "system", "content": PLAN_PROMPT},
        {"role": "user", "content": user_input}
    ])
    steps = parse_plan(plan_response)  # 提取步骤列表

    # 阶段 2:逐步执行
    results = []
    for step in steps:
        result = call_llm([
            {"role": "system", "content": "请执行以下任务步骤"},
            {"role": "user", "content": f"任务:{step}\n已有信息:{results}"}
        ])
        results.append(result)

    # 阶段 3:整合结果
    final = call_llm([
        {"role": "system", "content": "请整合以下信息,生成最终回答"},
        {"role": "user", "content": str(results)}
    ])
    return final

  特点:有条理,适合"帮我写一份报告"这种需要结构化输出的任务。但如果第一步规划错了,后面全跟着错。

Reflection 范式:做完自检

  生成回答后让 LLM 自我检查,不满意就修改。适合对质量要求高的场景:

"""
Reflection 范式:生成 + 自我反思
适合:写作、代码生成等需要高质量输出的场景
"""

def reflection_agent(user_input, max_rounds=3):
    # 第一次生成
    draft = call_llm([
        {"role": "system", "content": "你是一个写作助手"},
        {"role": "user", "content": user_input}
    ])

    for round in range(max_rounds):
        # 反思:检查质量
        critique = call_llm([
            {"role": "system", "content": "请严格评审以下内容,指出问题。如果质量够好,回复'PASS'"},
            {"role": "user", "content": f"原始需求:{user_input}\n\n当前内容:\n{draft}"}
        ])

        if "PASS" in critique:
            return draft  # 质量够了

        # 根据反馈修改
        draft = call_llm([
            {"role": "system", "content": "请根据反馈修改内容"},
            {"role": "user", "content": f"当前内容:\n{draft}\n\n反馈:\n{critique}"}
        ])

    return draft  # 达到最大轮次

  特点:输出质量高,但每多一轮反思就多两次 LLM 调用(一次评审 + 一次修改),速度慢、成本高。

效果对比

  问同一个问题“帮我写一段产品介绍”,三种范式的表现:

范式LLM 调用次数耗时输出质量
ReAct1 次~3 秒一般
Plan-and-Solve3-4 次~10 秒较好
Reflection5-7 次~20 秒最好

组合使用:Plan + ReAct + Reflect

  实际项目中,三种范式经常组合。比如“帮我规划北京三日游并写成攻略”:

image.png

  看一下代码实现:

"""
三范式组合:Plan 拆任务 → ReAct 执行每步 → Reflect 检查质量
"""

def combined_agent(user_input):
    # 阶段 1:Plan(拆解任务)
    plan = call_llm([
        {"role": "system", "content": "请将任务拆解为 3-5 个步骤"},
        {"role": "user", "content": user_input}
    ])
    steps = parse_plan(plan)

    # 阶段 2:ReAct(逐步执行,每步可调工具)
    results = []
    for step in steps:
        result = react_agent(step)  # 复用上面的 ReAct 逻辑
        results.append(result)

    # 阶段 3:Reflect(整合并自检)
    draft = call_llm([
        {"role": "system", "content": "请整合以下信息,生成完整攻略"},
        {"role": "user", "content": str(results)}
    ])

    # 自检一轮
    critique = call_llm([
        {"role": "system", "content": "检查攻略是否完整,有无遗漏"},
        {"role": "user", "content": draft}
    ])

    if "PASS" not in critique:
        draft = call_llm([
            {"role": "system", "content": "根据反馈修改"},
            {"role": "user", "content": f"{draft}\n\n反馈:{critique}"}
        ])

    return draft

  这就是我们后面搭建多 Agent 时用的思路——dispatcher 做 Plan(判断走哪些 Agent),各 Agent 内部用 ReAct(调工具),写作类任务可以加 Reflect。

刨根问底

序号问题
1️⃣Q:实际项目中只用一种范式吗?
A:不是。实际项目经常组合使用。比如:天气查询用 ReAct(简单,调一次工具就够了);深度研究用 Plan-and-Solve(先规划子任务,再逐个执行);写文案可以加 Reflection(生成后自检修改)。
2️⃣Q:怎么决定用哪种范式?
A:看任务复杂度。一两步就能完成 → ReAct;需要多步骤、有明确结构 → Plan-and-Solve;对输出质量要求高、允许慢一点 → Reflection。
3️⃣Q:Reflection 会不会无限循环?
A:会,所以必须加 max_rounds 限制。而且有时候 LLM 的“评审员”和“写作者”是同一个模型,可能会陷入“改来改去越改越差”的情况。所以实际使用中 2-3 轮就够了。

本篇小结

  • Agent 有三种经典工作模式:ReAct(边想边做)、Plan-and-Solve(先规划后执行)、Reflection(做完自检);
  • 没有最好的范式,只有最适合的——根据任务复杂度和质量要求选择;
  • 实际项目中经常组合使用多种范式;
  • 核心差异在于"循环的策略"不同,底层都是 LLM + 工具;

写在最后

  三种范式看起来是三种“技术方案”,但本质是三种“思维方式”。ReAct 像是敏捷开发(快速迭代、随时调整)、Plan-and-Solve 像是瀑布模型(先设计后实现);Reflection 像是 Code Review(写完回头审视)。

  选范式和选开发流程一样,没有万能解,只有取舍。

  下一篇预告:有了范式的认知,接下来我们用 LangGraph 框架搭建一个真正的多 Agent 系统——多个 Agent 各司其职,dispatcher 动态路由,支持串行和并行执行。