Agent Scope Java 2.x 系列【8】工具调用

文章目录

  • [1. 基础概述](#1. 基础概述)
    • [1.1 Tool 定位](#1.1 Tool 定位)
    • [1.2 三大核心构件](#1.2 三大核心构件)
    • [1.3 基础注册示例](#1.3 基础注册示例)
  • [2. 底层契约:AgentTool & ToolBase](#2. 底层契约:AgentTool & ToolBase)
    • [2.1 工具元信息属性(对外描述能力)](#2.1 工具元信息属性(对外描述能力))
    • [2.2 权限与执行生命周期方法](#2.2 权限与执行生命周期方法)
  • [3. 框架内置工具](#3. 框架内置工具)
    • [3.1 内置工具清单](#3.1 内置工具清单)
    • [3.2 注册代码](#3.2 注册代码)
    • [3.3 补充说明](#3.3 补充说明)
  • [4. 三种自定义 Tool 实现方式](#4. 三种自定义 Tool 实现方式)
    • [4.1 注解式 @Tool(轻量首选)](#4.1 注解式 @Tool(轻量首选))
    • [4.2 继承 ToolBase(高度定制场景)](#4.2 继承 ToolBase(高度定制场景))
    • [4.3 外部执行Tool(HITL人在回路)](#4.3 外部执行Tool(HITL人在回路))
  • [5. RuntimeContext 上下文透传](#5. RuntimeContext 上下文透传)
    • [5.1 @Tool 注解方法:自动注入](#5.1 @Tool 注解方法:自动注入)
    • [5.2 ToolBase 实现类:手动获取](#5.2 ToolBase 实现类:手动获取)
  • [6. 自我管理工具(Meta Tool reset_tools)](#6. 自我管理工具(Meta Tool reset_tools))
    • [6.1 ToolGroup 分组注册示例](#6.1 ToolGroup 分组注册示例)
    • [6.2 reset_tools 自动注册条件](#6.2 reset_tools 自动注册条件)
    • [6.3 运行时行为规则](#6.3 运行时行为规则)

1. 基础概述

1.1 Tool 定位

ToolAgent 对接外部环境的交互媒介,可完成业务逻辑执行、第三方 API 调用、数据读写等操作。所有工具统一通过 JSON Schema 向大模型暴露能力,Agent 依靠标准化统一接口完成调用执行。

1.2 三大核心构件

AgentScope 将工具体系拆分为 ToolToolkitTool Group 三层结构。

Tool 是满足 AgentTool 契约的执行单元,两种实现形态:

  • 普通类方法标注 @Tool 注解(反射式工具,由 Toolkit#registerTool(Object) 自动反射注册)
  • 继承 ToolBase 抽象基类,显式实现工具完整契约

Toolkit 是全局工具容器管理器,负责:

  • 注册 ToolMCP 客户端、Skill
  • 聚合生成工具 JSON Schema 下发模型
  • 分发调度每一次工具调用请求

Tool Group 是命名式集合:

  • 可收纳 Tool/MCP/Skill,支持整体启用/停用
  • Agent 运行时可通过内置元工具切换分组状态,精简 LLM 上下文。

1.3 基础注册示例

java 复制代码
import io.agentscope.core.tool.Toolkit;
import io.agentscope.core.tool.builtin.TodoTools;

Toolkit toolkit = new Toolkit();
toolkit.registerTool(new TodoTools());
toolkit.registerTool(new MyCustomTools());

规则:仅使用 registerTool(Object) 注册时,所有 @Tool 方法自动归入basic分组,该分组永久激活。可额外注册MCP、自定义ToolGroup、Skill扩展能力。

2. 底层契约:AgentTool & ToolBase

ToolBaseAgentTool 接口标准抽象实现,封装工具元信息、权限、执行全生命周期。

2.1 工具元信息属性(对外描述能力)

方法 返回类型 说明
getName() String 暴露给Agent的工具唯一名称
getDescription() String 面向LLM的工具功能描述
getParameters() Map<String, Object> 自定义入参JSON Schema结构
isConcurrencySafe() boolean 是否支持并发调用
isReadOnly() boolean 是否只读、无数据变更副作用
isExternalTool() boolean true=执行逻辑外置(人工HITL场景)
isStateInjected() boolean true=自动注入会话状态AgentState
isMcp() boolean 是否来源于MCP远程服务
getMcpName() String MCP服务标识,仅isMcp()=true生效

2.2 权限与执行生命周期方法

方法 是否必需 功能说明
checkPermissions(toolInput, context) 必选 调用前置权限校验,返回Mono<PermissionDecision>
matchRule(ruleContent, toolInput) 可选 权限体系自定义规则匹配,返回布尔值
generateSuggestions(toolInput) 可选 根据本次调用生成权限规则建议列表
callAsync(param) 可选 工具异步执行主逻辑,返回Mono<ToolResultBlock>;外部执行工具无需实现

3. 框架内置工具

3.1 内置工具清单

工具 功能说明 只读
TodoTools.todoWrite 维护会话结构化任务列表,全列表替换语义

3.2 注册代码

java 复制代码
Toolkit toolkit = new Toolkit();
toolkit.registerTool(new io.agentscope.core.tool.builtin.TodoTools());

3.3 补充说明

Toolkit 中存在自定义 ToolGroupSkill 资源时,框架自动注册两类元工具,无需手动实例化

  1. reset_tools:分组启停管理元工具
  2. load_skill_through_path:Skill加载查看工具

4. 三种自定义 Tool 实现方式

4.1 注解式 @Tool(轻量首选)

最简开发模式,框架自动解析 Java 类型生成 Schema,注解填充功能描述。

@Tool 核心属性

属性 类型 说明
name String 工具名称,默认取方法名
description String LLM可见功能描述
readOnly boolean 是否只读,默认false
concurrencySafe boolean 是否并发安全,默认false
stateInjected boolean 自动注入AgentState参数,默认false
dangerousFiles / dangerousDirectories String\[\] 自定义高危文件/目录黑名单
converter ToolResultConverter子类 自定义返回值序列化转换器

简单示例:

java 复制代码
import io.agentscope.core.tool.Tool;
import io.agentscope.core.tool.ToolParam;
import io.agentscope.core.tool.Toolkit;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

public class SimpleTools {
    @Tool(
            name = "get_current_time",
            description = "Returns the current time in a given IANA timezone.",
            readOnly = true,
            concurrencySafe = true)
    public String getCurrentTime(
            @ToolParam(name = "timezone", description = "IANA timezone, e.g. Asia/Shanghai")
                    String timezone) {
        return LocalDateTime.now(ZoneId.of(timezone))
                .format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }
}

// 注册
Toolkit toolkit = new Toolkit();
toolkit.registerTool(new SimpleTools());

4.2 继承 ToolBase(高度定制场景)

适用于自定义权限、复杂 Schema、特殊返回结构场景。

简单示例:

java 复制代码
import io.agentscope.core.message.TextBlock;
import io.agentscope.core.message.ToolResultBlock;
import io.agentscope.core.permission.PermissionDecision;
import io.agentscope.core.tool.ToolBase;
import io.agentscope.core.tool.ToolCallParam;
import io.agentscope.core.tool.ToolExecutionContext;
import java.util.List;
import java.util.Map;
import reactor.core.publisher.Mono;

public class WebSearchTool extends ToolBase {
    public WebSearchTool() {
        super(
                ToolBase.builder()
                        .name("WebSearch")
                        .description("Search the web for information on a given query.")
                        .inputSchema(Map.of(
                                "type", "object",
                                "properties", Map.of(
                                        "query", Map.of(
                                                "type", "string",
                                                "description", "The search query.")),
                                "required", List.of("query")))
                        .readOnly(true)
                        .concurrencySafe(true));
    }

    // 权限校验
    @Override
    public Mono<PermissionDecision> checkPermissions(
            Map<String, Object> toolInput, ToolExecutionContext context) {
        return Mono.just(PermissionDecision.allow("Web search is read-only."));
    }

    // 异步执行逻辑
    @Override
    public Mono<ToolResultBlock> callAsync(ToolCallParam param) {
        String query = (String) param.getInput().get("query");
        return doSearchAsync(query)
                .map(text ->
                        ToolResultBlock.builder()
                                .id(param.getId())
                                .name(getName())
                                .output(List.of(TextBlock.builder().text(text).build()))
                                .build());
    }
}

4.3 外部执行Tool(HITL人在回路)

执行逻辑剥离到 Agent 运行时外部(人工审批、第三方系统);Agent 调用后暂停,等待外部事件回调结果。

核心标识:externalTool(true),无需实现callAsync

执行流程:

  1. Agent 发起调用 → 推送RequireExternalExecutionEvent并暂停运行
  2. 人工/外部系统处理业务
  3. 通过ExternalExecutionResultEvent回传结果,Agent 恢复推理

简单示例:

java 复制代码
import io.agentscope.core.permission.PermissionDecision;
import io.agentscope.core.tool.ToolBase;
import io.agentscope.core.tool.ToolExecutionContext;
import java.util.List;
import java.util.Map;
import reactor.core.publisher.Mono;

public class HumanApprovalTool extends ToolBase {
    public HumanApprovalTool() {
        super(
                ToolBase.builder()
                        .name("HumanApproval")
                        .description("Request human approval for a sensitive operation.")
                        .inputSchema(Map.of(
                                "type", "object",
                                "properties", Map.of(
                                        "action", Map.of("type", "string"),
                                        "reason", Map.of("type", "string")),
                                "required", List.of("action", "reason")))
                        .readOnly(false)
                        .concurrencySafe(true)
                        .externalTool(true)); // 标记外部执行
    }

    @Override
    public Mono<PermissionDecision> checkPermissions(
            Map<String, Object> toolInput, ToolExecutionContext context) {
        return Mono.just(PermissionDecision.allow("External tool dispatch is always allowed."));
    }
}

5. RuntimeContext 上下文透传

agent.call(msgs, runtimeContext) 传入的运行上下文,会自动透传给本次会话内所有工具调用,分两种取值方式。

5.1 @Tool 注解方法:自动注入

未标注@ToolParam的参数,框架自动匹配注入源:

参数类型 注入来源
ToolEmitter 流式输出发射器
Agent 当前运行Agent实例
AgentState 会话独立状态(取自RuntimeContext)
RuntimeContext 单次调用全局上下文
ToolExecutionContext 兼容层,已废弃
自定义POJO runtimeContext.get(POJO.class)

POJO 判定规则 :无@ToolParam、非基础类型、非消息块/Msg、不属于java.* / javax.*包。该类参数不会出现在 LLM 入参 Schema

示例:

java 复制代码
public record UserContext(String username, String locale) {}

public class PersonalizedTools {
    @Tool(name = "greet", description = "Greet the user with a custom greeting")
    public String greet(
            @ToolParam(name = "greeting", description = "Greeting word, e.g. 'Hello'")
                    String greeting,
            UserContext userCtx) { // 框架自动注入
        return greeting + ", " + (userCtx == null ? "unknown" : userCtx.username()) + "!";
    }
}

// 调用方组装上下文
RuntimeContext ctx =
        RuntimeContext.builder()
                .put(UserContext.class, new UserContext("alice", "en"))
                .userId("alice")
                .build();

agent.call(List.of(new UserMessage("Greet me.")), ctx).block();

5.2 ToolBase 实现类:手动获取

callAsync中通过ToolCallParam读取上下文:

java 复制代码
import io.agentscope.core.agent.RuntimeContext;
import io.agentscope.core.tool.ToolBase;
import io.agentscope.core.tool.ToolCallParam;
import reactor.core.publisher.Mono;

public class TenantAwareTool extends ToolBase {
    @Override
    public Mono<io.agentscope.core.message.ToolResultBlock> callAsync(ToolCallParam param) {
        RuntimeContext rc = param.getRuntimeContext();
        String tenantId = rc != null ? rc.getUserId() : null;
        TenantConfig cfg = rc != null ? rc.get(TenantConfig.class) : null;
        // 租户隔离业务逻辑
    }
}

ToolCallParam额外支持获取:Agent 实例、原始入参、EmitterToolUseBlock 元数据。

6. 自我管理工具(Meta Tool reset_tools)

内置元工具允许 Agent 运行时自主启停分组,只暴露当前任务所需工具,降低上下文 Token消耗与模型混淆概率。

6.1 ToolGroup 分组注册示例

java 复制代码
import io.agentscope.core.ReActAgent;
import io.agentscope.core.tool.Toolkit;
import io.agentscope.core.tool.ToolGroup;
import io.agentscope.core.tool.ToolGroupScope;

Toolkit toolkit = new Toolkit();
toolkit.registerTool(new BasicTools()); // 归入basic永久分组

// 数据库分组:会话域、默认关闭
ToolGroup database =
        new ToolGroup(
                "database",
                "Tools for database operations.",
                ToolGroupScope.SESSION,
                false);
database.addTool("db_query");
database.addTool("db_migrate");
toolkit.registerTool(new DatabaseTools());
toolkit.registerToolGroup(database);

// 部署运维分组:会话域、默认关闭
ToolGroup deployment =
        new ToolGroup(
                "deployment",
                "Tools for deploying services.",
                ToolGroupScope.SESSION,
                false);
deployment.addTool("deploy");
deployment.addTool("rollback");
toolkit.registerTool(new DeploymentTools());
toolkit.registerToolGroup(deployment);

// 构建Agent并开启元工具
ReActAgent agent =
        ReActAgent.builder()
                .name("router")
                .toolkit(toolkit)
                .enableMetaTool(true)
                .build();

6.2 reset_tools 自动注册条件

同时满足两点自动注册并透出 Schema

  1. 存在至少一个非 basic 自定义 ToolGroup
  2. Agent 构建开启开关:enableMetaTool(true)

每个非 basic 分组在 reset_tools 入参 Schema 映射为独立布尔字段,Agent 传布尔值声明全部分组最终启用状态

6.3 运行时行为规则

  1. basic 分组永久激活,不受元工具任何操作影响;
  2. 全量覆盖模式:每次调用 reset_tools 整体刷新激活集合,非 basic 分组未显式设为 true 则强制停用,无视历史状态;
  3. 新激活分组自动拼接分组描述、自定义使用提示,随元工具返回值下发给 Agent
  4. 停用分组内所有工具从 LLM 工具 Schema 中移除,压缩上下文。

reset_tools 入参代表全局最终状态,并非增量开关。仅填写要开启的分组会导致其余所有自定义分组全部关闭,历史激活状态不会保留。

相关推荐
万岳科技系统开发2 小时前
外卖跑腿配送系统如何借助AI提升配送效率?
大数据·人工智能·机器学习
thinking_talk2 小时前
腾讯云AI Agent安全中心综合评测
人工智能·安全·腾讯云
JouYY2 小时前
聊一下知识答疑Agent的“层次聚类”流程
架构·llm·agent
格子软件2 小时前
2026年GEO优化系统源码解构:核心状态机与高并发流控深度剖析
java·vue.js·spring boot·vue·geo
weixin199701080162 小时前
[特殊字符]《京东订单API(jd.order.detail.get)对接ERP:企业认证+OAuth授权避坑指南》(附Python源码)
java·数据库·python
阿拉雷️2 小时前
Prompt工程设计实践:从基础模板到场景化策略
人工智能·语言模型·prompt
Kel2 小时前
MCP 传输链路全链路拆解:从字节流到协议栈的四层架构之旅
人工智能·设计模式·架构
魏祖潇2 小时前
DDD 完整指南——AI 时代工程师的第一道秩序分水岭
人工智能·后端
Mark0802032 小时前
散户做信息整理和研究记录时,不同AI工具更适合哪些环节
大数据·人工智能
L3S2 小时前
Agent为什么会死循环?
人工智能·agent