skills/a0-review-plugin/SKILL.md
Full-audit workflow for plugins in /a0/usr/plugins/<name>/. Run all 4 phases in order and report findings grouped by phase. Mark each item PASS, FAIL, or WARN.
For detailed checklists and code pattern references, read checklists.md in this skill directory when needed.
Read usr/plugins/<name>/plugin.yaml. Check:
name field handling matches the intended distribution target: for community / Plugin Index plugins it must be present, non-empty, match ^[a-z0-9_]+$, and match the directory name; for local-only plugins, a missing name is a WARN rather than a FAILtitle present and non-emptydescription present and non-emptyversion present, follows semver or simple x.y.z formatsettings_sections is a list; each value is one of: agent, external, mcp, developer, backupper_project_config and per_agent_config are booleans (if present)always_enabled is false or absent (only framework core plugins should use true)Inspect the plugin directory layout:
usr/plugins/ (not plugins/ - that is reserved for core)^[a-z0-9_]+$api/ exists: contains Python files only; each should subclass ApiHandlertools/ exists: contains Python files only; each should subclass Toolextensions/ exists: check subdirs follow python/<point>/, python/_functions/<module>/<qualname>/<start|end>/, or webui/<point>/ patterns; flag the retired flattened python/<module>_<qualname>_<start|end>/ formhelpers/ exists: shared Python logic (standard directory)prompts/ exists: prompt templates (standard directory)agents/ exists: agent profiles with <profile>/agent.yaml (standard directory)conf/ exists: configuration files such as model_providers.yaml (standard directory)webui/config.html exists: plugin must declare at least one settings_sections entryhooks.py exists: review whether it defines the lifecycle hook functions the plugin appears to rely on, especially install, pre_update, and uninstall when the plugin needs install-time, update-time, or cleanup behavior — if install() adds dependencies, flag a missing uninstall() as WARNexecute.py exists: check it has a main() function and if __name__ == "__main__": sys.exit(main())LICENSE at plugin root: Agent Zero does not require it for local plugins, but it is required at the repo root before submitting to the Plugin Index. If missing → WARN — LICENSE absent — required for community contribution (Plugin Index); optional for local-only usedefault_config.yaml (if present): valid YAMLStandard top-level layout: plugin.yaml, execute.py, hooks.py, default_config.yaml, optional README.md, LICENSE, __init__.py, plus api/, tools/, extensions/, webui/, helpers/, prompts/, agents/, conf/
Read source files and check for violations of Agent Zero conventions.
<div x-data>
<template x-if="$store.myStore">
<div x-init="$store.myStore.onOpen()" x-destroy="$store.myStore.cleanup()">
...
</div>
</template>
</div>
alpine:init event listeners inside HTML files (store logic must be in .js files)createStore imported from /js/AlpineStore.js<div> blocks bound to store.error or similar - must use notification system:
toastFrontendError(msg, "Plugin Name") / toastFrontendSuccess(...) etc./components/notifications/notification-store.jsGET /plugins/<name>/... (not hardcoded absolute paths)<head> via <script type="module" src="/plugins/<name>/webui/store.js">from agent import AgentContext, AgentContextType (not helpers.context)from initialize import initialize_agent (not a local reimport)ApiHandler from python/helpers/api.pyTool from helpers.toolget_plugin_config("plugin-name", agent=agent) from helpers.pluginscontext.communicate(UserMessage(...)), not direct socket writeshooks.py environment targeting: if installing packages for the agent runtime (not framework), subprocess must explicitly target the correct interpreter (e.g., /opt/venv/bin/python)sys.executable -m pip install for agent-runtime deps (that installs into framework runtime instead)eval() or exec() on user-supplied inputFetch the current index:
https://github.com/agent0ai/a0-plugins/releases/download/generated-index/index.json
Check:
name does not already exist as a folder in the indexgithub URLSummarize whether the plugin is ready for contribution:
LICENSE is a WARN but blocks contribution readiness until fixed)LICENSE can be noted as optional)## 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
checklists.md in this skill directory/a0/docs/agents/AGENTS.plugins.md/a0/docs/developer/plugins.md/a0/docs/agents/AGENTS.components.md/a0/skills/a0-contribute-plugin/SKILL.md