Kaelem

AI Agent 知道什么时候该少想一点吗?

·23 min read
AI AgentLLM EngineeringTool UseReasoningarXiv

一个网站首页有两个邮箱图标。第一个已经用本地的 gmail-icon.svg 渲染,第二个还在用 Font Awesome 的 fa-brands fa-google。用户的要求只有一句话:把第二个图标换成第一个的写法。

如果这是人类工程师在改,大概率会先搜一下那段类名,定位到文件,复制相邻 markup,保存。整个任务的本质是一次关键词定位加两行替换。

但很多 agent 会把它做成一次小型代码库审计。它会重新浏览目录,重新读 icon 依赖,重新推断项目结构,重新确认构建方式。最后改对了,可是路径明显过重:为一个局部替换支付了像架构迁移一样的上下文成本。

这篇论文最有意思的地方,不是又提出了一个“更强 agent 框架”。它问的是一个更基础、也更容易被忽略的问题:一个 AI agent 是否知道任务什么时候很简单?

简单任务不该被当成小型审计

先不要急着让 agent 更会推理

我们平时讨论 agent,经常默认“更多推理”是好事。更长的 chain-of-thought,更大的上下文窗口,更多工具调用,更谨慎的测试,更完整的检索。对于真正困难的任务,这些确实有价值。

问题是,工程任务不是每次都困难。

一个成熟工程师的能力,不只体现在能处理复杂重构,也体现在能快速看出“这只是一个局部替换”。他不会为了改一个 CSS 类名先读完整个代码库;也不会为了改文案先跑全量集成测试。这里的能力不是偷懒,而是判断:这个任务需要哪些信息,不需要哪些信息,最短可靠路径是什么。

论文把这个判断叫作 task-aware execution-scope estimation:先估计任务的执行范围,再决定要读多少、查多少、验证到什么程度。它不是问“模型该思考多少 token”,也不是问“该路由到哪个模型”,而是问:在行动之前,agent 应该理解多大一块世界?

这个转向很关键。

路由方法通常在固定菜单里选:用便宜模型还是贵模型,用浅推理还是深推理。E3 关心的变量更结构化:需要碰几个文件?要不要追依赖?要不要运行重测试?哪些已经见过的信息和当前修改无关?如果估错了,能不能在验证失败后补救,而不是一开始就把所有上下文都吞进来?

这就是论文的核心直觉:真正的效率不是“少做”,而是“先判断该做多少”。

什么叫任务本来应该花的最少努力

为了讨论“浪费”,我们需要一个参照物。否则说 agent 过度读取,很容易变成主观抱怨。

论文先定义了一个东西:minimum-sufficient execution。我们可以把它想成一条最便宜、但仍然可靠通过验收的轨迹。一个任务有自然语言请求、有环境(这里主要是代码仓库)、有验收检查。agent 的轨迹就是一串动作:列目录、搜索、读文件、追依赖、编辑、验证。每个动作都要付成本。

论文把成本拆成四个轴:延迟、token、工具调用、被完整拉入上下文的文件数。默认成本函数是

C = α × latency + β × tokens + γ × tool_calls + δ × inspected_files

其中“完整读入无关文件”被视为冗余的典型单位,所以文件权重较高。这个权重不是为了美化结果,后面论文专门做了 4000 组随机权重敏感性测试。

有了最小充分轨迹的成本 Cmin,浪费就可以被量化。论文定义的 ACRR(Agent Cognitive Redundancy Ratio)就是:

ACRR = (Cact - Cmin) / Cmin

如果 ACRR 等于 0,说明轨迹刚好贴近 oracle;如果 ACRR 等于 4,说明 agent 花了 5 倍必要成本,也就是 400% 冗余。注意,ACRR 只对成功运行计算。一个很便宜但失败的 agent,不会被奖励为“高效”。

这个定义朴素,但有用。它把“我感觉 agent 想太多了”变成了一个可比较的量:相对于这个任务本来需要的努力,它多花了多少。

E3 的机制:乐观开始,但不要鲁莽

E3 的名字很直白:Estimate, Execute, Expand。

第一步,Estimate。agent 不先读完整个仓库,而是用请求文本、便宜的环境探针和过去经验形成一个初始操作点 x0。这个 x0 不是答案,而是一组关于任务状态的估计:难度、范围、风险、置信度。比如“replace ... in index.html”加上明确文件名,很可能是单文件任务;“across the codebase”“every call site”“re-export”这类词,则暗示仓库级变更;如果文本线索不够,它可以做一次便宜搜索,看相关 token 出现在哪些地方。

第二步,Execute。根据估计出来的范围,agent 走最小可行路径。Level 1 就定位、编辑、局部验证;Level 2 复用搜索命中,改直接出现的多个位置;Level 3 才追 import,找 grep 看不到的间接站点,并运行更重的测试。

第三步,Expand。如果验证失败,E3 不会从头开始,也不会直接跳到“读全部”。它把范围扩大一级,复用已经找到的搜索命中,再重新执行。换句话说,E3 允许估计器便宜、乐观,甚至不完美;安全性来自后面的验证和渐进扩张。

E3:先估计,再行动,只在失败时扩张

这里有一个很微妙的设计取舍。

如果估计器必须一次判断完美,它就会变贵,最后又退回“先读很多再说”。如果估计器太鲁莽,简单任务省了,复杂任务会错。E3 的答案是把“估计”和“可恢复”绑定在一起:先做一个低成本的初始判断;一旦证据表明任务比想象中难,就扩张范围。它不是盲目少做,而是让成本增长必须有证据触发。

这也是它和普通 routing 的差别。routing 的错误通常是一次性错误:选错模型、选错推理深度,就把任务交出去了。E3 的估计则被设计成可修正的初始操作点,验证失败本身就是扩张信号。

MSE-Bench:为什么论文需要一个受控模拟器

论文没有直接拿一个商业 agent 跑 SWE-bench,然后报告省了多少 token。它先构造了一个受控 benchmark:MSE-Bench。

这个选择容易被误解。受控模拟器看起来“不真实”,但它解决了一个现实实验很难解决的问题:如果两个 agent 表现不同,我们到底是在测轨迹形状,还是在测模型采样运气?一个模型可能因为没读到文件失败,也可能因为读到了但写错补丁失败。后者是能力问题,前者才是执行范围问题。

MSE-Bench 把能力固定住。只要策略观察到了相关内容,它就能编辑成功;区别只在于它选择观察多少上下文。这样,论文就能精确构造每个任务的 oracle 最小轨迹,并把冗余归因到“看了不该看的东西”。

MSE-Bench 一共有 121 个任务,分三层:

  • Level 1:41 个本地单文件任务,oracle 动作是 locate, edit, verify。
  • Level 2:40 个跨文件任务,两个直接位置需要修改。
  • Level 3:40 个仓库级任务,两个直接位置加一个通过 alias 或 re-export 才能发现的间接位置,需要 dependency trace;其中 18 个是 deceptive tasks,表面措辞像局部修改,实际隐藏了间接依赖。

这个设计不是在声称覆盖所有真实软件工程任务。论文很明确:它是 controlled probe,用来隔离 execution redundancy。也正因为如此,它能回答一个很窄但重要的问题:如果编辑能力相同,哪种执行轨迹用更少上下文达到同样成功?

数字真正说明了什么

主结果很清楚。

Max-Context-First,也就是最大上下文优先策略,100% 成功,但平均成本是 122.85,平均读 4421 tokens、检查 8.46 个文件,ACRR 是 12.90。它像一个总是先审计全仓库的 agent。

Fixed ReAct 成本低得多,平均成本 17.16,但成功率只有 66.9%。它的问题也很典型:固定 search → read hits → edit → test 的轨迹永远不会追到 Level 3 的间接位置,所以所有 Level 3 都失败。便宜,但不可靠。

更强的对手是 Adaptive Retrieval。它会根据检索结果调整努力,遇到跨文件足迹会追 imports,因此 100% 成功。它的平均成本是 22.08,ACRR 是 1.21。这个 baseline 很重要,因为它不是稻草人;它已经比最大上下文策略精明很多。

E3 同样 100% 成功,平均成本 18.55,ACRR 0.55。相对 Max-Context-First,它把标量成本降低 84.9%,token 降低 90.9%,工具调用降低 52.3%,检查文件数降低 92.2%。相对更难打的 Adaptive Retrieval,它仍然在同等成功率下把标量成本降低 16.0%,检查文件数降低 66.8%。

这些数字的意义不是“E3 永远比任何 agent 省 85%”。更准确地说,在这个能力受控的轨迹实验里,最大浪费来自不区分任务复杂度的固定过度上下文;E3 用一个可恢复的初始范围判断,把这部分浪费切掉了。

冗余在最简单任务上最刺眼

最有教学价值的是按任务层级看的 ACRR。Max-Context-First 的冗余在 Level 1 最高:22.06;Level 2 是 11.00;Level 3 是 5.42。也就是说,任务越简单,固定“读全部”的相对浪费越夸张。

论文也很诚实地解释了这里的机械性:Max-Context-First 的实际成本几乎固定,而 Cmin 会随任务变难而变大,所以比值自然在简单任务上最大。这不是一个神秘 scaling law。但工程后果仍然真实:最不需要上下文的任务,反而最容易被固定开销淹没。

E3 的 ACRR 在三层上分别是 0.64、0.26、0.73,低且相对平。Adaptive Retrieval 在 Level 3 上甚至比 E3 更省(0.42 对 0.73),因为 E3 对 deceptive Level-3 会先低估,再支付一次扩张成本。这个细节很重要:E3 的优势主要在 Level 1 和 Level 2,分别比 Adaptive Retrieval 便宜 45% 和 43%;在真正困难的任务上,一个彻底的自适应检索策略是有竞争力的。

这不是缺点,反而说明结果形状和论文主张一致:E3 不是为了让硬任务也少做,而是为了别把简单任务做重。

消融实验说明:估计省成本,扩张保成功

如果去掉 Expand,会发生什么?成功率从 100% 掉到 85.1%,因为 18 个 deceptive Level-3 全部丢掉。成本确实更低,平均 14.88,但这是便宜失败,不是效率。

如果去掉 Estimate,会发生什么?成功率仍然 100%,但平均成本升到 22.21,Level-3 成本从 34.59 升到 47.01。因为 agent 总是从最小路径开始,然后在所有非平凡任务上付扩张代价。

这组消融把 E3 的两条腿拆开了:Estimate 负责少花钱,Expand 负责不掉成功率。单独任何一条都不够。只有“乐观估计 + 验证失败后扩张”组合起来,才让 agent 同时接近可靠性边界和成本边界。

论文还专门攻击了一个可能的质疑:估计器是不是靠模板关键词作弊?他们构造了 held-out instruction wording,把所有任务改写成和估计器关键词列表不重合的说法,还移除了“文件名 + 引号 literal”的快路径。估计器 exact-level accuracy 从 85.1% 掉到 66.9%,under-scope 比例从 14.9% 翻倍到 33.1%。

但 E3 成功率仍然是 100%,平均成本只从 18.55 升到 20.17,增加 8.7%,仍然比 Max-Context-First 低约 84%,比 Adaptive Retrieval 低约 9%。这说明 headline 不是关键词匹配的幻术,而是 Estimate–Expand 架构的效果:估计差一点会多扩张,但验证循环能把它拉回来。

成本权重也类似。论文随机采样 4000 组权重,甚至允许 token 或文件轴权重为 0。E3 在 99.8% 权重下仍是最便宜的 100% 成功策略;即使完全去掉文件惩罚 δ=0,它相对 Adaptive Retrieval 仍在 96.7% 抽样中更便宜。

真实 LLM-Case:边界比 headline 更重要

到这里,最该警惕的地方来了。

论文主实验没有调用语言模型。MSE-Bench 的数字是“策略在成本模型里的性质”,不是某个生产 agent 的线上测量。作者没有回避这一点,而是补了一个 LLM-Case harness:用真实 gpt-4o、真实工具调用、真实 vendored toml 0.10.2 代码、真实 pytest 验收,测同一类问题。

LLM-Case 只有 5 个任务,每个策略每个任务 3 次运行,所以它是 case study,不是 powered benchmark。这个边界必须说清楚。

结果也更温和。

在真实模型里,即便是“read everything first”的 thorough prompt,也没有像模拟器里的 MCF 那样真的读八九个文件;gpt-4o 本身已经相当节制,平均只检查 1 到 4 个文件。E3 仍然是整体最省 token、最快的策略:平均 80,503 tokens,ReAct 是 83,878,thorough 是 98,611;平均延迟 E3 是 157.6 秒,ReAct 165.9 秒,thorough 192.3 秒。相对 thorough,E3 少 18% token、快 18%;相对 ReAct,少 4% token、快 5%。

但它不是每一行都赢。两个 Level-1 小任务上三种策略差距很小,大约 4.5k 到 5.4k tokens;E3 的估计步骤基本成本中性。L2_commentdecoder 上 E3 明显更省,76k tokens 对 thorough 的 100k、ReAct 的 116k;但 L2_arrayseparator 上 E3 反而最贵。Level-3 deceptive 任务对所有策略都贵,可靠性还受限于 provider rate limit:thorough 三次都没成功,ReAct 三次成功,E3 的非限流运行成功,另一次遇到 HTTP 429。

论文证明的是轨迹形状,不是某个模型魔法

所以这篇论文最负责任的读法是:受控实验给出了清晰机制和强数字;真实模型实验说明这个现象没有消失,但效果更小、更不均匀,而且会受到模型本身节制程度、任务类型、限流和工具环境影响。

这不是削弱论文,而是让结论更可信。它没有把 85% 的模拟器数字直接包装成“真实 agent 立刻省 85%”。它说的是:如果我们把 agent 的执行范围判断当成一等公民,轨迹会更接近任务本来需要的最小充分路径;在真实模型上,这种好处表现为更温和的省 token、省时间,以及少把自己读到限流或步数预算失败里。

这篇论文真正给 agent 工程的启发

我觉得它最值得记住的不是 E3 这个具体名字,而是一个工程原则:agent 的第一步不应该总是“收集更多上下文”,而应该是“估计这个任务需要什么上下文”。

今天很多 agent 系统的默认防御姿态是最大化谨慎:多读一点总没错,多验证一点总没错,多思考一点总没错。短期看,这会减少某些漏改;长期看,它会把系统带到另一个失败模式:小任务变慢,token 账单上升,工具调用增加,长轨迹更容易撞限流、超时和上下文污染。

E3 提醒我们,谨慎不等于一开始就读全部。更好的谨慎,是把风险判断前置,把扩张和证据绑定。

对于实际 agent 设计,这可能落成几条很具体的规则:

第一,把任务范围估计显式化。不要只让模型“开始解决”,而是让它先输出需要碰的文件范围、验证强度、风险等级和置信度。

第二,让最小路径成为默认。单文件明确替换就走 locate → edit → local verify;只有当搜索结果、验证失败或低置信度提示更大范围时,再升级。

第三,扩张要复用已有证据。不要失败后从头读仓库;应该保留搜索命中、已读片段、失败检查输出,按范围一级一级扩大。

第四,用 oracle 或近似 oracle 度量冗余。哪怕真实任务没有精确 Cmin,也可以为常见维护任务建立 gold path,监控“多读文件数”“重复读取 token”“无关工具调用”等指标。否则我们只会盯着成功率,看不到成功背后的认知浪费。

论文最后借了一个电力系统里的 Newton–Raphson 类比:好的初始操作点不是答案,但它让迭代短而稳定;差的初始点会让求解器绕远,甚至发散。对 agent 也是一样。一个好的 scope estimate 不需要一次命中所有细节,它只需要把系统放进一个可验证、可修正、成本合理的区域。

这也许是下一代 agent 从“会用工具”走向“会工作”的一个小分水岭。

会用工具的 agent,能读文件、搜代码、跑测试。

会工作的 agent,还要知道什么时候不该读那么多。