1. 这道题到底在考什么
“Agent 怎么做规划”——这五个字扔出来,很多人第一反应是背概念:ReAct、Plan-and-Execute、Tree of Thoughts、Reflection,一套组合拳打出去,面试官面无表情,然后你就没有然后了。我前前后后帮几个团队做过 Agent 方向的面试官,也自己作为候选人被问过这道题,说实话,淘汰率高的原因根本不是候选人不知道那些名词,而是绝大多数人把“规划”理解成了一个静态的算法选型问题,而面试官真正想看的是你对“不确定性”的处理能力。
先把这道题的定位说清楚。它表面上问的是 Agent 的 planning 模块怎么设计,实际上考的是三层东西:第一层,你知不知道一个 Agent 在真实任务里,规划不是一次性生成一个完美计划然后照着执行,而是生成、执行、观测、修正这样一个循环;第二层,你能不能讲清楚不同规划粒度和不同规划时机之间的取舍,比如什么时候该先规划再执行,什么时候该边走边看;第三层,也是最容易被忽略的,你有没有踩过真实项目里的坑——计划漂移、上下文爆炸、工具调用失败后的重规划、子任务之间的依赖死锁。
我见过太多候选人上来就说“用 ReAct 就行”,然后面试官追问一句“那如果任务有二十步,ReAct 的上下文撑不住怎么办”,人就卡住了。这不是知识问题,是没有真正把一个 Agent 跑起来过。所以这篇东西我不打算写成教科书,而是按我自己做 Agent 项目的顺序,把规划这件事从设计思路到落地细节到踩坑排查,完整地捋一遍。适合谁看?如果你正在准备 Agent 方向的面试,或者正在自己搭一个能处理多步任务的 Agent,再或者你团队里要评审一个 Agent 方案,这篇应该都能对上号。
核心关键词我先摆在这:任务分解、规划粒度、重规划触发、上下文管理、工具编排、执行反馈闭环。后面所有内容都围绕这几个词展开,不会跑偏。
2. 规划的本质:在不确定中做决策
2.1 为什么“一次性生成完整计划”几乎总是错的
很多人对 Agent 规划的想象是这样的:用户给一个目标,Agent 在脑子里想清楚所有步骤,输出一个 1 到 N 的清单,然后一步步执行,执行完任务就完成了。这个模型在教科书里很漂亮,在真实环境里几乎必然翻车。
原因很简单:Agent 在执行每一步的时候,都会从环境里拿到新的信息,而这些信息在规划的那一刻是不存在的。举个我实际遇到的例子,一个 Agent 要完成“帮我把这份季度数据整理成报告”的任务。如果它一开始就规划“第一步读取文件,第二步清洗数据,第三步生成图表,第四步写结论”,看起来没问题。但真实情况是,它读到文件之后才发现数据里有三列是空的,清洗策略得改;生成图表的时候才发现某个字段是字符串格式,得先转换。这些都不是规划阶段能预知的。
所以正确的心理模型不是“规划然后执行”,而是**“规划一个足够好的起点,然后在执行中持续修正”**。面试的时候如果你能主动说出这一点,并且给出一个具体的修正机制,你就已经超过一大半人了。我通常会把规划分成两个层次来讲:粗粒度的高层规划负责定方向和里程碑,细粒度的即时决策负责每一步具体怎么做。高层规划可以一次性生成,因为它容忍模糊;细粒度决策必须边走边定,因为它依赖实时观测。
2.2 规划粒度:粗了没用,细了爆炸
规划粒度是这道题里最能体现经验的地方。粒度太粗,比如只规划“调研、分析、输出”三步,那这个规划等于没做,因为每一步内部还是黑盒,Agent 执行的时候照样抓瞎。粒度太细,比如把“打开文件”都拆成“定位路径、检查权限、读取字节、解析编码”,那计划本身就比任务还长,而且一旦某一步失败,整个计划全废。
我的经验是,规划粒度应该对齐“可验证的中间产物”。什么意思?就是每一个规划出来的步骤,都应该有一个明确的、可以检查的产出。比如“读取并解析数据文件”是一个好粒度,因为完成后你能验证“数据是否成功加载、行数列数对不对”;而“处理数据”就是一个坏粒度,因为你说不清它什么时候算完成。
在面试里回答粒度问题,我建议给一个具体的判断标准,而不是含糊地说“适中就好”。我常用的标准是三条:这一步能否独立验证结果、这一步失败后能否独立重试、这一步的产出能否被后续步骤直接消费。三条都满足,粒度就合适;有一条不满足,就说明要么该拆,要么该合。
2.3 规划时机:先规划还是边做边规划
这是另一个高频追问点。先规划(Plan-then-Execute)的优点是全局视野好,适合步骤之间依赖强的任务,比如“先注册再登录再操作”,顺序不能乱。边做边规划(Interleaved)的优点是灵活,适合探索性任务,比如“帮我找一份合适的资料”,你根本不知道下一步该干嘛,得看上一步找到什么。
真实项目里我基本都用混合模式:先做一个粗粒度的全局规划,把大阶段和依赖关系定下来,然后在每个阶段内部用边做边规划的方式推进。这样既有全局的方向感,又保留了局部的灵活性。面试的时候如果你能画出这个两层结构,并且说明“全局规划在什么条件下会被触发重写”,这个回答的完整度就很高了。
提示:不要试图在面试里给出一个“万能架构”。面试官更想听到你说“这取决于任务的依赖结构和不确定性程度”,然后给出你的判断依据。给出判断依据比给出结论重要得多。
3. 核心机制拆解:一个能跑的规划系统长什么样
3.1 任务分解的三种策略与选择依据
任务分解是规划的入口。我实际用过的分解策略主要有三种,各有适用场景。
第一种是基于模板的分解。针对高频任务类型,预先定义好分解模板,比如“数据分析类任务 = 加载 + 清洗 + 分析 + 可视化 + 总结”。优点是稳定、快、可控;缺点是只能覆盖已知任务类型,遇到新任务就失效。适合业务场景固定、任务类型收敛的产品。
第二种是基于 LLM 的动态分解。直接让模型根据目标和当前上下文生成子任务列表。优点是灵活,能处理开放任务;缺点是稳定性差,同一个任务两次分解可能不一样,而且容易分解出无法执行的步骤。我通常会给它加约束,比如“每个子任务必须能用一个工具或一次模型调用完成”,用约束来收敛它的发散性。
第三种是基于依赖图的分解。不是生成一个线性列表,而是生成一个有向图,节点是子任务,边是依赖关系。这样没有依赖的任务可以并行,有依赖的必须串行。这个策略在复杂任务里优势明显,但实现成本也高,需要额外维护依赖解析和调度逻辑。
选择依据我总结成一句话:任务类型收敛用模板,任务开放用动态分解,任务步骤多且有并行空间用依赖图。面试时能把这三种讲清楚并给出选择依据,基本就稳了。
3.2 执行反馈闭环:规划不是写完就完事
规划生成之后,真正的功夫在执行环节。一个健壮的 Agent 必须在每一步执行后做三件事:观测结果、判断是否符合预期、决定是否调整计划。
观测结果不是简单地把工具返回值塞进上下文,而是要提取关键信息。比如调用一个搜索工具返回了二十条结果,你不能把二十条全塞进去,得先做一轮筛选和摘要,提取出“哪些结果相关、关键信息是什么”。这一步做不好,上下文很快就会被垃圾信息撑爆。
判断是否符合预期,需要一个明确的判定标准。我的做法是给每个子任务定义一个成功条件,执行后拿实际结果去比对。成功条件可以是结构化的(比如“返回了非空列表”),也可以是模型判断的(比如“这段摘要是否覆盖了目标主题”)。前者快且稳,后者灵活但慢,通常混用。
决定是否调整计划,就是重规划的触发逻辑。这里有个反直觉的经验:不要每一步都重规划。频繁重规划会让 Agent 陷入“想太多”的状态,执行效率极低,而且容易在计划之间反复横跳。我的做法是设置明确的触发条件,只有满足条件才重规划,具体条件下一节展开。
3.3 上下文管理:规划系统里最容易被低估的部分
我可以很负责任地说,Agent 规划做得好不好,一半取决于上下文管理。因为规划、执行、观测的所有信息都要在上下文里流转,上下文一旦失控,再好的规划逻辑也跑不起来。
上下文管理我主要做三件事。第一是分层存储:把信息分成“全局目标”“当前计划”“历史执行记录”“当前观测”四层,不同层用不同的保留策略。全局目标永远保留,当前计划随重规划更新,历史执行记录做滚动摘要,当前观测用完即弃。
第二是主动摘要:当历史记录超过一定长度,不是简单截断,而是让模型做一次摘要,把“做了什么、结果如何、有什么遗留问题”压缩成几行。这样既保留了关键信息,又控制了长度。
第三是关键信息外置:把一些结构化的中间结果(比如解析后的数据表、提取的实体列表)存到外部存储,上下文里只放引用和摘要。这样上下文始终轻量,需要细节的时候再去取。
注意:上下文管理不是“省 token”这么简单,它直接决定了 Agent 能不能处理长任务。我见过太多 Agent 在前五步表现很好,到第十步就开始胡言乱语,根因基本都是上下文被污染了。
4. 实操落地:从零搭一个带规划的 Agent
4.1 整体流程与关键参数
我把一个带规划的 Agent 拆成六个环节,按执行顺序是:目标解析 → 全局规划 → 子任务调度 → 执行与观测 → 结果判定 → 重规划决策。这六个环节构成一个循环,直到全局目标达成或触发终止条件。
关键参数我列一下,这些是我实际调过的,不是拍脑袋来的:
| 参数 | 作用 | 我的常用取值 | 调整依据 |
|---|---|---|---|
| 最大规划步数 | 限制全局计划的长度 | 8 到 12 步 | 任务复杂度,超过 12 步通常说明分解粒度太细 |
| 单步最大重试 | 单个子任务失败后的重试次数 | 2 次 | 工具类任务 2 次够,模型类任务可到 3 次 |
| 重规划触发阈值 | 连续失败多少步后触发重规划 | 2 步 | 太低会频繁重规划,太高会卡死 |
| 上下文保留轮数 | 历史记录保留多少轮后摘要 | 6 轮 | 取决于单轮信息量,信息量大就调低 |
| 全局超时 | 整个任务的时间上限 | 按场景定 | 防止 Agent 无限循环 |
这些参数没有标准答案,但你必须能说出为什么这么设。比如“最大规划步数设 8 到 12”,理由是人的工作记忆容量大概在这个量级,超过之后模型对计划的把控力会明显下降,而且步骤太多意味着每步的粒度太细,容易在细节里迷失。
4.2 全局规划的生成与校验
全局规划我通常用一次模型调用生成,但生成之后必须做校验,不能直接用。校验主要查三件事:步骤是否可执行、依赖是否成环、是否有明确的终止条件。
可执行性校验是看每个步骤能不能对应到一个具体动作,如果出现“优化一下”“处理一下”这种模糊动词,就要求模型重新生成。依赖成环校验是防止出现 A 依赖 B、B 又依赖 A 的死锁。终止条件校验是确保计划有一个明确的“完成”状态,否则 Agent 不知道什么时候停。
这里有个实操技巧:让模型生成计划的同时,为每个步骤输出一个“完成判据”。比如“读取数据”这一步,完成判据是“成功加载且行数大于 0”。这样执行阶段就有明确的判定依据,不用再临时想。这个技巧能显著提升 Agent 的稳定性,我在多个项目里验证过。
4.3 子任务调度的依赖处理
如果用的是依赖图分解,调度就是核心。我的做法是维护一个就绪队列:所有依赖已满足的子任务进入就绪队列,从队列里取任务执行,执行完成后更新依赖状态,把新就绪的任务加入队列。
这里要注意一个坑:并行执行的任务如果有共享资源,会产生冲突。比如两个子任务都要写同一个文件,并行就会出问题。我的处理方式是给资源加锁,或者在规划阶段就识别出共享资源,强制相关任务串行。识别共享资源可以在规划校验阶段做,让模型标注每个步骤涉及哪些资源,有重叠的就串行。
对于大多数场景,我其实建议先串行跑通,再考虑并行。因为并行的收益在步骤数不多的时候并不明显,但带来的复杂度(调度、锁、错误传播)是实打实的。很多团队一上来就追求并行,结果 bug 一堆,得不偿失。
4.4 执行与观测的具体实现
执行环节的核心是工具调用 + 结果解析。工具调用本身不难,难的是结果解析和异常处理。
结果解析我分两步:先做结构化提取,把工具返回的原始内容转成结构化数据;再做相关性筛选,只保留和当前子任务相关的部分。比如搜索工具返回一堆结果,先提取出标题、摘要、链接,再根据当前子任务的目标筛选出最相关的几条。
异常处理我分三类:可重试异常(比如超时、临时失败)、不可重试异常(比如参数错误、权限不足)、未知异常。可重试的直接重试,不可重试的标记该子任务失败并触发重规划,未知异常先记录再按可重试处理,但重试次数减半。这个分类能避免 Agent 在明显不可能成功的操作上浪费时间。
提示:工具调用的返回结果一定要做长度限制。我见过一个 Agent 因为某个工具返回了几万字的原始数据,直接把上下文撑爆,后续所有步骤全部失效。限制单次返回长度,超出部分做摘要或截断,这是必须做的防护。
5. 常见问题与排查技巧实录
5.1 计划漂移:Agent 做着做着就跑偏了
计划漂移是我遇到最多的规划问题。表现是 Agent 执行到中途,做的事情和原始目标越来越远,最后产出一个完全不相关的结果。
根因通常是上下文里原始目标的权重被稀释了。随着执行步骤增多,历史记录越堆越多,原始目标在上下文里的相对占比越来越小,模型就慢慢“忘记”了最初要干嘛。
我的解法有两个。第一是在每次模型调用的 prompt 里,把原始目标放在最前面,并且用明确的标记框起来,比如用分隔符包住,让模型每次都能看到。第二是在重规划时强制回看原始目标,要求模型先复述一遍目标,再决定怎么调整计划。这两个措施配合使用,计划漂移的概率能降很多。
5.2 上下文爆炸:长任务跑到一半就崩
上下文爆炸的表现是 Agent 前期正常,跑到七八步之后开始出现重复、混乱、答非所问。根因就是上下文长度超过了模型的有效处理范围。
排查思路是看上下文增长曲线。如果每一步都在往上下文里塞大量原始数据,那增长就是线性的,很快就会爆。解法就是前面说的分层存储和主动摘要。我特别想强调主动摘要的时机:不要等到快满了才摘要,而是在每完成一个阶段就摘要一次,把阶段内的细节压缩掉,只留结论。这样上下文增长是阶梯式的,可控得多。
5.3 重规划死循环:改了又改,永远改不对
重规划死循环的表现是 Agent 反复重规划,每次改完执行还是失败,然后又重规划,陷入无限循环。
根因通常是重规划没有引入新信息。如果重规划只是让模型“再想想”,而模型拿到的信息和上次一样,那它大概率会生成类似的计划,然后再次失败。
解法是重规划必须携带失败原因。每次重规划前,把“哪个步骤失败了、失败的具体表现是什么、已经尝试过哪些方案”整理清楚,作为重规划的输入。这样模型才能基于新信息做出不同的决策。另外要设置重规划次数上限,超过上限就终止并报告,而不是无限循环。
5.4 常见问题速查表
| 问题表现 | 可能根因 | 排查方向 | 解决手段 |
|---|---|---|---|
| 计划漂移 | 原始目标权重被稀释 | 检查 prompt 里目标的位置和标记 | 目标前置 + 重规划时复述目标 |
| 上下文爆炸 | 原始数据无节制入上下文 | 看上下文增长曲线 | 分层存储 + 阶段摘要 + 结果截断 |
| 重规划死循环 | 重规划无新信息 | 检查重规划输入是否含失败原因 | 携带失败原因 + 设置次数上限 |
| 子任务卡死 | 依赖成环或资源冲突 | 检查依赖图 | 规划校验 + 资源锁 |
| 执行结果无法判定 | 缺少成功条件 | 检查子任务定义 | 规划时输出完成判据 |
| 工具调用频繁失败 | 参数格式或权限问题 | 看工具返回的错误码 | 参数校验 + 异常分类处理 |
5.5 几个我踩过的坑
第一个坑是过度依赖模型的自我判断。早期我让模型自己判断“这一步是否完成”,结果模型经常过于乐观,明明没完成也说完成了。后来改成结构化判据 + 模型判断双重校验,结构化判据先过一遍,过了再让模型判断,稳定性提升明显。
第二个坑是规划粒度一刀切。我一开始对所有任务都用同样的粒度,结果简单任务被拆得太碎,复杂任务又拆得不够。后来改成根据任务复杂度动态调整粒度,简单任务粗粒度,复杂任务细粒度,效果好很多。
第三个坑是忽略工具的超时设置。有一次一个工具调用卡住了,整个 Agent 就挂在那里,因为没设超时。后来所有工具调用都强制加超时,超时就当失败处理,触发重试或重规划。这个坑很基础,但真的很常见。
6. 面试怎么答才能过
回到最初那道题。如果你现在被问“Agent 怎么做规划”,我建议的回答结构是这样的:先讲清楚规划的本质是在不确定中做决策,然后讲两层规划结构(全局粗粒度 + 局部细粒度),再讲执行反馈闭环和重规划触发条件,最后讲上下文管理这个容易被忽略但决定成败的部分。中间穿插一两个你实际踩过的坑,比如计划漂移或者上下文爆炸,面试官会立刻知道你是有实战经验的。
千万不要一上来就背框架名字。框架名字谁都会背,但你能不能讲清楚为什么这么设计、什么情况下会失效、失效了怎么排查,这才是区分候选人的地方。我面过的人里,能把这三点讲清楚的,基本都过了。
最后分享一个我自己的判断标准:如果一个候选人讲规划的时候,全程没有提到“失败”“重试”“修正”这些词,那我基本会认为他没有真正跑过一个长任务的 Agent。因为只要跑过,就一定被失败教育过。规划这件事,说到底不是设计一个完美的计划,而是设计一个能在计划失败时优雅降级、快速恢复的系统。想明白这一点,这道题就不难了。