Java 接 AI 时,工具不是越多越强:动态工具发现正在成为新热点
过去一段时间,很多团队做 Java + AI,有个很自然的想法:既然模型会调工具,那就把能接的工具都接上。
一开始看,这思路没问题。天气、订单、知识库、工单、日历、审批、GitHub、Jira,能挂的全挂进去,模型好像就更“全能”了。
可项目一复杂,问题就来了。工具一多,prompt 先变胖,token 成本先涨,模型选工具也开始变笨。你以为自己是在增强 Agent,实际很可能是在给它制造噪音。
真正的问题,不是工具少,而是工具太早全塞进去
Spring AI 在动态工具发现指南里讲得很直白:一个典型的多服务场景,很容易就有 50 个以上工具。更麻烦的是,当模型面对 30 多个名字相近的工具时,选择准确率会下降。
这件事特别像后端系统里的接口膨胀。接口不是越多越好,关键是调用方能不能在正确时机看到正确能力。工具调用也是一样。模型如果一开始就看到一大堆定义,很多上下文根本还没开始聊,token 就先花出去了。
所以现在更值得关注的,不是“我的 Agent 有多少工具”,而是“模型在这一轮对话里,到底需要知道哪些工具”。
动态工具发现,解决的是工具爆炸问题
Spring AI 在 2025 年 12 月 11 日专门发文讲这个方向,核心思路很简单:不要一开始把所有工具定义都发给模型,而是先只给它一个“搜索工具”的能力。等模型真需要某类能力时,再让它去查,再把匹配到的工具动态扩进上下文。
这个模式在 Spring AI 里是通过ToolSearchToolCallAdvisor实现的,本质上建立在 Advisors 机制上。你可以把它理解成,在模型真正调用工具前,先加了一层“工具检索”。
这样做最直接的好处有两个。一个是省 token。Spring AI 官方给出的初步测试数据里,OpenAI、Anthropic、Gemini 三类模型的总 token 消耗分别下降了 34%、64% 和 60%。另一个是减少模型犯糊涂的概率,因为它不是在几十个工具里盲选,而是在一小撮相关工具里做判断。
这对 Java 团队为什么特别重要
Java 团队往往不是工具少,而是系统多。你接的不是一个天气查询 demo,而是好几个内部系统、几套业务能力、多个 MCP Server,后面还会不断长新工具。
这时候如果还沿用“一次性全注册、全暴露”的思路,问题不会立刻爆,但会慢慢出现。上下文越来越大,响应越来越贵,模型越来越容易选错。最要命的是,这种问题前期很难被当成 bug,因为系统看起来是“能跑”的。
动态工具发现更像一种工程收敛。它承认工具会越来越多,但不要求你每次都把全部能力摊给模型看。对 Java 后端来说,这个思路很顺手,因为它本质上就是按需暴露、分层组织、降低耦合。
它还有一个经常被低估的价值,就是让工具体系更容易治理。过去很多团队一接 AI,就会把工具定义散落在不同模块里,谁都能往模型上下文里塞一点。时间一长,工具描述重复、命名冲突、权限边界模糊,问题就出来了。动态工具发现逼着你先把“工具目录”整理出来,再决定哪些能力该被搜索到,哪些能力只该在特定场景暴露。这其实是在倒逼系统做一次工具层的重构。
什么时候该认真上这个能力
Spring AI 文档里给了一个很实用的判断线:如果你的系统里已经有 20 个以上工具,或者工具定义已经吃掉 5K 以上 token,又或者你接的是多个 MCP 服务,那动态工具发现就很值得上。
如果工具很少,而且每次会话几乎都会用到,那传统方式也没问题。可一旦你已经开始担心成本、准确率和后续扩展,这就不是“高级优化”了,而是架构该补的一层。
还有一点很现实。Spring AI 这套做法不是只绑定某一家模型。官方文档写得很清楚,它能工作在 OpenAI、Anthropic、Gemini、Ollama、Azure OpenAI 等不同提供方上。对 Java 团队来说,这意味着你优化的不是某个模型技巧,而是整个 AI 接入层的结构。
如果准备落地,我更建议 Java 团队把它拆成两层来看。第一层是工具注册层,负责把订单、知识库、审批、搜索这些真实能力整理成统一的工具元数据。第二层是工具发现层,负责在每轮对话里只把当前最相关的一小部分能力交给模型。这样后面无论你换模型、扩工具,还是把一部分能力迁到新的 MCP Server,上层业务代码都不会被拖着一起重写。
最后一句
很多团队现在做 AI,注意力还在“模型够不够强”。但真正进入系统阶段后,拉开差距的往往不是模型,而是你怎么管理工具。
工具不是越多越强,能让模型在合适的时候只看到合适的工具,才更像成熟系统。
夜雨聆风