plugins: update docs and skills for extensible refactor
Alessandro committed
Mar 23, 2026 at 03:42 UTC
c48b26797e6b87f2f78d695aa30f34f38d8ad22b
15 files changed
+82
-16
docs/agents/AGENTS.plugins.md
+12
-2
@@ -12,7 +12,7 @@ Agent Zero uses a convention-over-configuration plugin model where runtime capab
12
13
1. Backend discovery (python/helpers/plugins.py): Resolves roots (usr/plugins/ first, then plugins/) and builds the effective set of plugins.
14
2. Path resolution (python/helpers/subagents.py): Injects plugin paths into the agent's search space for prompts, tools, and configurations.
15
-3. Python extensions (python/helpers/extension.py): Executes lifecycle hooks from extensions/python/<point>/.
15
+3. Python extensions (python/helpers/extension.py): Executes named lifecycle hooks from `extensions/python/<point>/` and implicit `@extensible` hooks from `extensions/python/_functions/<module>/<qualname>/<start|end>/`.
16
4. WebUI extensions (webui/js/extensions.js): Injects HTML/JS contributions into core UI breakpoints (x-extension).
17
18
---
@@ -37,13 +37,23 @@ usr/plugins/<plugin_name>/
37
├── prompts/ # Prompt templates
38
├── agents/ # Agent profiles (agents/<profile>/agent.yaml)
39
├── extensions/
40
-│ ├── python/<point>/ # Backend lifecycle hooks
40
+│ ├── python/<point>/ # Named backend lifecycle hooks
41
+│ ├── python/_functions/<module>/<qualname>/<start|end>/ # Implicit @extensible hooks
42
│ └── webui/<point>/ # UI HTML/JS contributions
43
└── webui/
44
├── config.html # Optional: Plugin settings UI
45
└── ... # Full plugin pages/components
46
```
47
48
+### Python extension layouts
49
+
50
+Use one of these backend extension layouts, depending on what you are extending:
51
+
52
+- `extensions/python/<extension_point>/` for named lifecycle hooks such as `system_prompt`, `monologue_start`, or `tool_execute_before`
53
+- `extensions/python/_functions/<module>/<qualname>/<start|end>/` for implicit `@extensible` call sites
54
+
55
+The `_functions` layout preserves every module segment and every nested `__qualname__` segment. Do not use the retired flattened form `extensions/python/<module>_<qualname>_<start|end>/`; those folder names no longer match the runtime lookup logic.
56
+
57
### Python import rule for user plugins
58
59
For plugin-local Python code in `usr/plugins/<plugin_name>/`, import through the
docs/developer/plugins.md
+11
-1
@@ -6,7 +6,7 @@ This page documents the current Agent Zero plugin system, including manifest for
6
7
Plugins extend Agent Zero through convention-based folders. A plugin can provide:
8
9
-- Backend: API handlers, tools, helpers, Python lifecycle extensions
9
+- Backend: API handlers, tools, helpers, Python lifecycle extensions, and implicit `@extensible` hooks
10
- Frontend: WebUI components and extension-point injections
11
- Agent profiles: plugin-scoped subagent definitions
12
- Settings: scoped plugin configuration loaded through the plugin settings store
@@ -64,12 +64,22 @@ usr/plugins/<plugin_name>/
64
│ └── <profile>/agent.yaml # optional plugin-distributed agent profile
65
├── extensions/
66
│ ├── python/<extension_point>/
67
+│ ├── python/_functions/<module>/<qualname>/<start|end>/
68
│ └── webui/<extension_point>/
69
└── webui/
70
├── config.html # optional settings UI
71
└── ...
72
```
73
74
+## Python Extension Layouts
75
+
76
+Use one of these backend layouts:
77
+
78
+- `extensions/python/<extension_point>/` for named lifecycle hooks such as `agent_init`, `system_prompt`, or `tool_execute_before`
79
+- `extensions/python/_functions/<module>/<qualname>/<start|end>/` for implicit `@extensible` hook targets
80
+
81
+The `_functions` layout keeps the full module path and nested `__qualname__` path, which avoids collisions between similarly named functions. Do not create the retired flattened form `extensions/python/<module>_<qualname>_<start|end>/`; it is stale and will not be resolved by the current extensible system.
82
+
83
## Python Imports for User Plugins
84
85
For plugin-local Python imports inside `usr/plugins/<plugin_name>/`, use the
plugins/README.md
+7
-1
@@ -21,12 +21,18 @@ For detailed guides on how to create, extend, or configure plugins, refer to:
21
22
Plugins are automatically discovered based on the presence of a `plugin.yaml` file. Each plugin can contribute:
23
24
-- **Backend**: API handlers, tools, helpers, and lifecycle extensions
24
+- **Backend**: API handlers, tools, helpers, named lifecycle extensions, and implicit `@extensible` hooks under `extensions/python/_functions/...`
25
- **Frontend**: HTML/JS UI contributions via core extension breakpoints
26
- **Settings**: Isolated configuration scoped per-project and per-agent profile
27
- **Activation**: Global and scoped ON/OFF rules via `.toggle-1` and `.toggle-0` files, including advanced per-scope switching in the WebUI
28
- **Agent profiles**: Plugin-distributed subagent definitions under `agents/<profile>/agent.yaml`
29
30
+Backend extension layouts:
31
+- `extensions/python/<point>/` for named lifecycle hooks
32
+- `extensions/python/_functions/<module>/<qualname>/<start|end>/` for implicit `@extensible` hooks
33
+
34
+Do not use the retired flattened `extensions/python/<module>_<qualname>_<start|end>/` form.
35
+
36
## Plugin Manifest
37
38
Every plugin requires a `plugin.yaml` at its root:
plugins/_error_retry/README.md
+2
-2
@@ -22,8 +22,8 @@ It does **not** retry exceptions that are already treated as controlled agent fl
22
23
## Key Files
24
25
-- `extensions/python/agent_Agent_monologue_start/_10_reset_critical_exception_counter.py`
26
-- `extensions/python/agent_Agent_handle_exception_end/_80_retry_critical_exception.py`
25
+- `extensions/python/_functions/agent/Agent/monologue/start/_10_reset_critical_exception_counter.py`
26
+- `extensions/python/_functions/agent/Agent/handle_exception/end/_80_retry_critical_exception.py`
27
28
## Configuration Scope
29
plugins/_plugin_installer/README.md
+3
-3
@@ -1,6 +1,6 @@
1
# Plugin Installer
2
3
-Install and update Agent Zero plugins from ZIP uploads, Git repositories, or a community index.
3
+Install and update Agent Zero plugins from ZIP uploads, Git repositories, or the community Plugin Index surfaced through the Plugin Hub.
4
5
## What It Does
6
@@ -20,8 +20,8 @@ This plugin provides the built-in installation workflow for third-party plugins.
20
- Rejects plugin name conflicts.
21
- **Install hooks and refresh**
22
- Runs the plugin install hook when present and calls `after_plugin_change(...)` so the app refreshes plugin state.
23
-- **Community browsing UI**
24
- - The web UI store handles browsing index entries, showing readme content, prompting about third-party plugin risk, and launching install/update actions.
23
+- **Plugin Hub UI**
24
+ - The web UI store handles browsing Plugin Index entries, showing README content, prompting about third-party plugin risk, and launching install/update actions.
25
26
## Key Files
27
plugins/_plugin_validator/webui/plugin-validator-checks.json
+1
-1
@@ -16,7 +16,7 @@
16
},
17
"structure": {
18
"label": "Structure Validation",
19
- "detail": "Inspect the directory layout and role of each top-level file or folder. Check that api/ contains Python ApiHandler files, tools/ contains Tool subclasses, extensions/ follows python/<point>/ or webui/<point>/ conventions, webui/config.html is backed by settings_sections, hooks.py exposes install when expected, execute.py follows the main()/sys.exit(main()) pattern, and the root contains only expected plugin files. Also verify a file named LICENSE exists at the plugin root (same directory as plugin.yaml). Agent Zero does not require LICENSE for loading a local plugin, but the Plugin Index requires LICENSE at the repository root for community listings; a missing LICENSE must not be rated pass for this phase.",
19
+ "detail": "Inspect the directory layout and role of each top-level file or folder. Check that api/ contains Python ApiHandler files, tools/ contains Tool subclasses, extensions/ follows python/<point>/, python/_functions/<module>/<qualname>/<start|end>/, or webui/<point>/ conventions, and flag the retired flattened python/<module>_<qualname>_<start|end>/ form if present. Also verify webui/config.html is backed by settings_sections, hooks.py exposes install when expected, execute.py follows the main()/sys.exit(main()) pattern, and the root contains only expected plugin files. Also verify a file named LICENSE exists at the plugin root (same directory as plugin.yaml). Agent Zero does not require LICENSE for loading a local plugin, but the Plugin Index requires LICENSE at the repository root for community listings; a missing LICENSE must not be rated pass for this phase.",
20
"criteria": {
21
"pass": "Directory layout cleanly matches Agent Zero plugin conventions and LICENSE exists at the plugin root",
22
"warning": "Layout mostly works but LICENSE is missing at the plugin root (required for Plugin Index submission; optional for local-only use), or there are unusual files or minor convention drift",
plugins/_plugin_validator/webui/plugin-validator-guidance.md
+1
@@ -1,6 +1,7 @@
1
- Store gate pattern: wrap store-backed UI in `<template x-if="$store.myStore">` and mount cleanup on the inner element.
2
- Store definition: use `createStore` from `/js/AlpineStore.js`; do not register Alpine stores inline in HTML or via `alpine:init`.
3
- Notifications: use `toastFrontendError`, `toastFrontendSuccess`, or backend notification helpers; do not render inline error boxes.
4
+- Python extensions: use `extensions/python/<point>/` for named lifecycle hooks and `extensions/python/_functions/<module>/<qualname>/<start|end>/` for implicit `@extensible` hooks. The flattened `extensions/python/<module>_<qualname>_<start|end>/` layout is stale and should be flagged.
5
- API handlers: subclass `ApiHandler` and return a dict or `Response`.
6
- Tools: subclass `Tool` from `helpers.tool`.
7
- AgentContext imports: use `from agent import AgentContext, AgentContextType`, never `helpers.context`.
plugins/_plugin_validator/webui/plugin-validator-prompt.md
+1
-1
@@ -20,7 +20,7 @@ Follow these steps in order:
20
21
1. Resolve the plugin root and list every file below it. Do not sample; inspect the full plugin.
22
2. Read `plugin.yaml` and record the plugin's name, title, description, and version.
23
-3. Map the directory structure and identify every top-level file or folder that affects behavior. Record whether a `LICENSE` file exists at the plugin root (required for Plugin Index submission per project policy; optional for local-only plugins).
23
+3. Map the directory structure and identify every top-level file or folder that affects behavior. Record whether backend extensions use named points under `extensions/python/<point>/`, implicit `@extensible` hooks under `extensions/python/_functions/<module>/<qualname>/<start|end>/`, or any stale flattened `extensions/python/<module>_<qualname>_<start|end>/` folders. Record whether a `LICENSE` file exists at the plugin root (required for Plugin Index submission per project policy; optional for local-only plugins).
24
4. Run ONLY the selected validation phases listed below.
25
5. If a temporary clone or extracted directory was used, perform the cleanup exactly as instructed.
26
skills/a0-contribute-plugin/SKILL.md
+3
-1
@@ -60,10 +60,12 @@ your-plugin-repo/ <- GitHub repository root
60
├── prompts/ <- prompt templates
61
├── agents/ <- agent profiles
62
├── conf/ <- config files (e.g. model_providers.yaml)
63
-├── extensions/ <- lifecycle and UI extensions
63
+├── extensions/ <- lifecycle, UI, and implicit @extensible hooks
64
└── webui/ <- frontend pages, stores, components
65
```
66
67
+Inside `extensions/`, use `python/<point>/` for named lifecycle hooks, `python/_functions/<module>/<qualname>/<start|end>/` for implicit `@extensible` hooks, and `webui/<point>/` for UI breakpoints. Do not publish the retired flattened `python/<module>_<qualname>_<start|end>/` form.
68
+
69
### Runtime `plugin.yaml` requirements
70
71
The remote `plugin.yaml` must include a **`name` field** - this is validated by CI and must exactly match the index folder name:
skills/a0-create-plugin/SKILL.md
+4
-1
@@ -196,7 +196,8 @@ save_plugin_config(
196
conf/
197
model_providers.yaml # Optional: add or override model providers
198
extensions/
199
- python/agent_init/ # Python lifecycle extensions
199
+ python/<extension_point>/ # Named Python lifecycle extensions
200
+ python/_functions/<module>/<qualname>/<start|end>/ # Implicit @extensible hooks
201
webui/<point>/ # HTML/JS hook extensions
202
webui/
203
config.html # Optional: plugin settings UI
@@ -204,6 +205,8 @@ save_plugin_config(
205
my-store.js # Alpine stores
206
```
207
208
+Do not create the retired flattened extensible path form `extensions/python/<module>_<qualname>_<start|end>/`. The current runtime only resolves the deep `_functions/<module>/<qualname>/<start|end>` layout for implicit `@extensible` hooks.
209
+
210
### Import rule for plugin-local Python code
211
212
Use the fully qualified `usr.plugins.<plugin_name>...` path for plugin-local
skills/a0-debug-plugin/SKILL.md
+6
-1
@@ -85,6 +85,11 @@ python3 -m py_compile /a0/usr/plugins/<name>/api/my_handler.py
85
- Common breakpoints: `sidebar-quick-actions-main-start`, `plugins-list-header-buttons`, `chat-input-bottom-actions-end`
86
- Confirm the HTML file has a root element with `x-data` and an `x-move-*` directive
87
88
+For backend extension hooks:
89
+- Named lifecycle hooks must live under `extensions/python/<point>/`
90
+- Implicit `@extensible` hooks must live under `extensions/python/_functions/<module>/<qualname>/<start|end>/`
91
+- The retired flattened form `extensions/python/<module>_<qualname>_<start|end>/` no longer loads
92
+
93
---
94
95
## 6. Settings not saving / loading wrong values
@@ -138,7 +143,7 @@ Plugin-related errors appear as Python tracebacks mentioning the plugin path.
143
2. Any directory containing `plugin.yaml` is treated as a plugin
144
3. `usr/plugins/<name>` takes priority over `plugins/<name>` when both exist (user overrides core)
145
4. Toggle state is evaluated: `.toggle-0` disables, `.toggle-1` enables, no file = enabled by default
141
-5. Enabled plugins have their `extensions/`, `api/`, `tools/`, etc. registered into the runtime
146
+5. Enabled plugins have their `extensions/`, `api/`, `tools/`, etc. registered into the runtime, including both named extension points and implicit `_functions/...` extensible hooks
147
148
Plugins are re-scanned when:
149
- Agent Zero restarts
skills/a0-manage-plugin/SKILL.md
+1
@@ -127,6 +127,7 @@ If the scan times out or errors (500), inform the user and ask whether to procee
127
128
The Plugin Hub marks a plugin as **Installed** by cross-referencing Plugin Hub keys against `usr/plugins/` directory names at request time. To appear installed:
129
- The plugin directory must exist at `usr/plugins/<name>/` with a valid `plugin.yaml`
130
+- If the plugin ships extensions, the framework will register both named extension points under `extensions/python/<point>/` and implicit `@extensible` hooks under `extensions/python/_functions/<module>/<qualname>/<start|end>/` after the plugin cache is refreshed
131
- The framework plugin cache must be cleared (the API handles this automatically)
132
- Re-fetching the Plugin Hub index will then show it as installed
133
skills/a0-plugin-router/SKILL.md
+3
-1
@@ -72,7 +72,7 @@ always_enabled: false # forces ON, disables toggle (framework use only)
72
|---|---|
73
| `api/` | API handlers (`ApiHandler` subclasses) |
74
| `tools/` | Agent tools (`Tool` subclasses) |
75
-| `extensions/python/<point>/` | Backend lifecycle hooks |
75
+| `extensions/python/<point>/` and `extensions/python/_functions/<module>/<qualname>/<start_or_end>/` | Backend lifecycle hooks and implicit `@extensible` hooks |
76
| `extensions/webui/<point>/` | HTML/JS injected into UI breakpoints |
77
| `webui/config.html` | Plugin settings UI |
78
| `webui/*.html`, `webui/*.js` | Full plugin pages and Alpine stores |
@@ -84,6 +84,8 @@ always_enabled: false # forces ON, disables toggle (framework use only)
84
| `conf/model_providers.yaml` | Add/override model providers |
85
| `LICENSE` | Optional under `usr/plugins/`; required at the root of a plugin GitHub repo before submitting to the Plugin Index |
86
87
+For `@extensible` targets, the only valid implicit hook layout is `extensions/python/_functions/<module>/<qualname>/<start|end>/`. The older flattened `extensions/python/<module>_<qualname>_<start|end>/` folders are obsolete.
88
+
89
### Activation
90
91
- Global toggle: `.toggle-1` (ON) / `.toggle-0` (OFF) files in the plugin dir
skills/a0-review-plugin/SKILL.md
+1
-1
@@ -46,7 +46,7 @@ Inspect the plugin directory layout:
46
- [ ] Directory name matches `^[a-z0-9_]+$`
47
- [ ] If `api/` exists: contains Python files only; each should subclass `ApiHandler`
48
- [ ] If `tools/` exists: contains Python files only; each should subclass `Tool`
49
-- [ ] If `extensions/` exists: check subdirs follow `python/<point>/` or `webui/<point>/` pattern
49
+- [ ] If `extensions/` 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>/` form
50
- [ ] If `helpers/` exists: shared Python logic (standard directory)
51
- [ ] If `prompts/` exists: prompt templates (standard directory)
52
- [ ] If `agents/` exists: agent profiles with `<profile>/agent.yaml` (standard directory)
skills/a0-review-plugin/checklists.md
+26
@@ -124,6 +124,32 @@ class MyTool(Tool):
124
125
---
126
127
+## Python Extension Layout
128
+
129
+Use one of these backend extension layouts:
130
+
131
+```text
132
+extensions/python/<extension_point>/
133
+```
134
+
135
+For named lifecycle hooks such as `agent_init`, `system_prompt`, `monologue_start`, or `tool_execute_before`.
136
+
137
+```text
138
+extensions/python/_functions/<module>/<qualname>/<start|end>/
139
+```
140
+
141
+For implicit `@extensible` hook targets. The path must keep the full module path and every nested `__qualname__` segment.
142
+
143
+**FAIL pattern**:
144
+
145
+```text
146
+extensions/python/<module>_<qualname>_<start|end>/
147
+```
148
+
149
+That flattened form is stale and no longer matches the current extensible runtime lookup.
150
+
151
+---
152
+
153
## AgentContext Access
154
155
```python