首页
/ Agent Zero 工具开发指南:从 Tool 基类契约到插件化分发与验证

Agent Zero 工具开发指南:从 Tool 基类契约到插件化分发与验证

2026-09-14 11:15:41作者:宣海椒Queenly

本指南以 skills/a0-development/references/tools.md 为核心骨架,系统讲解 Agent Zero 框架中"工具(Tool)"的完整开发契约:包括 Tool 基类与 Response 返回协议、工具的发现与分发路径、四种存放位置的选择策略、提示词(Prompt)契约、进度上报与干预流程,以及配套 DOX 文档与测试验证规范。读完本文后,你将掌握在 Agent Zero 中新增一个自定义工具、将其正确注册为插件工具并为模型编写可用提示词的全部实操方法,并理解工具执行生命周期背后的源码原理。

工具在 Agent Zero 中的地位

在 Agent Zero 中,工具是 Agent 与外部世界交互的基本单元:模型的每次函数调用都会落到某个具体工具上,工具执行结果再写回消息历史,构成"模型发起调用 → 框架分发 → 工具执行 → 结果回填"的闭环。与许多框架将工具写成普通函数不同,Agent Zero 为工具定义了严格的类契约:所有工具都派生自 helpers.tool.Tool 基类,并实现统一的异步执行接口。

这套契约的核心文件(Source Anchors)如下:

职责 仓库路径
工具基类与响应契约 helpers/tool.py
核心工具目录的 DOX 契约 tools/AGENTS.md
工具分发路径(执行入口) agent.py
方法式工具的参考实现 tools/skills_tool.py
示例 profile 工具 agents/_example/tools/example_tool.py
提示词组织规范 prompts/AGENTS.md

工具基类契约:Tool 与 Response

最小可运行工具

所有工具都从 helpers.tool.Tool 派生,并实现 async def execute(self, **kwargs) -> Response。最小实现如下:

from helpers.tool import Tool, Response

class MyTool(Tool):
    async def execute(self, **kwargs) -> Response:
        return Response(message="done", break_loop=False)

从源码看,Tool 是抽象基类,execute@abstractmethod 装饰(见 helpers/tool.py),因此任何没有实现 execute 的子类都无法被实例化,这从语言层面保证了工具契约不会被绕过。

Response 返回协议

Response 是一个 dataclass(见 helpers/tool.py),字段含义如下:

字段 含义
message 作为工具结果追加到消息历史并回显给 Agent 的文本
break_loop True 时终止当前消息循环(如"任务完成,停止思考")
additional 可选的附加元数据,随工具结果一起写入(默认 None

break_loop 的执行语义可以在分发代码中得到验证:在 agent.py_execute_tool_request 中,只有当 response.break_loop 为真时,框架才会清空 pending 状态并直接返回工具消息,终止本轮循环。

工具实例的注入字段

Tool.__init__ 的签名(见 helpers/tool.py)表明,每个工具实例在构造时都会收到以下上下文:

  • agent:当前 Agent 实例,可访问历史、上下文、配置等;
  • name:工具名称(即模型调用时的 tool_name);
  • method:可选的方法名,用于"方法式工具"(method-style tool),例如 skills_tool:load 中的 load
  • args:模型传入的参数字典;
  • message:触发本次工具调用的原始消息;
  • loop_data:当前消息循环的状态数据。

其中 method 参数是方法式工具的关键:skills_tool 将多个动作(listsearchloadread_file)收敛在同一个工具类中,通过 action/method 参数分派(见 tools/skills_tool.py),这避免为每个动作单独创建一个工具文件。

工具发现与分发路径

当模型请求调用某个工具时,框架按以下链路完成分发:

  1. MCP 工具优先_execute_tool_request 首先尝试从 MCP 配置中查找同名工具(见 agent.py),若命中则直接使用 MCP 工具;
  2. 本地工具回退:未命中 MCP 时,调用 self.get_tool(...)
  3. 按 profile 层级搜索文件get_tool 通过 subagents.get_paths(self, "tools", name + ".py") 沿 Agent 的文件夹层级搜索名为 <tool_name>.py 的模块(见 agent.py),找到后用 extract_tools.load_classes_from_file 加载其中的 Tool 子类;
  4. 兜底 Unknown:若任何路径都找不到,则实例化 tools.unknown.Unknown 作为兜底,向 Agent 说明工具不存在。

工具执行前后还接入了扩展点与干预点,完整执行顺序(见 agent.py)为:

handle_intervention()          # 执行前检查暂停/干预
tool.before_execution()        # 打印调用参数、创建日志对象
extension "tool_execute_before" # 执行前扩展钩子
response = await tool.execute() # 执行工具本体
extension "tool_execute_after"  # 执行后扩展钩子
tool.after_execution(response)  # 清理结果写入历史并回显
handle_intervention()          # 执行后再次检查
if response.break_loop: return # 终止循环

值得注意,before_execution 会把每个参数通过 tool_output_update 扩展实时输出到界面,并打印彩色日志(见 helpers/tool.py);after_execution 则负责把结果文本 sanitize_string 后写入历史(hist_add_tool_result)并更新日志对象(见 helpers/tool.py)。因此工具实现者无需自己处理日志与历史回填。

工具的存放位置与选择策略

新工具放在哪里,直接决定它的作用域与分发优先级。框架按以下位置查找工具(优先级从高到低取决于 profile 层级):

位置 用途
tools/ 核心框架工具,只承载框架自带行为,不建议直接新增
plugins/<plugin>/tools/ 随插件分发的内置插件工具
usr/plugins/<plugin>/tools/ 用户级插件工具,自定义插件开发的首选位置
agents/<profile>/tools/ profile 级局部工具(需先验证当前版本的发现机制再依赖示例)

仓库现状印证了这一划分:核心工具如 a2a_chat.pysearch_engine.pyskills_tool.py 等直接位于 tools/ 下,而大量能力(编辑器、浏览器、邮件、语音等)都以插件形式打包在 plugins/ 各目录的 tools/ 子目录中。参考 tools/AGENTS.md 的 Ownership 声明,绝大多数新工具应当打包进插件,而不是直接塞进根级 tools/,否则会破坏"核心目录只承载框架行为"的边界。

Prompt 契约:让模型学会使用工具

仅有 Python 类还不够——模型必须知道工具的存在、JSON 参数形状与使用时机。因此每个工具都需要一个面向 Agent 的提示词片段(Prompt Fragment),框架按文件名约定自动装载:agent.system.tool.<tool_name>.md

常见放置位置:

  • 核心工具提示词:prompts/agent.system.tool.<tool_name>.md(如 prompts/agent.system.tool.a2a_chat.md);
  • 插件工具提示词:plugins/<plugin>/prompts/agent.system.tool.<tool_name>.md
  • 用户插件提示词:usr/plugins/<plugin>/prompts/agent.system.tool.<tool_name>.md
  • profile 覆盖提示词:agents/<profile>/prompts/agent.system.tool.<tool_name>.md

参考仓库中的示例工具,agents/_example/tools/example_tool.py 对应提示词 agents/_example/prompts/agent.system.tool.example_tool.md,其中明确写道"该文件因命名为 agent.system.tool.*.md 而自动被包含进系统提示词",并给出了模型的调用 JSON 示例:

{
    "thoughts": [
        "Let's test the example tool...",
    ],
    "headline": "Testing example tool",
    "tool_name": "example_tool",
    "tool_args": {
        "test_input": "XYZ",
    }
}

prompts/AGENTS.md 进一步给出提示词开发红线:不得在模板中放入密钥、真实 API Key 或用户私有数据;修改占位符与文件名前必须先阅读渲染路径;prompt 变更会改变 Agent 行为,编辑应保持窄而有意。

变更纪律:凡是改动工具名、参数形状、输出行为、安全规则或 break_loop 语义,都必须同步更新对应的提示词片段与测试。这是因为提示词与代码是同一契约的两面,只改一边必然造成模型调用与实际实现脱节。

进度上报与人工干预

对长耗时或需要外部结果的工作流,工具实现者应遵循以下规范:

  • await self.set_progress(...):通过 tool_output_update 扩展把进度实时推送到界面,同时写入本地 self.progress(见 helpers/tool.py);
  • self.add_progress(...):仅在本地累积进度文本,不触发扩展事件(见 helpers/tool.py),适用于不希望频繁刷界面的场景;
  • 暂停/干预:对于长运行或依赖外部结果的工作流,按 tools/AGENTS.md 的 Local Contracts,应在关键节点使用 await self.agent.handle_intervention(...)(定义见 agent.py),让暂停/干预流程生效。分发代码在 before_execution 前后、execute 前后共插入四次干预检查点,工具执行期间 Agent 随时可以被安全暂停;
  • 安全规范:工具输出在写入日志或返回前必须脱敏/掩码(sanitize 与 mask),严禁把密钥、凭据泄露进日志或消息历史。after_execution 中对 message 调用 sanitize_string 正是这一规范的底层防线。

核心工具的 DOX 文档契约

Agent Zero 对根级核心工具实施"文件级 DOX"(file-documented DOX)制度:

  • 规则tools/ 下的每个直接 *.py 工具模块,必须有同目录下同名追加 .dox.md 的配套文档(即 tools/*.pytools/*.py.dox.md),例如 tools/search_engine.py 对应 tools/search_engine.py.dox.mdtools/a2a_chat.py 对应 tools/a2a_chat.py.dox.md
  • DOX 文件拥有的内容:工具用途、参数/概念、输出与 break_loop 行为、副作用、重要辅助依赖、提示词契约说明与验证指引(见 tools/AGENTS.md Local Contracts);
  • 同步义务:工具模块的新增、删除、改名或行为变更,必须与配套 DOX 在同一变更中完成,不允许删除/改名后遗留过期 DOX;
  • 边界:插件工具的工具文档属于该插件自己的 docs 或 DOX 契约,不应写入根级 tools/,从而保持核心目录文档的纯粹性。

验证与测试

工具改动后的验证路径分为四层:

  1. 定向工具测试:修改工具或其提示词契约后,运行该工具的针对性测试;
  2. 提示词/快照测试:当工具指令或输出形状变化时,运行 prompt/snapshot 相关测试,防止系统提示词预算或渲染结果漂移(可参考 tests/test_prompt_protocol.py 等测试);
  3. DOX 覆盖检查:对根级核心工具,用脚本或 shell 循环逐一核对每个 tools/*.py 都有同名 .py.dox.md(这正是 tools/AGENTS.md Verification 一节要求的标准做法);
  4. 插件级检查:若工具属于插件作用域,还需按该插件自身 AGENTS.md 执行插件专属检查项。

实战:从零新增一个插件工具的 Checklist

综合上述契约,在 Agent Zero 中新增一个自定义插件工具的最小工作流如下:

  1. 在插件目录(推荐 usr/plugins/<plugin>/tools/)创建 my_tool.py,定义 class MyTool(Tool) 并实现 async def execute(self, **kwargs) -> Response
  2. 依据执行语义正确设置 Response(message=..., break_loop=...),需要元数据时补充 additional
  3. usr/plugins/<plugin>/prompts/ 创建 agent.system.tool.my_tool.md,写明工具名、JSON 参数形状、使用时机与示例调用;
  4. 长流程中使用 await self.set_progress(...) 上报进度、await self.agent.handle_intervention(...) 尊重暂停/干预,输出前对敏感信息脱敏;
  5. 为该工具补充插件内的文档(DOX 或 docs),并运行定向测试、prompt/snapshot 测试与插件专属检查。

遵循以上五步,即可让一个新的工具能力被框架自动发现、被模型正确调用、被日志系统完整记录,并保持与 Agent Zero 核心契约长期兼容。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
34
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.21 K
2.81 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
945
1.86 K
docsdocs
暂无描述
Markdown
906
5.84 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
537
607
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
864
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
4.28 K
1.03 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.39 K
1.48 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
550
401
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.19 K
347