skills/a0-debug-plugin/SKILL.md
Work through these checks in order. Stop at the first failure and fix it before continuing.
# Check plugin.yaml exists
ls /a0/usr/plugins/<name>/plugin.yaml
# Validate YAML
python3 -c "import yaml; yaml.safe_load(open('/a0/usr/plugins/<name>/plugin.yaml'))"
# Check directory name doesn't start with '.'
ls /a0/usr/plugins/
Common causes:
plugin.yaml - plugin not discovered. - skipped by discovery# Check toggle state
ls -la /a0/usr/plugins/<name>/.toggle-*
# Check for conflicting scoped toggles
ls -la project/.a0proj/plugins/<name>/.toggle-* 2>/dev/null
ls -la /a0/usr/agents/default/plugins/<name>/.toggle-* 2>/dev/null
api/ and subclasses ApiHandlerPOST /api/plugins/<plugin_name>/<handler_filename_without_.py>from agent import AgentContext not from helpers.context import AgentContext# Check for syntax errors in handler
python3 -m py_compile /a0/usr/plugins/<name>/api/my_handler.py
<head> via <script type="module">createStore(...) matches $store.<name> in templatesextensions/webui/<correct_breakpoint_name>/webui/index.html or component files for <x-extension id="...">)sidebar-quick-actions-main-start, plugins-list-header-buttons, chat-input-bottom-actions-endx-data and an x-move-* directiveFor backend extension hooks:
extensions/python/<point>/@extensible hooks must live under extensions/python/_functions/<module>/<qualname>/<start|end>/extensions/python/<module>_<qualname>_<start|end>/ no longer loadsConfig resolution order (highest priority first):
project/.a0proj/agents/<profile>/plugins/<name>/config.jsonproject/.a0proj/plugins/<name>/config.jsonusr/agents/<profile>/plugins/<name>/config.jsonusr/plugins/<name>/config.jsonplugins/<name>/default_config.yaml# Find which config file is actually being loaded
find /a0 -path "*/plugins/<name>/config.json" 2>/dev/null
The install() hook is called automatically by the plugin installer after placement. If it didn't run:
install (not on_install or similar)code_execution_tool python - that uses /opt/venv, not /opt/venv-a0):cd /a0 && /opt/venv-a0/bin/python -c "
import asyncio
from helpers.plugins import call_plugin_hook
asyncio.run(call_plugin_hook('<plugin_name>', 'install'))
print('Done')
"
If the pre_update() hook is not running before plugin updates:
pre_updatecd /a0 && /opt/venv-a0/bin/python -c "
import asyncio
from helpers.plugins import call_plugin_hook
asyncio.run(call_plugin_hook('<plugin_name>', 'pre_update'))
print('Done')
"
If the uninstall() hook is not running when the plugin is removed:
uninstall (not on_uninstall or similar)uninstall() hook is called by uninstall_plugin() in helpers/plugins.py before the plugin directory is deleted. If the user removed the plugin manually (rm -rf), the hook was bypassed — always use the API or UI to uninstall.cd /a0 && /opt/venv-a0/bin/python -c "
import asyncio
from helpers.plugins import call_plugin_hook
asyncio.run(call_plugin_hook('<plugin_name>', 'uninstall'))
print('Done')
"
# Find recent log files
ls -lt /a0/logs/*.html | head -5
Plugin-related errors appear as Python tracebacks mentioning the plugin path.
usr/plugins/ then plugins/ at startupplugin.yaml is treated as a pluginusr/plugins/<name> takes priority over plugins/<name> when both exist (user overrides core).toggle-0 disables, .toggle-1 enables, no file = enabled by defaultextensions/, api/, tools/, etc. registered into the runtime, including both named extension points and implicit _functions/... extensible hooksPlugins are re-scanned when:
/a0/docs/agents/AGENTS.plugins.md/a0/skills/a0-manage-plugin/SKILL.md