首页/新闻资讯/正文详情

【AgentScope Java新手村系列】(3)工具系统:用 @Tool 给 ReActAgent 接上第一把扳手

发布时间:2026/9/26 10:49:25 来源:云帆数科 栏目:资讯中心
【AgentScope Java新手村系列】(3)工具系统:用 @Tool 给 ReActAgent 接上第一把扳手
1. 从“只会聊天”到“能干活”ReActAgent 为什么需要工具如果你刚接触 AgentScope Java大概率已经跑通过一个只会回话的 ReActAgent你问它问题它给你一段文字。但只要需求稍微真实一点比如“现在北京几点了”“帮我算一下 123 乘 456”“查一下这个订单的状态”它就开始一本正经地胡说——因为它没有获取实时信息、执行计算、访问业务系统的能力。工具系统就是给 Agent 装上的“手”。在 AgentScope Java 里Tool注解负责把普通 Java 方法注册成 ReActAgent 可调用的能力Agent 在 ReAct 循环里自己判断这个问题要不要调工具、调哪个、参数填什么。整个过程不需要你写 if-else 去路由模型根据工具的名称和描述做决策。这篇是新手村系列第三篇聚焦工具系统入门。我会从零讲清Tool注解怎么用、参数怎么描述、返回值有什么约定、调用链路长什么样然后给一份可以直接复制的工具类骨架和 Agent 注册配置最后带你本地跑一次亲眼看到工具被正确触发。适合已经能跑起 ReActAgent、想让它真正“动手”的 Java 开发者。2. 前置准备TaoToken 接入与依赖确认在写工具之前先把模型接入这块理顺。AgentScope Java 本身不绑定某一家模型它通过OpenAIChatModel这类适配器对接兼容 OpenAI 协议的服务。我这边习惯用 TaoToken 来做统一接入原因是它同时提供对话和编码两类能力后面从工具调用过渡到 Coding Plan 不用换一套配置。你需要先拿到一个 API Key。打开 https://taotoken.net/api-keys 创建然后把它放进环境变量别硬编码在代码里export TAOTOKEN_API_KEYsk-你的key模型服务的基础地址用 https://taotoken.net/api 注意这个地址不带任何查询参数直接作为baseUrl使用。如果你后面要跑 Claude Code 这类编码场景可以看 https://taotoken.net/claude-code 不过本篇还是聚焦纯 Java 工具调用。依赖方面确认你的pom.xml里有 AgentScope 的核心包。版本号按你项目实际用的填这里只示意结构dependency groupIdio.agentscope/groupId artifactIdagentscope-core/artifactId version你的版本/version /dependency注意工具调用依赖模型本身支持 function calling。选模型时确认它具备工具调用能力否则 Agent 不会触发任何工具只会用文字回答。3. 可复制配置Tool 工具类骨架与 Agent 注册3.1 最小工具类一个方法就是一把扳手先看最核心的写法。一个普通 Java 方法加上Tool就变成 Agent 可调用的工具参数上加ToolParam描述含义。下面这个类包含两个工具查时间和做加法。package com.example.tools; import io.agentscope.core.tool.Tool; import io.agentscope.core.tool.ToolParam; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; public class BasicTools { Tool(name get_current_time, description 获取指定时区的当前时间。当用户询问某个地点的当前时间时使用此工具。) public String getCurrentTime( ToolParam(name timezone, description 时区名称例如 Asia/Shanghai、America/New_York) String timezone) { try { ZoneId zoneId ZoneId.of(timezone); LocalDateTime now LocalDateTime.now(zoneId); DateTimeFormatter fmt DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); return String.format(Current time in %s: %s, timezone, now.format(fmt)); } catch (Exception e) { return Error: Invalid timezone. Try Asia/Shanghai or America/New_York; } } Tool(name add_numbers, description 计算两个数字的和。当用户需要做加法运算时使用此工具。) public String addNumbers( ToolParam(name a, description 第一个加数) double a, ToolParam(name b, description 第二个加数) double b) { return String.format(%.2f %.2f %.2f, a, b, a b); } }这里有几个关键点值得单独说。Tool的name是工具的唯一标识Agent 调用时用的就是这个名字所以别起重复的。description是模型判断“要不要调这个工具”的唯一依据写得越清楚触发越准。ToolParam标注在参数上描述参数含义和格式模型据此填参数。3.2 注册到 Toolkit 并挂到 ReActAgent工具类写好后创建Toolkit实例把工具对象注册进去再传给 Agent 的 builder。import io.agentscope.core.ReActAgent; import io.agentscope.core.agent.RuntimeContext; import io.agentscope.core.formatter.openai.OpenAIChatFormatter; import io.agentscope.core.message.UserMessage; import io.agentscope.core.model.OpenAIChatModel; import io.agentscope.core.tool.Toolkit; import com.example.tools.BasicTools; public class ToolAgentDemo { public static void main(String[] args) { String apiKey System.getenv(TAOTOKEN_API_KEY); Toolkit toolkit new Toolkit(); toolkit.registerTool(new BasicTools()); ReActAgent agent ReActAgent.builder() .name(ToolAgent) .sysPrompt(你是一个可以使用工具的助手。需要准确信息时请调用工具 并在调用前简要说明你在做什么。) .model(OpenAIChatModel.builder() .apiKey(apiKey) .modelName(你的模型名) .baseUrl(https://taotoken.net/api) .stream(true) .formatter(new OpenAIChatFormatter()) .build()) .toolkit(toolkit) .build(); String reply agent.call( new UserMessage(现在北京几点了), RuntimeContext.empty()) .block() .getTextContent(); System.out.println(reply); } }sysPrompt里加一句“需要准确信息时请调用工具”是有用的它给模型一个行为倾向。但真正决定调不调的还是工具描述本身系统提示只是辅助。3.3 返回值约定能返回什么工具方法的返回值会被自动转成字符串交给 Agent。常见几种返回类型// 1. 直接返回字符串 Tool(name echo, description 回显输入内容) public String echo(ToolParam(name input, description 要回显的文本) String input) { return Echo: input; } // 2. 返回对象自动序列化为 JSON Tool(name get_user, description 根据用户 ID 查询用户信息) public MapString, Object getUser( ToolParam(name userId, description 用户 ID) String userId) { return Map.of(id, userId, name, Alice, age, 30); } // 3. 返回 voidAgent 收到空结果 Tool(name log_message, description 记录一条日志) public void logMessage( ToolParam(name message, description 日志内容) String message) { System.out.println([LOG] message); }实测下来返回 JSON 对象在需要结构化数据时最方便模型能直接读到字段。返回 void 适合纯副作用操作但模型拿不到反馈容易重复调用慎用。4. 验证请求本地跑一次看工具被触发代码就绪后直接运行ToolAgentDemo。你会在控制台看到类似这样的输出具体措辞因模型而异我需要查一下北京时间调用 get_current_time 工具。 Current time in Asia/Shanghai: 2025-01-15 14:32:08 现在是北京时间 2025-01-15 14:32:08。这条链路值得拆开看。第一步模型读到用户问题“现在北京几点了”结合工具描述判断需要调用get_current_time。第二步模型生成工具调用请求参数timezone填Asia/Shanghai。第三步框架执行你的 Java 方法拿到返回值。第四步返回值作为工具结果回传给模型模型整理成自然语言回复。想确认工具真的被调用了而不是模型瞎编时间可以在工具方法里加一行打印Tool(name get_current_time, description 获取指定时区的当前时间) public String getCurrentTime( ToolParam(name timezone, description 时区名称) String timezone) { System.out.println([TOOL CALLED] get_current_time, timezone timezone); // ... 原有逻辑 }再跑一次如果控制台出现[TOOL CALLED]说明工具确实被触发了。这一步是新手最容易忽略的验证很多人看到回复里有时间就以为成功了其实可能是模型自己编的。5. 本篇常见错排查5.1 工具完全没被调用Agent 直接文字回答最常见的原因是工具描述太模糊。比如description 做事情模型根本不知道什么时候该用。改成明确的功能边界加使用场景比如“获取指定城市的当前天气当用户询问天气时使用”。另一个原因是模型不支持 function calling换一个支持工具调用的模型再试。5.2 参数填错或类型不匹配ToolParam的description要写清格式和取值范围。如果参数是double模型可能传字符串123框架一般会做转换但保险起见在方法里加 try-catch出错时返回明确的错误提示字符串让模型有机会纠正重试。5.3 工具名重复导致注册失败同一个Toolkit里注册两个name相同的工具会冲突。检查所有Tool(name ...)确保全局唯一。工具多的时候建议按业务前缀命名比如order_query、user_query。5.4 返回值太大把上下文撑爆工具返回的内容会进入对话上下文。如果返回一个几万字的 JSON会挤占后续推理空间。返回前做裁剪只给模型需要的字段。比如查数据库只返回关键列别SELECT *全丢回去。5.5 时区、编码这类环境问题ZoneId.of(Asia/Shanghai)在标准 JDK 上没问题但如果你的运行环境时区数据不全可能抛异常。工具方法里捕获异常并返回可读错误比让整个调用链崩掉要好。编码问题同理涉及文件读写时显式指定 UTF-8。6. 下一步从单工具到工具系统到这里你已经能让 ReActAgent 调用第一个 Java 工具了。但真实项目里工具会越来越多十几个甚至几十个全塞给模型会让工具描述占满上下文触发准确率也会下降。这时候就需要工具分组和元工具机制让 Agent 自己决定激活哪一组工具。如果你打算把工具调用用到长期编码或 Agent 场景建议了解一下 Coding Plan它在工具编排和上下文管理上做了更多优化https://taotoken.net/coding-plan 。想先验证不同模型对工具调用的支持情况可以直接在模型对话里试https://taotoken.net/chat 。接入过程中遇到工具注册或参数传递的问题接入文档里有更细的说明https://taotoken.net/doc 。我自己的经验是工具描述值得反复打磨。同一个工具描述改三遍触发准确率能差出一大截。别指望一次写对跑起来看日志看模型在什么情况下没调、什么情况下调错再回去改描述。这个迭代过程本身就是工具系统调优的核心工作。

相关推荐

AI编程实战:用TaoToken统一Key接入Cline,我把代码生产效率提升200%
AI编程实战:用TaoToken统一Key接入Cline,我把代码生产效率提升200%

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 10:49:25

OpenClaw 命令行升级实战:npm 与 PowerShell 自测流程 + TaoToken 配置骨架
OpenClaw 命令行升级实战:npm 与 PowerShell 自测流程 + TaoToken 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 10:49:25

AI前沿 | 2026年9月19日:蚂蚁 Realtime-Venus 全双工音视频 Agent + 异步委派 + 打断式交互
AI前沿 | 2026年9月19日:蚂蚁 Realtime-Venus 全双工音视频 Agent + 异步委派 + 打断式交互

AI前沿 | 2026年9月19日:蚂蚁 Realtime-Venus 全双工音视频 Agent 异步委派 打断式交互 📖 首屏导读 本教程配套付费专栏:《大模型工程师修炼手记》 19.9 元(AI 编程 Agent 实战 本文同主题系统课程) 《AI时代程序… · 2026/9/26 10:49:25

UltraISO制作启动U盘全指南:从引导写入到BIOS设置与排错
UltraISO制作启动U盘全指南:从引导写入到BIOS设置与排错

1. 为什么都2025年了,我还是推荐UltraISO做启动盘先说个反直觉的事实:现在市面上做启动U盘的工具一大堆,Rufus、Ventoy、balenaEtcher各有拥趸,但如果你常年在帮人装机、维护老机器、或者折腾各种Linux发行版,UltraISO… · 2026/9/26 12:01:23

openDCIM部署与机房数据建模实战指南
openDCIM部署与机房数据建模实战指南

简介:openDCIM是一款基于PHP开发的开源数据中心基础设施管理(DCIM)系统,遵循GPL v3协议,面向IT运维工程师、数据中心管理员及DevOps实践者,用于统一纳管机柜、设备、电源、网络连接等物理资源,支… · 2026/9/26 12:01:23

浏览器直连下载百度网盘大文件:免客户端抓直链与IDM多线程加速实战
浏览器直连下载百度网盘大文件:免客户端抓直链与IDM多线程加速实战

1. 为什么我要折腾浏览器直连下载这件事百度网盘大概是国内使用频率最高的文件分享渠道之一,但它的下载体验一直是个绕不开的话题。官方客户端装完之后后台常驻进程、限速、弹窗推广,这些事大家都懂。我自己的工作机常年保持"能不装就不装"的原… · 2026/9/26 12:01:23

openDCIM本地DCIM系统部署与机柜资产管理实战指南
openDCIM本地DCIM系统部署与机柜资产管理实战指南

简介:openDCIM是一款遵循GPL v3协议的开源数据中心基础设施管理(DCIM)系统,面向IT运维工程师、数据中心管理员及PHP技术栈开发者,用于统一纳管机柜、设备、电源、网络连接等物理资源,支持从小型托管环境到中… · 2026/9/26 12:01:23

【硬核实战】2026论文降AIGC:DeepSeek+文心+豆包多模型协同,两步工作流将80%暴降至10%|TaoToken统一Key配置指南
【硬核实战】2026论文降AIGC:DeepSeek+文心+豆包多模型协同,两步工作流将80%暴降至10%|TaoToken统一Key配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 12:01:23

Linux磁盘挂载从入门到精通:mount命令、fstab配置与排错实战
Linux磁盘挂载从入门到精通:mount命令、fstab配置与排错实战

1. 先搞懂什么是磁盘挂载 1.1 从日常场景理解挂载 很多刚接触Linux的朋友第一次听到“挂载”这个词,往往一脸懵。装个新硬盘,插上去之后用 fdisk -l 能看到设备,但进到系统里却找不到它,更别说往里存数据了。这时候老手会告诉你… · 2026/9/26 12:01:16

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码