news 2026/9/15 11:25:45

Agent Zero 插件开发实战:从 plugin.yaml 到 Plugin Hub 的全栈插件创建指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent Zero 插件开发实战:从 plugin.yaml 到 Plugin Hub 的全栈插件创建指南

Agent Zero 插件开发实战:从 plugin.yaml 到 Plugin Hub 的全栈插件创建指南

【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero

导读

本文以 Agent Zero 内置技能 a0-create-plugin/AGENTS.md 及其核心载体 SKILL.md 为主干,系统讲解在 Agent Zero 中创建、扩展、修改插件的完整工作流。读完本文,你将掌握插件清单plugin.yaml的字段语义、usr/plugins/目录布局规范、前端 Store Gate 与 A0 通知体系、后端 AgentContext 与插件配置读写、execute.pyhooks.py的生命周期用法,以及社区插件从 GitHub 仓库到 Plugin Index 提交的完整发布流程。文中所有结论均可在当前仓库的 插件契约、插件运行时 与内置插件实例中逐一验证。


一、插件体系概览:谁是插件,插件放在哪里

Agent Zero 把"可扩展能力"统一收敛为**插件(Plugin)**这一形态:UI 钩子、API 处理器、生命周期扩展、设置面板、工具、提示词模板、模型提供商覆盖,全部通过插件承载。围绕插件的开发、审查、贡献、管理,仓库内建了四个配套技能:

  • a0-create-plugin:创建、扩展、修改插件(本文主线);
  • a0-review-plugin:审查插件;
  • a0-contribute-plugin:社区插件全流程贡献(含 git 操作);
  • a0-manage-plugin:插件管理。

1.1 两个插件根目录,一条硬性红线

仓库中存在两个插件根目录,用途严格分离:

目录用途说明
plugins/核心系统插件仅存放随框架发布的内置插件,目录名与plugin.yamlname均以下划线_开头(如_chat_naming_a0_connector),避免与社区插件冲突
usr/plugins/用户自定义插件所有新建的自定义插件必须放在这里

这是 a0-create-plugin 技能的第一条硬性约束:新插件一律创建于usr/plugins/<plugin_name>/。从源码看,插件的发现顺序也是"用户优先":get_plugin_roots 按usr/pluginsplugins的顺序返回根路径,find_plugin_dir 在 ID 冲突时同样优先解析usr/plugins下的版本,即用户插件可以覆盖同名内置插件。

1.2 一条铁律:不要留下"永生"的副作用

技能文档明确要求:插件被删除时,不应残留未托管的服务、符号链接或插件自有路径之外的文件。除非用户显式要求且插件文档写明了清理方式。这与 插件契约 中"插件删除或禁用不得遗留未管理副作用"的约定完全一致。同样被禁止的还有:硬编码密钥、绕过认证、产生持久化的非托管副作用。


二、第一步先问清:本地插件还是社区插件?

动手前必须向用户确认一个关键问题:

这个插件是仅本地使用(留在你的 Agent Zero 安装内),还是社区插件(发布到 Plugin Index 供他人安装)?

  • 本地插件:直接在usr/plugins/<plugin_name>/创建,无需 Git 仓库,直接进入清单编写环节;
  • 社区插件:插件必须托管在独立的 GitHub 仓库(运行时清单plugin.yaml位于仓库根目录),随后还要向 Plugin Index 提交一个单独的索引 PR,需要分两步引导用户完成。

这一步决定了后续的目录结构、清单字段与发布流程,务必先确认再动手。


三、插件清单 plugin.yaml:没有它就不会被发现

每个插件目录必须包含plugin.yaml,否则运行时无法发现该插件。基础模板如下:

name: my_plugin # 社区插件必填;必须与目录名一致(^[a-z0-9_]+$) title: My Plugin description: What this plugin does. version: 1.0.0 settings_sections: - agent per_project_config: false per_agent_config: false

各字段语义与取值约束:

  • name:仅允许小写字母、数字、下划线(^[a-z0-9_]+$)。提交 Plugin Index 时 CI 会强制校验,必须与索引目录名完全一致
  • title/description/version:插件的展示名、描述与版本号;
  • settings_sections:控制"设置"界面中哪些标签页显示本插件的子区块。合法值为agentexternalmcpdeveloperbackup;设为[]表示不显示子区块;
  • per_project_config/per_agent_config:置为true可启用按项目/按 Agent 作用域的精细化配置切换;
  • always_enabled:仅供框架内置插件使用,锁定插件永久开启并禁用 UI 开关。

运行时的PluginMetadata模型在 helpers/plugins.py 中与上述字段一一对应;开关状态由.toggle-1/.toggle-0标记文件驱动(见 determined_toggle_from_paths)。插件的激活默认是 ON——只要没有禁用标记就处于启用状态,这一点与 plugins/AGENTS.md 契约一致。

仓库内的真实示例可对照两个内置插件:_chat_naming/plugin.yaml(settings_sections: [agent]per_project_config: trueper_agent_config: truealways_enabled: true)与 _a0_connector/plugin.yaml(settings_sections: [external, developer])。

3.1 默认配置与解析顺序

插件默认值放在default_config.yaml;运行时用户设置则落在usr/下。根据插件契约,配置解析顺序为:项目/Agent 档案(project/profile)→ 项目(project)→ 用户/档案(user/profile)→ 用户插件配置 → 打包的default_config.yaml。这与 get_plugin_config 的查找链一致:先按作用域找config.json,找不到再回落default_config.yaml,且支持通过get_plugin_config钩子二次加工。


四、目录布局:插件该长成什么样

usr/plugins/<name>/的推荐布局如下:

usr/plugins/<name>/ plugin.yaml # 必需:清单 execute.py # 可选:用户手动触发的安装/维护脚本 hooks.py # 可选:框架运行时钩子函数 default_config.yaml # 可选:默认设置回退 README.md # 本地可选;社区插件强烈建议 LICENSE # 本地可选(存在时显示在插件列表中);Plugin Index 提交时仓库根目录必须 agents/ <profile>/agent.yaml # 可选:随插件分发的 Agent 档案 api/ # API 处理器(ApiHandler 基类) tools/ # 工具子类 helpers/ # 共享 Python 逻辑 prompts/ # 提示词模板 conf/ model_providers.yaml # 可选:新增或覆盖模型提供商 extensions/ python/<extension_point>/ # 具名 Python 生命周期扩展 python/_functions/<module>/<qualname>/<start|end>/ # 隐式 @extensible 钩子 webui/<point>/ # HTML/JS 钩子扩展 webui/ config.html # 可选:插件设置 UI my-modal.html # 完整插件页面 my-store.js # Alpine 状态 store

4.1 扩展点目录的两代布局(重要)

  • 具名扩展点:extensions/python/<extension_point>/,目录内放继承Extension基类的 Python 类;
  • 隐式扩展点extensions/python/_functions/<module>/<qualname>/<start|end>/,这是@extensible装饰器自动生成的扩展点路径。装饰器按func.__module__.拆段、func.__qualname__按嵌套层级拆段(剔除<locals>),组合出 start/end 两个目录,见 helpers/extension.py。

严禁使用已废弃的拍平式旧布局extensions/python/<module>_<qualname>_<start|end>/——当前运行时只解析深层的_functions/<module>/<qualname>/<start|end>形式。

4.2 插件本地 Python 导入规则

插件内部的 Python 模块必须使用全限定路径usr.plugins.<plugin_name>...导入:

# 正确 from usr.plugins.my_plugin.helpers.runtime import do_work import usr.plugins.my_plugin.helpers.state as state
# 避免 sys.path.insert(0, ...) from helpers.runtime import do_work from plugins.my_plugin.helpers.runtime import do_work

这样做的好处是插件可以保留常规的helpers/目录名而无需改名,同时规避sys.path污染和符号链接安装。契约规定:内置插件(来自plugins/树)可用plugins.<plugin_name>...导入,用户插件(usr/plugins/)必须走usr.plugins.<plugin_name>...


五、强制前端模式:Store Gate、独立 Store 与 A0 通知

5.1 Store Gate 模板(每个组件必用)

为避免竞态条件和 undefined 报错,每个组件必须使用如下包装:

<div x-data> <template x-if="$store.myPluginStore"> <div x-init="$store.myPluginStore.onOpen()" x-destroy="$store.myPluginStore.cleanup()"> <!-- Content goes here --> </div> </template> </div>

x-init在进入时调用onOpen()x-destroy在离开时调用cleanup(),确保状态生命周期可控。

5.2 独立 Store 模块

Store 逻辑必须放在独立的.js文件中,禁止在 HTML 内使用alpine:init监听器:

// webui/my-store.js import { createStore } from "/js/AlpineStore.js"; export const store = createStore("myPluginStore", { status: 'idle', init() { ... }, onOpen() { ... }, cleanup() { ... } });

随后在 HTML 的<head>中以模块方式引入:

<head> <script type="module" src="/plugins/<plugin_name>/webui/my-store.js"></script> </head>

5.3 用户反馈:只用 A0 通知系统

不要用内联提示框(比如把红色<div>绑定到store.error)展示错误或成功信息,必须走项目通知系统,让 toast 与历史保持一致:

  • 错误toastFrontendError(message, "My Plugin")(或$store.notificationStore.frontendError(...));
  • 成功toastFrontendSuccess(message, "My Plugin")
  • 警告/信息toastFrontendWarningtoastFrontendInfo,来自/components/notifications/notification-store.js

在 Store 中 import 并调用即可,不要在模板中渲染专门的错误/成功区块。完整 API 见 通知开发文档。这也与 插件契约 中"插件 UI 必须使用 A0 通知系统而非内联成功/错误框"的要求呼应。


六、插件设置:webui/config.html 与作用域持久化

如果插件需要用户可配置项,添加webui/config.html即可——系统会自动检测该文件,并按plugin.yamlsettings_sections在对应标签页显示设置按钮。

6.1 设置弹窗契约

弹窗提供 Project + Agent 档案上下文选择器;插件设置包装器通过$store.pluginSettingsPrototype实例化局部弹窗上下文。在config.html中,插件字段绑定到config.*,弹窗级状态与动作使用context.*

<html> <head> <title>My Plugin Settings</title> <script type="module"> import { store } from "/components/plugins/plugin-settings-store.js"; </script> </head> <body> <div x-data> <input x-model="config.my_key" /> <input type="checkbox" x-model="config.feature_enabled" /> </div> </body> </html>

点击弹窗的 Save 按钮后,config会被持久化为config.json,写入正确的作用域(项目/Agent/全局)。这正是 save_plugin_config 依据project_nameagent_profile计算写入路径的落盘逻辑。

6.2 侧边栏入口点

如果要在侧边栏放置入口按钮:

  • 扩展点:sidebar-quick-actions-main-start
  • 样式类:class="config-button"
  • 位置:x-move-after=".config-button#dashboard"
  • 动作:@click="openModal('/plugins/<plugin_name>/webui/my-modal.html')"

6.3 后端读取与写入插件设置

from helpers.plugins import get_plugin_config, save_plugin_config # 运行时读取(有运行中的 agent,自动从上下文解析项目/档案) settings = get_plugin_config("my-plugin", agent=agent) or {} # 显式写入目标(project/profile 作用域) save_plugin_config( "my-plugin", project_name="my-project", agent_profile="default", settings=settings, )

七、后端 API 与上下文:主动发消息的正确姿势

7.1 导入路径

  • 正确:from agent import AgentContext, AgentContextType
  • 正确:from initialize import initialize_agent
  • 正确(插件本地模块):from usr.plugins.<name>.helpers.module import ...
  • 避免:sys.path黑魔法、依赖符号链接的from plugins.<name>...导入

AgentContext定义在 agent.py:它是运行中 Agent 会话的运行时上下文,通过AgentContext.use(context_id)取用、AgentContext.current()获取当前上下文,AgentContextType枚举区分user/task/background三种会话类型(agent.py)。

7.2 主动发送消息

from agent import AgentContext from helpers.messages import UserMessage context = AgentContext.use(context_id) task = context.communicate(UserMessage("Message text")) response = await task.result()

communicate()返回异步任务,await task.result()等待处理结果——这是插件主动向 Agent 投递消息的标准调用链。


八、execute.py:用户手动触发的操作脚本

如果插件需要用户触发的安装、维护、修复类操作,在插件根目录添加execute.py。典型用途:

  • 安装依赖、下载模型/资源;
  • 插件拷贝就位后的后置安装步骤;
  • 重建缓存、索引或生成文件;
  • 执行迁移、修复步骤或同步任务;
  • 仅在用户显式要求时执行的周期性维护。

关键原则execute.py只做用户发起的工作;框架内部逻辑或应随插件生命周期自动发生的行为,应放入hooks.py或生命周期扩展。它是一次可重复运行的手动操作——成功返回0,失败返回非零,并打印进度让用户理解发生了什么;尽量做到可安全重入,若不可重入则检测状态并给出明确提示。

import subprocess import sys def main(): print("Installing plugin dependencies...") result = subprocess.run( [sys.executable, "-m", "pip", "install", "requests==2.31.0"], text=True, ) if result.returncode != 0: print("ERROR: Installation failed") return result.returncode print("Refreshing plugin resources...") # Add post-install, repair, migration, or maintenance logic here. print("Done.") return 0 if __name__ == "__main__": sys.exit(main())

用户在插件 UI 中触发该脚本。运行时在 get_enhanced_plugins_list 中通过has_execute_script检测其存在并在列表中展示。


九、hooks.py:框架运行时钩子

需要框架内部钩子点时,在插件根目录添加hooks.py。框架通过helpers.plugins.call_plugin_hook(...)按函数名调用导出的钩子(见 call_plugin_hook,支持同步与异步函数)。

重要hooks.py运行在Agent Zero 框架运行时内,而非独立的 Agent 执行环境。适合的场景:安装钩子、更新前钩子、插件注册、缓存建立、文件准备等框架内部操作。

当前内置调用点:

  • 插件安装器将插件放入usr/plugins/后调用install()
  • 插件更新器在拉取新代码前调用pre_update()
  • 插件卸载器在删除插件目录前调用uninstall()——用于清理install()创建的依赖与状态。

钩子应可逆、可安全清理,优先使用框架托管状态与插件自有路径,而不是永久修改系统。

9.1 环境定位规则

hooks.py中执行sys.executable -m pip install ...会安装到运行 Agent Zero 的同一 Python 环境——这对框架运行时内需要的依赖是正确的。但如果依赖是给独立 Agent 运行时或 OS 级工具用的,不要假设当前环境正确,应在子进程中显式切换目标:

  • 调用目标运行时对应的确切 Python 解释器;
  • 在子进程中先激活目标虚拟环境再执行pip
  • 从针对目标环境配置的子进程运行 OS 包管理器。

在 Docker 中,hooks.py通常作用于/opt/venv-a0,除非你明确指定/opt/venv或其他环境。


十、社区插件:GitHub 仓库 + Plugin Index 提交

用户选择社区插件时,本地构建测试完成后还有额外步骤。

10.1 仓库结构:内容必须在仓库根目录

your-plugin-repo/ ← GitHub 仓库根目录 ├── plugin.yaml ← 运行时清单(必须包含 name 字段!) ├── default_config.yaml ├── README.md ├── LICENSE ← Plugin Index 提交前仓库根目录必须存在 ├── api/ ├── tools/ ├── extensions/ └── webui/

根目录的运行时plugin.yaml必须包含name字段,且与索引目录名完全一致:

name: my_plugin # REQUIRED - must match index folder name exactly title: My Plugin description: What this plugin does. version: 1.0.0

10.2 索引清单 index.yaml:与运行时清单不同

Plugin Index 使用独立的index.yaml,只描述可发现性,与运行时plugin.yaml是两套 schema:

title: My Plugin description: What this plugin does. github: https://github.com/yourname/your-plugin-repo tags: - tools - example screenshots: # 可选,最多 5 个完整图片 URL - https://raw.githubusercontent.com/yourname/your-plugin-repo/main/docs/screen1.png

必填字段:titledescriptiongithub;可选:tags(最多 5 个)、screenshots(最多 5 个 URL)。注意:CI 还会校验远端plugin.yaml中的name字段与索引目录名精确匹配。

10.3 提交流程

  1. Fork Plugin Index 仓库;
  2. 在 fork 中创建plugins/<your_plugin_name>/目录:
    • 目录名仅限小写字母、数字、下划线(^[a-z0-9_]+$),不含连字符
    • 必须与远端plugin.yamlname完全一致;
  3. 在目录内添加index.yaml(可选附带 ≤ 20 KB 的方形缩略图thumbnail.png/thumbnail.jpg/thumbnail.webp);
  4. 打开 PR,且一个 PR只能新增一个插件目录
  5. CI 自动校验,维护者审查后合并。

提交约束:目录名唯一且稳定、^[a-z0-9_]+$_开头目录预留给内部使用;title最长 50 字符、description最长 500 字符、index.yaml总长不超过 2000 字符。完整的 git 操作引导见 a0-contribute-plugin 技能。


十一、Plugin Index 与 Plugin Hub

Plugin Index是社区插件中心。Agent Zero 通过内置的Plugin Hub向用户暴露索引插件:用户从Plugins对话框的Browse标签页或Install按钮打开,即可查看插件详情并直接从 UI 安装。插件的安装、更新、扫描、校验分别由内置插件_plugin_installer_plugin_scan_plugin_validator承担,详见 插件契约 的子插件索引表。

插件静态资源通过GET /plugins/<name>/<path>提供,API 处理器走POST /api/plugins/<name>/<handler>,管理动作走POST /api/plugins——这些路由契约同样定义在 插件契约。


十二、全流程清单与验证要点

一个完整插件从零到上线的检查清单:

  1. 确认类型:本地插件(usr/plugins/)还是社区插件(独立仓库 + 索引 PR);
  2. 清单plugin.yaml字段合法,name匹配目录名(^[a-z0-9_]+$);
  3. 布局:api / tools / helpers / prompts / webui / extensions 按需创建,扩展点使用extensions/python/<point>/_functions/<module>/<qualname>/<start|end>/深层布局;
  4. 前端:Store Gate 包装每个组件、Store 独立成 js、反馈一律走 A0 通知;
  5. 设置:需要配置项则提供webui/config.html,字段绑定config.*
  6. 后端usr.plugins.<name>...导入、AgentContext发消息、get_plugin_config/save_plugin_config读写设置;
  7. 生命周期:用户触发的操作进execute.py,框架内部逻辑进hooks.py,并遵循环境定位规则;
  8. 无残留:删除插件不留下非托管服务、符号链接或越界文件;
  9. 发布(社区插件):仓库根目录含plugin.yaml(带name)+LICENSE,提交index.yamlPR,通过 CI 与维护者审查。

技能文档本身还给出了两条元规则,开发者在改造框架后应同步更新技能:a0-create-plugin/AGENTS.md 要求——当插件加载器、Plugin Hub、设置弹窗、扩展或 WebUI 模式变化时更新本技能;并定期人工通读 SKILL.md 检查过时路径与相关插件技能间的衔接,保证文档与运行时始终一致。


延伸阅读

  • 插件开发文档(生命周期与发布)
  • 通知开发文档(toast 全量 API)
  • 插件运行时实现(发现、开关、配置、钩子)
  • 扩展机制实现(@extensible 与扩展点解析)
  • WebUI 组件规范、WebUI JS 规范、WebUI CSS 规范
  • 内置插件实例:_chat_naming(设置分区 + 分作用域配置 + always_enabled)、_a0_connector(external/developer 分区)

【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 11:25:22

建设一个网站选择的服务器一文搞懂备案与避坑指南

建设一个网站选择的服务器一文搞懂备案与避坑指南 刚接手第一个网站项目,最让人头大的往往不是代码怎么写,而是域名解析和服务器备案。很多新手盯着后台那一堆“审核中”的状态发呆,心里直打鼓:这服务器到底选对了没?备案流程一头雾水,怕填错一个字段就要重来一周。别慌,这篇指南就是为了解决你此刻的焦虑。咱们不整…

作者头像 李华
网站建设 2026/9/15 11:24:36

Mermaid 时序图进阶教程:3 个场景画会条件分支与并行流程

Mermaid 时序图进阶教程&#xff1a;3 个场景画会条件分支与并行流程 【免费下载链接】mermaid Generation of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid 你…

作者头像 李华
网站建设 2026/9/15 11:24:34

GLM-5开源大模型技术解析与工程实践

1. GLM-5开源模型的技术突破与工程价值作为2023年最受瞩目的开源大模型之一&#xff0c;GLM-5的完整开源标志着Agentic Engineering时代的真正到来。这个由智谱AI团队研发的模型不仅在benchmark测试中表现出色&#xff0c;更重要的是它首次实现了从预训练模型到完整工程解决方案…

作者头像 李华
网站建设 2026/9/15 11:18:57

手机上怎么做网站避坑指南:3步让流量暴涨50%

手机上怎么做网站避坑指南:3步让流量暴涨50% 网站做好了没人访问,这是90%站长和开发者最崩溃的瞬间。你熬夜调像素、改代码,甚至花大价钱买了独立服务器,结果百度指数查了一下,日均UV不到20。别急着怪算法,90%的情况是因为你在“手机上怎么做网站”这个环节,从一开始就选错了技术路线和运营切入点。今…

作者头像 李华