随着工具数量的增加,一个自然的问题是:不同角色的Agent应该使用哪些工具?显然不能将所有工具都暴露给所有角色。本章将深入解析AgentScope 2.0提供的“工具分组”机制,并演示如何通过配置文件精确控制每个Agent可见和可调用的工具集合。核心思路是将工具权限从代码中解耦,实现可配置、可热更新的灵活方案。
第十三章 工具分组:使用workspace/tools.json和toolFilter按角色配置化限定工具权限
13.1 工具分组的两种方式
AgentScope 2.0 提供了两套“工具分组”机制,可以单独使用,也可组合使用:

| 方式 | 配置位置 | 适用场景 |
|---|---|---|
Java 端 Toolkit | HarnessAgent.builder().toolkit(toolkit) | 通过Java代码定义工具,编译后即固定不变 |
Java 端 toolsConfig | HarnessAgent.builder().toolsConfig(config) | 通过代码设置allow/deny,无需JSON文件,灵活配置 |
workspace tools.json | workspace/tools.json | 运行时可以修改,支持多环境差异化配置 |
13.2 第一个 tools.json
{
"tools": [
{ "name": "query_order", "class": "demo.tools.OrderTool", "description": "查订单" },
{ "name": "query_logistics", "class": "demo.tools.LogisticsTool", "description": "查物流" },
{ "name": "refund_order", "class": "demo.tools.RefundTool", "description": "退款" }
]
}
在启动时,HarnessAgent.builder().workspace(...) 会自动扫描 workspace/tools.json 并将工具注册到Agent中。需要注意的是,如果没有传递classpath,默认关闭此功能,需要显式开启:
HarnessAgent agent = HarnessAgent.builder()
...
.workspace(Path.of("./workspace"))
.loadWorkspaceTools(true) // 2.0 新增
.build();
13.3 角色级 toolFilter:allow / deny
一个 tools.json 文件可以同时定义工具列表和可见性规则:
{
"tools": [
{ "name": "query_order", "class": "demo.tools.OrderTool" },
{ "name": "query_logistics", "class": "demo.tools.LogisticsTool" },
{ "name": "refund_order", "class": "demo.tools.RefundTool" }
],
"toolFilter": {
"allow": ["query_order", "query_logistics"],
"deny": ["refund_order"]
}
}
行为:
allow白名单模式:仅允许名称精确匹配的工具,其余全部不可见deny黑名单模式:移除名称匹配的工具,其余全部可见allow和deny同时存在:deny 优先(先执行 allow 再执行 deny)
注意:使用精确工具名进行匹配,不支持通配符。 HarnessAgent 启动时会根据 toolFilter 对工具列表进行过滤,然后将过滤后的列表交给LLM。LLM无法看到的工具,其描述也不会出现在prompt中,从而避免“模型想调用却调用不到”的问题。
13.4 给 subagent 单独配置 tools.json
每个子Agent(subagent)可以在 workspace/subagents/ 文件中声明自己的工具集:
# customer_service.md
id: customer_service
description: 客服 agent;只能查订单和物流,不能退款
toolsFile: customer_service.tools.json
sysPrompt: |
你是客服,只能查订单和物流,不能直接退款。如需退款,转人工。
workspace/subagents/customer_service.tools.json:
{
"tools": [
{ "name": "query_order", "class": "demo.tools.OrderTool" },
{ "name": "query_logistics", "class": "demo.tools.LogisticsTool" }
],
"toolFilter": { "deny": ["refund_order"] }
}
13.5 在 Java 端过滤
如果不使用JSON文件,也可以通过 ToolsConfig 对象直接配置:
ToolsConfig config = new ToolsConfig();
config.setAllow(List.of("query_order", "query_logistics"));
config.setDeny(List.of("refund_order"));
HarnessAgent agent = HarnessAgent.builder()
...
.toolsConfig(config)
.build();
ToolsConfig 的语义与 tools.json 中的 toolFilter 字段完全一致。
13.6 工具权限的“四层防线”
在生产环境中,建议采用工具分组与Permission双保险机制:
第 1 层:工具注册(class必须在classpath中)
第 2 层:toolFilter(allow/deny精确匹配)
第 3 层:Permission规则(运行时再次校验)
第 4 层:Middleware(onModelCall/onActing,用于埋点和限流)
例如,若希望“退款”工具在运行时必须经过人工审批:
PermissionContextState perms = PermissionContextState.builder()
.mode(PermissionMode.ACCEPT_EDITS)
.addAskRule("refund_order",
new PermissionRule("refund_order", null, PermissionBehavior.ASK, "userSettings"))
.build();
HarnessAgent agent = HarnessAgent.builder()
.permissionContext(perms)
.build();
即使 LLM 想调 refund_order,Permission 也会拦下来问用户。
13.7 完整可运行示例
以下示例展示了如何设置不同角色的工具权限:
import io.agentscope.core.tool.Tool;
import io.agentscope.core.tool.Toolkit;
import io.agentscope.harness.agent.tools.ToolsConfig;
import io.agentscope.harness.HarnessAgent;
import java.util.List;
public class Chapter13_ToolFilter {
// 业务工具类:@Tool 注解标记方法名即工具名
public static class OrderTools {
@Tool(name = "query_order", description = "查询订单状态和详情")
public String queryOrder(String orderId) {
return "订单 " + orderId + ":已发货。";
}
}
public static class LogisticsTools {
@Tool(name = "query_logistics", description = "查询物流轨迹")
public String queryLogistics(String trackingId) {
return "物流 " + trackingId + ":快件在北京分拣中心。";
}
}
public static class RefundTools {
@Tool(name = "refund_order", description = "处理订单退款")
public String refundOrder(String orderId) {
return "订单 " + orderId + " 退款已处理。";
}
}
public static void main(String[] args) {
// 1. 全部工具注册到同一个 Toolkit
Toolkit baseToolkit = new Toolkit();
baseToolkit.registerTool(new OrderTools());
baseToolkit.registerTool(new LogisticsTools());
baseToolkit.registerTool(new RefundTools());
// 2. 客服 agent:deny "refund_order" — 看不到退款工具
ToolsConfig csConfig = new ToolsConfig();
csConfig.setDeny(List.of("refund_order"));
HarnessAgent customerService = HarnessAgent.builder()
.name("customer_service")
.sysPrompt("你是客服,只能查订单和物流。不能退款,如需退款请转人工。")
.model(model())
.workspace(Path.of("./workspace"))
.toolkit(baseToolkit)
.toolsConfig(csConfig)
.build();
// 3. 财务 agent:allow "refund_order" — 只能看到退款工具
ToolsConfig finConfig = new ToolsConfig();
finConfig.setAllow(List.of("refund_order"));
HarnessAgent finance = HarnessAgent.builder()
.name("finance")
.sysPrompt("你是财务,只处理退款。")
.model(model())
.workspace(Path.of("./workspace"))
.toolkit(baseToolkit)
.toolsConfig(finConfig)
.build();
// 问客服"订单 123 的状态"——能答
// 问客服"退款"——会说"请转人工"
// 问财务"订单 123 的状态"——看不到 query 工具
// 问财务"退款"——正常处理
}
}
13.8 本章小结
workspace/tools.json将工具配置从Java代码中分离,支持运行时修改。toolFilter通过 allow/deny 和精确工具名来限定每个角色可调用的工具。- subagent 可以声明自己的 toolsFile,独立配置工具集。
- 推荐采用四层防线保障工具权限:注册 → toolFilter → Permission → Middleware。
