概述
Tool 是 agent 与外部世界交互的方式 —— 执行业务操作、调用 API、读写数据等。每个 tool 通过 JSON Schema 暴露给 LLM,agent 通过统一接口完成调用。 AgentScope 把 tool 相关的构件组织成三个概念:- Tool —— 任意实现
AgentTool接口(通常通过继承ToolBase)或在普通类的方法上标注@Tool注解的对象。Java 端把后者称为 reflective function tool,由Toolkit#registerTool(Object)自动反射注册。 - Toolkit —— 容器,负责注册 tool、MCP 客户端与 skill,向模型暴露它们的 JSON schema,并把每次工具调用分发到对应的 tool 对象。
- Tool Group —— 一组带名称的 tool / MCP / skill 集合,可以作为整体激活或停用。Agent 在运行时通过内置 meta tool 切换 group,让上下文保持聚焦。
registerTool(Object) 时,被注册对象上所有 @Tool 方法都进入特殊的 "basic" 组 —— 该组始终激活。追加 MCP 客户端、tool group 或 skill 即可拓展 agent 的能力 —— 见下文各节。
Java Tool
Java tool 是任意满足AgentTool 契约的对象。AgentScope 同时提供了一个 ToolBase 抽象基类用于显式建模带参数 schema 的 tool,以及一个反射适配器用于把普通方法包装成 tool。
AgentTool / ToolBase 接口
ToolBase 是 AgentTool 的抽象实现,下表列出其属性与方法。
向 agent 与运行时描述 tool 的属性:
接入执行流程与权限系统的方法:
使用内置 Tool
AgentScope 当前提供以下内置 tool:
使用方式:
自定义 Tool(注解式)
最轻量的写法:在普通类的方法上标注@Tool 与 @ToolParam,然后通过 Toolkit#registerTool(Object) 反射注册。框架自动从 Java 类型推导 JSON schema,从 description 取面向 agent 的说明。
@Tool 常用属性:
自定义 Tool(继承 ToolBase)
需要自定义权限策略、外部执行或更复杂的 schema 时,继承 ToolBase:
定义外部执行 Tool
外部执行 tool 把实际执行委派给 agent 运行时之外 —— 通常是人工操作员或外部系统。Agent 调用此类 tool 时会发出RequireExternalExecutionEvent 并暂停。下一次调用回传匹配的 ToolResultBlock 后,agent 会发出带有相同 replyId 的 ExternalExecutionResultEvent,然后继续执行。
这种模式是 human-in-the-loop 工作流的基础 —— 某些动作需要人工确认或人工执行。
创建外部执行 tool 只需把 externalTool 设为 true,不必实现 callAsync:
agentscope-examples/documentation/.../tool/ToolBaseExample.java、tool/ToolExecutionContextExample.java。
接收 Context
每次agent.call(msgs, runtimeContext) 传入的 RuntimeContext 会自动透传到所在 reply 内每一次工具调用。Tool 可以用两种方式拿到它:注解式 tool 走自动注入,ToolBase.callAsync 走 ToolCallParam。
自动注入(@Tool 方法)
@Tool 方法签名里,没有标注 @ToolParam 的参数会被框架视为「需要从框架注入」,并按下表的优先级解析:
「用户自定义 POJO」的判定:参数没有
@ToolParam、不是基本类型、不是 ContentBlock / Msg、不在 java.* / javax.* 包下。其余参数(带 @ToolParam 或属于上述兜底类型)从 LLM 提供的 JSON 输入按名称取值。
call 就会自动把对应实例分发到所有需要它的 tool:
userCtx 写进 JSON 参数——schema 里也不会出现它。完整示例:agentscope-examples/documentation/.../tool/ToolExecutionContextExample.java。
ToolBase.callAsync 中访问
继承 ToolBase 的 tool 通过 ToolCallParam 取 context:
ToolCallParam 同时暴露 getAgent()、getInput()、getEmitter()、getToolUseBlock() 以及(已 deprecated 的)getContext()。新代码使用 getRuntimeContext()。
协调 hook 与 tool
RuntimeContext 的 string 层(put(String, Object) / get(String))是同一次 call 内 middleware 与 tool 之间的临时通信通道——middleware 在 onActing/onReasoning 等位置写入,tool 通过注入 RuntimeContext 参数读取;调用结束后该实例与 hook 一并解绑。
MCP
AgentScope 集成 Model Context Protocol (MCP),让 agent 可以接入任意 MCP 兼容的工具提供方。框架自动处理协议协商、工具发现与结果转换。 支持三种连接方式:- STDIO —— 本地进程 stdin/stdout 通信
- SSE / Streamable HTTP —— 远程 HTTP 长连接
mcp__{server_name}__{tool_name} 命名,避免冲突;标注了 readOnlyHint 的 tool 会被权限系统自动放行。
注册 MCP Tool
通过McpClientBuilder 构建 McpClientWrapper,再注册到 Toolkit:
- STDIO
- Streamable HTTP
- SSE
agentscope-examples/documentation/.../mcp/McpStdioExample.java、mcp/McpSseExample.java、mcp/McpStreamableHttpExample.java。
Skill
Skill 是基于 markdown 的指令集,无需写新工具代码即可拓展 agent 能力。每个 skill 是一个目录,包含一个带 frontmatter 元数据与详细指令的SKILL.md 文件。
与 tool 不同,skill 不能被直接调用。Agent 通过自动注册的查看器工具 load_skill_through_path 读取 skill 指令,再用现有的 tool 按指令执行。
注册 Skill
通过ReActAgent.builder().skillRepository(...) 直接挂载一个或多个 AgentSkillRepository。Builder 在 build() 时自动装配 DynamicSkillMiddleware,每次 call() 都会按 skill 来源刷新 skill prompt 与 tool group:
skillRepository(...) 按调用顺序追加(低 → 高优先级),同名 skill 后者覆盖前者;如需替换整批,调用 skillRepositories(List<AgentSkillRepository>)。
参考实现:agentscope-examples/documentation/.../skill/AgentSkillExample.java、skill/SkillWithToolGroupExample.java。
Skill 的工作方式
Toolkit 在含 skill 时,注册与查看分两阶段进行。
初始化阶段:
- Toolkit 扫描所有注册的 skill 来源,收集每个 skill 的名称、描述与目录。
- 自动把内置查看器工具
load_skill_through_path(实现位于io.agentscope.core.skill.SkillToolFactory)注册到skill-build-in-tools这个 tool group。 - 组装一段 system prompt 片段,列出可用 skill(仅名称与描述),并指示 agent 通过
load_skill_through_path读取完整内容。
调用示例:
- 返回请求的内容(
SKILL.mdmarkdown,或指定的资源文件)。 - 激活该 skill —— Toolkit 中与之绑定的 tool group 被启用,本轮对话余下时段都可调用 skill 自带的工具。如果
path不存在,查看器会返回错误并列出可用资源路径(SKILL.md始终排在第一位),便于 agent 重试。
Skill 不是 tool —— agent 不能直接调用 skill。它必须先用
load_skill_through_path 读取指令,再用其他 tool 按描述的步骤执行。Skill 执行脚本:配置 Shell 工具
Skill 只提供指令,真正的执行依赖 agent 已有的 tool。如果 skill 指令涉及脚本执行(例如scripts/run.py),agent 需要拥有 shell 执行能力:
ReActAgent—— 注册ShellCommandTool到 toolkit:
HarnessAgent—— harness 模块自带 workspace 感知的 shell 与文件工具(execute、read_file、write_file等),无需额外注册。
Skill + ToolGroup:按需披露工具
SkillToolGroup 把一组 tool 绑定到某个 skill name —— agent 加载该 skill 时 tool group 自动激活,未加载时 tool 不出现在模型 schema 中,减少上下文噪音。
load_skill_through_path 加载名为 data-analysis 的 skill 时,analysis-tools group 自动激活,其中的 tool 立即可用。配合 enableMetaTool(true),模型还可以通过 reset_tools 主动管理 tool group 的激活状态。
参考实现:agentscope-examples/documentation/.../skill/SkillWithToolGroupExample.java。
自我管理 Tool
内置 meta tool(reset_tools)让 agent 在运行时自我管理哪些 tool group 处于激活状态,从而保持上下文聚焦 —— 只有与当前任务相关的 tool 暴露给模型。
定义 Tool Group
ToolGroup 是带名称的 tool / MCP / skill 集合。把 group 注册到 Toolkit 后再用 builder 启用 meta tool:
ToolGroup 接收名称、描述、作用域(ToolGroupScope)以及初始激活态。保留名 "basic" 由 Toolkit#registerTool(Object) 自动构成,且始终激活。
使用 Meta Tool
只要存在至少一个非 basic 的 tool group,并通过enableMetaTool(true) 打开开关,Toolkit 就会自动注册 reset_tools 并把其 schema 暴露给 agent。每个非 basic group 在 schema 中表示为一个布尔字段,agent 调用 meta tool 时声明期望的最终状态。
运行时行为:
"basic"组中的 tool 始终暴露,meta tool 不会影响它们。- 每次调用
reset_tools都会整体覆盖激活集合 —— 任何未显式置为true的非 basic group 都会被停用,无论之前的状态。 - 对每个本次切换为激活的 group,其 description 与(若提供的)使用说明会被拼接进 meta tool 的返回值,告诉 agent 如何正确使用该组。
- 未激活 group 中的 tool 不会出现在 agent 的工具 schema 中,从而把上下文留给当前激活的工具集。
延伸阅读
Agent
Agent 如何在 ReAct 循环中编排 tool 调用
Permission System
精细控制哪个 tool 可以执行、何时执行
Middleware
用洋葱式 middleware 拦截并改写 tool 调用
Human-in-the-Loop
外部执行 tool 与人工审批工作流