把「下一步做什么」交给模型,要付什么代价?
本课一问:第 2 课说,agent 的路在运行时长出来,所以它修好了 workflow 修不好的 parse_date。那干脆所有任务都用 agent?把「下一步做什么」交给模型,要付什么代价?
这一课先不碰:循环怎么写、什么时候停(A1);token 换成钱、缓存能省多少(A8);「好不好」怎么系统地评测(A9)。
从已有出发
第 2 课的结论:workflow 的边在设计时画好,agent 的边在运行时长出来。T2 的比分也是这样:workflow 2 / 4,agent 3 / 4。
贯穿任务 parse_date 仍在表里,但这一课要看的是另外三个任务:它们让「一律用 agent」的账算得更清楚。
先自己设计:一律用 agent
最省心的策略:既然 agent 能走出 workflow 走不出的路,那所有任务都交给 agent,反正它自己会看着办。
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
数据:本课项目 T2 双轨录制(agent-t2-workflow.json,2026-09-26;Qwen/Qwen3-8B-MLX-4bit,本机 mlx_lm.server;两条轨道同为 seed 1、同一沙箱;workflow 单次调用 max_tokens 8192,agent 每轮 4096、上限 30 轮)。每条轨道每个任务只跑 1 次:只能当例子,不能当比率。token 与轮数可比;耗时受本机同时运行的其他任务影响,只能粗看。本地模型没有账单,成本以 token 计;按价格换算留到 A8。
三笔账,一笔比一笔难躲:
- token 与时间:每多一轮就多一次请求,而每次请求都把此前的全部对话整份重发(A1 第 2 课)。模型调用从 1 次变成 5、6 次,token 就翻几倍。
- 更多的出错机会:每一轮都是一次采样,都可能写满上限被截断、调用被丢弃、改了不该改的地方。word_freq 在 workflow 里一次就过,交给 agent 反而没修好。
- 可预期性:同样的配置、同样的 seed,两次运行可以走出两条路(下面的孪生运行)。你事先说不准它会走几轮、花多少。
所以不是「一律用 agent」,而是先判别这个任务需不需要把下一步交出去。
length 停。再用同样的配置、同样的 seed 重跑:4 个任务里 2 个在第 3 / 8 轮分叉,parse_date 一次过、一次没过。 试三件事:① 在 word_freq 上展开 agent 轨第 3、4、6 轮:都是思考写满上限、这一轮什么也没做;第 5 轮说要调工具却没给出调用;② 切到 leap_year:两条轨道都修好了,看底部那一行的倍数;③ 切到 slugify:agent 修好了,可最后 7 轮全是被截断的思考,一共 28,672 token 没产出任何动作。
改进:先判别,再选轨道
项目在录制之前写下了三条判别标准,录制之后不改(04-实践项目/MILESTONES.md · A0 · M0):
- 修复需要的信息是否全在「报错 + 被测源文件」里?是 → workflow 够。
- 下一步是否取决于运行时才出现的输出(修完一处才暴露下一处、要装的依赖名只在报错里)?是 → 需要 agent。
- 改动范围能否预先确定(文件确定、整文件覆写可行)?能 → workflow 够。
拿它逐个预测,再和 T2 对照:
| 任务 | 录制前的预测 | workflow(token) | agent(轮 · token) | 够用的最简单轨道 | 预测 |
|---|---|---|---|---|---|
parse_date | 需要 agent | ✗ · 3,081 | ✓ · 8 · 21,687 | 需要 agent | 对 |
slugify | workflow 够 | ✗ · 3,727 | ✓ · 13 · 54,301 | 需要 agent | 错 |
word_freq | workflow 够 | ✓ · 4,290 | ✗ · 6 · 22,852 | workflow 够 | 对 |
leap_year | workflow 够 | ✓ · 2,020 | ✓ · 5 · 9,091 | workflow 够 | 对 |
预测对 3 / 4。错的那个 slugify 很有意思:按三条标准它本该 workflow 够(规格写在 docstring 里、只改一个文件),workflow 也确实答对了修法——输掉的是程序自己的写回规则(第 1 课)。所以这次预测错,错在标准没覆盖「workflow 的实现本身有漏洞」,不是任务需要 agent。修好写回规则,再录一次,才能知道标准本身准不准。
两家官方给的判断方向和这三条是一致的。Anthropic:agent 适合说不准要几步、没法写死路径的开放式问题,而且每一步都要能从环境拿到真实反馈(工具结果、代码执行);代价是更高的成本和可能累积的错误,所以要在沙箱里充分测试 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条官方经验描述,调研 3-0 满票核实原文;没有给出对照实验。 出处Anthropic · Building effective agents · When to use agents ↗需联网 。OpenAI:优先考虑需要复杂判断、规则多到难以维护、严重依赖非结构化数据的流程,否则一个确定性的方案可能就够了 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条官方指南的建议,同样是经验性的。 出处OpenAI · A practical guide to building agents(2025-04)p.6 ↗需联网 。编码任务正好有一样别的领域少有的东西:测试,每一轮都能拿到客观的真实反馈——这是编码 agent 能成立的前提,也是第 2 条标准里「运行时的输出」的来源。
还有一条常被引用的建议:先直接调模型 API,很多模式几行代码就能写;用框架就要懂它底下在做什么。这是 Anthropic 那篇文章的原意(原文用的是 suggest),依据是他们与几十个团队合作的经验。它正是这门课「从 0 写 harness」的出发点,但要注意它的证据等级——见下面的误解。
极小真数字:agent 的 token 花在哪
parse_date 的 agent 轨一共 21,687 token,是 workflow 轨(3,081)的 ×7.0。拆开看:
孪生运行:同样的配置、同样的 seed
A1 录过一批运行,其中有 4 次与 T2 的 agent 轨配置逐键相同、seed 都是 1。按道理应该一模一样。实际上:
数据:本课项目 T2 双轨录制(agent-t2-workflow.json,2026-09-26;Qwen/Qwen3-8B-MLX-4bit,本机 mlx_lm.server;两条轨道同为 seed 1、同一沙箱;workflow 单次调用 max_tokens 8192,agent 每轮 4096、上限 30 轮)。每条轨道每个任务只跑 1 次:只能当例子,不能当比率。token 与轮数可比;耗时受本机同时运行的其他任务影响,只能粗看。本地模型没有账单,成本以 token 计;按价格换算留到 A8。
试三件事:① parse_date:前两轮逐条相同(灰),第 3 轮的请求差了 3 个 token——上一轮的测试输出里,traceback 的路径含着工作区目录名,两次运行的目录名不同;之后两条路越走越远,一次通过、一次重复修改同一处而没过;② 切到 slugify:第 8 轮分叉,测试输出除了目录名,还差了 0.000s 与 0.001s,最后一个 13 轮、一个 10 轮;③ 切到 word_freq 与 leap_year:逐条消息完全相同——环境输出一个字节都没差,就能复现。
采样带 seed,可 seed 只固定了「同一份输入 → 同一个随机序列」;环境的输出(路径、耗时、时间戳)只要差一个 token,输入就变了,之后的每一次采样都跟着变。再看同一配置只换 seed 的三次:
数据:本课项目 miniagent 的真实运行(src/data/project/agent-traces.json,2026-09-26 导出;模型 Qwen/Qwen3-8B-MLX-4bit,本机 mlx_lm.server)。token 数取自服务端 usage;思考截取约 600 字、正文与工具输出约 900 字(保留头尾)。耗时受本机同时运行的其他任务影响,只能粗看;token 与轮数才可比。
三次运行 8 / 6 / 7 轮、25,714 / 16,971 / 16,905 token、✗ / ✓ / ✓。workflow 轨的形状则永远是 5 步、1 次模型调用——它的输出内容也是采样出来的,但下一步是什么,事先就知道。
常见误解一:「Anthropic 官方明确反对用框架。」 原文的意思是建议开发者先直接调 API,用框架要懂它底下的代码;依据是与几十个团队合作的经验,没有方法、样本和数据。深度调研对这一条的投票是 2-1,不是满票 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条非满票(2-1)· 官方自报 · 轶事性经验。引用时还要改掉三处常见的走样:原文说的是 implementations 不是 production;「简单可组合的模式」与「几行代码直接调 API」是两句独立的话;原文是 suggest,不是「明确反对」。 出处Anthropic · Building effective agents · When and how to use frameworks ↗需联网 。它可以当作这门课的出发点,不能当作实测结论。另外,这篇文章的页首现在多了一段说明:工具生态自 2024 年 12 月以来已经大变,并指向 Anthropic 2026 年的 Managed Agents 文章——建议本身没被撤回,但文中点名的框架清单不该再当成现状。
常见误解二:「seed 一样,运行就能复现。」 上面的孪生运行:同配置、同 seed,2 / 4 个任务在中途分叉。seed 只管模型这一侧;agent 的输入里有环境的输出,环境一变,整条路就变。要复现一次 agent 运行,靠的是录下来的 trace,不是重跑。
🔍 为什么孪生运行的工作区目录名不同?这算不算项目的 bug?
本课项目给每次运行建一个独立的工作区,目录按 run id 命名(t2-parse_date-agent 与 pd-v2-unlimited-s1)。测试失败时,Python 的 traceback 会打印测试文件的完整路径,于是两次运行的工具输出差了几个 token。导出给课程用的数据把本机路径统一脱敏成 <workspace>,在导出版里两次输出看起来一模一样;分叉点和差异行是生成脚本回到原始 trace 比出来的(只保留 workspaces/ 之后的部分)。这不是 bug,是真实环境本来的样子:路径、耗时、时间戳、随机端口,都会进入模型的上下文。想让两次运行可比,要么固定这些东西(同一个目录名、冻结时间),要么接受「每次都不一样」、用多次运行的统计来说话(A9 的 pass@k)。
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 在「交出决定权」之前先判别:路径可预知的任务不必付 agent 的代价 |
| ② 为什么可能有效? | agent 的每一轮都是一次整份重发的请求、一次可能出错的采样;轮数越多,token 越多、出错机会越多、路径越难预知 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条「每轮整份重发」由 API 无状态直接推出,本页逐轮 prompt_tokens 与服务端一致;「出错机会随轮数增加」是在每轮独立出错的前提下的推论。 出处A1 第 2 课:每一轮都整份重发 ↗ |
| ③ 实验上呢? | workflow 已能解决的任务上 token <b>×5.3</b>(word_freq)与<b>×4.5</b>(leap_year);同配置同 seed 2 / 4 个任务分叉;按三条标准的预测对 3 / 4 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条项目实测:单一本地模型(Qwen3-8B 4bit)、4 个小任务、每条轨道每个任务 1 次。倍数与比例不能外推到别的模型和任务;成本以 token 计,本地模型没有账单。 出处本课项目 T2 录制(实验课) ↗ |
演进地图:你在这里
- 解决了只调一次模型,每一步都写在代码里:可预期、好测、便宜。卡在T2 workflow 轨 2 / 4 通过。parse_date 只改了报错指到的那一行,重跑才露出第二处(
datetime.date(2024, 2, 5) != datetime.date(2024, 3, 5));slugify 的回复只有函数片段,兜底规则把 130 字符的片段当整份文件写回(原文件 365 字符),丢了import re。 - 第一代 加步骤、加分支:五种 workflow 模式 prompt chaining · routing · parallelization · orchestrator-workers · evaluator-optimizer解决了每一类失败补一条预先写好的路径:测试没过就带着新报错再来一次(评估者是测试的退出码)、回复格式不对就拒绝写回。卡在分支要在设计时写出来,可真实路径是在运行时长出来的:T2 agent 轨 4 个任务走出 4 条不同的工具序列;同一配置重跑 4 次 parse_date(seed 1 / 2 / 3 / 1),走出 4 条。
- 解决了边在运行时长出来:T2 agent 轨 3 / 4 通过,包括 workflow 没修好的 parse_date 与 slugify。卡在代价:workflow 已经能解决的任务上 token word_freq ×5.3、leap_year ×4.5,其中 word_freq 的 agent 反而没修好;同配置、同 seed 重跑,2 / 4 个任务在中途分叉。
- 解决了录制前写下三条标准并逐个预测,录制后对照:预测对 3 / 4。卡在预测错的 slugify 不是任务本身需要 agent,而是 workflow 自己的写回规则出了错(回复没有
FILE:标记时的兜底)。每条轨道每个任务只跑 1 次:只能当例子,不能当比率。 - 解决了编排形状固定的部分(并行审查、逐条验证、断点续跑)写进脚本;模型只决定「要不要调这个 workflow、传什么参数」。卡在同一个仓库里两种说法并存:README
:11与:41说 agency 来自训练、不是编排;:239说编排形状固定就写进代码。界线画在哪,没有实验回答。 - 解决了同一个循环,识别出代码工作区后注入编码说明(约 577 token,Qwen3 tokenizer 计)与工作区快照;focus 模式才会收窄工具集与技能索引。卡在判定靠文件标记:本课任务仓单独拷出来(README.md、dateparse.py、test_dateparse.py,没有 .git)在默认 auto 下被判成 general;放在项目目录里原地跑,却因为往上 3 层有个
requirements.txt被判成 coding。姿态在会话开始解析一次,中途不变。
一句话
先停在这里:记住三条判别标准,和「seed 管不住环境」。
再深一层:岔路 通用 agent 和编码 agent 差在哪?——同一个循环,为什么在代码仓库里要换一套说法;或者直接去实验课,先预测再看 4 个任务的双轨结果。
下一个缺口
模型决定下一步的那个循环,到底长什么样? → A1 循环:模型只会吐文字,它怎么改你的文件?什么时候停?
这一章一直把 agent 轨当成一个黑盒:「模型每一轮决定调哪个工具,或者停」。A1 打开它:模型写出的那段调用由谁执行、结果怎么送回去、为什么每轮都要整份重发、「不调工具就停」够不够——slugify 最后那几轮被截断的思考,A1 第 3 课会给它一个名字。
你可能会问
- 「编码任务和别的任务比,到底特别在哪?通用 agent 能直接拿来修 bug 吗?」 见岔路 通用 agent 和编码 agent 差在哪?:同一个循环,换的是守则、工作区快照,以及测试这种现成的反馈。
- 「token 倍数换成钱是多少?」 本课项目用的是本地模型,没有账单;按云端价格换算要用同一份官方价格快照,而且缓存命中的部分单价不同,这是 A8 的内容。
- 「换一个更强的模型,结论会变吗?」 很可能会:更强的模型也许不会被截断、不会漏掉第二处 bug,单次调用就修好的任务会变多,agent 也会少走弯路。Anthropic 在 2026 年的一篇工程文章里就写到,harness 里「模型做不到什么」的假设会随模型变强而过时(见岔路 B1)。判别标准要跟着你用的模型重新验证,这也是为什么项目要求「先写预测、再跑、再对照」。
- 「能不能折中:平时走 workflow,失败了再交给 agent?」 能,这就是光谱上的混合形态。learn-claude-code 的 s16 走的是反方向:agent 在循环里,把固定的编排写成它可以调用的一个工具(岔路 B1)。