小岛AIAI 航行日志

小岛 / 岛刊社 / 文章

给 Agent 临时加工具,缓存不用从头算了

小岛AI

Claude API 新增 tool_addition beta,长会话里临时加工具、改 schema 或升级服务时,不必重写顶部工具清单。它解决的是缓存重算,不是工具治理本身。

Agent 工程模型与发布

一个 Agent 已经跑了很久,代码库读了一半,系统提示词和一串 MCP 工具,也就是接到外部服务的一组标准接口,都吃进去了。它准备去查一个外部服务,才发现少一个接口。

这时最顺手的动作,通常就是往请求顶部的 tools 数组再塞一段 schema,也就是工具能收什么参数的说明。

看着像加一行配置,账单却可能突然长出一截。

Claude 的官方文档把原因写得很直白。提示词缓存不是把整段对话一锅端地存起来,它有层级,工具定义在最前面,后面才是 system 和 messages。你改了工具定义,后面几层都得重新算。长任务跑到一半再接个工具,前面积累的可复用前缀就容易白攒。

好家伙,Agent 最擅长的事明明是边干活边发现自己还缺把扳手,运行时却要求你先把工具箱封死。

Claude Platform 在 9 月 22 日补了一个 beta 能力,tool_addition 可以放进对话中途的 system message。它允许把完整工具定义直接追加到会话里,新增工具、更新 schema,或者把服务器工具换到新版本时,不必去改顶部 tools 数组。官方的说法很克制,只是说明这样不会让已有的 prompt cache 失效。

这事儿不花哨,但对长任务 Agent 挺要命。

因为它把一个原来只能开新会话或重算的动作,变成了会话内的能力变更。模型还在同一条上下文里,常驻工具、系统约束和已经走过的对话不必重新搬家。对每次都要带着仓库说明、业务规则、权限边界跑很多轮的 Agent 来说,少一次缓存重建,不只是省 token,也少了等待。

工具模块插入长会话管线

工具在需要时插入,前面积累的上下文不必回到起点。

官方发布说明在这里,Claude Platform release notes。这项能力要带 inline-tools-2026-09-15 beta header,目前是 beta,别把它当成已经稳如地基的默认写法。

那张隐形账单,藏在工具清单前面

很多人做 Agent 时,脑子里先浮出来的是模型单价。输入多少钱,输出多少钱,缓存读取打几折,算盘打得噼里啪啦。

可长会话真正难受的地方,常常不是模型自己多说了几百个 token,而是你把前缀弄变了。

一个典型的请求里,工具描述可能有几十段。MCP server 一多,每个 schema、说明、参数枚举和权限提示都像行李一样堆在开头。模型还没开始写代码,先得把这只工具箱读一遍。

缓存命中时,这部分会便宜很多。工具定义一改,缓存从变更点开始断掉。官方的缓存说明甚至把规则列成了表,修改 tool definitions 会让 tools、system、messages 三层都失效。它还提醒,切换 web search 或 citations、改 tool_choice、改 thinking 配置、改变图像输入与否,也会碰到不同层级的 cache miss。

这就解释了一个很常见的错觉。你以为只是给 Agent 加了一个查库存、查工单或者读内部文档的能力,实际却让它下一个回合重新读完了整套说明书。

厉害了,工具多到最后,工具本身开始反过来决定成本和延迟。

这不是说工具要越少越好。少到模型没有手,也干不了活。问题在于,哪些工具必须从第一轮就放在桌上,哪些工具应该等任务真的走到那儿再递过去。

官方原本给过一条路,使用 defer_loading 配合 tool search。常驻工具留在可缓存前缀里,按需工具在模型发现后以 tool_reference 的形式追加进对话历史,原有前缀不动,缓存还能接着用。它适合工具很多、模型也能正确找到工具的场景。

tool_addition 解决的是另一类情况。不是让模型自己去找,而是你的运行时已经知道,下一步必须接上一个新工具或新版 schema。比如某个外部服务在任务进行中完成了授权,或者同一服务要从旧接口迁到新接口。以前你得重写工具数组,现在可以把变更作为会话中的 system 消息追加进去。

两条路别混。

defer_loading 像把不常用的扳手收进抽屉,模型需要时自己翻。tool_addition 像编排器看见工序到了,直接把扳手递过去。前者考验发现能力,后者考验你的运行时判断。

新能力加在哪儿,不能只看能不能跑

官方给出的结构很小。中途的 system message 里放一个 tool_addition 块,块里携带完整定义。下面是按官方字段整理过的最小形状,只展示结构,不替代你自己的 SDK 类型检查。

{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": {
          "name": "lookup_inventory",
          "description": "读取已授权仓库的库存状态",
          "input_schema": {
            "type": "object",
            "properties": {
              "sku": {"type": "string"}
            },
            "required": ["sku"]
          }
        }
      }
    }
  ]
}

请求还要启用对应 beta header。官方也支持按引用添加或移除工具。如果你接的是 MCP connector,配合 mcp-client-2026-09-15,工具定义可以是 MCP toolset。响应里会返回 mcp_tool_listing,把它原样回传,列表才被固定住。

这里有个很工程师的细节,别跳过。tool_addition 和 tool_removal 不能紧挨在一个暂停的 assistant 回合后面。比如该回合已经发出了 server tool result,但还没恢复完,这时先把它恢复,再在下一个 system message 里改工具。把顺序搞反,缓存问题还没轮到你,协议状态先给你一个 400。

还有一个坑,缓存没失效不等于整个 Agent 就安全了。工具的 schema、权限范围和服务版本本来就是行为的一部分。你把读取工具换成能写入的工具,或者把一个宽权限 MCP server 塞进正在处理用户内容的会话,成本没涨,风险照样会涨。

所以动态加工具最好由自己的编排层决定,不要让外部网页、用户输入或模型随口一句话直接改变可调用能力。工具定义也该有版本号、最小权限和回滚路径。听起来有点土,但总比半夜看着 Agent 拿错扳手强。

受控追加工具的版本与回滚

动态加工具要留痕、最小授权,也要留一条回滚的路。

到底要不要现在接

我的判断是,可以试,但不要因为看见 cache preservation 就把所有工具治理都改成运行时拼装。

如果你的 Agent 工具很少,几轮对话就结束,或者每个任务本来就开新会话,这个 beta 带来的收益有限。固定 tools 数组反而更直观,排障也更省心。

如果你有长任务、MCP 多、系统提示词重,又经常在任务中途拿到新凭据、切换服务版本或补上专用工具,这个能力值得做一个小范围接入。重点不是看模型能不能调通,而是把它放进真实的运行轨迹里量。

可以先盯三件事。缓存读取 token 占比有没有上去,首个有效输出和完整任务耗时有没有下来,工具变更后的失败率有没有变高。再补一项,出现错误时能不能看清当时到底加载了哪一版工具定义。

这四件事里,收尾那一项往往最容易被忘掉。等任务跑到第几十轮,出现一次参数不匹配,你总不能靠祈祷从日志里猜出工具箱是什么时候被换掉的。

更稳妥的接法,是先挑一类很窄的能力做试点。比如只在完成授权后追加一个只读查询工具,或者只把已经稳定的工具切到一个兼容的新版本。触发条件由编排层写死,工具的名字、schema 摘要和版本号一起记进事件日志。任务完成后,还能把同一段对话和同一版工具定义重放一遍。

这听起来像是在给一个 beta 功能加很多护栏。没办法,动态能力天然会把问题往后推。顶部工具数组固定时,配置错了,启动就能看见。工具在第十几轮才出现时,问题可能躲到用户追问、服务升级和重试叠在一起的那一分钟。到那时再翻一长串 conversation log,真挺折磨人。

还有个边界别被缓存这两个字带跑偏。缓存保住的,是前缀复用,不是模型对新工具的理解,也不是新工具的可用性。新增的 schema 写得含糊,模型还是会传错参数。服务端换了返回格式,旧的任务计划还是会撞墙。把工具加得更快,不会自动把工具说明写得更好。

所以接入前可以问自己一句,这个工具是任务真的走到这里才需要,还是我只是担心以后可能用得上。前一种值得动态追加,后一种更适合继续延迟加载,甚至干脆别给。Agent 的工具箱不是越满越专业,真正专业的是知道什么时候不递那把扳手。

如果团队已经有 cache hit、请求耗时和 tool error 的观测面板,可以把这次试点做成一组对照。相同任务,一边维持旧的固定工具清单,一边在满足条件时追加工具。不要只盯平均 token 成本,长尾耗时和失败后的重试次数往往更诚实。一次 cache miss 也许没什么,连续几次叠在复杂任务上,用户等到屏幕发呆时就有感觉了。

Claude 同日的大新闻当然是 Opus 5.5 和价格调整,很多标题也都在聊 1M 上下文和默认模型切换。但我更在意这块小小的接口缝。模型越来越会干活以后,真正磨人的不再只是选哪一个模型,而是它干到一半时,工具、缓存和权限还能不能不打架。

工具箱终于可以在航行途中换一把扳手了。至于换哪把,谁批准,换完怎么验收,还是得我们自己盯着。

你们现在的 Agent 工具是一次性全塞进上下文,还是有自己的按需加载和版本切换策略?