首页
/ Agent Zero 插件全面审查指南:基于 a0-review-plugin 技能的四阶段审计工作流

Agent Zero 插件全面审查指南:基于 a0-review-plugin 技能的四阶段审计工作流

2026-09-14 23:58:15作者:宣聪麟

导读

a0-review-plugin 是 Agent Zero 框架内置的插件审查技能,覆盖插件清单(manifest)、目录结构、代码模式(Store Gating、通知、导入规范)与安全合规的完整审计,并在最后与社区插件索引做查重比对。本文以 skills/a0-review-plugin/AGENTS.md 及其同目录下的 SKILL.mdchecklists.md 为核心骨架,结合 helpers/plugins.py 等源码佐证,完整讲解该技能的触发方式、四个审查阶段、判定标准与报告格式。读完后,你可以按同一套标准对 usr/plugins/ 下的任意插件执行专业审计,判断其能否安全使用或提交到社区 Plugin Index。


1. 技能定位与触发方式

a0-review-plugin 是一个技能(Skill),其入口元数据定义在 skills/a0-review-plugin/SKILL.md 的 frontmatter 中:

  • namea0-review-plugin
  • description:对 usr/plugins/ 下的 Agent Zero 插件做全面审计,覆盖清单有效性、目录结构、代码模式(Store Gating、通知、导入)、安全与社区索引查重;当用户要求 review、audit、validate 或 check 现有插件时使用
  • version:1.0.0
  • tagspluginsreviewauditvalidatesecuritychecklist
  • trigger_patternsreview pluginaudit pluginvalidate plugincheck pluginplugin reviewis my plugin correctplugin 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_]+$ 且与目录名一致;仅本地使用的插件缺失 nameWARN 而非 FAIL
  • titledescription 必须存在且非空;
  • version 必须存在,遵循 semver 或简单 x.y.z 格式;
  • settings_sections 必须是列表,取值只能是 agentexternalmcpdeveloperbackup 之一;
  • per_project_configper_agent_config(若存在)必须是布尔值;
  • always_enabled 必须为 false 或缺失(只有框架核心插件才允许 true);
  • 出现 schema 之外的未知字段记 WARN。

plugin.yaml 的完整字段参考见 checklists.mdplugin.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 模型解析这些字段(nametitledescriptionversionsettings_sectionsper_project_configper_agent_configalways_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:核对插件依赖的生命周期钩子函数是否定义,尤其是 installpre_updateuninstall;若 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.yamlexecute.pyhooks.pydefault_config.yaml,可选 README.mdLICENSE__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_initsystem_promptmonologue_starttool_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.jscreateStore 的实现——它通过 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.pyNotificationTypeNotificationPriorityNotificationManager),审查时核对的是前端 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_confighelpers/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 在索引中不存在同名文件夹;
  • 没有其他索引条目指向相同的 github URL;
  • 插件用途未被已有索引条目覆盖(语义重叠记 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.pyapi/plugin_validator_queue.pyapi/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. 进一步阅读

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

项目优选

收起
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