Agent 如何拆解任务:从经典范式到真实产品

发布时间:2026/7/29 7:44:43
Agent 如何拆解任务:从经典范式到真实产品 Agent 如何拆解任务一个反直觉的事实当你问 Claude Code 重构这个支付模块时它不会一次性生成完整方案而是边探索边决策、边执行边调整。这不是模型不够强而是 Agent 任务拆解的本质——不是一次性规划而是动态调度。一、开篇为什么任务拆解不是一次性规划直觉上以为 Agent 接到用户请求后会像项目经理一样先列个完整计划然后一步步执行。实际观察 Claude Code、Codex CLI 的行为会发现它们更像是走一步看一步——先判断当前状态决定下一步行动执行后观察结果再决定下一步。这不是工程能力的缺陷而是 Agent 任务的特殊性决定的。Agent 的任务通常有强不确定性搜索结果不可预测、工具调用可能失败、用户需求可能在执行中变化。一次性规划的致命问题是一旦现实偏离假设整个计划就崩了。所以主流 Agent 的任务拆解本质上是在不确定性中做动态调度——有规划但不迷信规划有执行但随时能调整。这种动态调度能力来源于三种经典范式的组合ReAct边想边做、Plan-and-Solve先规划再执行、Reflection自我反思修正。下面逐一拆解它们的机制、适用场景和工程要点。二、ReAct边想边做的步进式决策ReActReasoning Acting是最基础的 Agent 范式由 Shunyu Yao 在 2022 年提出。核心思想是模仿人类解决问题的方式把推理和行动显式结合形成Thought → Action → Observation的循环。工作流程当用户提出请求帮我重构这个支付模块解决并发扣款问题时ReAct Agent 的执行过程是这样的第一步Agent 进入 Thought 状态我需要先了解现有代码结构找到支付模块的入口。接着进入 Action 状态调用工具glob(src/payment/**/*.py)。工具返回 Observation找到 15 个文件。Agent 回到 Thought 状态文件有点多我先看核心的 service.py。第二步Actionread_file(src/payment/service.py)。Observation返回 2000 行代码。Thought代码量很大我需要先看关键函数。第三步Actiongrep(def process_payment, src/payment/service.py)。Observation找到函数在第 45 行。Thought我先读这个函数。第四步Actionread_file(src/payment/service.py, offset45, limit100)。Observation返回函数代码。Thought我发现了问题没有加锁高并发下可能重复扣款。我需要设计分布式锁方案。循环继续直到 Agent 在 Thought 中判断问题已经分析清楚可以开始修改然后进入 Final Answer 阶段给出重构方案。最小实现ReAct 的核心逻辑可以用不到 50 行 Python 代码实现。这是一个简化但完整的循环def react(task: str, model, tools: dict, max_steps: int 10): ReAct 循环 - 完整实现 # 存储完整的交互历史包括思考、行动、观察 history [] # 每个元素: {role: assistant 或 tool, content: str} observations [] # 仅存储观察结果用于构建 prompt trace [] # 初始化把任务加入历史 history.append({role: user, content: task}) for step in range(max_steps): # 1. 构建 prompt包含完整历史 prompt build_prompt_with_history(history, tools) # 2. LLM 思考并决策 decision model.generate_json(prompt) # 记录思考过程 history.append({ role: assistant, content: fThought: {decision.get(reason_summary, )}\n fAction: {decision.get(tool, none)} fwith args {decision.get(args, {})} }) # 3. 判断是否结束 if decision[type] final: return { answer: decision[answer], trace: trace, status: completed, steps: step 1, history: history } # 4. 执行工具 tool_name decision.get(tool) if tool_name not in tools: obs {ok: False, error: unknown_tool, tool: tool_name} else: args decision.get(args, {}) try: obs tools[tool_name](**args) obs[ok] True except Exception as e: obs {ok: False, error: str(e), tool: tool_name} # 5. 将观察结果加入历史关键 obs_summary summarize(obs) history.append({ role: tool, content: fObservation: {obs_summary} }) # 6. 更新记录 observations.append(obs) trace.append({ step: step 1, tool: tool_name, args: decision.get(args, {}), reason_summary: decision.get(reason_summary, ), observation_summary: obs_summary }) # 7. 关键上下文已经通过 history 传递下一轮循环会自动使用 # 超时处理 return { answer: None, trace: trace, status: max_steps_exceeded, steps: max_steps, history: history }关键的工程细节最大步数限制max_steps硬护栏防止死循环。生产级 Agent 通常设为 10-20 步根据任务复杂度调整。审计日志trace每一步都记录工具调用和推理摘要失败时可排查成功时可复盘。观察摘要summarize工具返回的 Observation 可能很长如文件内容需要摘要后再存入上下文避免上下文爆炸。将观察结果写入历史中JSON 格式输出让模型返回结构化 JSON而非自由文本便于解析和验证。生产级 Agent 会加格式校验防止模型输出非 JSON 导致解析失败。核心优势ReAct 的强项在于动态规划与纠错能力。与一次性生成完整计划不同ReAct 是走一步看一步——根据每一步的 Observation 动态调整后续 Thought 和 Action。如果搜索结果不理想它可以在下一步修正搜索词、重新尝试如果代码读不懂它可以追加上下文、换角度分析。这种适应性让 ReAct 在开放式任务如调试、搜索、代码理解上表现优异。另一个优势是工具协同能力。ReAct 把 LLM 的推理能力与外部工具的执行能力天然结合LLM 负责运筹帷幄规划与推理工具负责解决具体问题搜索、计算、读文件。这种协同突破了单一 LLM 在知识时效性、计算准确性上的固有局限。固有局限ReAct 的第一个问题是对 LLM 能力的强依赖。整个流程的成功与否高度依赖底层 LLM 的综合能力。如果 LLM 的逻辑推理能力、指令遵循能力或格式化输出能力不足就很容易在 Thought 环节产生错误规划或在 Action 环节生成不符合格式的指令导致流程中断。第二个问题是执行效率。完成任务通常需要多次调用 LLM每次调用都伴随着网络延迟和计算成本。对于需要很多步骤的复杂任务串行的思考-行动循环会导致较高的总耗时和费用。这也是为什么生产级 Agent 都会设置最大步数限制、超时限制避免无限制循环。第三个问题是可能陷入局部最优。步进式决策意味着缺乏全局、长远的规划。Agent 可能因为眼前的 Observation 选择一个看似正确但长远来看并非最优的路径甚至在某些情况下陷入原地打转的循环。这就是为什么很多 Agent 会加入重复检测机制——如果发现最近几步的 Action 重复就强制切换策略或请求用户干预。三、Plan-and-Solve先规划再执行的两阶段策略如果说 ReAct 像侦探根据现场线索一步步推理、随时调整方向那么 Plan-and-Solve 就像建筑师动工之前先绘制完整蓝图然后严格按照蓝图施工。对应到推理模式上它把 ReAct 里混在一起的「规划推理」和「执行推理」给完全拆开了行话理解说白了就是两件事分开干各管各的专门用一个 LLM 负责「做规划」把大目标拆成一步一步的执行清单用另一个 LLM或者模块负责「按清单执行」执行完了再统一汇总。React是一个LLm做所有两阶段工作流当用户提出请求帮我写一份关于 Agent 上下文压缩的技术报告时Plan-and-Solve Agent 首先进入规划阶段。LLM 调用生成一个结构化的计划1. 搜索上下文压缩相关论文和博客收集核心概念 2. 阅读主流产品Claude Code、Codex CLI的压缩策略文档 3. 整理压缩策略的分类体系截断、摘要、offload 等 4. 分析压缩的触发机制和阈值设计 5. 总结压缩的安全风险和工程实践 6. 撰写报告初稿规划完成后Agent 进入执行阶段严格按照计划逐一执行。每一步的输入包含原始问题、完整计划、前序步骤的执行结果。比如执行步骤 2 时Agent 会知道这是计划的第 2 步前一步已经收集了核心概念这一步要阅读具体产品文档。核心优势Plan-and-Solve 的强项在于目标一致性强。因为计划在执行前已经制定完成Agent 在整个执行过程中都有明确的导航图不会走到一半忘了要干嘛。这对于需要长远规划的复杂任务如报告撰写、代码生成、数学推理特别有效。另一个优势是上下文结构清晰。ReAct 的上下文是累积式的逐步追加 Thought/Action/Observation容易变长、变乱Plan-and-Solve 的上下文是结构式的计划在前 执行记录在后逻辑层次分明对模型更友好。固有局限Plan-and-Solve 的第一个问题是规划依赖初始信息。规划阶段的 LLM 调用只有用户请求作为输入缺乏执行过程中发现的新信息。如果执行过程中发现某些假设是错的比如找不到某份文档原来的计划可能不再适用但 Agent 可能还在按旧计划执行——这就是过度依赖规划的风险。第二个问题是灵活性不足。面对动态变化的任务如调试、实时搜索Plan-and-Solve 可能不如 ReAct 敏捷。这也是为什么很多产品会采用混合策略对于结构性强的子任务用 Plan-and-Solve对于探索性强的子任务用 ReAct。四、Reflection自我反思修正的第三层保障ReAct 和 Plan-and-Solve 都是向前走Reflection 是回头看执行一轮后让模型自我批判找出不足然后修正或重试。Reflection 不是一套独立的完整流程而是给 ReAct、Plan-and-Execute 加的「锦上添花的 buff」它不改变原本的做事流程只是在原本的基础上加了一层「自我检查、自我修正」的环节。还是用最熟悉的考试例子你一下就能看懂三者的关系。ReAct 就像你一道题一道题挨着做做一道过一道不回头看。Plan-and-Execute 是你先把整张卷子的做题顺序、时间分配定好再按计划做题。Reflection 则是你做完一道题或者整张卷子回头再检查一遍看看有没有算错数、有没有看错题发现错了马上改改完再交卷。工作流程当 Agent 完成一轮执行无论是 ReAct 循环还是 Plan-and-Solve 计划后Reflection 模块会启动。LLM 被要求对执行结果进行批判性评估这个答案完整吗有逻辑漏洞吗是否满足用户的所有约束如果反思发现问题如预算计算有误差、没有考虑边界情况Agent 会进入修正阶段调整下一步行动、修改部分结果、或重新执行某个子任务。修正后再次反思直到满意为止。核心价值Reflection 的价值在于提升输出的可靠性。对于质量要求高的任务如代码生成、数学推理、关键决策单次执行往往有疏漏Reflection 提供了自我纠错的机会显著提高成功率。另一个价值是适应性强。Reflection 不改变 Agent 的主流程ReAct 或 Plan-and-Solve而是作为一个可选的后处理模块叠加在最外层。这种松耦合设计让它可以灵活地嵌入各种 Agent 系统。固有局限Reflection 的第一个问题是增加延迟和成本。每轮反思都是一次额外的 LLM 调用如果反思多轮总耗时和费用会显著上升。这也是为什么生产级 Agent 通常只在关键节点触发反思而非每一步都反思。第二个问题是可能过度修正。如果反思模块过于严格Agent 可能陷入反复改、改不完的循环甚至把原本正确的答案改错。这也是为什么反思模块的设计需要平衡挑剔和放手。进阶进阶动态 Replan 和 Reflexion讲完了三个基础范式再补充两个在实际项目中经常会遇到的进阶机制面试时能说出来会很加分。第一个是动态 Replan它解决的是 Plan-and-Execute 的一个核心痛点计划定死了中途遇到意外怎么办比如你规划了五步来写竞品分析报告执行到第三步发现某个竞品已经被收购了原来的分析框架需要调整但计划已经定好了后面的步骤还是按老计划跑输出的报告就会有问题。动态 Replan 的做法是在每个步骤执行完之后把当前结果和剩余计划一起交给规划模块让它判断「原来的计划还合理吗需不需要调整」。如果需要就生成一份新的剩余步骤计划替换掉原来的。这样既保留了 Plan-and-Execute「先规划再执行」的结构优势又不会因为计划太僵硬而在意外情况下翻车。代价是每步都多了一次「重新评估计划」的 LLM 调用token 消耗会增加。第二个是Reflexion它把 Reflection 的「自我反思」推到了更深的层次。普通的 Reflection 是「做完了检查一遍、发现问题就重做」有点像考试做完检查一遍。Reflexion 在这个基础上多做了一件关键的事它不仅检查输出对不对还会把每次失败的原因总结成一段「经验教训」存进记忆里下次再遇到类似任务时这段教训会作为上下文传给 LLM让它避免重蹈覆辙。这个机制有点像你做错了一道数学题不只是改答案还会在错题本上写「这类题容易漏掉符号变化下次要特别注意」下次遇到同类题时翻一下错题本再动笔。Reflexion 的效果到底有多强在 HumanEval 代码生成基准测试上Reflexion 机制把 GPT-4 的 pass1 准确率从 80% 提升到了 91%提升幅度超过了 10 个百分点。这个数据非常能说明问题同样的基座模型仅仅加了「反思 记住教训」这个机制代码一次写对的概率就大幅提高。背后的原因也好理解代码生成天然适合 Reflexion因为代码可以运行、可以测试执行结果就是最直接的反馈信号。Agent 写完代码跑一遍测试没通过的话就分析是哪里出了问题把「这个 API 的参数顺序搞反了」或者「边界条件没处理」这样的具体教训记下来下次重试时带着这些教训去改成功率自然就高了。这种「verbal reinforcement learning」语言强化学习的思路让 Agent 不需要梯度更新就能从错误中学习非常适合在推理阶段提升质量。五、三种范式对比从概念到工程把三种范式放在一起看差异会更清晰。核心维度对比维度ReActPlan-and-SolveReflection决策时机每一步动态决策一次性规划后执行执行后回头看停止条件模型判断够了或硬编码上限计划执行完毕满意为止或达到上限上下文压力累积式逐步追加 Thought/Action/Observation结构式计划在前 执行记录在后反思追加执行效率多次串行 LLM 调用延迟和成本较高规划 1 次 执行 n 次相对可控额外反思调用增加延迟灵活性高根据 Observation 随时调整中计划可调整但不够敏捷高可反复修正目标一致性弱可能走到一半忘了目标强有完整计划导航中反思能纠偏适用场景开放式探索调试、搜索、代码理解结构化任务报告撰写、代码生成高质量要求关键决策、代码生成典型任务表现对比从公开实验和工程实践来看三种范式在不同任务类型上的表现有显著差异开放式搜索任务ReAct 成功率最高因为能根据搜索结果动态调整策略。Plan-and-Solve 容易因为初始假设错误而跑偏成功率低 15-25%。结构化推理任务Plan-and-Solve 成功率最高因为有完整计划导航不会走到一半忘目标。ReAct 容易陷入局部最优成功率低 10-15%。代码生成任务Plan-and-Solve Reflection 组合表现最好——先规划架构再逐块实现最后反思检查边界情况。纯 ReAct 容易生成能跑但不优雅的代码。调试任务ReAct 表现最好因为调试本质上就是根据报错动态调整。Plan-and-Solve 几乎不适用——你没法在开始前就知道会报什么错。三种范式在 token 消耗上的差异是选型时必须考虑的现实因素咱们用一个具体的例子来直观感受一下。假设有一个需要 5 步工具调用的任务每步产生的推理和工具结果平均占 2000 token。用 ReAct 来跑因为每次调 LLM 都要把完整历史带上第一步输入 2000 token第二步 4000第三步 6000依次递增光输入就是 2000 4000 6000 8000 10000 30000 token增长曲线是线性的步骤越多越吃钱。换成 Plan-and-Execute消耗集中在规划阶段和汇总阶段这两个「大头」上。规划阶段调一次 LLM输入是任务描述加工具列表大约 3000 token。执行阶段每步只需要带当前步骤的指令和前面步骤的结果摘要不是完整的推理历史每步大约 1500 token5 步总共 7500 token。汇总阶段再调一次 LLM把所有结果综合起来大约 4000 token。加起来总消耗约 14500 token比 ReAct 的 30000 token 低了一半多。如果再用上前面说的「强模型规划、弱模型执行」策略虽然 token 数量差不多但执行阶段用便宜模型跑实际花费能再降 70% 以上。加了 Reflection 之后每个需要反思的节点至少多一次 LLM 调用评估一次不达标还要重做token 消耗会在基础范式上再增加 30% 到 100%取决于反思的轮次和严格程度。如果一个步骤反思了两轮才通过那这一步的消耗就翻了三倍。所以 Reflection 不是越多越好得有个上限控制一般设置最多反思 2 到 3 轮就够了。生产级 Agent 的组合策略主流产品不会只用一种范式而是组合入口判断根据任务复杂度选择 ReAct 或 Plan-and-SolveReAct 主循环大多数任务用 ReAct 式步进决策Plan-and-Solve 子任务结构性强的子任务如遍历这个目录找所有 .py 文件用 Plan-and-Solve 派给 SubAgentReflection 关键节点重要修改前触发反思确认方向正确六、真实产品的任务拆解机制从公开资料来看Claude Code 和 Codex CLI 的任务拆解是上述范式的工程化组合而非单一范式的应用。Claude Code分层多 Agent 动态 SteeringClaude Code 采用主 Agent协调 SubAgent执行专项任务的分层架构。主 Agent 接收用户请求后判断是否需要派给 SubAgent如果任务涉及代码搜索、文件遍历等探索性工作就派给 Explore 类 SubAgent如果任务涉及具体修改就自己执行。SubAgent 在独立上下文里执行子任务只把结论返回给主 Agent。这种隔离设计避免了上下文污染——SubAgent 产生的大量中间观察不会塞满主 Agent 的上下文只有高密度的结论被保留。主 Agent 的决策方式是 ReAct 式的步进决策但加入了实时 Steering机制用户可以随时中断、调整方向系统自动保存状态并无缝切换。这解决了传统 Agent 必须等完整执行结束才能调整的痛点。Codex CLIHandoff 思维 Session Memory 优先Codex CLI 带来的一个观念转变是压缩不是 Summary总结发生了什么而是Handoff交接给下一个模型该做什么。压缩 prompt 明确要求包含Current progress and key decisions made、What remains to be done (clear next steps)——这是前瞻性的而非回顾性的。另一个关键是Session Memory 优先策略Codex 会先检查结构化的 session memory任务状态、文件编辑历史、关键决策能否替代完整摘要用简单的if判断判断是否为空。或者Hash和diff计算文件完整性。或者逻辑检测关键字段检测。必要字段检测。大多数自动压缩走这条路径根本不调 LLM——既省钱又快。只有 session memory 不够时才走服务端压缩。基于当前结构化的任务状态你觉得有没有信息缺失只回答是或否。六、工程关键点拉开差距的细节任务拆解的范式只是骨架真正拉开差距的是工具设计、停止条件、错误恢复、可观测性这些工程细节。工具设计找到 Goldilocks 区工具不能太万能也不能太碎。太万能的例子是Terminal Tool 什么都管——模型写管道命令rg | grep | sed错误信息被管道吞掉Agent 只看到一个空结果无从判断是真的没找到还是查找过程中出错了。这就是不可诊断的致命问题。太碎的例子是每个功能点都拆成独立工具——模型在第一步就卡住不知道该用FindByName、FindByPattern还是Glob。选工具本身就消耗大量 attention。正确的做法是找到Goldilocks 区高频、强确定性的动作如读文件、搜索、列表拆成原子工具每一步都有明确的输入、输出、状态低频、弱确定性的动作如复杂的 shell 操作放到兜底层明确禁止什么而非允许什么。真实项目复盘管道命令事故我们团队在开发一个 Code Agent 时曾踩过一个典型坑给 Terminal Tool 开了绿灯允许模型自由写管道命令。那天测试一个简单需求帮我搜一下process_data函数的定义。模型很快给出一条看起来挺专业的命令rg -n def process_data src/ | grep -v test | sed -n 1,50p但执行结果是空的。Agent 看到空结果后开始各种补救换搜索词、换目录、甚至怀疑是不是记错了函数名。三轮重试后它放弃了告诉我我在仓库里没有找到这个函数。但我手动去仓库看了那个函数明明就在src/utils/helpers.py第 42 行。排查后发现启动 Agent 时的工作目录不是项目根目录而是项目下的一个子目录。src/相对当前目录不存在rg直接报错退出。但因为命令用了管道错误信息被管道吞掉了——rg的错误输出没有传到 stdout而是被导向了下一个命令的输入。Agent 只看到一个空字符串根本不知道上游失败了。这次事故消耗了27 步工具调用和15 万 token最后给出的是错误结论。修复方案是禁止管道命令把高频操作拆成原子工具Glob、Grep、Read每个工具都有明确的成功/失败状态码。修改后同样任务只需要4 步调用和2 万 token。停止条件不能只靠模型判断ReAct 循环不能无限跑下去。工程上必须硬编码最大步数限制如 20 步、超时限制如 5 分钟、重复检测如最近 3 步 Action 相同就强制切换策略。这些硬护栏防止 Agent 陷入死循环或无限制消耗 token。错误恢复失败不是终点是输入工具调用失败不能让整个循环崩掉。正确做法是把失败信息包装成 Observation让 Agent 根据错误类型决定下一步如换搜索词、换工具、请求用户澄清。这把失败变成了可处理的输入而非终止信号。可观测性把黑盒变玻璃盒Agent 的每一步都要有审计日志调了什么工具、传了什么参数、返回什么结果、模型怎么推理的。没有这些日志失败了排查不了成功了也不知道为什么成功。这就是 Extra09 强调的可观测性把黑盒变玻璃盒。七、总结任务拆解的本质是动态调度主流 Agent 的任务拆解不是简单的用户请求 → LLM 拆成子任务 → 执行而是入口判断用户请求进来先判断复杂度和任务类型简单请求直接 ReAct 式步进决策快速响应复杂请求Plan-and-Solve 式规划或派给 SubAgent 隔离执行执行中动态 Steering用户可随时中断、调整方向关键节点 Reflection质量要求高的环节加入反思修正上下文管理兜底压缩、offload、子代理隔离保证工作记忆不爆真正拉开差距的不是用哪种范式而是工具设计Goldilocks 区、停止条件硬护栏、错误恢复失败变输入、可观测性黑盒变玻璃盒、上下文管理工作记忆不爆这些工程细节。这也是为什么读最佳实践文章不够必须看真实踩坑经验——前者告诉你该怎么做后者告诉你做错了会怎样、怎么救回来。延伸阅读本文的工程细节主要来自 hello-agents 的 Extra09《Agent应用开发实践踩坑与经验分享》那里有管道命令事故、工具设计 Goldilocks 区、可观测性的真实案例。理论框架来自 hello-agents 第四章《智能体经典范式构建》有 ReAct、Plan-and-Solve、Reflection 的完整实现代码。产品实践来自 AgentGuide 的《上下文工程业界最佳实践精华》和 Claude Code 源码分析。