Tool Search原理实战:海量AI Agent工具轻量化上下文最佳实践
文章目录前言一、LLM 是个嘴炮王者工具才是它的手脚二、工具数量爆炸从小钥匙串到移动五金店内置工具在膨胀MCP 工具更是重量级三、Tool Search给工具列表瘦身的骚操作核心思路名字先行Schema 后置Deferred 工具 vs 直接加载工具四、模型只看到名字怎么找到对的工具第一层保障工具名本身就是语义索引第二层保障toolSearch 的两种搜索模式方式一关键词搜索不确定名字时用方式二select: 精确匹配推荐方式激活是持久的五、完整流程走一遍查 BTC 价格启动阶段第 1 轮请求第 1 轮响应第 2 轮请求第 2 轮响应六、工程实现里的那些坑阈值判断工具少的时候别瞎 defer模型兼容性不是所有模型都配合系统提示的字节稳定性子 Agent 不开 defer七、主流方案对比八、总结一下P.S. 目前国内还是很缺AI人才的希望更多人能真正加入到AI行业共同促进行业进步增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow教程通俗易懂高中生都能看懂还有各种段子风趣幽默从深度学习基础原理到各领域实战应用都有讲解我22年的AI积累全在里面了。注意教程仅限真正想入门AI的朋友否则看看零散的博文就够了。前言大家好我是那个在 AI 圈混了 22 年的老油条。今天咱们聊一个特别接地气的话题当你的 AI Agent 手里攥着 400 多个工具上下文窗口都快被挤爆了怎么办 这就好比你请了一个全能管家结果管家每次出门都要把家里所有钥匙串在腰上——从大门钥匙到鱼缸钥匙从保险柜钥匙到猫砂盆钥匙。走两步叮叮当当响不知道的还以为你雇了个移动五金店。别笑这场景在 AI Agent 开发里每天都在上演。一、LLM 是个嘴炮王者工具才是它的手脚先说个冷知识大语言模型本身啥也干不了。它就是个高级复读机你喂它文本它吐文本。它不能读文件不能跑命令不能查数据库连给自己倒杯水都做不到。那 AI Agent 为啥能干这么多事因为模型会指挥工具。模型说“我要调用readFile参数是package.json”。客户端收到指令真的去读文件再把内容塞回给模型。模型一看“哦原来依赖是这样的”然后继续下一步。这套模型发号施令客户端跑腿执行的循环就是 Agent 的核心玩法。 你可以把 LLM 想象成一个坐在轮椅上的战略家——脑子绝顶聪明但身体动不了。工具就是它的轮椅、拐杖和电动滑板车。没有工具它只能对着空气发表高见。每个工具长啥样三个零件name工具名比如readFiledescription自然语言描述告诉模型这玩意儿能干啥inputSchemaJSON Schema定义参数格式这三个东西拼在一起每次请求都要塞进tools数组发给模型。模型靠 description 判断用哪个靠 schema 生成合法参数。二、工具数量爆炸从小钥匙串到移动五金店内置工具在膨胀Agent 产品刚上线时内置工具可能就十几个读文件、写文件、执行命令、搜索代码。但产品一迭代工具就像野草一样疯长。联网搜索、网页抓取、子 Agent 委派、待办管理、后台任务…… Claude Code、Cursor、Codex 这些主流产品哪个不是几十个内置工具打底MCP 工具更是重量级如果说内置工具是自家菜园那 MCPModel Context Protocol就是农贸市场。接个 GitHub MCP ServerAgent 就能创建 Issue、合并 PR。接个数据库 MCP ServerAgent 就能跑 SQL 查询。接个交易所 MCP Server……等等交易所对真有这玩意儿。一个加密货币交易所的 MCP Server覆盖现货交易、合约交易、资产划转、行情查询、余额查询……一口气给你 400 个工具。 400 个工具什么概念你让模型每次请求都背 400 个工具的完整定义相当于让一个人每次开会前先把整本《新华字典》背一遍。不是哥们咱们是来开会的不是来参加最强大脑的。一个中等复杂度的工具定义大概 150-300 token。400 个工具 × 平均 160 token 64,000 token。用户还没开口问问题光工具定义就占了 64k。如果模型上下文窗口是 128k一半没了。这还没算 system prompt 和对话历史。三、Tool Search给工具列表瘦身的骚操作既然全量注入太费 token那能不能只告诉模型有哪些工具等它真要用的时候再加载详细定义能。这就是Tool Search按需加载。核心思路名字先行Schema 后置传统做法每次请求把 400 个工具的完整定义name description schema全塞进去。Tool Search 做法系统提示里只放工具名字清单不放 schema给模型一个内置的toolSearch工具模型需要某个工具时先调toolSearch加载它的 schema下一轮请求里这个工具的完整定义就出现了上下文占用从 64k 降到 3-5k名字清单 按需加载的几个工具 schema。 这就好比你去图书馆借书。传统做法是每次进图书馆把全部藏书搬到桌上Tool Search 是只给你一份目录想看哪本再让管理员拿过来。管理员累是累点但你桌子不会塌啊。Deferred 工具 vs 直接加载工具不是所有工具都要延迟加载。有些劳模工具每轮都可能用到必须直接加载工具功能为什么直接加载readFile读文件几乎所有编码任务都要先读文件edit编辑文件写代码的核心操作shell执行命令跑测试、装依赖、git 操作grep搜索代码定位代码位置toolSearch工具搜索加载 deferred 工具的唯一入口它自己必须先在场剩下的工具比如webSearch、webFetch、todoWrite以及所有 MCP 工具全部 defer。 你可以把直接加载的工具理解为随身工具包——螺丝刀、扳手、胶带走哪带哪。Deferred 工具就是仓库里的设备——电焊机、龙门吊、3D 打印机用的时候再去搬。四、模型只看到名字怎么找到对的工具这是个好问题。系统提示里只列了名字模型连参数都不知道怎么判断该用哪个第一层保障工具名本身就是语义索引MCP 工具名一般长这样mcp__github__create_issue—— GitHub 创建 Issuemcp__gate__cex_spot_get_ticker—— Gate 交易所现货行情名字遵循server__resource__verb的命名规范本身就是一层语义索引。模型看到get_ticker就知道是查行情看到create_order就知道是下单。 这就好比你看到老干妈三个字不需要看配料表也知道是辣椒酱。要是工具名叫tool_001、tool_002那这套方案直接崩盘——模型会一脸懵逼“tool_001 是啥是开门的还是炸厨房的”第二层保障toolSearch 的两种搜索模式toolSearch支持两种调用方式方式一关键词搜索不确定名字时用模型传toolSearch({query: spot ticker})客户端拿 query 和每个工具的预处理文本做关键词匹配按得分排序返回前几个。举个例子。假设 deferred 目录里有这些工具工具名搜索文本mcp__gate__cex_spot_get_tickergate cex spot get ticker 获取现货行情 currency_pairmcp__gate__cex_spot_create_ordergate cex spot create order 创建现货订单 currency_pair side amount pricemcp__github__create_issuegithub create issue 创建 issue title body labels模型搜spot tickercex_spot_get_ticker“spot” 命中 10“ticker” 命中 10总分 20 ✓cex_spot_create_order“spot” 命中 10“ticker” 没命中总分 10github_create_issue都没命中总分 0返回得分最高的几个模型自己挑。Codex 用的是 BM25 算法搜索引擎同款核心思路一样拿 query 关键词匹配工具搜索文本按相关度排序。 注意这里不需要 embedding也不需要再调一次模型。就是纯字符串匹配——同样的 query、同样的工具集结果永远一致。不像某些方案每次搜索结果都带点随机性跟开盲盒似的。方式二select: 精确匹配推荐方式模型直接传toolSearch({query: select:mcp__gate__cex_spot_get_ticker})客户端按名字精确查找不打分直接返回。模型怎么知道确切名字因为系统提示的## Deferred Tools段里列出了所有 deferred 工具的完整名字。模型每轮都能看到这份名单。toolSearch的 description 里直接告诉模型如果已经知道名字优先用select:不确定名字时再用关键词描述能力。 实际使用中模型大多数情况下会走select:因为它能直接从名单里看到工具名。关键词搜索是备胎——比如工具名太长、有多个相似工具时模型可能用spot order这种模糊查询让客户端帮它筛。激活是持久的一旦某个 deferred 工具被toolSearch激活它就会一直留在tools数组里后续轮次不用重复搜索。代价是首次使用某个 deferred 工具时至少需要2 轮 API 调用——先搜索下一轮才能调用。 这就好比你去餐厅点菜。第一次来你得先看菜单toolSearch然后才能点菜调用工具。但下次再来你直接喊老样子菜单都不用看了。当然如果你记性不好对话轮次太多早期的 tool_result 被压缩掉了可能又得重新看菜单——这时候客户端会提醒“这道菜你点过了直接上菜就行。”五、完整流程走一遍查 BTC 价格咱们用查 BTC 现货价格这个场景完整走一遍 Tool Search 的流程。启动阶段客户端从 MCP Server 全量拿到 400 个工具的完整定义存在本地内存里。但只把名字写进系统提示的## Deferred Tools段。第 1 轮请求用户说“帮我查一下 BTC 的现货价格。”发给模型的内容System Prompt包含 deferred 名字清单核心工具 schemareadFile、edit、shell、grep、toolSearch 等用户消息模型看到名单里有cex_spot_get_ticker但没有它的 schema无法直接调用。模型决定先调toolSearch。toolSearch({query: select:mcp__gate__cex_spot_get_ticker})第 1 轮响应客户端精确匹配命中把cex_spot_get_ticker加入activated集合。返回给模型Loaded 1 tool(s) — now callable directly on your next step: mcp__gate__cex_spot_get_ticker: 获取现货行情第 2 轮请求客户端合成新的tools数组核心工具 toolSearchcex_spot_get_ticker的完整 schema。模型现在能看到cex_spot_get_ticker的参数定义了直接调用cex_spot_get_ticker({currency_pair: BTC_USDT})第 2 轮响应客户端执行 MCP 工具调用拿到价格塞回给模型。模型回复“BTC 现货价格是 63,521.30 USDT。” 整个过程就像你去药店买药第一次来不知道药在哪问导购toolSearch。导购告诉你在第三排货架。下次再来你直奔第三排导购都懒得理你。但如果药店搬家了activated 变了你可能又得问一次。六、工程实现里的那些坑阈值判断工具少的时候别瞎 defer工具少的时候全量注入更简单也不需要多一轮往返。x-code-cli 的做法估算所有候选 deferred 工具的 schema token 量如果不超过模型上下文窗口的 10%就跳过 defer退回全量加载。毕竟为了省几百个 token 搞一套 deferred 机制纯属杀鸡用牛刀。模型兼容性不是所有模型都配合Tool Search 依赖模型主动去调toolSearch。如果模型不支持工具调用或者模型太笨理解不了这套机制deferred 工具就永远加载不出来。各家处理策略不同产品策略Codex在models.json里按具体模型版本配置supports_search_tool布尔字段。明确支持的才启用未知模型默认关闭。Claude Code检查 API 能力而非模型智力用modelSupportsToolReference()检查是否支持tool_reference协议块。默认排除haiku可远程动态更新。x-code-cli粗粒度字符串匹配WEAK_MODEL_PATTERNS [haiku, nano, glm-4v]模型名包含这些子串就退回全量注入。问题是区分不了同一系列的不同版本——Claude 3 Haiku 和 Claude 3.5 Haiku 能力差距很大但都会被一刀切。 x-code-cli 这个方案相当于看到张姓就默认对方不会武功。张三丰“”系统提示的字节稳定性LLM API 的前缀缓存prefix caching依赖请求前缀不变。systemtools组成的前缀如果每轮都一样就能命中缓存按折扣价计费。这就要求系统提示里的 deferred 名单不能在运行中动态修改。x-code-cli 的做法启动时生成systemPromptCache并冻结整个 session 不再改动。副作用来了工具激活后系统提示里的名单仍然写着这个工具是未加载状态但tools数组里已经有了它的完整 schema。模型看到的系统提示和实际的工具列表之间存在不一致。 这就好比你家墙上挂着此处无狗的牌子但地上明明趴着一只金毛。访客会疑惑“这狗是量子态的吗”不过在实际使用中这个不一致很少造成问题。强模型Sonnet、GPT-4o 等级在收到第一次toolSearch的 tool_result 后会记住工具已经加载后续直接调用而不会重复搜索。重复搜索只在极端情况下出现——对话轮次非常多、早期的 tool_result 被压缩掉了、模型又看到系统提示里写着未加载时才可能再搜一次。x-code-cli 加了一层防御如果搜索的工具已经在activated集合里返回Already loaded — call xxx directly now.避免模型陷入搜索循环。Claude Code 和 Codex 从架构上避免了这种不一致——它们靠各自 API 的服务端能力处理工具激活客户端不需要改tools数组。x-code-cli 因为要跨多个 provider没法依赖单一 API 的服务端能力只能走客户端重注入。子 Agent 不开 defer子 Agent 的工具集由白名单控制大多数子 Agent 只有几个内置工具。比如 explore 子 Agent 只有readFile、glob、grep、listDir、shell五个工具。工具这么少加 tool search 纯属脱裤子放屁。 这就好比你出门买瓶酱油非要先写个采购计划书。便利店老板会以为你在拍《职场风云》。七、主流方案对比产品全量注入动态机制匹配算法Claude Code否ToolSearch工具关键词打分 select:Codex否tool_search工具BM25 全文检索Gemini CLI是无—x-code-cli否toolSearch工具关键词打分 select:Claude Code、Codex、x-code-cli 三家思路几乎一样区别只在激活后的 schema 怎么对模型可用——Claude Code 和 Codex 靠各自 API 的服务端能力x-code-cli 靠客户端重注入。Gemini CLI 目前没有内置 tool search属于硬核全量注入派。 这就好比四个人去爬山。Claude Code 和 Codex 坐缆车x-code-cli 自己爬但带了登山杖Gemini CLI 光着脚往上冲。respect。八、总结一下Tool Search 的核心逻辑就一句话名字先行Schema 后置按需激活持久缓存。启动时从 MCP Server 全量拿到工具定义存在本地内存核心工具直接加载非核心工具和所有 MCP 工具 defer系统提示里只列 deferred 工具的名字清单模型通过toolSearch加载需要的工具 schema激活后的工具持久保留后续轮次可直接调用代价是首次使用某个 deferred 工具时多一轮 API 调用先搜索后调用。收益是上下文占用从 64k 降到 3-5k对话历史和用户消息有了更多空间。 最后说句掏心窝子的话做 AI Agent 开发工具管理就像收拾房间。东西少的时候随便扔东西多了就得分类、贴标签、按需取用。不然你每次找东西都要翻箱倒柜效率低到怀疑人生。Tool Search 就是给你的工具箱装了个智能索引——不是让工具变少而是让找工具变快。好了今天就聊到这。如果你觉得有用点个赞咱们下期见本文基于 x-code-cli、Claude Code、Codex 等开源项目的源码分析整理而成。P.S. 目前国内还是很缺AI人才的希望更多人能真正加入到AI行业共同促进行业进步增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow教程通俗易懂高中生都能看懂还有各种段子风趣幽默从深度学习基础原理到各领域实战应用都有讲解我22年的AI积累全在里面了。注意教程仅限真正想入门AI的朋友否则看看零散的博文就够了。