Agent Zero 插件全面审查指南:基于 a0-review-plugin 技能的四阶段审计工作流
导读
a0-review-plugin 是 Agent Zero 框架内置的插件审查技能,覆盖插件清单(manifest)、目录结构、代码模式(Store Gating、通知、导入规范)与安全合规的完整审计,并在最后与社区插件索引做查重比对。本文以 skills/a0-review-plugin/AGENTS.md 及其同目录下的 SKILL.md 与 checklists.md 为核心骨架,结合 helpers/plugins.py 等源码佐证,完整讲解该技能的触发方式、四个审查阶段、判定标准与报告格式。读完后,你可以按同一套标准对 usr/plugins/ 下的任意插件执行专业审计,判断其能否安全使用或提交到社区 Plugin Index。
1. 技能定位与触发方式
a0-review-plugin 是一个技能(Skill),其入口元数据定义在 skills/a0-review-plugin/SKILL.md 的 frontmatter 中:
- name:
a0-review-plugin - description:对
usr/plugins/下的 Agent Zero 插件做全面审计,覆盖清单有效性、目录结构、代码模式(Store Gating、通知、导入)、安全与社区索引查重;当用户要求 review、audit、validate 或 check 现有插件时使用 - version:1.0.0
- tags:
plugins、review、audit、validate、security、checklist - trigger_patterns:
review plugin、audit plugin、validate plugin、check plugin、plugin review、is my plugin correct、plugin checklist
按 AGENTS.md 的分工约定:SKILL.md 拥有审查工作流与阶段顺序,checklists.md 拥有详细的审查标准(按需加载)。审查对象默认是 usr/plugins/<name>/ 下的用户插件,除非明确要求审查随框架分发的核心插件——这是文档明示的边界:核心插件位于 plugins/ 目录(目录名以 _ 开头,例如 _plugin_validator),用户插件则位于 usr/plugins/。
整个审查流程固定为 4 个阶段,按顺序执行,每个检查项标记为 PASS / FAIL / WARN,最后按阶段分组输出报告。
2. Phase 1:清单(Manifest)验证
第一阶段读取 usr/plugins/<name>/plugin.yaml,验证清单本身的有效性:
- 文件必须存在于插件根目录;
- 必须是可解析的合法 YAML,且顶层为映射(mapping);
name字段按分发目标区分对待:面向社区 / Plugin Index 的插件必须存在、非空、匹配^[a-z0-9_]+$且与目录名一致;仅本地使用的插件缺失name记 WARN 而非 FAIL;title、description必须存在且非空;version必须存在,遵循 semver 或简单x.y.z格式;settings_sections必须是列表,取值只能是agent、external、mcp、developer、backup之一;per_project_config与per_agent_config(若存在)必须是布尔值;always_enabled必须为false或缺失(只有框架核心插件才允许true);- 出现 schema 之外的未知字段记 WARN。
plugin.yaml 的完整字段参考见 checklists.md 的 plugin.yaml Schema Reference 小节:
name: my_plugin # 社区索引必需(^[a-z0-9_]+$,且须与目录名一致)
title: My Plugin # 必需,UI 显示名
description: What it does. # 必需
version: 1.0.0 # 必需
settings_sections: # 可选,合法值: agent | external | mcp | developer | backup
- agent
per_project_config: false # 可选,开启项目级配置
per_agent_config: false # 可选,开启 agent 配置档级配置
always_enabled: false # 可选,仅供框架核心使用
与源码对照:框架侧正是用 helpers/plugins.py 中的 PluginMetadata Pydantic 模型解析这些字段(name、title、description、version、settings_sections、per_project_config、per_agent_config、always_enabled),插件加载失败时会在 get_enhanced_plugins_list 中打印错误并跳过该插件。这也印证了清单解析是插件能否被框架识别的第一道门槛——审查技能要求 name 匹配 ^[a-z0-9_]+$,与框架目录发现约定(目录名不允许以 . 开头)以及社区索引的文件夹命名规则完全对齐。
3. Phase 2:结构(Structure)验证
第二阶段检查插件目录布局,核心判定是目录位置与标准布局:
- 插件必须位于
usr/plugins/(而不是plugins/,后者保留给核心插件); - 目录名匹配
^[a-z0-9_]+$; api/(若存在):只含 Python 文件,每个类须继承ApiHandler;tools/(若存在):只含 Python 文件,每个类须继承Tool;extensions/(若存在):子目录必须遵循python/<point>/、python/_functions/<module>/<qualname>/<start|end>/或webui/<point>/布局;已废弃的扁平化形式python/<module>_<qualname>_<start|end>/需要标记;helpers/、prompts/、agents/(<profile>/agent.yaml)、conf/(如model_providers.yaml)均为标准目录;- 若存在
webui/config.html,插件必须在plugin.yaml中声明至少一个settings_sections条目; - 若存在
hooks.py:核对插件依赖的生命周期钩子函数是否定义,尤其是install、pre_update、uninstall;若install()添加了依赖而缺少uninstall(),记 WARN; - 若存在
execute.py:必须有main()函数以及if __name__ == "__main__": sys.exit(main())入口; LICENSE:本地插件不强制要求,但提交 Plugin Index 前仓库根目录必须存在 LICENSE;缺失记 WARN(LICENSE absent — required for community contribution (Plugin Index); optional for local-only use);default_config.yaml(若存在)必须是合法 YAML;- 顶层出现标准布局之外的条目记 WARN。
标准顶层布局为:plugin.yaml、execute.py、hooks.py、default_config.yaml,可选 README.md、LICENSE、__init__.py,以及 api/、tools/、extensions/、webui/、helpers/、prompts/、agents/、conf/ 子目录。
该布局与框架的插件资产发现机制一一对应:核心插件 plugins/AGENTS.md 明确"用户插件必须使用 usr.plugins.<plugin_name>... 导入,禁止 sys.path hack 或持久化符号链接导入",而框架通过 find_plugin_assets 按 项目→agent 配置档→usr→框架内置 的优先级顺序搜索 config.json、.toggle-0/.toggle-1 等插件资产——审查时对顶层"意外条目"的 WARN,正是为了防止这些资产发现路径之外的文件破坏可逆性与可清理性。
3.1 extensions 布局的源码依据
checklists.md 对 Python 扩展布局给出了正反例:
extensions/python/<extension_point>/
适用于 agent_init、system_prompt、monologue_start、tool_execute_before 等命名生命周期钩子;而隐式 @extensible 钩子目标必须使用:
extensions/python/_functions/<module>/<qualname>/<start|end>/
该路径必须保留完整模块路径与每一层嵌套 __qualname__ 段。FAIL 模式是扁平化的 extensions/python/<module>_<qualname>_<start|end>/——这一旧形式已无法匹配当前的 extensible 运行时查找逻辑。plugins/AGENTS.md 同样强调"_functions 扩展布局保留每个模块与嵌套 qualname 段,不要使用已废弃的扁平化扩展文件夹名"。
4. Phase 3:代码模式(Code Pattern)审查
第三阶段阅读源码,对照 Agent Zero 约定逐条检查,分为前端(HTML/JS)与后端(Python)两部分。
4.1 前端:Store Gate 模式
任何访问 store 的 Alpine 组件都必须用 x-if 门(Store Gate)包裹内容:
<!-- 正确 -->
<div x-data>
<template x-if="$store.myPluginStore">
<div x-init="$store.myPluginStore.onOpen()" x-destroy="$store.myPluginStore.cleanup()">
<!-- content -->
</div>
</template>
</div>
<!-- 错误:store 未初始化时会抛 undefined 错误 -->
<div x-data x-init="$store.myPluginStore.onOpen()">
<!-- content -->
</div>
原因:Alpine store 是异步注册的(见 webui/js/AlpineStore.js 中 createStore 的实现——它通过 globalThis.Alpine 代理读写,在 Alpine 尚未就绪时把 alpine:init 事件挂起注册)。没有 x-if 门,组件引用尚未加载的 store 就会抛 undefined 错误。
同时规定:
- HTML 文件内禁止
alpine:init事件监听器(store 逻辑必须放在.js文件中); - Alpine store 必须使用从
/js/AlpineStore.js导入的createStore创建; - 禁止在 HTML 内联
<script>+Alpine.store(...)定义 store。
合法的 Store 定义模式(见 checklists.md):
// webui/my-store.js
import { createStore } from "/js/AlpineStore.js";
export const store = createStore("myPluginStore", {
myData: null,
init() { // 注册时全局调用一次
},
onOpen() { // 组件挂载时调用
},
cleanup() { // x-destroy 时调用
}
});
在 HTML <head> 中以 module 方式导入:<script type="module" src="/plugins/my_plugin/webui/my-store.js"></script>。
4.2 前端:通知系统(禁用内联错误框)
禁止渲染内联 error/success 块,必须使用 A0 通知系统:
// 前端(Alpine store 或组件)
import {
toastFrontendError,
toastFrontendSuccess,
toastFrontendWarning,
toastFrontendInfo
} from "/components/notifications/notification-store.js";
toastFrontendError("Connection failed", "My Plugin");
toastFrontendSuccess("Saved successfully", "My Plugin");
# 后端(Python)
from helpers.notification import AgentNotification
AgentNotification.error("Something went wrong", context_id=context.id)
AgentNotification.success("Operation complete", context_id=context.id)
FAIL 模式(不允许放行):
<!-- 错误:内联错误框 -->
<div x-show="store.error" class="error-box" x-text="store.error"></div>
这一约定与 plugins/AGENTS.md 的本地契约一致:"插件 UI 必须使用 A0 通知系统反馈错误、警告、成功与信息,而不是内联 success/error 框"。框架侧的通知实体定义在 helpers/notification.py(NotificationType、NotificationPriority、NotificationManager),审查时核对的是前端 toast 导入路径与后端 AgentNotification 用法。
4.3 前端:静态资源与导入
- 静态资源通过
GET /plugins/<name>/...提供,禁止硬编码绝对路径; - store 模块必须在 HTML
<head>中用<script type="module" src="/plugins/<name>/webui/store.js">导入。
4.4 后端:导入路径与基类
- 正确导入:
from agent import AgentContext, AgentContextType(而不是helpers.context,后者不存在——agent.py 中定义了AgentContextType枚举); from initialize import initialize_agent(禁止本地重新导入);- API 处理器继承
python/helpers/api.py中的ApiHandler(见 helpers/api.py); - 工具继承
helpers.tool中的Tool(见 helpers/tool.py); - 插件配置读取:
get_plugin_config("plugin-name", agent=agent)(来自helpers.plugins); - 用户消息发送:必须通过
context.communicate(UserMessage(...)),禁止直接写 socket; hooks.py环境定位:如果为 agent 运行时(而非框架)安装依赖包,subprocess 必须显式指定目标解释器(如/opt/venv/bin/python);- 禁止对 agent 运行时依赖使用
sys.executable -m pip install(那会安装进框架运行时)。
4.5 后端核心代码模式速查
checklists.md 提供了完整的正例代码,审查时可直接对照:
API Handler(路由自动注册为 POST /api/plugins/my_plugin/my_handler):
# api/my_handler.py
from helpers.api import ApiHandler, Request, Response
class MyHandler(ApiHandler):
async def process(self, input: dict, request: Request) -> dict | Response:
# input 是解析后的请求体
# 返回 dict(自动序列化为 JSON)或 Response 对象
return {"ok": True, "data": "result"}
Tool:
# tools/my_tool.py
from helpers.tool import Tool, ToolResult
class MyTool(Tool):
async def execute(self, arg1: str, arg2: str = "default"):
# Tool 逻辑
return ToolResult("Result text")
AgentContext 访问:
from agent import AgentContext, AgentContextType
context = AgentContext.use(context_id)
from helpers.messages import UserMessage
task = context.communicate(UserMessage("Message text"))
response = await task.result()
错误写法:from helpers.context import AgentContext # 不存在。
插件配置读写(get_plugin_config / save_plugin_config 在 helpers/plugins.py 中实现,会按当前运行 agent 解析项目/配置档作用域):
from helpers.plugins import get_plugin_config, save_plugin_config
# 读取配置(从运行 agent 解析项目/配置档作用域)
settings = get_plugin_config("my_plugin", agent=agent) or {}
# 写入指定作用域
save_plugin_config(
"my_plugin",
project_name="my-project",
agent_profile="default",
settings={"key": "value"},
)
配置解析的优先级(从高到低)为:项目/agent 配置档 → 项目 → 用户/agent 配置档 → 用户插件配置 → 插件内置 default_config.yaml,与 plugins/AGENTS.md 声明的解析顺序一致。
hooks.py 环境定位正例(钩子由框架运行时执行,见 call_plugin_hook 的动态加载机制):
# 安装进框架运行时(/opt/venv-a0)——默认行为
def install():
subprocess.run([sys.executable, "-m", "pip", "install", "some-package==1.0.0"], check=True)
# 安装进 AGENT 执行运行时(与框架分离)
def install():
agent_python = "/opt/venv/bin/python"
subprocess.run([agent_python, "-m", "pip", "install", "some-package"], check=True)
uninstall() 负责清理 install() 添加的依赖,pre_update() 在插件更新拉取新代码前执行;异步钩子(async def)同样受支持。绝不要在需要 agent 运行时的情况下使用 sys.executable——它指向的是框架运行时。
execute.py 模式:必须有 main()、sys.exit(main()) 入口;成功返回 0、失败返回非零;打印进度;必须可安全重复执行。
4.6 其它值得注意的 WebUI 模式
checklists.md 还覆盖了插件设置页与侧边栏按钮模式:
webui/config.html:通过$store.pluginSettingsPrototype绑定,输入值绑到config.*,弹窗状态/动作绑到context.*(与 plugins/AGENTS.md 的约定一致);- 侧边栏按钮扩展点:位于
extensions/webui/sidebar-quick-actions-main-start/,组件带根 Alpine 作用域,并使用x-move-after指令锚定静态断点位置。
5. Phase 4:安全审查 + 社区索引查重
5.1 安全检查项
- 任何文件中不得存在硬编码密钥、API Key、token 或密码;
- 禁止对用户输入执行
eval()或exec(); - 文件路径操作必须使用安全拼接(不允许用户输入拼接导致越出沙箱);
- subprocess 调用不得把未净化的用户输入作为 shell 字符串传入;
- ZIP 解压(如有)必须有路径穿越防护;
- 未经用户知晓的第三方出站网络调用记 WARN(而非自动 FAIL)。
审查报告不得暴露密钥或私有插件数据——这是 AGENTS.md 中明确的本地契约("Do not expose secrets or private plugin data in review output")。
5.2 社区索引查重
从社区索引仓库的 generated-index 发布物拉取当前索引:
https://github.com/agent0ai/a0-plugins/releases/download/generated-index/index.json
检查三项:
- 插件
name在索引中不存在同名文件夹; - 没有其他索引条目指向相同的
githubURL; - 插件用途未被已有索引条目覆盖(语义重叠记 WARN,不记 FAIL)。
5.3 社区索引的 CI 校验规则
checklists.md 明确区分了提交索引时 CI 校验的三份材料:
index.yaml(位于索引仓库,不是plugin.yaml):字段为title(≤50 字符)、description(≤500 字符)、github(必需)、tags(可选,≤5 个)、screenshots(可选,≤5 个 URL);文件总长度 ≤2000 字符;不允许未知字段;- 远端
plugin.yaml(插件自己的仓库):必须位于仓库根目录,且name字段必须与索引文件夹名完全一致; LICENSE(插件自己的仓库):提交 Plugin Index 前仓库根目录必须存在;- 文件夹名:匹配
^[a-z0-9_]+$(下划线,无连字符)、不能以_开头、索引内唯一。
6. 报告输出格式
审查结果按阶段分组输出,每个检查项一行,格式如下(来自 SKILL.md 的 Reporting Format):
## Plugin Review: <plugin_name>
### Phase 1: Manifest
PASS name: my_plugin
PASS title: My Plugin
FAIL version: missing
...
### Phase 2: Structure
PASS plugin.yaml present
WARN Unexpected file at root: notes.txt
...
### Phase 3: Code Patterns
PASS Store Gating: found in webui/main.html
FAIL Inline error box found in webui/settings.html (use toastFrontendError instead)
...
### Phase 4: Security + Index
PASS No hardcoded secrets found
PASS No duplicate in community index
WARN Outbound HTTP call to external service in api/handler.py:42
### Summary
Status: NEEDS WORK
Fix required: version missing in plugin.yaml, inline error box in webui/settings.html
6.1 社区就绪度评估(Community readiness)
总结阶段按三档给出结论:
- READY:所有 FAIL 项已解决;对于 Plugin Index 提交,无阻塞性 WARN(缺失
LICENSE是 WARN,但在修复前会阻塞贡献就绪状态); - NEEDS WORK:列出需要修复的具体 FAIL 项;
- OPTIONAL IMPROVEMENTS:列出非阻塞 WARN 项(如果用户仅本地使用,缺失
LICENSE可标注为可选项)。
7. 与框架内置验证能力的对照
除技能外,Agent Zero 还内置了一个 _plugin_validator 核心插件(plugins/_plugin_validator/README.md),它以清单、结构、代码模式与安全约定为目标做自动化校验:通过 helpers/prompt.py 构建结构化验证提示词,在临时 agent 上下文中运行审查并生成 Markdown 报告;核心执行器位于 api/plugin_validator_run.py(同步校验),配套 api/plugin_validator_prepare_zip.py、api/plugin_validator_queue.py 与 api/plugin_validator_start.py 完成 zip 预处理、排队与启动。审查清单(plugin-validator-checks.json)与提示词文本存放在其 webui/ 资产中。
两套能力互补:a0-review-plugin 技能适合由 Agent 主动驱动的交互式深度审计(四阶段 + 索引查重),_plugin_validator 插件适合集成到安装流程中做自动化预检(其 WebUI 扩展点 extensions/webui/install-zip-actions/ 与 install-git-actions/ 提供了校验按钮)。审查技能的检查清单与插件验证器的判定标准共享同一套插件契约来源,即 plugins/AGENTS.md。
8. 进一步阅读
- 审查工作流与阶段顺序:skills/a0-review-plugin/SKILL.md
- 详细检查清单与全部代码模式正例:skills/a0-review-plugin/checklists.md
- 插件架构契约(内置插件与用户插件共用):plugins/AGENTS.md
- 开发者插件生命周期指南:docs/developer/plugins.md
- 组件系统约定:webui/components/AGENTS.md
- 审查通过后准备发布:阅读 skills/a0-contribute-plugin/SKILL.md
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.24 K638- DDeepSeek-V4.1-FlashDeepSeek-V4.1-Flash 是一个多模态混合专家(MoE)模型,拥有 5520 亿骨干参数,并支持最多一百万 token 的上下文长度。该模型原生支持图像和文本输入,并以自回归方式生成文本Python670
SlideSCIPPT插件,支持素材库、AI助手、一键添加图片标题,复制粘贴位置、一键图片对齐、一键插入Markdown(加粗、超链接等行内样式、代码块、LaTeX等块级样式)、便捷导出图片!C#230
hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程Python52874
new-apiAI模型聚合管理中转分发系统,一个应用管理您的所有AI模型,支持将多种大模型转为统一格式调用,支持OpenAI、Claude、Gemini等格式,可供个人或者企业内部管理与分发渠道使用。🍥 A Unified AI Model Management & Distribution System. Aggregate all your LLMs into one app and access them via an OpenAI-compatible API, with native support for Claude (Messages) and Gemini formats.Go22545
JeecgBoot🔥企业级低代码平台集成了AI应用平台,帮助企业快速实现低代码开发和构建AI应用!前后端分离架构 SpringBoot,SpringCloud、Mybatis,Ant Design4、 Vue3.0、TS+vite!强大的代码生成器让前后端代码一键生成,无需写任何代码! 引领AI低代码开发模式: AI生成->OnlineCoding-> 代码生成-> 手工MERGE,显著的提高效率,又不失灵活~Java36351