Anthropic 发布 Claude Sonnet 5.5,从发布页看仍是一轮常规升级:API 单价未变、生成速度更快,Terminal-Bench、CursorBench 等 Agent 基准成绩明显上涨。但把几组运行数据放在一起,变化并不只发生在模型输出层。Lovable 的测试中,Tool Call 数量减少约三分之一、Shell Run 接近减半;Base44 的应用构建任务里,平均迭代次数从 7.7 次降到 3.6 次。Anthropic 还提到,新模型更频繁地把多个工具调用放在同一批执行。
这意味着 Agent 成本不能只看 Token。一次任务真正消耗资源的地方,还包括工具等待、状态回填、重新规划、上下文增长和失败恢复;只要 model—tool 循环足够长,这些成本就会持续叠加。在“模型变聪明了”的背后,工程上对应的是模型具备了静态依赖分析与执行图压缩的能力,使原本笨重的 Agent Runtime 架构得以瘦身。
Agent 与聊天模型的工作方式不同。聊天模型一次请求结束、计算基本结束;Agent 则需要持续维护一个会变化的工作状态,包括用户目标、已验证假设、工具返回、代码改动、环境状态和未解决问题。每完成一次 Tool Call,runtime 都要把新结果合并进当前状态,再让模型重新判断原计划是否仍成立。这里有一层很实际的成本,可称为 state rehydration:模型下一轮不只需要读一段刚返回的测试日志,还要知道为什么运行这项测试、此前动过哪些文件、哪些假设已被排除。随着任务推进,工作状态不断膨胀,每次重新进入 reasoning 都要恢复与当前决策相关的那部分状态。
失败路径会进一步放大问题。假设代码 Agent 一开始判断错误,把问题归到认证中间件,于是搜索相关 symbol、读取文件、修改逻辑、运行测试,最后发现真正原因来自 session serialization。前面的代码、修改记录、测试日志和中间判断已经进入上下文,如果 runtime 只是不断追加历史内容,后面的正确路径仍要在这批残留状态里继续工作。所以长上下文本身并不能解决 Agent 成本问题:上下文窗口变大解决的是历史能不能保存,runtime 更难处理的是哪些内容还应留在当前 working set。稳定的长期 Agent 需要把当前节点直接依赖的信息留在活动区,把已形成稳定结论的内容压缩成结构化状态,而原始日志、重复搜索结果和已失去依赖关系的 observation 应尽快退出工作集。这也解释了为什么一次无效 Tool Call 的代价通常高于它本身——错误搜索不仅浪费一次工具执行,还会制造额外状态。
传统 ReAct 的执行方式是一条严格串行链:模型决定动作、工具执行、结果返回、模型再判断。这种方式默认每个工具之间都存在依赖,即使很多操作本可同时进行。代码排障就是典型场景:搜索异常字符串、读取 package 配置、定位测试文件、检查几个 symbol 的引用关系,很多时候只是读取当前代码状态,彼此没有必须等待的顺序。Batch Tool Call 要求模型在进入工具层之前先做一次局部依赖判断,把可共同执行的动作放到同一批里。真正被压缩的是 synchronization barrier:原来模型每拿到一个结果都要停下来恢复状态并重新规划,现在先确定这一阶段需要哪些信息,中间多个 barrier 可直接消失,工具并行运行后结果再一次性交回模型。
这要求模型具备 partial-order planning,判断哪些动作存在先后关系、哪些只读状态、哪些会改变状态。只读操作容易并行,写操作则必须考虑 read-after-write 和 write-after-write 关系,比如测试必须看到修改后的代码,两个 subagent 同时编辑同一文件还会产生写冲突。因此执行图能不能压缩,关键不是一次发出多少 Tool Call,而是同步点放在哪里。批量执行还有反向问题:fan-out 太大以后会产生很重的 fan-in,一次并发十几个工具虽减少等待,但模型下一轮可能收到大量代码、日志和搜索结果,若原样进入上下文,前面省下的同步成本又会以 observation 膨胀的形式回来。runtime 还需要在工具返回后做 result reduction,合并重复内容、把长日志缩成与当前决策相关的片段、过滤低价值结果。Sonnet 5.5 同时出现更频繁的 batch 和更少的 Tool Call 总量,说明变化不只是并发更多,而是模型在一些任务里更早形成了一组相对完整的信息需求。
当模型开始参与决定执行图怎么展开,effort 的作用也随之变化。在单轮任务里,提高 effort 主要增加模型内部的 test-time compute;进入 Agent 场景后,内部 reasoning 会直接改变外部动作。如果模型在修改代码前多做一轮依赖检查,发现两个 change-set 存在接口顺序关系,后面可能直接避免一次冲突、一次测试失败和一次回滚,这种额外 reasoning 虽增加内部计算,却减少了外部执行。反过来,如果证据已足够而模型仍继续扩展分析,就可能启动更多 code review、subagent 和验证,把额外计算变成更多执行节点。Anthropic 在 FrontierCode 上出现过 Max effort 低于 Xhigh 的情况,一种解释是高 effort 让模型更频繁调用 code-review skill 并拆给多个 subagent,部分分支随后超时或产生超出任务边界的修改。这不是某个 benchmark 的高低,而是 effort 改变了 branch factor。
更合理的 effort 策略应落到节点级,而非整条任务固定一个档位。读取仓库、搜索 symbol 这类低风险步骤可用较轻 reasoning 快速生成查询集合;准备跨文件写入、修改 schema 或执行高副作用动作之前,可增加 reasoning,把计算放在依赖检查和 change-set planning 上;代码写入后尽快进入测试,因为真实环境反馈比继续内部推演更有效,验证失败再根据新 observation 提高 reasoning。这里还需要 checkpoint:如果每次失败都从任务开头重新恢复状态,retry 会把执行链重新拉长;若 runtime 在关键写操作前保存稳定状态,失败后只回退最近一次变更,影响就能局限在较小范围。代码 Agent 可借助独立 worktree、临时分支或沙箱隔离候选修改,让 subagent 在独立环境验证,通过后再合并进主工作区。
到这一层,Agent runtime 已不再只是一个 model—tool 循环,而更像一个动态 controller:维护工作状态、决定同步点、控制 fan-out、为高风险节点分配更多 reasoning、在写操作前保存 checkpoint,再根据验证结果决定继续、回滚还是提交。Sonnet 5.5 这次变化里值得保留的结论或许是:模型能力开始直接影响 Agent runtime 的结构。如果模型能在动作之前更好地判断依赖,runtime 就可减少同步点;如果 observation 能被及时压缩,working set 就不会随任务长度持续膨胀;如果 effort 被放在错误代价更高的节点上,额外的 test-time compute 就有机会换掉后面的失败执行,而不是继续扩大搜索空间。
因此后续衡量 Agent,输入输出 Token 只是底层计量。更有用的指标会是一次任务经历多少 model—tool barrier、batch 中多少结果真正被后续决策使用、失败以后需要回退多远、active working set 在运行过程中增长到什么程度,以及 subagent 产生了多少最终没有提交的分支。这些数据能直接判断一套 Agent 系统的问题出在模型、执行器、状态管理还是 controller 本身。Sonnet 5.5 带来的变化,最终仍落在同一个工程问题上:如何把更多计算放到真正能消除后续执行成本的位置,而不是让 Agent 用更多 reasoning 去制造更大的执行图。