云计算百科
云计算领域专业知识百科平台

AgentScope 2.0:8. Tool —— 工具系统架构与生产级实践深度解析

目录: 1. 面向生产环境的智能体工程平台 2. 快速上手 从零构建生产级智能体 3. Agent —— 智能体的核心抽象与工程化实践 4. Message & Event —— 消息模型与事件流深度解 5. Middleware —— 无侵入式智能体扩展机制深度解析 6. Model —— 统一模型接入层与容错机制深度解析 7. Permission System —— 权限控制系统深度解析 8. Tool —— 工具系统架构与生产级实践深度解析 9. Context —— 运行时上下文与状态管理深度解析

一、引言:工具是智能体的"手和脚"

没有工具的 LLM 只能"说"。有了工具,智能体才能"做"——查询数据库、调用 API、执行计算、读写文件、搜索网络。

在 AgentScope Java 2.0 的构建块体系中,Tool(工具) 是连接智能体推理能力与外部世界的执行层。官方文档将其定位为 io.agentscope.core.tool 包下的完整工具框架,提供:

注解驱动定义 × 自动 JSON Schema 生成 × 响应式执行 × 工具组动态管理 × MCP 协议集成 × 权限管控 × 沙箱隔离

AgentScope Java 的工具系统有四个显著特点:

  • 注解驱动:@Tool + @ToolParam,一个普通 Java 方法秒变工具
  • 响应式原生:同步、异步 Mono、流式 Flux 全支持
  • 自动 Schema:框架自动生成 JSON Schema,LLM 可以直接理解
  • 工具组管理:按场景动态激活/停用工具 本文将系统解析 AgentScope Java 2.0 工具系统的完整架构。

二、工具系统架构总览

2.1 分层架构

┌─────────────────────────────────────────────────────────────────┐
│ Agent 层 │
│ ReActAgent / HarnessAgent │
│ 在 ReAct 循环中自主决定调用哪个工具、何时调用 │
└──────────────────────────────┬──────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│ Toolkit(工具编排中心) │
│ 注册全量工具 → toolFilter 过滤 → 生成 JSON Schema → 分发给模型 │
└──────────────────────────────┬──────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│ ToolGroup(工具分组) │
│ 按域组织工具,支持动态激活/停用 │
└──────────────────────────────┬──────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│ ToolBase(工具基类) │
│ 统一抽象:名称、描述、参数 Schema、执行逻辑、安全检查 │
└──────────────────────────────┬──────────────────────────────────┘

┌────────────────┼────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ ReflectiveTool │ │ 内置工具 │ │ MCP 工具 │
│ (@Tool 注解) │ │ Bash/Read/Write │ │ 外部 MCP Server │
└──────────────────┘ └──────────────────┘ └──────────────────┘

2.2 核心组件关系

组件职责包路径
@Tool / @ToolParam 注解驱动的工具定义 io.agentscope.core.tool
Toolkit 工具注册、编排、Schema 生成 io.agentscope.core.tool
ToolGroup 按域分组、动态激活 io.agentscope.core.tool
ToolBase / AgentTool 工具统一抽象基类 io.agentscope.core.tool
ReflectiveFunctionTool 注解 → 可执行工具的适配器 io.agentscope.core.tool
ToolsConfig 工具过滤配置(allow/deny) io.agentscope.harness.agent.tools
内置工具集 Bash/Read/Write/Edit/Glob/Grep/Skill io.agentscope.harness.tools
MCP 集成 外部 MCP Server 工具发现 io.agentscope.core.tool.mcp

三、注解驱动:@Tool + @ToolParam

3.1 基本定义

AgentScope 2.0 采用注解驱动方式定义工具,开发者只需在普通 Java 方法上添加注解,框架自动完成:

  • 方法签名解析
  • JSON Schema 生成
  • 参数类型映射
  • 工具注册

import io.agentscope.core.tool.Tool;
import io.agentscope.core.tool.ToolParam;

public class WeatherTools {

@Tool(name = "get_weather", description = "获取指定城市的当前天气信息")
public String getWeather(
@ToolParam(name = "city", description = "城市名称,如:北京、上海")
String city,
@ToolParam(name = "unit", description = "温度单位:celsius 或 fahrenheit", required = false)
String unit) {

// 实际业务逻辑
return String.format("%s:晴天,气温 25℃", city);
}
}

3.2 自动生成的 JSON Schema

框架通过反射自动将上述方法转换为 LLM 可理解的 JSON Schema:

{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的当前天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如:北京、上海"
},
"unit": {
"type": "string",
"description": "温度单位:celsius 或 fahrenheit"
}
},
"required": ["city"]
}
}
}

核心价值:开发者无需手动编写 JSON Schema,框架自动生成,LLM 可以直接理解并调用。

3.3 支持的返回类型

返回类型说明适用场景
String 同步返回文本结果 简单查询
Mono 异步返回 网络请求、数据库查询
Flux 流式返回 大文件读取、实时数据
byte[] 二进制数据 图片、文件下载
自定义对象 自动序列化为 JSON 结构化数据

3.4 异步工具示例

@Tool(name = "search_database", description = "在数据库中搜索记录")
public Mono<String> searchDatabase(
@ToolParam(name = "query", description = "搜索关键词") String query,
@ToolParam(name = "table", description = "目标表名") String table) {

return Mono.fromCallable(() -> {
// 异步数据库查询
List<Record> results = dbService.search(table, query);
return formatResults(results);
}).subscribeOn(Schedulers.boundedElastic());
}

3.5 上下文注入

工具方法可以注入运行时上下文信息:

@Tool(name = "get_user_orders", description = "获取当前用户的订单列表")
public String getUserOrders(
@ToolParam(name = "status", description = "订单状态过滤", required = false)
String status,
RuntimeContext ctx) { // 自动注入,不暴露给 LLM

String userId = ctx.getUserId();
return orderService.getOrders(userId, status).toString();
}

设计精妙之处:RuntimeContext 参数不会出现在 JSON Schema 中,LLM 不知道它的存在,但工具执行时可以获取当前用户、会话等上下文信息。

四、Toolkit:工具编排中心

4.1 核心职责

Toolkit 是工具系统的编排中心,负责:

  • 注册所有工具(Java 工具 + MCP 工具)
  • 生成工具描述列表(JSON Schema)
  • 根据 toolFilter 过滤可见工具
  • 分发工具调用请求
  • 管理工具生命周期
  • 4.2 注册与使用

    // 创建 Toolkit 并注册工具
    Toolkit toolkit = new Toolkit();
    toolkit.registerTool(new WeatherTools());
    toolkit.registerTool(new DatabaseTools());
    toolkit.registerTool(new FileOperationTools());

    // 构建 Agent 时传入 Toolkit
    ReActAgent agent = ReActAgent.builder()
    .name("assistant")
    .model("dashscope:qwen-plus")
    .sysPrompt("你是一个全能助手。")
    .toolkit(toolkit)
    .build();

    4.3 工具调用流程

    用户消息到达


    Agent 推理(Reasoning)

    ▼ 模型决定调用工具
    ┌─────────────────────────────────────────────────────────┐
    │ Toolkit.execute(toolUseBlock) │
    │ │
    │ 1. 根据 toolName 查找已注册工具 │
    │ 2. 权限检查(PermissionEngine) │
    │ 3. 参数反序列化(JSON → Java 对象) │
    │ 4. 调用工具方法 │
    │ 5. 结果序列化(Java 对象 → String/JSON) │
    │ 6. 返回 ToolResultBlock │
    └─────────────────────────────────────────────────────────┘


    Agent 继续推理(下一轮 Reasoning)

    4.4 工具批处理(_ToolCallBatch)

    当模型在一轮推理中同时请求调用多个工具时,Toolkit 支持并发批处理:

    模型输出: [ToolUseBlock_1, ToolUseBlock_2, ToolUseBlock_3]


    Toolkit.executeBatch()

    ├── 并发执行 Tool_1 ──→ Result_1
    ├── 并发执行 Tool_2 ──→ Result_2
    └── 并发执行 Tool_3 ──→ Result_3


    合并为 [ToolResultBlock_1, ToolResultBlock_2, ToolResultBlock_3]

    生产意义:并发执行显著减少多工具调用场景的总耗时,从串行的 T1+T2+T3 降低为 max(T1,T2,T3)。

    五、ToolGroup:按域组织与动态激活

    5.1 设计动机

    在实际业务中,一个 Agent 可能注册了 20+ 个工具,但不同场景下只需要激活其中一部分:

    • 客服场景:只需订单查询、物流追踪
    • 运维场景:需要服务器监控、日志查询
    • 开发场景:需要代码搜索、文件编辑

    5.2 ToolGroup 定义

    // 定义工具组
    ToolGroup customerServiceGroup = ToolGroup.builder()
    .name("customer-service")
    .description("客服相关工具")
    .tools("query_order", "track_logistics", "refund_request")
    .build();

    ToolGroup devOpsGroup = ToolGroup.builder()
    .name("devops")
    .description("运维相关工具")
    .tools("check_server", "query_logs", "restart_service")
    .build();

    // 注册到 Toolkit
    toolkit.registerGroup(customerServiceGroup);
    toolkit.registerGroup(devOpsGroup);

    5.3 动态激活/停用

    // 运行时动态切换工具组
    toolkit.activateGroup("customer-service");
    toolkit.deactivateGroup("devops");

    // Agent 此时只能看到客服工具
    // 模型不会收到 devops 工具的描述

    5.4 Agent 自主管理工具组

    AgentScope 2.0 支持 Agent 自主决定激活/停用工具组:

    // 内置元工具:ResetTools
    // Agent 可以通过调用 reset_tools 工具来切换自己的工具集
    @Tool(name = "reset_tools", description = "切换当前可用的工具组")
    public String resetTools(
    @ToolParam(name = "group_name", description = "要激活的工具组名称")
    String groupName) {
    toolkit.activateGroup(groupName);
    return "已切换到工具组: " + groupName;
    }

    设计哲学:让模型自己决定需要什么能力,而非框架强制编排。

    六、内置工具集详解

    6.1 工具全景

    AgentScope Java 2.0 通过 HarnessAgent 提供了一套开箱即用的内置工具:

    工具功能权限级别
    Bash 执行 Shell 命令 高危(需权限管控)
    Read 读取文件内容 低危
    Write 写入文件 中危
    Edit 编辑文件(精确替换) 中危
    Glob 文件名模式匹配 低危
    Grep 文件内容搜索 低危
    Skill 查看可用技能 低危
    ResetTools 切换工具组(元工具) 中危

    6.2 Bash 工具:最复杂的权限检查

    public class BashTool extends ToolBase {

    @Override
    public ToolResult execute(Map<String, Object> input, ToolContext ctx) {
    String command = (String) input.get("command");

    // 1. 内置安全检查(不可绕过)
    SecurityCheckResult check = validateCommand(command);
    if (!check.isSafe()) {
    return ToolResult.error("命令被安全策略拦截: " + check.getReason());
    }

    // 2. 在沙箱中执行
    ProcessResult result = sandbox.execute(command,
    Duration.ofSeconds(30)); // 超时保护

    // 3. 截断过长输出
    String output = truncate(result.getOutput(), MAX_OUTPUT_LENGTH);

    return ToolResult.success(output);
    }
    }

    安全特性:

    • 危险命令黑名单(rm -rf /、mkfs、dd if=)
    • 敏感路径保护(~/.ssh/、/etc/passwd、.env)
    • 执行超时保护
    • 输出长度截断
    • 沙箱隔离执行

    6.3 文件操作工具(Read/Write/Edit)

    // Read:读取文件
    @Tool(name = "read_file", description = "读取指定文件的内容")
    public String readFile(
    @ToolParam(name = "file_path", description = "文件路径") String filePath,
    @ToolParam(name = "offset", description = "起始行号", required = false) Integer offset,
    @ToolParam(name = "limit", description = "读取行数", required = false) Integer limit) {
    // 支持分页读取大文件
    }

    // Write:写入文件
    @Tool(name = "write_file", description = "将内容写入指定文件")
    public String writeFile(
    @ToolParam(name = "file_path", description = "文件路径") String filePath,
    @ToolParam(name = "content", description = "要写入的内容") String content) {
    // 自动创建目录、权限检查
    }

    // Edit:精确编辑
    @Tool(name = "edit_file", description = "精确替换文件中的指定内容")
    public String editFile(
    @ToolParam(name = "file_path", description = "文件路径") String filePath,
    @ToolParam(name = "old_string", description = "要替换的原文") String oldString,
    @ToolParam(name = "new_string", description = "替换后的内容") String newString) {
    // 精确匹配替换,避免全文重写
    }

    6.4 搜索工具(Glob/Grep)

    // Glob:文件名匹配
    @Tool(name = "glob", description = "按模式匹配搜索文件")
    public String glob(
    @ToolParam(name = "pattern", description = "匹配模式,如 **/*.java") String pattern) {
    // 返回匹配的文件路径列表
    }

    // Grep:内容搜索
    @Tool(name = "grep", description = "在文件中搜索指定内容")
    public String grep(
    @ToolParam(name = "pattern", description = "搜索模式(正则)") String pattern,
    @ToolParam(name = "path", description = "搜索路径", required = false) String path,
    @ToolParam(name = "include", description = "文件过滤", required = false) String include) {
    // 返回匹配行及上下文
    }

    6.5 Skill 工具与 ResetTools 元工具

    // Skill:查看可用技能描述
    @Tool(name = "skill", description = "查看指定技能的详细说明")
    public String viewSkill(
    @ToolParam(name = "skill_name", description = "技能名称") String skillName) {
    // 返回 workspace/skills/ 目录下的技能文档
    }

    // ResetTools:切换工具组
    @Tool(name = "reset_tools", description = "重置当前可用的工具集")
    public String resetTools(
    @ToolParam(name = "tools", description = "要激活的工具列表") List<String> tools) {
    // 动态调整 Agent 可见的工具集
    }

    七、ToolBase 协议:统一工具抽象

    7.1 接口定义

    public interface AgentTool {

    /** 工具名称(唯一标识) */
    String getName();

    /** 工具描述(给 LLM 看的) */
    String getDescription();

    /** 参数 JSON Schema */
    Map<String, Object> getParameterSchema();

    /** 执行工具 */
    ToolResult execute(Map<String, Object> input, ToolContext ctx);

    /** 是否为外部工具(前端执行) */
    default boolean isExternalTool() { return false; }

    /** 安全检查(不可绕过) */
    default boolean isSafe(Map<String, Object> input) { return true; }
    }

    7.2 ToolBase 抽象基类

    public abstract class ToolBase implements AgentTool {

    private final String name;
    private final String description;
    private final Map<String, Object> parameterSchema;
    private final boolean externalTool;

    /**
    * 安全检查 —— 在 PermissionEngine 之前执行,不可绕过
    */

    @Override
    public boolean isSafe(Map<String, Object> input) {
    return true; // 子类可覆写
    }

    /**
    * 实际执行逻辑
    */

    @Override
    public abstract ToolResult execute(Map<String, Object> input, ToolContext ctx);
    }

    7.3 两种适配器

    适配器说明适用场景
    ReflectiveFunctionTool 将 @Tool 注解方法适配为 AgentTool 业务自定义工具
    McpTool 将 MCP Server 的远程工具适配为 AgentTool 外部 MCP 集成

    7.4 externalTool 机制

    // 前端工具:不在后端执行,而是发送事件给前端
    public class ApprovalTool extends ToolBase {

    public ApprovalTool() {
    super("request_approval", "请求人工审批", schema, true); // externalTool = true
    }

    @Override
    public ToolResult execute(Map<String, Object> input, ToolContext ctx) {
    // 不会实际执行,而是触发 PermissionRequestEvent
    // Agent 暂停,等待前端用户操作后恢复
    throw new ExternalToolExecutionException();
    }
    }

    设计意图:支持 HITL(Human-in-the-Loop)场景,某些"工具"的执行主体是前端用户而非后端服务。

    八、MCP 协议集成

    8.1 声明式接入

    AgentScope 2.0 通过 workspace/tools.json 实现一行声明一个 MCP Server:

    {
    "mcpServers": {
    "github": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-github"],
    "env": {
    "GITHUB_TOKEN": "${GITHUB_TOKEN}"
    }
    },
    "postgres": {
    "url": "http://localhost:3001/sse",
    "transport": "sse"
    },
    "slack": {
    "command": "python",
    "args": ["-m", "mcp_slack_server"],
    "transport": "stdio"
    }
    }
    }

    8.2 支持的传输协议

    协议说明适用场景
    stdio 标准输入输出 本地进程
    sse Server-Sent Events HTTP 长连接
    ws WebSocket 双向实时通信

    8.3 工具发现流程

    Agent 启动


    读取 workspace/tools.json


    ┌─────────────────────────────────────────────────────────┐
    │ 对每个 MCP Server: │
    │ 1. 建立连接(stdio/sse/ws) │
    │ 2. 调用 tools/list 获取工具列表 │
    │ 3. 将每个远程工具适配为 McpTool(实现 AgentTool 接口) │
    │ 4. 注册到 Toolkit │
    └─────────────────────────────────────────────────────────┘


    Agent 可调用所有本地 + 远程工具

    8.4 工具命名冲突解决

    当多个 MCP Server 暴露同名工具时,按以下优先级保留:

    优先级来源说明
    最高 Toolkit 中 Java 端注册的工具 本地优先
    第一个启动成功的 MCP Server 先到先得
    后续同名工具 被忽略 + WARN 日志

    8.5 McpMeta:调用元数据

    // MCP 工具调用时可传递元数据
    McpMeta meta = McpMeta.builder()
    .sessionId(ctx.getSessionId())
    .userId(ctx.getUserId())
    .build();

    九、工具分组与过滤:workspace/tools.json + toolFilter

    9.1 配置化工具过滤

    2.0 提供 ToolsConfig 按 allow/deny 精确匹配过滤:

    {
    "roles": {
    "customer-service": {
    "allow": ["query_order", "track_logistics", "get_weather"],
    "deny": ["bash", "write_file", "edit_file"]
    },
    "dba": {
    "allow": ["execute_sql", "read_file", "grep"],
    "deny": ["bash", "write_file"]
    },
    "admin": {
    "allow": ["*"],
    "deny": []
    }
    }
    }

    9.2 Java 端配置

    HarnessAgent agent = HarnessAgent.builder()
    .name("customer-service-agent")
    .model("dashscope:qwen-plus")
    .toolkit(toolkit)
    .toolFilter(ToolsConfig.builder()
    .allow("query_order", "track_logistics", "get_weather")
    .deny("bash", "write_file", "edit_file")
    .build())
    .build();

    9.3 设计优势

    同一套工具,两个角色,两个视野。

    • Toolkit 注册全量工具(一次注册)
    • ToolsConfig 按角色过滤(多次复用)
    • 新增角色只需加配置,不改 Java 代码

    十、工具与权限系统的集成

    10.1 执行链路

    模型决定调用工具


    ┌─────────────────────────────────────────────────────────┐
    │ Step 1: ToolBase.isSafe() —— 工具自身安全检查(不可绕过) │
    └──────────────────────────────┬──────────────────────────┘
    │ 通过

    ┌─────────────────────────────────────────────────────────┐
    │ Step 2: PermissionEngine.evaluate() —— 权限规则匹配 │
    │ DENY 规则 → ASK 规则 → ALLOW 规则 → Mode 默认 → 兜底 │
    └──────────────────────────────┬──────────────────────────┘
    │ ALLOW

    ┌─────────────────────────────────────────────────────────┐
    │ Step 3: Middleware.onActing() —— 中间件拦截 │
    │ 追踪 / 审计 / 限流 / 参数校验 │
    └──────────────────────────────┬──────────────────────────┘


    ┌─────────────────────────────────────────────────────────┐
    │ Step 4: ToolBase.execute() —— 实际执行 │
    │ 在沙箱中执行,超时保护,输出截断 │
    └─────────────────────────────────────────────────────────┘

    10.2 沙箱执行

    // 工具在沙箱中执行,隔离宿主环境
    SandboxConfig sandbox = SandboxConfig.builder()
    .type(SandboxType.DOCKER) // LOCAL / DOCKER / E2B
    .image("agentscope-sandbox:latest")
    .workspacePath("/workspace")
    .timeout(Duration.ofSeconds(30))
    .memoryLimit("512m")
    .cpuLimit(1.0)
    .build();

    十一、工具与事件系统的集成

    11.1 工具调用事件

    每次工具调用都会产生对应的事件:

    agent.streamEvents(userMsg, ctx)
    .doOnNext(event -> {
    switch (event.getType()) {
    case TOOL_CALL_START -> {
    ToolCallStartEvent e = (ToolCallStartEvent) event;
    System.out.println("🔧 调用工具: " + e.getToolCallName());
    System.out.println(" 参数: " + e.getParameters());
    }
    case TOOL_CALL_END -> {
    ToolCallEndEvent e = (ToolCallEndEvent) event;
    System.out.println("✅ 工具完成: " + e.getToolCallName());
    System.out.println(" 耗时: " + e.getDuration() + "ms");
    }
    case TOOL_RESULT -> {
    ToolResultEvent e = (ToolResultEvent) event;
    System.out.println("📋 结果: " + truncate(e.getContent(), 200));
    }
    }
    })
    .subscribe();

    11.2 事件序列

    ToolCallStartEvent (工具名、参数)

    ├── [如果 ASK] → PermissionRequestEvent → 等待 → PermissionResponseEvent

    ├── [执行中…]

    └── ToolCallEndEvent (耗时、状态)
    └── ToolResultEvent (执行结果)

    十二、完整实战:构建多工具业务 Agent

    12.1 场景描述

    构建一个电商客服 Agent:

    • 可查询订单、追踪物流
    • 可申请退款(需人工审批)
    • 可查询天气(辅助推荐)
    • 不能执行系统命令

    12.2 完整代码

    public class EcommerceAgentDemo {

    public static void main(String[] args) {

    // === 1. 定义业务工具 ===
    Toolkit toolkit = new Toolkit();

    // 订单工具
    toolkit.registerTool(new Object() {
    @Tool(name = "query_order", description = "查询订单详情")
    public String queryOrder(
    @ToolParam(name = "order_id", description = "订单号") String orderId,
    RuntimeContext ctx) {
    return orderService.getOrder(ctx.getUserId(), orderId).toJson();
    }

    @Tool(name = "track_logistics", description = "追踪物流状态")
    public String trackLogistics(
    @ToolParam(name = "order_id", description = "订单号") String orderId) {
    return logisticsService.track(orderId).toJson();
    }
    });

    // 退款工具(外部工具,需前端审批)
    toolkit.registerTool(new Object() {
    @Tool(name = "request_refund", description = "申请退款")
    public String requestRefund(
    @ToolParam(name = "order_id", description = "订单号") String orderId,
    @ToolParam(name = "reason", description = "退款原因") String reason,
    RuntimeContext ctx) {
    // 标记为 externalTool,触发 HITL 审批
    return "REFUND_PENDING_APPROVAL";
    }
    });

    // 天气工具
    toolkit.registerTool(new WeatherTools());

    // === 2. 配置工具过滤 ===
    ToolsConfig toolFilter = ToolsConfig.builder()
    .allow("query_order", "track_logistics", "request_refund", "get_weather")
    .deny("bash", "write_file", "edit_file") // 禁止危险操作
    .build();

    // === 3. 配置权限 ===
    PermissionContextState permCtx = PermissionContextState.builder()
    .mode(PermissionMode.DEFAULT)
    .addAllowRule("query_order", PermissionRule.allow("query_order"))
    .addAllowRule("track_logistics", PermissionRule.allow("track_logistics"))
    .addAllowRule("get_weather", PermissionRule.allow("get_weather"))
    .addAskRule("request_refund", PermissionRule.ask("request_refund"))
    .build();

    // === 4. 构建 Agent ===
    HarnessAgent agent = HarnessAgent.builder()
    .name("ecommerce-cs")
    .sysPrompt("""
    你是电商客服助手。你可以:
    – 查询订单详情
    – 追踪物流状态
    – 申请退款(需要用户确认)
    – 查询天气
    你不能执行任何系统命令或修改文件。
    """
    )
    .model("dashscope:qwen-plus")
    .toolkit(toolkit)
    .toolFilter(toolFilter)
    .permissionContext(permCtx)
    .middleware(new OtelTracingMiddleware())
    .middleware(new AuditMiddleware())
    .build();

    // === 5. 流式调用 ===
    RuntimeContext rt = RuntimeContext.builder()
    .sessionId("session-001")
    .userId("user-alice")
    .build();

    agent.streamEvents(
    new UserMessage("帮我查一下订单 ORD-2024-001 的物流状态"),
    rt
    )
    .doOnNext(event -> {
    if (event instanceof TextBlockDeltaEvent delta) {
    System.out.print(delta.getDelta());
    }
    if (event instanceof ToolCallStartEvent toolStart) {
    System.out.println("\\n🔧 [" + toolStart.getToolCallName() + "]");
    }
    if (event instanceof PermissionRequestEvent permReq) {
    System.out.println("\\n⚠️ 需要审批: " + permReq.getToolName());
    }
    })
    .blockLast();
    }
    }

    12.3 执行效果

    用户: 帮我查一下订单 ORD-2024-001 的物流状态

    🔧 [track_logistics]
    Agent: 您的订单 ORD-2024-001 的物流状态如下:

    📦 当前状态:运输中
    🚚 承运商:顺丰速运
    📍 当前位置:杭州转运中心
    ⏰ 预计送达:2026-08-09 14:00

    物流轨迹:
    – 08-07 08:30 到达杭州转运中心
    – 08-06 22:15 从上海仓库发出
    – 08-06 18:00 商家已发货

    如需进一步帮助,请随时告诉我。

    十三、从 1.x 到 2.0 的工具系统演进

    13.1 对比总结

    维度1.x2.0
    工具定义 继承 Tool 抽象类 @Tool 注解 + 反射
    Schema 生成 手动编写或半自动 全自动生成
    工具管理 简单列表 Toolkit + ToolGroup
    动态激活 不支持 ToolGroup 动态切换
    权限管控 PermissionEngine 六步决策
    沙箱执行 LOCAL / DOCKER / E2B
    MCP 集成 tools.json 声明式
    工具过滤 硬编码 ToolsConfig 配置化
    批处理 串行 并发执行
    事件追踪 ToolCallStart/End/Result
    前端工具 externalTool 机制

    13.2 迁移示例

    1.x 写法:

    // 1.x: 继承抽象类,手动实现
    public class WeatherTool extends Tool {
    @Override
    public String getName() { return "get_weather"; }

    @Override
    public String getDescription() { return "获取天气"; }

    @Override
    public Map<String, Object> getParameterSchema() {
    // 手动编写 JSON Schema…
    }

    @Override
    public String execute(Map<String, Object> params) {
    return weatherApi.query((String) params.get("city"));
    }
    }

    2.0 写法:

    // 2.0: 注解驱动,零样板代码
    public class WeatherTools {
    @Tool(name = "get_weather", description = "获取天气")
    public String getWeather(
    @ToolParam(name = "city", description = "城市名") String city) {
    return weatherApi.query(city);
    }
    }

    十四、设计哲学与最佳实践

    14.1 核心设计原则

    原则体现
    注解驱动 > 继承 @Tool 比继承 Tool 类更轻量、更 Java 化
    自动 > 手动 JSON Schema 自动生成,无需手写
    配置 > 代码 tools.json 声明 MCP,toolFilter 配置过滤
    安全不可绕过 ToolBase.isSafe() 在权限系统之前执行
    模型自主 Agent 自己决定调用哪个工具、何时调用
    响应式原生 同步/异步/流式全覆盖

    14.2 最佳实践

  • 工具描述要精确:LLM 依赖 description 决定何时调用,模糊描述会导致误调用
  • 参数描述要具体:包含示例值、取值范围、格式要求
  • 单一职责:每个工具只做一件事,避免"万能工具"
  • 错误信息要有用:返回的错误信息应指导 LLM 如何修正
  • 输出要截断:避免超长输出撑爆上下文
  • 敏感操作加 ASK:删除、修改、支付等操作必须人工确认
  • 使用 ToolGroup 管理可见性:避免 20+ 工具全部暴露给模型
  • 14.3 工具描述编写指南

    // ❌ 差的描述
    @Tool(name = "search", description = "搜索")

    // ✅ 好的描述
    @Tool(name = "search_orders",
    description = "根据订单号、用户ID或时间范围搜索订单。" +
    "返回订单列表(最多20条)。" +
    "如果用户只提供了模糊信息,先用此工具确认具体订单。")

    十五、与其他构建块的协作关系

    ┌─────────────────────────────────────────────────────────────────┐
    │ Agent 层 │
    │ ReAct 循环:Reasoning → Acting → Observation → Reasoning │
    └──────────────────────────────┬──────────────────────────────────┘
    │ 决定调用工具

    ┌─────────────────────────────────────────────────────────────────┐
    │ Middleware 层 │
    │ onActing: 追踪 / 限流 / 审计 / 参数校验 │
    └──────────────────────────────┬──────────────────────────────────┘


    ┌─────────────────────────────────────────────────────────────────┐
    │ Permission 层 │
    │ PermissionEngine: DENY → ASK → ALLOW → Mode → 兜底 │
    └──────────────────────────────┬──────────────────────────────────┘
    │ ALLOW

    ┌─────────────────────────────────────────────────────────────────┐
    │ Tool 层 │
    │ Toolkit → ToolBase.execute() → 沙箱执行 → 返回结果 │
    └──────────────────────────────┬──────────────────────────────────┘


    ┌─────────────────────────────────────────────────────────────────┐
    │ Event 层 │
    │ ToolCallStartEvent → ToolCallEndEvent → ToolResultEvent │
    └──────────────────────────────┬──────────────────────────────────┘


    ┌─────────────────────────────────────────────────────────────────┐
    │ Message 层 │
    │ ToolUseBlock (ASSISTANT) → ToolResultBlock (TOOL) │
    │ 写入 AgentState,参与上下文压缩 │
    └─────────────────────────────────────────────────────────────────┘

    十六、结语

    AgentScope Java 2.0 的 Tool 构建块,用注解驱动将工具定义简化到极致,用自动 Schema 生成消除了手写 JSON 的繁琐,用 Toolkit + ToolGroup 实现了灵活的工具编排,用 MCP 协议打通了外部工具生态,用权限系统 + 沙箱守住了安全底线。 它的核心价值在于:

    让"给 Agent 加一个能力"这件事,从"写一个类 + 配一堆 Schema + 处理一堆异常",变成"加一个注解"。

    对于 Java 开发者而言,这套设计完美契合了 Spring 生态的注解驱动传统——@Tool 之于 AgentScope,就像 @RestController 之于 Spring MVC:一个注解,开启一个世界。

    工具定义了智能体"能做什么",权限定义了"允许做什么",事件定义了"正在做什么"。三者合一,构成了一个既能做事、又受约束、还可观测的智能体执行体系。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » AgentScope 2.0:8. Tool —— 工具系统架构与生产级实践深度解析
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!