给一个 AI Agent 接上搜索、数据库、邮件、日历、代码执行、CRM、支付、内部知识库……看起来很自然:模型能力不够,就继续加 Tool。

问题是,当工具从 10 个变成 50 个,再从 50 个变成 500 个时,事情并不会简单地变成“模型会做更多事”。

你很可能遇到另一种情况:工具明明已经接好了,模型却选错;该调用 A,却调用了 B;或者光是理解有哪些工具可用,就消耗掉大量 Context。

所以,真正的问题不是“模型最多能接多少个 Tool”,而是:当工具数量不断增加时,如何让模型在当前任务中,只看到真正有用的那几个。

几十个 Tool 时,最先出现的不是容量问题,而是选择问题

假设一个 Agent 有 30 个工具。

其中有 search_websearch_docssearch_emailsearch_crm,还有 get_customerget_contactfind_user

对人来说,这些名字已经有一点相似。对模型来说,它不只要看名字,还要理解每个 Tool 的描述、参数和适用边界,然后判断用户这句话应该对应哪一个。

比如用户说:

“帮我找一下上个月和 Acme 沟通过的人。”

这是查 CRM,还是邮件?找 company、contact,还是 conversation?

Tool 越多,这类语义重叠越频繁。

因此,几十个 Tool 时,一个常见问题是:模型不是不会调用工具,而是不知道应该调用哪个。

这也是为什么 Tool 描述非常重要。一个只有“搜索信息”四个字的 Tool,很容易和其他搜索类 Tool 混淆。好的描述应该告诉模型:它查什么、不查什么、什么时候使用,以及返回什么。

工具数量较少时,这些问题通常还能靠命名、描述和 Prompt Engineering 缓解。

但到了几百个,方法就要变了。

几百个 Tool 时,把全部工具塞进 Context 开始变得昂贵

假设你有 500 个 Tool,每个都有名称、用途说明、参数 Schema。

即使模型的 Context Window 足够大,把它们全部放进去也不代表这是好设计。

原因至少有三个。

第一,工具定义本身会占 Context。

模型每次处理“帮我查一下明天下午有没有会”这种简单请求,都要同时面对支付、代码部署、数据库管理、客服系统等数百个完全无关的工具。

这和你去便利店买瓶水,店员先递给你一本几千页的商品目录没有区别。

第二,候选项越多,选择越困难。

假设只有两个 Tool,一个查日历,一个发邮件,模型的选择空间很小。如果同时存在十几个相似的 calendar、schedule、meeting、availability 工具,歧义自然增加。

第三,长 Context 不只是“装得下”的问题。

模型还需要从这些信息里找到当前任务真正相关的部分。Context 能放 100 万 Token,不等于你应该每次都放 100 万 Token。

Context Window 是容量,不是垃圾桶。

所以,当工具进入几十甚至几百规模后,一个更合理的问题应该是:

“这一轮任务需要哪些 Tool?”

而不是:

“我能不能一次把所有 Tool 都给模型?”

Tool Retrieval,就是先替模型缩小选择范围

Tool Retrieval 可以理解成“给工具做搜索”。

用户输入:

“查一下深圳明天下午天气,然后发邮件告诉团队。”

系统不一定立即把全部 500 个 Tool 交给模型,而是先根据任务检索出最相关的一小组:

weather_forecast

然后把这几个工具连同用户请求一起交给主模型。

于是原本是:

用户问题 → 500 个 Tool → 模型选择

变成:

用户问题 → Tool Retrieval → 5~10 个候选 Tool → 模型选择

这和搜索引擎很像。

互联网上有几十亿网页,搜索引擎不会把所有网页一次性塞给你,让你自己找答案。它先检索一批候选结果,再排序,再展示最值得看的部分。

Tool Retrieval 做的是同一件事,只不过被检索的对象从“网页”变成了“工具”。

工具规模越大,这一层越重要。

动态加载 Tool,关键在于把“发现”和“执行”分开

一种比较实用的 Agent 架构,是把 Tool 分成两层。

第一层不是业务工具,而是“找工具的工具”。

比如系统先理解用户任务属于什么领域:邮件、日历、代码、数据库、销售、客服。

然后从 Tool Registry 中寻找相关工具,再把结果动态加入当前 Context。

假设用户说:

“看看明天下午我有没有空,如果有空就给张三发邮件约半小时。”

系统可能经历这样的过程:

任务识别 → 日历 + 联系人 + 邮件
Tool Retrieval → 找到相关工具
加载 Tool Schema → 主模型规划
调用 Calendar → 查询空闲时间
调用 Contacts → 找到张三
调用 Mail → 生成或发送邮件

注意,这里并不要求模型一开始就知道系统里所有能力的完整参数。

它只需要知道:“我可以寻找需要的工具。”

这有点像程序里的动态加载。

你不会为了调用一个图片处理函数,就在程序启动时加载公司所有服务的 SDK。需要什么,再加载什么。

对于 Agent,同样如此。

Tool Rerank 有没有必要?看你的候选工具有多像

Retrieval 并不一定一次就能找到最好的工具。

例如用户问:

“看看客户最近有没有反馈产品问题。”

Retriever 可能找到:

search_crm_notes
search_support_tickets
search_email
search_slack
get_customer_profile
search_product_feedback

这些 Tool 都“有点相关”。

这时可以增加 Tool Rerank:先粗召回一批候选工具,再使用更精细的判断重新排序,最终只把排名靠前的几个交给主模型。

流程就变成:

Retrieve → Rerank → Load → Execute

但 Rerank 并不是永远必要。

如果系统只有 20 个 Tool,而且边界非常清晰,增加一层 Rerank 可能只是增加延迟和复杂度。

如果你有数百个 Tool,并且存在大量名称相似、功能重叠、不同团队重复建设的接口,那么 Rerank 的价值会明显提高。

判断是否需要它,可以观察一个很简单的现象:

Retriever 经常能找到“差不多对”的工具,却不是“最应该用”的工具吗?

如果答案是经常,那么值得加。

真正值得优化的指标,不是 Tool 数量

设计 Agent 时,人很容易展示一个数字:

“我们的 Agent 已经接入 300 个工具。”

这个数字听起来很强,却未必代表系统真的好用。

更应该关注的是:面对一个真实任务,系统能不能快速把数百个工具缩小成几个正确候选,并且让模型稳定地选中正确的那个。

所以,一个比较健康的演进路径通常是:

工具少时,先把 Tool 名称、描述和边界设计清楚。

工具增加后,引入分类、命名空间或者 Tool Registry。

达到几十到几百规模后,开始使用 Tool Retrieval,避免把所有 Schema 永久塞进 Context。

当候选工具高度相似、Retriever 排名不稳定时,再加入 Rerank。

这时系统的重点已经从“让模型认识所有工具”,变成了“让模型在正确的时间认识正确的工具”。

这两个目标,看起来只差几个字,架构却完全不同。

一个真正可扩展的 Agent,不应该像一个员工被要求背完整家公司的所有 SOP、系统菜单和 API 文档。

更合理的状态是:它知道自己现在要完成什么任务,也知道去哪里找到完成这件事所需要的能力。

当 Tool 从几十个增长到几百、几千个时,模型能力当然重要,但决定系统能否继续扩展的,往往是模型之前那一层:检索、筛选和动态加载。

工具越多,越不应该全部交给模型。

Agent 架构真正成熟的标志,也许不是“我们有多少 Tool”,而是用户提出一句话之后,系统能不能只拿出那几个此刻真正有用的 Tool。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐