Tool Calling 工具调用:让 Agent 查询数据库、调用接口和执行任务
前言前一篇我们解决了一个关键问题让模型稳定返回后端能解析的结构化结果。但 Agent 到这里还只能“理解”。例如用户说帮我查订单 10001 的物流。模型可以识别出{intent:QUERY_LOGISTICS,orderNo:10001}但模型本身并不知道订单 10001 的真实物流信息。要获取真实数据就需要 Tool Calling。可以把 Tool Calling 理解为模型负责决定调用什么工具 后端负责安全地执行工具 工具结果再交给模型组织成最终回答这一篇我们会学习Tool Calling 是什么工具和普通接口有什么区别如何设计工具名称、参数和返回值为什么模型不能直接操作数据库Java 中如何封装工具如何做权限校验、参数校验和审计日志如何避免危险工具调用一、Tool Calling 是什么Tool Calling 又常被称为Function Calling 工具调用 函数调用它的核心流程是用户提出问题 | 模型理解意图 | 模型选择工具并生成参数 | 后端校验工具和参数 | 后端执行工具 | 工具返回真实结果 | 模型根据结果生成最终回答例如用户查订单 10001 的物流。模型不会直接回答物流状态而是请求{name:queryOrderLogistics,arguments:{orderNo:10001}}后端调用订单服务拿到真实数据{orderNo:10001,status:IN_TRANSIT,latestMessage:包裹已到达分拨中心}模型再回答订单 10001 当前正在运输中最新物流状态是包裹已到达分拨中心。二、Tool Calling 和普通 API 调用的区别普通 API 调用通常由前端或后端代码明确决定。前端调用 /order/10001/logistics而 Tool Calling 中调用哪个工具由模型在允许范围内决定。用户自然语言 | 模型判断 | 选择 queryOrderLogistics | 后端执行工具但这里必须强调模型有调用建议权 后端拥有最终执行权模型不能绕过权限校验 参数校验 业务规则 审计日志 风控规则三、工具不是“把所有接口暴露给模型”一个常见误区是项目有 200 个接口就给 Agent 暴露 200 个工具。这通常不是好做法。工具过多会导致模型更难选择正确工具工具描述占用更多 Token权限管理更复杂调试成本更高工具误调用概率增加高风险操作更难控制更推荐从少量、高价值、职责清晰的工具开始。例如订单助手第一版只提供getCurrentUser queryOrderDetail queryOrderLogistics queryRefundStatus createAfterSaleTicket不要一开始就开放deleteOrder updateOrderStatus executeSql runShellCommand四、一个好工具应该具备什么特点一个好工具通常具备下面几个特征。1. 名称明确不推荐doOrder handleData queryInfo推荐queryOrderDetail queryOrderLogistics createAfterSaleTicket工具名称应该让模型和开发者都能看懂。2. 职责单一不推荐manageOrder因为它可能包含查询、修改、删除、退款等太多行为。推荐拆开queryOrderDetail queryOrderLogistics applyRefund cancelOrder这样权限控制和审计更清晰。3. 参数清晰不推荐{data:10001}推荐{orderNo:10001}参数名称要表达业务含义。4. 返回结果稳定不推荐直接返回数据库所有字段。推荐返回 Agent 真正需要的信息{orderNo:10001,orderStatus:PAID,deliveryStatus:WAITING_SHIPMENT,latestLogisticsMessage:null}返回字段越稳定模型越容易正确理解。5. 具备安全边界工具必须校验当前用户是谁 能否访问目标数据 参数是否合法 当前操作是否允许 是否需要二次确认五、工具定义示例下面是queryOrderLogistics的工具说明。{name:queryOrderLogistics,description:查询当前登录用户指定订单的物流信息。仅当用户提供明确订单号时调用。,parameters:{type:object,required:[orderNo],properties:{orderNo:{type:string,description:订单号只允许数字和字母长度不超过 32 位。}},additionalProperties:false}}文字说明工具定义通常包含工具名称工具描述参数 Schema必填字段字段说明是否允许额外参数模型会根据工具描述判断是否调用。所以描述要准确。例如仅当用户提供明确订单号时调用。可以减少模型在订单号缺失时盲目调用工具。六、为什么模型不能直接连接数据库有些人会想既然模型能生成 SQL那让模型直接查数据库不就行了不建议这样做。原因包括模型可能生成错误 SQL模型可能生成危险 SQL模型可能查询超出权限的数据模型可能返回敏感字段难以做稳定审计SQL 结构变化后容易失效容易受到提示词注入影响正确方式应该是模型 - 受控工具 - Service - Mapper - 数据库而不是模型 - 任意 SQL - 数据库七、Java 中定义工具参数对象先定义工具参数。packagecom.example.agent.tool.order;importjakarta.validation.constraints.NotBlank;importjakarta.validation.constraints.Pattern;publicrecordQueryOrderLogisticsArgs(NotBlank(message订单号不能为空)Pattern(regexp^[A-Za-z0-9]{1,32}$,message订单号格式不正确)StringorderNo){}文字说明工具参数和普通 Controller DTO 一样也应该做参数校验。模型生成的参数不是可信参数。例如模型可能返回orderNo 查询全部订单或者orderNo 10001; delete from orders即使模型不会真的执行 SQL参数校验仍然是必须的。八、定义统一工具接口可以给 Agent 工具定义一个统一接口。packagecom.example.agent.tool;publicinterfaceAgentToolA,R{Stringname();Rexecute(ToolContextcontext,Aarguments);}再定义工具调用上下文。packagecom.example.agent.tool;publicrecordToolContext(LonguserId,Stringusername,StringtraceId){}文字说明ToolContext用于保存当前请求上下文。例如当前登录用户 ID 用户名 traceId 租户 ID 用户角色工具执行时不能依赖模型传入“当前用户是谁”。当前用户必须来自 JWT、拦截器或 ThreadLocal。九、实现查询订单物流工具下面以订单物流工具为例。packagecom.example.agent.tool.order;importcom.example.agent.tool.AgentTool;importcom.example.agent.tool.ToolContext;importcom.example.entity.Order;importcom.example.exception.BusinessException;importcom.example.service.OrderService;importlombok.RequiredArgsConstructor;importorg.springframework.stereotype.Component;ComponentRequiredArgsConstructorpublicclassQueryOrderLogisticsToolimplementsAgentToolQueryOrderLogisticsArgs,OrderLogisticsResult{privatefinalOrderServiceorderService;OverridepublicStringname(){returnqueryOrderLogistics;}OverridepublicOrderLogisticsResultexecute(ToolContextcontext,QueryOrderLogisticsArgsarguments){OrderorderorderService.queryUserOrder(context.userId(),arguments.orderNo());if(ordernull){thrownewBusinessException(404,未查询到当前用户的订单);}returnnewOrderLogisticsResult(order.getOrderNo(),order.getDeliveryStatus(),order.getLogisticsCompany(),order.getLatestLogisticsMessage());}}返回对象packagecom.example.agent.tool.order;publicrecordOrderLogisticsResult(StringorderNo,StringdeliveryStatus,StringlogisticsCompany,StringlatestLogisticsMessage){}文字说明这个工具没有直接调用 Mapper而是调用OrderService原因是订单归属、订单状态、权限校验等业务规则应该放在 Service 层。工具本身只是 Agent 和业务服务之间的一层适配。十、Service 层继续负责业务和权限packagecom.example.service;importcom.example.entity.Order;publicinterfaceOrderService{OrderqueryUserOrder(LonguserId,StringorderNo);}packagecom.example.service.impl;importcom.example.entity.Order;importcom.example.mapper.OrderMapper;importcom.example.service.OrderService;importlombok.RequiredArgsConstructor;importorg.springframework.stereotype.Service;ServiceRequiredArgsConstructorpublicclassOrderServiceImplimplementsOrderService{privatefinalOrderMapperorderMapper;OverridepublicOrderqueryUserOrder(LonguserId,StringorderNo){returnorderMapper.selectByOrderNoAndUserId(orderNo,userId);}}Mapper 接口packagecom.example.mapper;importcom.example.entity.Order;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Param;MapperpublicinterfaceOrderMapper{OrderselectByOrderNoAndUserId(Param(orderNo)StringorderNo,Param(userId)LonguserId);}Mapper XMLselectidselectByOrderNoAndUserIdresultTypecom.example.entity.Orderselect order_no, delivery_status, logistics_company, latest_logistics_message from orders where order_no #{orderNo} and user_id #{userId}/select文字说明这里的关键是anduser_id#{userId}即使模型生成了一个真实存在的订单号也只能查询当前登录用户自己的订单。这才是 Agent 工具正确的安全边界。十一、工具注册中心当 Agent 有多个工具时可以通过注册中心统一管理。packagecom.example.agent.tool;importorg.springframework.stereotype.Component;importjava.util.List;importjava.util.Map;importjava.util.function.Function;importjava.util.stream.Collectors;ComponentpublicclassToolRegistry{privatefinalMapString,AgentTool?,?toolMap;publicToolRegistry(ListAgentTool?,?tools){this.toolMaptools.stream().collect(Collectors.toMap(AgentTool::name,Function.identity()));}publicAgentTool?,?getTool(StringtoolName){returntoolMap.get(toolName);}}文字说明Spring 会自动注入所有实现了AgentTool接口的工具。例如QueryOrderLogisticsTool QueryOrderDetailTool CreateAfterSaleTicketTool注册中心再通过工具名称找到对应实现。这个设计比在代码中写大量if(queryOrderLogistics.equals(toolName)){...}更清晰也方便后续扩展。十二、工具执行器需要做什么工具执行器不应该拿到模型请求后直接执行。建议至少做这些检查1. 工具是否存在 2. 工具是否属于当前 Agent 的允许列表 3. 工具参数是否可以解析 4. 参数是否通过 Validation 5. 当前用户是否有权限 6. 是否超过调用次数限制 7. 是否属于高风险操作 8. 是否需要人工确认 9. 是否记录审计日志可以把执行流程理解成模型请求工具 | 检查工具白名单 | 解析参数 | 参数校验 | 权限校验 | 执行业务服务 | 脱敏工具结果 | 记录日志 | 返回模型十三、工具错误结果不要直接抛给模型工具失败时不建议把底层异常直接给模型。例如数据库异常SQLSyntaxErrorException: Unknown column ...不应该作为模型上下文返回。可以转换成受控结果{success:false,errorCode:ORDER_QUERY_FAILED,message:订单查询暂时失败请稍后重试。}文字说明这样做有几个好处不暴露数据库和系统实现模型更容易理解错误类型用户看到的提示更友好后端日志仍然可以记录完整异常方便 Agent 决定是否重试或降级十四、高风险工具必须增加确认下面这些操作属于高风险工具删除数据 取消订单 申请退款 创建支付 发送外部消息 修改权限 发布内容 执行部署命令不建议模型一次决定后直接执行。更推荐的流程用户提出请求 | 模型生成操作草稿 | 后端展示确认信息 | 用户明确确认 | 后端再次校验权限和状态 | 执行工具 | 记录审计日志例如用户说帮我取消订单 10001。Agent 应该先回答订单 10001 当前状态为已付款取消后将发起退款流程。是否确认取消用户确认后才允许执行取消工具。十五、工具结果也要控制长度工具返回数据不要过大。例如查询订单列表时不应该把 500 条订单全部交给模型。更推荐工具层分页 只返回必要字段 限制最大记录数 摘要化返回 敏感字段脱敏例如{total:128,items:[{orderNo:10001,status:PAID,amount:99.00}]}如果用户需要更多内容Agent 可以继续追问或分页查询。十六、工具调用需要限制次数Agent 可能出现这种情况调用工具 | 结果不满意 | 再次调用相同工具 | 继续调用 | 进入循环所以需要限制单次请求最大工具调用次数 单个工具最大调用次数 单个工具超时时间 总请求超时时间 最大 Token 消耗例如单次 Agent 请求最多调用 5 次工具 同一个工具最多调用 2 次 单个工具超时 5 秒文字说明这些限制不是为了让 Agent “变笨”而是防止成本失控响应时间过长工具被重复调用外部系统被大量请求复杂异常导致死循环十七、常见问题1. 模型调用了不存在的工具后端不能猜测模型想调用什么。应该返回受控错误{success:false,errorCode:TOOL_NOT_FOUND,message:当前不支持该工具调用。}同时记录日志用于优化工具描述和 Prompt。2. 工具参数不合法怎么办例如模型返回{orderNo:查询全部用户订单}应该通过 DTO 校验拒绝。不能因为模型“看起来是在完成任务”就绕过参数校验。3. 工具调用成功但模型总结错了怎么办工具结果是真实的但模型可能仍然理解错。例如工具返回status WAITING_SHIPMENT模型却说订单已经发货。这种问题需要清晰的工具返回字段Prompt 约束“只能基于工具结果回答”关键状态使用模板化后端文案记录结果用于评估高风险业务避免让模型自由解释4. 能不能让模型执行 Shell 命令默认不建议。如果确实需要操作服务器也应该限定命令白名单 限制执行目录 限制参数范围 隔离执行环境 记录审计日志 增加人工确认 禁止 root 权限不要给模型任意 Shell 权限。十八、实际开发建议工具要少而精优先暴露高价值、职责单一的能力。模型只负责选择工具真正执行必须经过后端校验。工具内部优先调用 Service不要让模型或工具直接操作数据库。工具参数必须使用 DTO、Validation 和业务校验。查询类工具与修改类工具要区分风险等级。高风险操作必须增加用户确认和审计日志。工具结果要脱敏、限长、结构化不要直接返回底层异常和全量数据。为 Agent 设置工具调用次数、超时和成本限制。十九、总结这一篇我们完成了 Agent 从“理解用户问题”到“调用真实业务能力”的关键一步。Tool Calling 的本质是模型负责决策 工具负责执行 后端负责安全和业务规则整个流程可以总结为用户输入 | 模型选择工具 | 后端校验工具和参数 | Service 执行业务 | Mapper 查询或修改数据 | 工具结果返回模型 | 模型生成最终回复学完这一篇后Agent 已经不只是聊天而是可以在受控范围内查询订单、调用接口、创建任务和连接业务系统。下一篇我们继续学习 ReAct 模式理解 Agent 如何在“思考、行动、观察”之间完成多步骤任务。

相关新闻

Kimi K3大模型API实战:从调用到本地知识库问答系统构建

Kimi K3大模型API实战:从调用到本地知识库问答系统构建

最近在AI圈子里,Kimi Chat的K3版本发布引起了不小的讨论,很多开发者都在关注其宣称的“超越GPT-5.5和Opus-4.8”的性能表现。作为一名长期关注AI应用落地的开发者,我第一时间进行了深度体验和测试。本文将从一个技术实践者的角度,…

2026/9/30 7:24:07 阅读更多 →
体育赛事技术复盘:Python数据分析与可视化在体操平衡木决赛中的应用

体育赛事技术复盘:Python数据分析与可视化在体操平衡木决赛中的应用

这次我们来看一个体育赛事分析项目,它并非传统的AI模型或软件工具,而是一个聚焦于竞技体育,特别是体操项目关键赛事的技术分析与数据可视化案例。项目标题“邓琳琳高分震慑全场,外国选手彻底崩盘,中国包揽平衡木金银牌…

2026/9/29 14:47:26 阅读更多 →
Hexo部署遇到的问题

Hexo部署遇到的问题

1,修改配置后不生效 hexo clean2,更换主题后样式错乱 hexo clean && hexo g3,端口占用,更换端口 hexo server -p 50004,github 仓库博客地址乱码打不开 # 修改 _config.yml 找到 url 这一行,博…

2026/9/28 17:57:56 阅读更多 →

最新新闻

任少卿时隔十年再出手:MM-Future让自动驾驶“走一步想十步”

任少卿时隔十年再出手:MM-Future让自动驾驶“走一步想十步”

「多模式联合世界‑动作模型」 目录 01 自动驾驶世界‑动作模型现存两难矛盾 1.1 三类主流WAM范式的固有短板 02 MM‑Future完整技术链路 2.1 面向规划的MM‑Tokens压缩表征 2.2 多模式联合世界‑动作条件流生成 2.3 未来条件提案打分器 03 NAVSIM、HUGSIM仿真…

2026/9/30 7:23:18 阅读更多 →
30-seconds-of-code:CSS 逻辑属性与物理属性对照指南(Logical  Physical Properties)

30-seconds-of-code:CSS 逻辑属性与物理属性对照指南(Logical Physical Properties)

教程文档 【免费下载链接】30-seconds-of-code Coding articles to level up your development skills 项目地址: https://gitcode.com/gh_mirrors/30/30-seconds-of-code 点击查看 免费下载 导读 CSS 逻辑属性(Logical Properties)让开发者…

2026/9/30 7:23:18 阅读更多 →
Java集合-02-ArrayList源码:扩容、System.arraycopy 与 fail-fast

Java集合-02-ArrayList源码:扩容、System.arraycopy 与 fail-fast

1. 结论先行:ArrayList 本质是动态数组ArrayList 是 Java 集合框架中最常用的 List 实现之一,其底层本质是一个可动态扩容的对象数组。它之所以查询快、增删慢,根源就在于这个数组结构:数组支持按下标 O(1) 随机访问,但…

2026/9/30 7:23:18 阅读更多 →
友为合同管理系统 | 模板与条款标准化——上线前最重要的一步

友为合同管理系统 | 模板与条款标准化——上线前最重要的一步

01 引言:模板乱了,系统就白建了核心观点:合同模板和条款的标准化,是合同管理系统能否真正发挥价值的基础。现实情况却往往令人担忧。企业真正有多少模板、散落在哪些位置、哪些存在版本冲突,法务部门往往并不清楚。大量…

2026/9/30 7:23:18 阅读更多 →
流水灯控制实验

流水灯控制实验

实验1 流水灯控制实验 一、实验目的 掌握STM32 GPIO寄存器底层原理,理解GPIO端口寄存器地址、配置参数。掌握寄存器方式编写GPIO输出驱动,实现LED流水灯。学会STM32标准外设库工程建立、库文件添加方法,标准库方式驱动LED。掌握HAL库外部中断…

2026/9/30 7:23:18 阅读更多 →
《Linux 网络编程》深入理解 IO 多路复用:select 函数详解与 Echo 服务实战

《Linux 网络编程》深入理解 IO 多路复用:select 函数详解与 Echo 服务实战

🔥小叶-duck:个人主页 ❄️个人专栏:《Data-Structure-Learning》《C入门到进阶&自我学习过程记录》 《Linux系统从入门到实践》《Linux网络从入门到实践》 《Qt 方寸极境》 《MySQL》 ✨未择之路,不须回头 已择之路&#xf…

2026/9/30 7:22:17 阅读更多 →

日新闻

Base64 图片头部特征识别:从文件头到格式判断的完整指南

Base64 图片头部特征识别:从文件头到格式判断的完整指南

1. 项目概述:为什么说看懂 base64 图片头部是基本功这几年跟 base64 打交道的机会越来越多,后端接口返回图片、前端渲染验证码、小程序里存小图、还有一些老系统导出报表,动不动就给你一段长到怀疑人生的 base64 字符串。很多人拿到字符串就直…

2026/9/30 0:00:35 阅读更多 →
Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

简介:本资源是一份面向Java初学者与课程设计学生的公交站牌广告灯箱管理系统毕业设计文档,聚焦城市公共广告资源信息化管理痛点,提供从需求分析到技术实现的完整方案。文档采用标准学术论文结构,含摘要、英文摘要、目录及五章正文…

2026/9/30 0:00:35 阅读更多 →
用 Redis Lua 构建大模型 API 多租户原子配额治理体系

用 Redis Lua 构建大模型 API 多租户原子配额治理体系

我去年年底接了一个内部 AI 平台的治理需求,背景很直接:公司把 DeepSeek、MiniMax 这类大模型 API 统一封装成内部网关,开放给几个业务团队用。结果第一个月账单出来,额度直接超了 4 倍。仔细查日志,发现原因并不复杂—…

2026/9/30 0:00:35 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 8:16:59 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 16:41:41 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/29 8:24:48 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/29 19:29:29 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/29 5:58:00 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/29 3:55:56 阅读更多 →