尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Agent架构设计:Planning与动态任务规划

Agent架构设计:Planning与动态任务规划
📅 发布时间:2026/7/28 0:12:12

Agent架构设计:Planning与动态任务规划

很多 Agent 的问题,不是不会调用工具,而是不知道什么时候该停下来规划。

简单任务中,边思考边执行没有问题。但当任务涉及多个模块、多个步骤时,Agent 很容易陷入一种状态:每一步都合理,最后结果却和最初目标不一致。区别在于:执行能力和规划能力是两个独立的问题。

目录

  • 没有规划的Agent
  • 规划的本质
  • 为什么LLM不会天然规划
  • 两种范式
  • Plan不是任务列表
  • 怎么拆任务
  • 动态调整
  • 实战:核心流程
  • 小结

没有规划的Agent

在 AgentLoop 那篇文章里,我们讲过 Agent 的基本循环:收到用户输入,推理,调工具,拿到结果,再推理,直到任务完成。这个模式在简单任务上表现很好。创建一个文件、查一个信息、改一段代码,Agent 每一步都能看到当前状态,做出合理判断。

但任务一旦变复杂,这个模式就开始暴露问题。

让 Agent “把一个单体项目拆成微服务”。它没有先想清楚要拆几个服务、边界在哪、共享数据怎么处理,而是直接上来就开始动手:先创建了一个目录,然后开始搬代码。搬着搬着发现两个模块之间有循环依赖,于是停下来处理依赖关系。处理完继续搬,又发现数据库表被两个模块共用,不知道该放哪个服务里。它每一步都在做局部最优的决策,但这些局部最优拼在一起,并不等于全局最优。

如果有规划呢?提前查好景点开放时间,按地理位置排好路线,吃饭的地方也标好。同样的时间,能多去两个地方,还不累。

Agent 也是一样。没有规划的 Agent 是 reactive 的,走一步看一步;有规划的 Agent 是 proactive 的,先想清楚再动手。

规划的本质

从工程角度看,Planning 解决的是执行前的信息组织问题:提前明确目标、步骤以及每一步的预期结果。

人类做复杂任务时天然就会规划。搭一个博客系统,脑子里会先过一遍:要有哪些模块?数据库怎么设计?先做什么后做什么?这些思考发生在动手写代码之前,但 LLM 不一样,它不会天然规划。

为什么 LLM 不会天然规划

LLM 本身并不维护任务状态。它看到的是当前上下文,而不是一个结构化的任务模型。在 AgentLoop 里,每一步的决策都是根据当前 messages 预测下一个动作,执行后把结果塞回 messages,进入下一轮。

问题在于两点:

当前上下文 ≠ 完整任务状态。messages 里堆的是历史对话和工具输出,但它不包含"这个任务的最终目标是什么"、“已经完成了哪些子目标”、"还剩什么没做"这类结构化的任务状态信息。LLM 看到的是一堆碎片,它需要从碎片中推断全局,这本身就是一个不稳定的任务。

当前最优动作 ≠ 全局最优路径。每一步 LLM 都在做局部最优决策,但局部最优拼起来不等于全局最优。

所以复杂任务会出现这种典型的局部决策陷阱:

Step1: "创建目录 src/modules/" ↓ Step2: "写代码搬进去" ↓ Step3: 发现目录结构不合理,和另一个模块冲突 ↓ 返工

每一步在当时看都是合理的,但从全局看,Step1 的目录结构就不对。

Planning 是额外引入一个结构化的能力层:

任务状态模型(当前在哪、目标是什么) + 目标分解(大目标拆成小目标) + 执行路线(先做什么、后做什么、每步产出什么)

这三层不是 LLM 天然具备的,需要我们在架构层面主动加进去。在 Agent 开始执行之前,先插入一个"规划阶段",让 LLM 把任务拆解成步骤,生成一个计划,然后按计划逐步执行。

两种范式

目前主流的 Agent 执行范式有两种:ReAct和Plan-and-Execute。

ReAct就是我们之前讲的 AgentLoop 的模式。每一步都是:思考(Reason)→ 行动(Act)→ 观察(Observe)→ 再思考。Agent 永远在根据当前状态做即时反应。

ReAct 循环: 用户输入 │ ▼ 思考:我该做什么? │ ▼ 行动:调用工具 │ ▼ 观察:拿到结果 │ ▼ 思考:下一步该做什么? │ ▼ 行动:调用工具 │ ...

Plan-and-Execute多了一个规划阶段。先让 LLM 生成一个完整的执行计划,然后逐步执行。执行过程中如果发现计划需要调整,再重新规划。

Plan-and-Execute 流程: 用户输入 │ ▼ 规划:生成执行计划 [步骤1, 步骤2, 步骤3, ...] │ ▼ 执行步骤1 → 观察结果 │ ▼ 执行步骤2 → 观察结果 │ ▼ 需要调整吗?→ 是 → 重新规划 │ ▼ 执行步骤3 → ...

两者的区别在决策时机:ReAct 是"边做边想",Plan-and-Execute 是"先想后做"。

维度ReActPlan-and-Execute
决策时机每步即时决策先规划再执行
全局视角弱强
适用场景简单任务、步骤少复杂任务、步骤多且有依赖

但实际生产环境的 Agent 很少纯粹用其中一种。更多是混合模式:

Plan 提供方向,ReAct 提供执行灵活性。目前很多代码 Agent 都采用类似思路:先生成执行方向,再进入工具调用循环,并在必要时重新调整计划。和之前讲的 Agent 错误恢复也是同一个思路——执行过程中出问题了,暂停、调整、继续。

对于大多数简单任务,ReAct 足够了。但当任务步骤超过五六步、且步骤之间有依赖关系时,Planning 的全局视角就能避免很多"局部最优、全局混乱"的问题。Agent 不需要每步都重新想"我该做什么",它只需要看一眼计划,执行当前步骤,然后继续。

Plan不是任务列表

会有初学者理解的 Plan 是这样的:

1. 创建文件 2. 安装依赖 3. 写代码 4. 跑测试

这只是一个 Task List,不是 Plan。Task List 只告诉你"做什么",不告诉你"为什么做"、“做到什么程度”、“怎么验证做对了”。

一个完整的 Plan 应该包含五个要素:

要素含义示例
Goal最终目标搭建一个可运行的 React 项目
State当前状态和目标状态当前:空目录 → 目标:npm run build 通过
Constraints约束条件React 18、TypeScript、feature 目录结构
Steps执行步骤初始化 → 配置 → 实现 → 验证
Validation验证条件npm run build 无报错、ESLint 无警告

为什么这个区分重要?因为在 Agent 执行过程中,最容易出问题的不是"下一步调哪个工具",而是任务目标有没有漂移。

举个例子。Agent 的目标是"搭建一个 React 项目,用 feature 模块划分目录"。执行到第三步时,它发现 Vite 默认模板用的是 pages 结构,于是顺手就按 pages 结构搭了。每一步的代码都没问题,但最终结果偏离了原始需求。

这就是只维护 Task List 不维护 Plan State 的后果。Agent 知道自己在执行第几步,但它不知道"原始目标是什么"、“当前进度和目标之间的差距有多大”。没有 Goal 和 Constraints 做锚点,执行过程中很容易被中间结果带偏。

所以 Planner 输出的不应该只是步骤列表,还应该包含目标描述和约束条件,执行过程中持续对照,防止漂移。

怎么拆任务

规划的核心环节是任务拆解。把一个大任务拆成可执行的步骤列表,这是 Planner 的职责。

最直接的方式:让 LLM 根据用户输入,输出一个步骤列表。

给 LLM 的 prompt 模板:

你是一个任务规划器。根据用户的请求,生成一个执行计划。 每个步骤必须是可独立执行的原子操作。 输出 JSON 格式。 用户请求: {user_request} 可用工具: {tool_descriptions} 输出格式: { "steps": [ {"id": 1, "description": "步骤描述", "tool": "工具名", "params": {...}}, ... ] }

LLM 返回的计划大概长这样:

{"steps":[{"id":1,"description":"初始化 TypeScript 项目","tool":"bash","params":{"command":"npm create vite@latest . -- --template react-ts"}},{"id":2,"description":"安装 ESLint 和 Prettier","tool":"bash","params":{"command":"npm install -D eslint prettier eslint-config-prettier"}},{"id":3,"description":"写入 ESLint 配置","tool":"write_file","params":{"path":".eslintrc.js","content":"..."}},{"id":4,"description":"写入 Prettier 配置","tool":"write_file","params":{"path":".prettierrc","content":"..."}},{"id":5,"description":"按 feature 创建目录结构","tool":"bash","params":{"command":"mkdir -p src/features/auth src/features/dashboard ..."}}]}

这种方式简单直接,适合步骤不多的任务。但有个问题:如果任务本身很复杂,一步"搭建后端"太粗了,需要进一步拆解。

这时候可以递归拆解。先让 LLM 把任务拆成几个大步骤,再把每个大步骤继续拆,直到每一步都是"一个工具调用能完成"的粒度。

defplan_task(task:str,tools:list,depth:int=0,max_depth:int=3)->list:"""递归拆解任务"""ifdepth>=max_depth:return[{"task":task,"subtasks":[]}]# 让 LLM 拆解任务plan_prompt=f"""把以下任务拆成 2-5 个子任务,每个子任务用一句话描述。 任务:{task}输出 JSON: {{"subtasks": ["子任务1", "子任务2", ...]}}"""result=json.loads(llm(plan_prompt))subtasks=[]forstinresult["subtasks"]:# 根据工具能力判断是否需要继续拆ifis_atomic(st,tools):subtasks.append({"task":st,"subtasks":[]})else:subtasks.append({"task":st,"subtasks":plan_task(st,tools,depth+1,max_depth)})returnsubtasksdefis_atomic(task:str,tools:list)->bool:"""判断任务是否可以用单个工具调用完成"""prompt=f"""判断以下任务是否可以用单个工具调用完成。 任务:{task}可用工具及参数:{describe_tools(tools)}判断标准:任务的输入能否完全映射到一个工具的参数,输出是否就是该工具的返回值。 回答 yes 或 no。"""return"yes"inllm(prompt).lower()

递归拆解出来的是一棵任务树,而不是扁平的列表。执行时按深度优先遍历,先处理叶子节点,再向上汇总。

判断"任务是否足够细粒度"不应该完全依赖 LLM。LLM 说"一步就能完成",实际上可能需要三步。更好的做法是结合工具能力来判断——如果一个任务的输入能完全映射到某个工具的参数,输出就是该工具的返回值,那它就是原子的。比如"创建 User.java 文件并添加字段",可以拆成 write_file 一个调用,是原子的;但"搭建用户管理模块"涉及建表、写 Model、写 Service、写 Controller,不是原子的。

不过在实际工程中,递归拆解的 token 消耗比较大,大多数场景下让 LLM 直接输出扁平的步骤列表就够了。只有当任务确实需要多层分解时,才值得用递归方式。

动态调整

计划不是一成不变的。Agent 在执行过程中会遇到各种意外:某个步骤执行失败了,执行结果和预期不一样,或者执行过程中发现了新的信息需要调整后续计划。

所以 Plan-and-Execute 需要一个Replan机制。

但实际系统不会每一步都 Replan。一个 100 步的任务,每步都调一次 Replanner,等于多了一倍的 LLM 调用,成本扛不住。生产环境通常用触发式 Replan:

执行步骤 │ ▼ 是否满足触发条件? │ ┌──┴──┐ 否 是 │ │ ▼ ▼ 继续 Replan 执行 生成新计划

常见的触发条件有三种:

触发条件示例
执行失败write_file 权限不足,bash 命令报错
关键状态变化发现数据库里已有同名表,结构不同
连续偏离计划连续 N 步的实际结果和预期不符
defshould_replan(step:dict,result:str,history:list)->bool:"""判断是否触发 Replan"""# 条件1:执行失败if"error"inresult.lower()or"failed"inresult.lower():returnTrue# 条件2:结果和预期不符ifstep.get("expected")andstep["expected"]notinresult:returnTrue# 条件3:连续 N 步偏离recent_failures=sum(1forhinhistory[-3:]ifh.get("deviated"))ifrecent_failures>=2:returnTruereturnFalse

举个实际场景。Agent 的计划是"创建数据库表 → 写 Model 类 → 写 API 接口"。执行第一步时发现数据库里已经有一个同名的表,结构还不一样。触发条件命中,Agent 暂停执行,把"表已存在"这个信息反馈给 Planner,Planner 生成新计划:先对比已有表结构和需求的差异,再决定是修改表还是修改 Model 类。

如果第一步顺利,第二步也顺利,那就正常往下走,不触发 Replan。只有出问题了才暂停调整。

这就是动态规划和静态规划的区别。静态规划是一次性的,生成完就不管了;动态规划是持续的,按需触发调整。实际项目中几乎都是动态规划,因为现实世界太复杂,不可能一次就把所有情况都考虑到。

实战:核心流程

把上面的概念串起来,Plan-and-Execute 的核心流程用伪代码表示:

# 规划阶段 plan = planner.generate(user_request) # 执行阶段 while plan.has_next(): step = plan.next_step() result = executor.run(step) # 触发式 Replan:执行失败或结果不符预期时才调整 if need_replan(step, result): plan = planner.replan(plan.state, result) plan.mark_done(step, result)

三个组件的职责:

  • Planner:接收用户请求,结合工具定义,生成结构化的执行计划(Goal + Steps + Constraints)
  • Executor:执行单个步骤,调用对应的工具,返回结果
  • Replanner:在触发条件命中时,根据当前状态和执行结果调整剩余计划

整个流程走一遍:

用户: "创建一个 Python 项目,包含 main.py 和 requirements.txt" 计划: 步骤1: write_file → 创建 main.py 步骤2: write_file → 创建 requirements.txt 执行: 创建 main.py → done 执行: 创建 requirements.txt → done 全部完成

如果中间出了问题,比如写文件权限不足,Replanner 会收到失败信息,调整计划。实际项目中,Executor 的工具调用应该通过沙箱执行(参考 Agent 沙箱那篇),而不是直接暴露 shell。

小结

Planning 并不是所有 Agent 都必须增加的一层。对于简单任务,ReAct 已经足够;但当任务包含多个依赖步骤时,引入规划阶段可以降低执行过程中的方向偏移和返工。实际工程中的做法通常是混合模式:Plan 给方向,ReAct 做执行,Replan 兜底。生成计划和 Replan 都有 token 成本,五步以内的任务加规划层反而更慢,规划的价值在复杂任务中才真正体现。

相关新闻

  • 1.30训练
  • TVA数字小脑:具身智能商业化落地的关键支撑(7)
  • 2026 微信小程序开发大赛启动,以“与 AI 共生”为主题面向全球征集作品!

最新新闻

  • 扒开 HTTP/1.1 的底裤:报文结构、状态码与连接管理一次讲透
  • 2026年济南企业搬家连锁店推荐哪家 实用避坑选择指南 - 热点品牌推荐
  • 2026 北京业主常见疑惑汇总:漏水着急入住能不能加急施工,防水施工需要全天留人吗,北京各区上门时效,各类渗漏维修工期长短,轻微小漏水起步收费标准。 - 伶鹿到家
  • 2026年四川木质套装门制造商推荐几家 高适配性厂商选型参考 - 热点品牌推荐
  • 告别网盘限速:netdisk-fast-download让你的下载速度飞起来
  • 服装AI质检的标准边缘包含哪些?

日新闻

  • 力旷智能:伺服驱动系统在制药收瓶设备中的应用解析
  • 2026 网安入门避坑指南,零基础如何避开无效学习直接上手实战
  • 揭秘CFC项目:如何通过手机摄像头实现850kbps无网络文件传输

周新闻

  • 大连理工大学与东京大学联手打造的“主动型AI助手“
  • 170.2026年国家级科研瓶颈:超精密单点金刚石切削(SPDT)光学表面生成
  • SongBloom:革命性歌曲生成框架深度解析——如何通过交织自回归与扩散模型创作完整音乐

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号