多步规划
先规划好还是边走边定?取舍在连贯性与适应性之间,而实用的答案通常是:一份浅计划,随时改。
agent 面对一个多步任务时有两条路:先把整条序列想清楚,或者走到哪一步再定那一步。
两条路都有各自标志性的失败方式,而认出你正看着的是哪一种,就知道该往哪边调。
先规划
生成一份明确的计划,然后照着执行。
1. 查找配置文件
2. 读取它
3. 找到数据库小节
4. 更新连接字符串
5. 校验语法它买到什么。 连贯性——各步骤串成一体、指向同一个目标。可审查,因为人可以在任何东西跑起来之前先过一遍计划。范围有界,因为计划本身就隐含了步数。而且写下来的推理是实打实的计算,所以规划本身还会让每一步更好。
它在哪失败。 计划是在无知的状态下写出来的。第 3 步假设存在一个数据库小节,而它并不存在。这时 agent 要么放弃计划——计划就成了摆设——要么带着计划一路走向失败。死板地照计划执行是一种确实被观察到的失效模式:agent 继续执行三步前就已经不成立的步骤。
边走边定
每一步都从当前状态出发做决定,完全没有计划。这就是朴素的 agent 循环。
它买到什么。 完全的适应性。每个决定都用上了至今学到的一切,意外情况也能自然处理,因为事先没有做任何承诺。
它在哪失败。 漂移。没有持续存在的目标,长时间的运行就会游荡——去追一个有意思的岔路,把原本的目标丢了。每个局部决定看上去都合理,轨迹却哪儿也没去。它也容易陷入重复,一遍遍重试某个失败做法的变体,完全不记得这条路已经试过了。
真正管用的做法
有效的中间路线:一份浅计划,边学边改。
规划三到五步,而不是十五步。执行。一旦结果和某个假设矛盾,就重新规划。
具体做法二选一:给 agent 一个明确的 update_plan 工具,或者按固定节奏重新规划——每隔几步,重述目标、已经学到什么、还剩什么。计划于是变成一份工作假设,而不是一份合同。
有两个配套做法和这个结构本身一样重要:
把目标顶在它眼前。 每一轮都重述目标,而不只是写在 system prompt 里。漂移在很大程度上就是目标被越堆越多的记录埋掉了。
记录试过什么。 一份明确的「试过哪些做法、结果如何」清单,能挡掉最常见的无效迭代。它也是防重复循环最便宜的防线。
任务分解
对于真正庞大的任务,「给步骤排序」这个框架本身就是错的。要拆成拥有各自上下文的子任务。
每个子任务拿到一份全新、简短的记录,返回一个紧凑的结果。这直接打击了单个长循环的上下文平方级增长,也意味着某个子任务失败不会污染其他子任务。
代价是协调——子任务之间没有彼此的上下文,所以切边界时必须切到它们不需要对方上下文。这一点成立时,分解是唯一能扩展到长时间工作的做法。
为什么长程任务依然难
两条算术事实框住了能做到的上限。
可靠性是往下连乘的。 每步 95%,十步下来约 60%,二十步只有 36%。规划改变不了这个指数。
上下文是平方级增长的。 每一轮都要重发全部内容,所以二十步的一次运行,成本远不止十步运行的两倍。
两者指向同一个方向:更少、更可靠的步骤胜过更多步骤。检查点之所以重要,也是同一个道理——第 8 步失败不该把第 1 到第 7 步都丢掉。
实际形态
对大多数工作:浅计划、每轮重述的明确目标、一份试过什么的清单、假设破裂时重新规划、检查点,以及一个硬性的迭代上限。
一到三步的任务就完全别规划——只会白白增加 token 和延迟。
如果序列事先已知,就别用 agent。直接写工作流。规划这套机制存在的意义,是应付那些路径确实无法事先知道的场合。
要点回顾
- 先规划带来连贯性和可审查性,失败方式是照着已经不适用的计划往下走
- 边走边定适应性最强,失败方式是漂移和重复
- 实用答案:一份浅计划,反复修改——再加上每轮重述目标、记录试过什么
- 把大任务拆成上下文独立的子任务;这是唯一能扩展的做法
- 可靠性往下连乘,上下文平方增长——两者都偏好更少但更好的步骤
下一篇: Agent 如何失效