Spring AI系列之Tool Calling 实战:3 种工具定义方式

在 Spring AI 开发 AI Agent 的过程中,Tool Calling(工具调用) 是最核心、最能体现 AI 智能化的能力。
很多同学在实战时都会遇到这些问题:

  • 工具到底有几种写法?
  • 函数式工具怎么用才规范?
  • 编程式 ToolCallback 适合什么场景?
  • 项目里到底该选哪种?

今天这篇就带着大家一次性吃透 Spring AI 3 种标准工具定义方式,全部是可直接复制运行的企业级代码,图文并茂、一看就会!

环境:

  • Spring AI 1.1.3
  • SpringBoot 3.5.7
  • JDK 17

一、先看懂:Tool Calling 执行流程(图文秒懂)

Tool Calling 的本质:
让大模型自主判断是否需要调用外部方法 → 自动调用 → 取回结果 → 自然语言回答

🔁 Tool Calling 标准执行流程图

Tool Calling 完整执行流程

流程步骤:

  1. 用户提问
  2. 模型分析是否需要调用工具
  3. Spring AI 自动调度对应工具
  4. 执行 Java 方法/函数并返回结果
  5. 模型整合结果,给出最终回答

二、Spring AI 3 种工具定义方式(全文重点)

Spring AI 目前提供 3 种标准工具定义方式,覆盖 99% 开发场景:


方式 1:注解式 @Tool(最简单、企业最常用)

直接在普通 Java 方法上加 @Tool 注解,Spring AI 自动识别为可调用工具。

📦 代码示例

@Component
public class TimeTools {

    /**
     * 获取当前系统时间工具
     */
    @Tool(description = "获取当前系统的日期与时间,格式:yyyy-MM-dd HH:mm:ss")
    public String getCurrentTime() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
}

✅ 优点

  • 写法最简单直观
  • 业务代码清晰
  • 支持复杂逻辑、依赖注入

🎯 适用场景

时间查询、天气查询、数据库操作、订单服务、消息推送等常规业务工具


方式 2:函数式工具 Function / BiFunction(官方推荐、极简)

这是 Spring AI 原生支持的优雅写法,也是官方文档重点推荐的方式。
不需要类、不需要注解,基于 JDK 函数式接口定义。

🧩 代码示例 1:编程式构建

// 定义入参、出参
record WeatherRequest(String city, String unit) {}
record WeatherResponse(double temperature, String unit) {}

// 函数式接口
interface WeatherService extends Function<WeatherRequest, WeatherResponse> {
    @Override
    WeatherResponse apply(WeatherRequest request);
}

@Test
void testFunctionTool() {
    // 构建函数式工具
    ToolCallback tool = FunctionToolCallback.builder("currentWeather", new WeatherService() {
                @Override
                public WeatherResponse apply(WeatherRequest request) {
                    return new WeatherResponse(25.5, request.unit());
                }
            })
            .description("获取指定城市的实时天气")
            .inputType(WeatherRequest.class)
            .build();

    // 调用
    String result = ChatClient.create(chatModel)
            .prompt("长沙今天天气怎么样?")
            .tools(tool)
            .call()
            .content();

    System.out.println(result);
}

🧩 代码示例 2:配置类 Bean 方式(企业推荐)

@Configuration
public class AiToolConfig {
    public static final String WEATHER_TOOL = "currentWeather";

    @Bean(WEATHER_TOOL)
    @Description("获取指定城市的实时天气")
    public Function<WeatherRequest, WeatherResponse> currentWeather() {
        return request -> new WeatherResponse(30.0, request.unit());
    }
}

🚀 调用方式

@Test
void testConfigFunctionTool() {
    String content = ChatClient.create(chatModel)
            .prompt("今天长沙天气怎么样?")
            .toolNames(AiToolConfig.WEATHER_TOOL)
            .call()
            .content();

    System.out.println(content);
}

✅ 优点

  • 代码极简、无冗余
  • 结构化强、支持强类型
  • Spring 容器无缝整合

🎯 适用场景

轻量工具、结构化工具、快速开发、企业级规范项目。


方式 3:编程式构建 ToolCallback(最灵活、底层)

完全手动构建工具:名称、描述、入参 Schema、执行体全部自己控制
适合:动态工具、插件化、运行时注册、多租户场景

⚙️ 代码示例

// 计算器工具
public class CalcTools {
    public Integer add(int a, int b) {
        return a + b;
    }
}

@Test
void testProgrammaticTool() {
    // 反射获取方法
    Method method = ReflectionUtils.findMethod(CalcTools.class, "add", int.class, int.class);

    // 手动定义工具元数据
    ToolDefinition definition = ToolDefinition.builder()
            .name("add")
            .description("计算两个整数的和")
            .inputSchema("""
                {
                    "type": "object",
                    "properties": {
                        "a": { "type": "integer", "description": "第一个数字" },
                        "b": { "type": "integer", "description": "第二个数字" }
                    },
                    "required": ["a", "b"]
                }
            """)
            .build();

    // 构建 ToolCallback
    ToolCallback callback = MethodToolCallback.builder()
            .toolDefinition(definition)
            .toolMethod(method)
            .toolObject(new CalcTools())
            .build();

    // 调用
    String content = ChatClient.builder(chatModel).build()
            .prompt("100 加 1000 等于多少?")
            .tools(callback)
            .call()
            .content();

    System.out.println(content);
}

✅ 优点

  • 最灵活,完全代码控制
  • 支持动态生成工具
  • 支持自定义入参 Schema
  • 适合高级架构、插件系统

🎯 适用场景

动态工具、插件化 AI Agent、工作流、多租户、低代码平台。


三、3 种工具方式对比(一张表看懂)

工具方式 难度 代码量 灵活性 企业使用
@Tool 注解 极少 主流、首选
函数式 Function ⭐⭐ 极简 中高 推荐、规范
编程式 ToolCallback ⭐⭐⭐ 中等 最高 动态/插件架构

一句话选择:

  • 普通业务 → @Tool
  • 快速优雅开发 → 函数式工具
  • 动态/插件/高级场景 → ToolCallback

四、企业级最佳实践(必看)

  1. 工具描述必须精准,模型靠它决定是否调用
  2. 函数式工具优先使用 @Bean 注册,便于管理
  3. 工具内部必须捕获异常,避免调用失败
  4. 敏感操作必须加权限校验
  5. 生产环境建议使用 MCP 协议 做工具网关
  6. 开启日志可查看完整调用过程

五、总结

Spring AI Tool Calling 3 种标准工具定义方式

  1. @Tool 注解 → 简单、稳定、业务首选
  2. 函数式 Function → 优雅、强类型、企业推荐
  3. 编程式 ToolCallback → 灵活、动态、高级架构

这一篇吃透,你就能轻松开发企业级 AI 智能体(Agent)!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐