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

相关推荐
努力写A题的小菜鸡2 小时前
01-PyTorch加载数据初认识(dataset运用)
人工智能·pytorch·python
TMT星球2 小时前
魔法原子上交会首秀VLA K02大模型,完成具身智能从“执行”到“理解”的能力跃迁
人工智能·算法·机器学习
2301_764441332 小时前
番茄钟+AI:高效专注的秘密武器
人工智能·算法·数学建模·动态规划·交互
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第112题】【并发篇】第12题:AQS 中节点的入队时机有哪些?
java·开发语言·面试
摇滚侠2 小时前
SpringMVC 入门到实战 处理静态资源的过程 64
java·后端·spring·maven·intellij-idea
影寂ldy2 小时前
C# 泛型委托
java·算法·c#
SilentSamsara2 小时前
RAG 系统入门:LangChain/LlamaIndex + Chroma 向量数据库的检索增强实战
数据库·人工智能·python·青少年编程·langchain
东方佑2 小时前
分形递归状态机 (FRSM) 实验报告-更新对比
人工智能·语言模型·自然语言处理·开源
YOLO视觉与编程2 小时前
jetson orin nano烧录jetpack7.2系统
人工智能·深度学习·yolo·目标检测·机器学习