1. 从一句经验之谈说起:Agent 编码的规划工作流到底在选什么
第一次听到“小任务直接 one shot,中大型任务先 grill 再考虑 /wayfinder”这个说法,我的反应是:这不就是把我们平时做需求分级的直觉,搬到了 Agent 编码场景里吗。但仔细一琢磨,它其实点出了一个很多人踩过的坑——把 Agent 当成万能执行器,什么任务都丢一句 prompt 让它自己跑,结果小任务浪费了规划开销,大任务又因为缺少前置澄清而跑偏。
所谓 Agent 编码,指的是让具备工具调用能力的智能体去完成代码相关的任务,比如改一个函数、加一个接口、重构一个模块、甚至从零搭一个可运行的小系统。它和我们平时用聊天式对话问代码问题最大的区别在于:Agent 会真的去读写文件、执行命令、跑测试,是一个有副作用的执行体。正因为有副作用,规划工作流的选择就变得格外重要——规划得太轻,Agent 容易在复杂任务里迷路;规划得太重,简单任务反而被一堆流程拖慢。
标题里提到的三个关键词,其实对应了三种不同量级的规划策略。one shot指的是一次性直接下达指令,不做额外的规划环节,让 Agent 一口气完成;grill指的是在动手之前先对需求进行“拷问式”澄清,把模糊点、边界条件、验收标准逼问清楚;/wayfinder则是一种更重的规划工作流,通常表现为先做路径探索、任务分解、里程碑设定,再进入执行。这三者不是互相替代的关系,而是按任务规模分层使用的工具箱。
这篇文章适合谁看?如果你已经在用 Agent 写代码,但总觉得“有时候它很聪明,有时候它像个傻子”,那大概率不是模型的问题,而是你没有根据任务规模选对规划工作流。如果你刚开始接触 Agent 编码,那更应该先建立这套分层意识,避免一上来就用最重或最轻的方式去处理所有任务。接下来我会把这三层策略拆开讲清楚,包括它们各自的适用边界、背后的判断逻辑、具体怎么操作,以及我在实际使用中踩过的坑。
2. 三层规划工作流的核心设计逻辑
2.1 为什么不能只用一种规划方式
很多人对 Agent 编码的期待是“我说一句话,它把活干完”。这个期待在小任务上基本成立,但在中大型任务上几乎必然翻车。原因不复杂:Agent 的上下文窗口、推理步数和工具调用次数都是有限资源,任务越复杂,需要维护的状态越多,一旦中间某一步理解偏了,后面就会沿着错误方向一路狂奔,最后交出一个看似完整但根本跑不通的结果。
反过来,如果所有任务都走最重的规划流程,小任务就会被过度工程化。改一个变量名也要先做需求澄清、路径探索、任务分解,那还不如自己动手改。规划本身是有成本的,这个成本包括时间、token 消耗,以及你和 Agent 之间来回确认的沟通成本。所以核心设计逻辑就一句话:规划开销应该与任务的不确定性和影响范围成正比。
不确定性和影响范围是两个独立的维度。一个任务可能影响范围很小但不确定性很高,比如“把这个函数的性能优化一下”,改动范围就一个函数,但怎么优化、优化到什么程度、能不能改变行为,这些都是不确定的。另一个任务可能不确定性很低但影响范围很大,比如“把所有用到旧版 API 的地方替换成新版”,规则明确,但涉及几十个文件。这两种任务需要的规划策略是不一样的。
2.2 one shot、grill、wayfinder 各自的定位
把这三层策略放到一个坐标系里,可以这样理解:
| 策略 | 规划开销 | 适用任务特征 | 典型场景 |
|---|---|---|---|
| one shot | 极低 | 目标明确、影响范围小、验收标准清晰 | 改配置、加日志、修简单 bug、写单个函数 |
| grill | 中等 | 目标模糊、边界不清、需要澄清验收标准 | 加一个新功能、调整交互逻辑、处理模糊需求 |
| wayfinder | 高 | 跨模块、多步骤、依赖关系复杂、需要探索路径 | 重构核心模块、搭建新子系统、迁移技术栈 |
one shot 的本质是“我信任你对这个任务的理解,直接干”。它的前提是任务本身足够具体,具体到不需要额外解释。比如“把 utils.py 里 format_date 函数的默认时区从 UTC 改成东八区”,这种指令没有歧义,Agent 直接执行就行。
grill 的本质是“我不确定我有没有把需求说清楚,你先问我”。它适合那些你脑子里有大致方向,但细节还没想明白的任务。比如“给用户列表加一个筛选功能”,筛选什么字段、单选还是多选、要不要保存筛选状态、空结果怎么展示,这些你不主动说,Agent 就会自己猜,猜错了返工成本很高。
wayfinder 的本质是“这个任务太复杂,我们先一起探路,把地图画出来再走”。它适合那种你甚至不知道从哪下手的大任务。比如“把这个单体应用拆成微服务”,这不是一个能一次性描述清楚的任务,需要先梳理模块边界、确定拆分顺序、识别共享依赖、制定迁移策略,然后才能进入具体执行。
2.3 判断任务量级的三个实用信号
说了这么多,实际操作时怎么判断一个任务该用哪层策略?我总结了三个信号,基本能覆盖大部分情况。
第一个信号是你能否用一句话把验收标准说清楚。如果能,比如“这个函数返回结果按时间倒序排列”,那大概率是 one shot。如果不能,比如“让这个页面体验更好”,那就需要先 grill。
第二个信号是任务涉及的文件数量和你对代码库的熟悉程度。只涉及一两个你熟悉的文件,one shot 或轻量 grill 就够。涉及多个模块,而且你对其中一些模块的细节记不清了,那就该考虑 wayfinder,因为 Agent 在探索过程中可能会遇到你也没预料到的依赖关系。
第三个信号是做错了之后的回滚成本。改一个注释错了就错了,回滚成本几乎为零。但如果是要改数据库 schema 或者调整对外接口,一旦方向错了,回滚成本很高,这时候多花点时间做前置规划是值得的。
注意:这三个信号不是孤立的,实际判断时要综合看。一个任务可能验收标准很清晰,但涉及文件很多且回滚成本高,那它依然需要 wayfinder 级别的规划。
3. one shot 策略的实操要点与边界
3.1 什么样的任务适合直接 one shot
one shot 不是“随便丢一句话”,而是“用足够精确的指令让 Agent 一次做对”。适合 one shot 的任务通常满足这几个条件:目标单一、上下文自包含、验收标准可自动验证、失败后重试成本低。
举几个我实际用 one shot 处理过的例子。给某个函数加参数校验,输入为空时抛出明确异常;把一段硬编码的配置项抽成常量并统一引用;修复一个已经定位到具体行的空指针问题;给现有函数补单元测试,覆盖几个边界条件。这些任务的共同点是:我知道要改哪里、改成什么样、怎么验证改对了。
one shot 的指令写法很关键。我的经验是遵循“位置 + 动作 + 约束 + 验证”四要素。位置是指明具体文件甚至函数名,动作是描述要做什么改动,约束是说明不能破坏什么,验证是告诉 Agent 怎么确认改对了。比如:
在 src/utils/date.py 的 format_date 函数中,把默认时区参数从 UTC 改为 Asia/Shanghai。 不要修改函数签名,不要影响现有调用方。 改完后运行 pytest tests/test_date.py 确认全部通过。这种指令几乎没有歧义,Agent 执行起来很顺。反过来,如果你只说“改一下日期格式”,Agent 就得猜你是要改默认时区、改输出格式、还是改解析逻辑,猜错的概率很高。
3.2 one shot 的常见翻车场景
one shot 最容易翻车的地方,是任务表面看起来简单,但实际上隐含了多个改动点。比如你说“把这个接口的返回字段改一下”,Agent 可能只改了 controller 层的返回结构,但没改对应的 DTO、没改前端调用的地方、没改测试用例。它觉得自己完成了,你一跑测试发现一堆失败。
还有一种翻车是任务本身简单,但 Agent 顺手做了你没让它做的事。比如你让它修一个 bug,它修完之后觉得代码风格不好,顺手把整个文件格式化了一遍,结果 diff 里全是无关改动,review 起来很痛苦。这种情况的解决办法是在指令里明确加一句“只做必要改动,不要重构无关代码”。
第三个常见问题是 one shot 遇到需要外部信息的情况。比如你让它“把这个函数的超时时间改成配置项”,但配置项该加在哪个配置文件、用什么命名规范,这些信息 Agent 不知道,它就会自己编一个。编得对不对全看运气。所以 one shot 的前提是任务所需的信息都在你的指令里或者代码库里能直接找到。
3.3 提升 one shot 成功率的实操技巧
第一个技巧是先让 Agent 复述任务再执行。你可以在指令末尾加一句“先告诉我你打算怎么改,确认后再动手”。这样你能在它执行前发现理解偏差,避免白跑一轮。这个技巧在任务稍微复杂一点的时候特别有用。
第二个技巧是把验证命令写进指令。不要只说“改完确认没问题”,而是给出具体的验证命令,比如“运行 npm test -- --grep 'user filter'”。Agent 有了明确的验证手段,就不会靠感觉判断自己是否完成。
第三个技巧是控制单次 one shot 的改动范围。我的经验是,单次 one shot 涉及的文件最好不要超过三个,改动行数最好控制在五十行以内。超过这个范围,Agent 出错的概率会明显上升,这时候就该考虑升级到 grill 或 wayfinder。
实操心得:one shot 的成功率和你对代码库的熟悉程度正相关。你越清楚改动的影响面,指令就能写得越精确。如果你自己都不确定改这里会不会影响别的地方,那这个任务就不适合 one shot。
4. grill 策略:把模糊需求逼问清楚再动手
4.1 grill 的本质是需求澄清而非任务分解
grill 这个词用得很形象,它的核心动作是“追问”。当你给出一个模糊需求时,Agent 不应该直接开干,而应该反过来问你一系列问题,把需求中的模糊点逐个消除。这和 wayfinder 的区别在于:grill 不涉及路径探索和任务分解,它只解决“你到底想要什么”的问题。
举个例子,你说“给后台管理页面加一个批量操作功能”。这是一个典型的需要 grill 的需求。Agent 应该追问:批量操作的对象是什么,用户还是订单还是商品?支持哪些操作,删除、导出、还是修改状态?批量选择的交互方式是什么,勾选还是全选?操作前要不要二次确认?操作失败怎么反馈?这些问题不澄清,Agent 只能靠猜,猜出来的结果大概率不是你想要的。
grill 的价值在于把返工成本前置。你在需求阶段多花五分钟回答几个问题,比 Agent 做完之后你发现方向错了再返工要划算得多。尤其是当任务涉及交互设计或者业务规则时,模糊需求带来的返工成本往往是指数级的。
4.2 怎么引导 Agent 做好 grill
grill 不是让 Agent 随便问,而是要有结构地问。我通常会把 grill 分成四个维度:范围、行为、边界、验收。
范围维度问的是“这个需求涉及哪些部分”。比如“这个功能只影响前端还是也要改后端”“要不要考虑移动端适配”“是否需要兼容旧版本数据”。
行为维度问的是“具体怎么表现”。比如“点击按钮后是弹窗还是跳转”“加载中是显示骨架屏还是转圈”“错误提示是 toast 还是内联”。
边界维度问的是“异常情况怎么处理”。比如“没有选中任何项时按钮是否禁用”“网络请求失败是否重试”“并发操作怎么处理”。
验收维度问的是“怎么算做完了”。比如“有没有设计稿可以参考”“要不要写测试”“上线前需要谁确认”。
你可以直接把这四个维度写进 prompt,让 Agent 按这个框架来追问。比如:
我要给后台管理页面加一个批量操作功能。 在动手之前,请从范围、行为、边界、验收四个维度向我提问,把需求澄清清楚。 每个维度至少问两个问题,等我回答后再开始规划实现。这样 Agent 的追问就有章法,不会东问一句西问一句,你回答起来也更有条理。
4.3 grill 阶段的注意事项
第一个注意事项是不要过度 grill。有些任务其实没那么复杂,你问太多问题反而让用户烦。判断标准是:如果一个问题你自己想想就能确定答案,那就不需要问。比如“按钮用什么颜色”,这种问题看现有设计规范就知道了,不需要专门澄清。
第二个注意事项是grill 的结论要落成文字。Agent 问完、你答完之后,最好让它把澄清后的需求整理成一段简短的规格说明,你确认无误后再进入执行。这样做的目的是避免“我以为我说清楚了,它以为它听明白了”这种经典误会。
第三个注意事项是grill 之后不一定直接执行。如果澄清过程中发现任务比预想的大,比如原本以为只是加个按钮,结果发现要改数据模型,那就应该从 grill 升级到 wayfinder,先做路径规划再执行。
常见问题:grill 阶段 Agent 问的问题质量不高怎么办?我的经验是给它一个提问框架(比如上面说的四个维度),比让它自由发挥效果好很多。另外你可以在 prompt 里加一句“不要问代码库里能直接找到答案的问题”,减少无效提问。
5. wayfinder 策略:复杂任务的路径探索与规划
5.1 wayfinder 解决的是什么问题
wayfinder 这个词的字面意思是“寻路者”,它解决的是“不知道路怎么走”的问题。当一个任务复杂到你自己都不确定该从哪下手时,直接让 Agent 执行或者简单 grill 都不够,你需要先和 Agent 一起把路径探出来。
什么样的任务需要 wayfinder?我总结了几类:跨多个模块的重构、从零搭建一个子系统、技术栈迁移、性能优化这种目标明确但手段不明确的任务。这些任务的共同点是:执行路径不唯一,不同路径的成本和风险差异很大,而且一旦走错方向,回头成本很高。
wayfinder 的核心产出是一份执行地图,它应该包含:任务的整体目标、拆解后的子任务列表、子任务之间的依赖关系、每个子任务的验收标准、以及推荐的执行顺序。有了这份地图,后续的执行就可以拆成多个 one shot 或 grill 来完成。
5.2 wayfinder 的实操流程
我的 wayfinder 流程通常分四步:现状梳理、目标确认、路径枚举、路径选择。
现状梳理是让 Agent 先读代码、理解当前架构。这一步不能省,因为很多规划错误都源于对现状的理解偏差。你可以让 Agent 输出一份现状说明,包括涉及的模块、关键文件、数据流向、外部依赖。你 review 这份说明的过程,也是你自己重新理解代码库的过程。
目标确认是把“我想要什么”说清楚。这一步和 grill 有重叠,但 wayfinder 的目标确认更宏观,关注的是最终状态而不是具体行为。比如“把单体拆成微服务”这个目标,需要确认的是拆成几个服务、服务之间怎么通信、数据怎么隔离,而不是某个接口怎么改。
路径枚举是让 Agent 给出多种可能的执行路径,并分析每种路径的优缺点。比如重构一个模块,可以按功能拆、按层拆、按依赖关系拆,每种拆法的风险和工作量都不一样。这一步的价值在于让你看到自己没想到的选项。
路径选择是结合你的约束条件(时间、人力、风险容忍度)选定一条路径,然后把这条路径拆成可执行的子任务。每个子任务应该足够具体,具体到可以用 one shot 或 grill 来完成。
5.3 wayfinder 产出的执行地图长什么样
一份好的执行地图不是简单的任务列表,它应该包含依赖关系和里程碑。我用一个模拟的“用户模块重构”任务来说明。
| 阶段 | 子任务 | 依赖 | 验收标准 | 预估工作量 |
|---|---|---|---|---|
| 1 | 梳理现有用户模块的接口和数据模型 | 无 | 输出接口清单和数据表关系图 | 小 |
| 2 | 设计新模块的接口契约 | 阶段1 | 接口文档通过评审 | 中 |
| 3 | 实现新数据访问层 | 阶段2 | 单元测试覆盖率达标 | 中 |
| 4 | 迁移业务逻辑 | 阶段3 | 新旧逻辑并行跑通 | 大 |
| 5 | 切换调用方 | 阶段4 | 全量回归通过 | 中 |
| 6 | 清理旧代码 | 阶段5 | 无残留引用 | 小 |
有了这张表,你就知道现在该做哪一步、下一步依赖什么、什么时候可以并行。Agent 在执行每个子任务时也有明确的边界,不会跑着跑着就跑到别的阶段去了。
实操心得:wayfinder 阶段最容易被忽略的是“回滚方案”。对于高风险任务,执行地图里应该包含每一步的回滚策略。比如阶段4迁移业务逻辑时,如果新逻辑有问题,怎么快速切回旧逻辑。这个不想清楚,执行起来会提心吊胆。
6. 三层策略的切换时机与组合使用
6.1 任务执行中升级策略的信号
实际工作中,任务量级往往不是一开始就能判断准的。你可能觉得是个小任务,one shot 下去发现 Agent 改了半天没改对,这时候就该考虑升级策略了。我总结几个升级信号。
第一个信号是Agent 连续两次执行结果都不符合预期。第一次可能是理解偏差,第二次还不对,说明任务本身有模糊点没澄清,该从 one shot 升级到 grill。
第二个信号是执行过程中发现改动面比预想的大。比如你让它改一个函数,它说这个函数被二十个地方调用,改签名会影响所有调用方。这时候任务已经从单点改动变成了跨模块改动,该升级到 wayfinder。
第三个信号是你自己对任务的理解在过程中发生了变化。比如原本以为只是加个字段,做着做着发现要改数据模型、要迁移数据、要兼容旧版本。这种认知升级一旦发生,就应该停下来重新规划,而不是硬着头皮往下做。
6.2 降级策略:什么时候可以简化流程
反过来,也不是所有任务都需要严格按三层来。有些任务虽然看起来复杂,但实际上路径很清晰,这时候可以降级处理。比如“把项目里所有 console.log 替换成统一的日志工具”,涉及文件很多,但规则极其明确,每个文件的改法都一样。这种任务可以用 one shot 批量处理,不需要 wayfinder。
降级的判断标准是:任务是否可以被规则化描述。如果可以用“对所有满足条件 X 的地方做 Y 操作”来描述,那即使涉及文件多,也可以走 one shot 或轻量 grill。如果每个文件的改法都不一样,需要分别判断,那就需要 wayfinder。
6.3 组合使用的实际案例
我拿一个模拟的“给现有系统加权限控制”任务来说明三层策略怎么组合。
第一步用 wayfinder 做整体规划。梳理现有系统的接口和角色、确定权限模型(RBAC 还是 ABAC)、规划改造阶段(先加权限校验框架、再逐个接口接入、最后清理绕过校验的旧逻辑)。
第二步对每个阶段用 grill 澄清细节。比如“权限校验框架”这个阶段,需要澄清:权限数据存哪里、校验失败返回什么、超级管理员怎么处理、权限变更是否实时生效。
第三步对每个具体改动用 one shot 执行。比如“给 /api/users 接口加权限校验”,位置明确、动作明确、验收标准明确,直接 one shot。
这个组合的关键是不要跳步。很多人容易犯的错误是 wayfinder 做完就直接开始 one shot,跳过了 grill 阶段,结果每个子任务执行时都要临时澄清细节,效率反而低。正确的做法是每个阶段开始前先把该阶段的细节 grill 清楚,然后批量 one shot。
7. 常见问题与排查技巧实录
7.1 规划工作流选择速查表
| 现象 | 可能原因 | 建议调整 |
|---|---|---|
| one shot 结果总是差一点 | 指令缺少验收标准 | 在指令中补充验证命令 |
| one shot 改动了无关代码 | 没有限制改动范围 | 加“只做必要改动”约束 |
| grill 问了一堆没用的问题 | 缺少提问框架 | 给出范围/行为/边界/验收四维度 |
| grill 后执行还是跑偏 | 澄清结论没落成文字 | 让 Agent 先输出规格说明再执行 |
| wayfinder 规划太粗无法执行 | 子任务粒度不够 | 拆到每个子任务可 one shot 完成 |
| wayfinder 规划太细浪费时间 | 过度分解 | 合并同质化子任务,按阶段规划 |
| 执行中频繁升级策略 | 初始判断不准 | 用三个信号重新评估任务量级 |
7.2 几个容易踩的坑
第一个坑是把 one shot 当成默认策略。因为 one shot 最省事,很多人习惯性地对所有任务都用 one shot,结果在中大型任务上反复失败,还以为是模型能力不行。实际上换个规划策略,同样的模型表现会好很多。
第二个坑是grill 阶段问得太泛。比如 Agent 问“你希望这个功能怎么实现”,这种问题太开放,用户很难回答。好的 grill 问题应该是具体的、有选项的,比如“这个操作需要二次确认吗,还是直接执行”。有选项的问题回答起来快,澄清效率高。
第三个坑是wayfinder 规划完不落地。有些人做完规划觉得“地图都有了,执行肯定没问题”,结果执行时发现地图和实际代码对不上。规划不是一劳永逸的,执行过程中要允许地图修正。我的做法是每完成一个阶段就回顾一下地图,看看后续阶段是否需要调整。
第四个坑是忽略上下文长度限制。wayfinder 阶段如果涉及大量代码阅读,很容易把上下文塞满,导致后续执行时 Agent 记不住前面的规划。解决办法是把规划结论落成文档,执行时只加载相关部分,而不是把整个规划过程都塞进上下文。
7.3 提升整体效率的几个习惯
第一个习惯是任务开始前先花三十秒判断量级。不要拿到任务就开干,先问自己:验收标准清楚吗、涉及几个文件、错了回滚成本高吗。这三个问题回答完,该用哪层策略基本就定了。
第二个习惯是把常用指令模板化。one shot 的四要素指令、grill 的四维度框架、wayfinder 的四步流程,都可以做成模板。用的时候直接套,省去每次重新组织语言的时间。
第三个习惯是记录每次策略选择的实际效果。我会简单记一下:什么任务、用了哪层策略、结果如何、有没有中途升级。记多了之后,你对任务量级的判断会越来越准,策略选择也越来越顺手。
最后分享一个小技巧:如果你不确定一个任务该用哪层策略,可以先按最轻的策略试一下,但给自己设一个止损点。比如 one shot 试两次不成功就升级到 grill,grill 澄清完发现还是复杂就升级到 wayfinder。这样既不会过度规划,也不会在错误方向上死磕。