mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-07-09 17:08:29 +00:00
Refactor a0-development into grounded references
Split the monolithic a0-development skill into a lean entry point plus focused reference files for runtime, DOX, tools, extensions, API/WebUI, profiles, prompts, skills, projects, and plugin workflow. Update the skill DOX ownership for the new references directory and clarify the root framework-vs-agent Python runtimes plus port-discovery guidance. Verified with git diff --check, targeted skill/tool tests under PYTHONPATH, and live localhost:32769 skill loading/read_file checks before committing.
This commit is contained in:
parent
d707fe7bcf
commit
4b49386f96
11 changed files with 752 additions and 820 deletions
18
AGENTS.md
18
AGENTS.md
|
|
@ -3,8 +3,8 @@
|
|||
[Generated using reconnaissance on 2026-02-22]
|
||||
|
||||
## Quick Reference
|
||||
Tech Stack: Python 3.12+ | Flask | Alpine.js | LiteLLM | WebSocket (Socket.io)
|
||||
Dev Server: python run_ui.py (runs on http://localhost:50001 by default)
|
||||
Tech Stack: Framework Python 3.12+ | Agent execution Python 3.13 in Docker | Flask | Alpine.js | LiteLLM | WebSocket (Socket.io)
|
||||
Dev Server: python run_ui.py (discover host/port from startup output or runtime configuration; do not assume a default port)
|
||||
Run Tests: pytest (standard) or pytest tests/test_name.py (file-scoped)
|
||||
Documentation: README.md | docs/
|
||||
Frontend & Plugin DOX: [WebUI](webui/AGENTS.md) | [Components](webui/components/AGENTS.md) | [Frontend JS](webui/js/AGENTS.md) | [Plugins](plugins/AGENTS.md)
|
||||
|
|
@ -43,22 +43,24 @@ Do not combine these commands; run them individually:
|
|||
pip install -r requirements.txt
|
||||
```
|
||||
- Start WebUI: python run_ui.py
|
||||
- Discover the WebUI URL from startup output, launcher/Docker port mappings, or explicit `--host`/`--port`/`WEB_UI_PORT` configuration; do not hardcode a default port.
|
||||
|
||||
---
|
||||
|
||||
## Docker Environment
|
||||
|
||||
When running in Docker, Agent Zero uses two distinct Python runtimes to isolate the framework from the code being executed:
|
||||
When running in Docker, Agent Zero uses two distinct Python runtimes to isolate the framework itself from code executed on behalf of the agent:
|
||||
|
||||
### 1. Framework Runtime (/opt/venv-a0)
|
||||
- Version: Python 3.12.4
|
||||
- Purpose: Runs the Agent Zero backend, API, and core logic.
|
||||
- Packages: Contains all dependencies from requirements.txt.
|
||||
- Purpose: Runs the Agent Zero framework itself: WebUI backend, API, core loop, scheduler, framework imports, and plugin hooks/tools that execute inside the framework process.
|
||||
- Packages: Contains framework dependencies from requirements.txt.
|
||||
- Verification: Use this runtime for framework/backend import checks, WebUI startup checks, and plugin hook behavior unless the code explicitly switches environments.
|
||||
|
||||
### 2. Execution Runtime (/opt/venv)
|
||||
### 2. Agent Execution Runtime (/opt/venv)
|
||||
- Version: Python 3.13
|
||||
- Purpose: Default environment for the interactive terminal and the agent's code execution tool.
|
||||
- Behavior: This is the environment active when you docker exec into the container. Packages installed by the agent via pip install during a task are stored here.
|
||||
- Purpose: Default Python environment for the agent's terminal/code-execution tasks and user code run by the agent.
|
||||
- Behavior: Packages installed by the agent during a task belong here so task dependencies do not pollute or prove the framework runtime. Do not use this runtime as evidence that framework imports, WebUI startup, or plugin hooks work.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,27 +3,35 @@
|
|||
## Purpose
|
||||
|
||||
- Own the broad Agent Zero development guide used by agents extending the framework.
|
||||
- Keep architecture, tools, extensions, API, agents, prompts, projects, and skills guidance in sync with the repository.
|
||||
- Keep architecture, tools, extensions, API, agents, prompts, projects, plugins, runtime, and skills guidance in sync with the repository.
|
||||
|
||||
## Ownership
|
||||
|
||||
- `SKILL.md` owns the development overview, path conventions, and implementation references.
|
||||
- `SKILL.md` owns the concise development entry point, routing workflow, path conventions, and reference map.
|
||||
- `references/` owns detailed source-grounded development references loaded on demand.
|
||||
|
||||
## Local Contracts
|
||||
|
||||
- Keep paths and examples current with source files and DOX contracts.
|
||||
- Route plugin-specific tasks to the plugin router or specialist plugin skills.
|
||||
- Do not duplicate long contracts that belong in narrower AGENTS.md files when a reference is enough.
|
||||
- Reference files must identify current source or DOX anchors and avoid hardcoded default WebUI ports.
|
||||
|
||||
## Work Guidance
|
||||
|
||||
- Update this skill after durable framework workflow, extension, tool, API, prompt, or profile changes.
|
||||
- Keep examples operational and compatible with the current helper classes.
|
||||
- Keep `SKILL.md` lean; move detailed schemas, examples, and topic-specific guidance to `references/`.
|
||||
|
||||
## Verification
|
||||
|
||||
- Manually read `SKILL.md` for stale architecture references and broken related-skill links.
|
||||
- Manually read `SKILL.md` and changed reference files for stale architecture references, broken relative paths, and specialist-skill duplication.
|
||||
- Load the skill after reference-map changes and confirm `skills_tool` exposes the expected reference file tree.
|
||||
|
||||
## Child DOX Index
|
||||
|
||||
No child DOX files.
|
||||
Direct child DOX files:
|
||||
|
||||
| Child | Scope |
|
||||
| --- | --- |
|
||||
| [references/AGENTS.md](references/AGENTS.md) | Source-grounded development references loaded by this skill. |
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
name: a0-development
|
||||
description: Development guide for extending and building features for the Agent Zero AI framework. Covers architecture, tools, extensions, API endpoints, agent profiles, projects, prompts, and skills — with correct paths, imports, and patterns matching the current codebase.
|
||||
version: 1.0.0
|
||||
description: Development guide for extending Agent Zero from current source and DOX. Use for framework architecture, tools, extensions, API/WebUI handlers, agent profiles, prompts, skills, projects, runtime boundaries, and contribution workflow. Load the focused reference files before giving implementation guidance.
|
||||
version: 1.1.0
|
||||
author: Agent Zero Team
|
||||
tags: ["development", "framework", "agent-zero", "extending", "tools", "extensions", "skills", "api", "agents", "prompts"]
|
||||
tags: ["development", "framework", "agent-zero", "extending", "tools", "extensions", "skills", "api", "agents", "prompts", "dox"]
|
||||
trigger_patterns:
|
||||
- "extend agent zero"
|
||||
- "agent zero development"
|
||||
|
|
@ -21,826 +21,60 @@ trigger_patterns:
|
|||
- "extension hook points"
|
||||
- "prompt system"
|
||||
- "agent profile"
|
||||
- "dox"
|
||||
---
|
||||
|
||||
# Agent Zero Development Guide
|
||||
# Agent Zero Development
|
||||
|
||||
This skill provides comprehensive, accurate guidance for extending and building features for Agent Zero. Use it when you need to:
|
||||
Use this skill as the entry point for Agent Zero framework development. It is intentionally lean: load only the reference files that match the task, then verify against the current repository before changing code.
|
||||
|
||||
- Understand the **architecture** and project layout
|
||||
- Create new **Tools** for agent capabilities
|
||||
- Add **Extensions** to hook into the framework lifecycle
|
||||
- Build **API Endpoints** for the Web UI
|
||||
- Create **Agent Profiles** (subordinates) with custom prompts
|
||||
- Understand and extend the **Prompt System**
|
||||
- Create **Skills** (see the dedicated `build-skill` skill for the full wizard)
|
||||
- Work with **Projects** and workspace configuration
|
||||
## Reality Rules
|
||||
|
||||
> **Path convention:** Throughout this guide, `/a0/` refers to the framework root — this is `/a0/` inside Docker, or your local repository root in development. All paths are relative to this root.
|
||||
1. Source and nearest DOX beat memory, examples, and this skill if they disagree.
|
||||
2. Before editing, read the applicable `AGENTS.md` chain from the repo root to every file you expect to touch.
|
||||
3. New capabilities should usually be plugins. For plugin-specific work, load `a0-plugin-router` and follow the routed specialist skill.
|
||||
4. Do not assume ports. Discover WebUI host/port from startup output, launcher or Docker mapping, or explicit `--host`, `--port`, `WEB_UI_HOST`, and `WEB_UI_PORT` configuration.
|
||||
5. In Docker, framework checks belong to `/opt/venv-a0` and agent/user code execution belongs to `/opt/venv`. Do not use one runtime as proof for the other.
|
||||
6. Treat `/a0/` as the runtime framework root inside Docker. In local development it means the repository root. If a live container matters, prove that `/a0` matches the checkout before trusting source-only conclusions.
|
||||
7. Do not document or change ignored `usr/` or `tmp/` runtime state unless the user explicitly asks.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Plugins are the primary way to extend Agent Zero.** Most new tools, extensions, and prompts should be packaged as plugins. For all plugin tasks (create, review, manage, debug, contribute), load the `a0-plugin-router` skill which routes to the appropriate specialist. This guide covers the underlying framework patterns that plugins build upon.
|
||||
## Reference Map
|
||||
|
||||
Related skills: `a0-plugin-router` (plugin tasks) | `build-skill` (skill creation wizard) | `a0-create-plugin` | `a0-review-plugin` | `a0-manage-plugin` | `a0-contribute-plugin` | `a0-debug-plugin`
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Project Layout
|
||||
|
||||
```
|
||||
/a0/ # Framework root
|
||||
├── agent.py # Core Agent + AgentContext + AgentConfig classes
|
||||
├── initialize.py # Agent initialization logic
|
||||
├── models.py # Model definitions
|
||||
├── run_ui.py # Web UI entry point
|
||||
│
|
||||
├── tools/ # Core tools (search, response, browser, etc.)
|
||||
├── extensions/
|
||||
│ ├── python/ # Python lifecycle extensions
|
||||
│ │ ├── <hook_point>/ # e.g., agent_init/, system_prompt/, etc.
|
||||
│ │ │ └── _NN_name.py # Numbered extension files
|
||||
│ │ └── _functions/ # Implicit @extensible decorator extensions
|
||||
│ └── webui/ # JavaScript WebUI extensions
|
||||
│ └── <hook_point>/ # e.g., json_api_call_before/
|
||||
│ └── name.js
|
||||
├── api/ # Flask API endpoint handlers
|
||||
├── helpers/ # Framework utilities and base classes
|
||||
│ ├── tool.py # Tool + Response base classes
|
||||
│ ├── extension.py # Extension base class + @extensible decorator
|
||||
│ ├── api.py # ApiHandler base class
|
||||
│ ├── files.py # File operations + prompt reading
|
||||
│ ├── plugins.py # Plugin system manager
|
||||
│ ├── print_style.py # Console output formatting
|
||||
│ └── ... # Many more utility modules
|
||||
│
|
||||
├── prompts/ # Core prompt fragments (system, tools, framework)
|
||||
├── agents/ # Agent profiles (subordinate specializations)
|
||||
│ ├── default/ # Base profile (inherited by others)
|
||||
│ ├── agent0/ # Main user-facing agent
|
||||
│ ├── developer/ # Developer subordinate
|
||||
│ ├── hacker/ # Security subordinate
|
||||
│ ├── researcher/ # Research subordinate
|
||||
│ └── _example/ # Example profile with tool + extension samples
|
||||
│
|
||||
├── plugins/ # Core plugins (tools, extensions, prompts)
|
||||
│ ├── _code_execution/ # Terminal/Python/Node.js execution
|
||||
│ ├── _memory/ # Persistent memory system
|
||||
│ ├── _text_editor/ # File read/write/patch
|
||||
│ ├── _model_config/ # LLM model selection
|
||||
│ ├── _infection_check/ # Prompt injection safety
|
||||
│ └── ... # More core plugins
|
||||
│
|
||||
├── skills/ # Core skills (SKILL.md bundles)
|
||||
├── knowledge/ # Knowledge base files
|
||||
├── webui/ # Web UI frontend
|
||||
├── docs/ # Documentation
|
||||
│
|
||||
└── usr/ # User-space (survives updates)
|
||||
├── agents/ # User-created agent profiles
|
||||
├── plugins/ # User-installed plugins
|
||||
├── skills/ # User-created skills
|
||||
├── knowledge/ # User knowledge base files
|
||||
├── extensions/ # Standalone user extensions (created on demand; prefer plugins instead)
|
||||
├── projects/ # Project workspaces (created on demand when user adds projects via UI)
|
||||
└── workdir/ # Default working directory
|
||||
```
|
||||
|
||||
### Key Architecture Patterns
|
||||
|
||||
1. **Plugin-first design** — Most capabilities (tools, extensions, prompts) are delivered via plugins in `/a0/plugins/` (core) or `/a0/usr/plugins/` (user).
|
||||
2. **Extensions execute in numeric order** — Files named `_10_*.py`, `_20_*.py`, etc. run sequentially within each hook point.
|
||||
3. **Tools inherit from `Tool`** — All tools implement the `execute()` method returning a `Response`.
|
||||
4. **Shared `AgentContext`** — Enables state persistence across agents in a conversation.
|
||||
5. **Async/await throughout** — All tool execution, extensions, and API handlers are async.
|
||||
6. **Prompt fragments compose** — System prompts are assembled from named fragments with includes and variable substitution.
|
||||
7. **Profile inheritance** — Agent profiles inherit from `default/` and override specific prompt fragments.
|
||||
8. **User-space separation** — Everything under `/a0/usr/` survives framework updates.
|
||||
|
||||
### Agent Loop
|
||||
|
||||
The core execution cycle works as follows:
|
||||
|
||||
1. **User message** arrives (via UI or API)
|
||||
2. **System prompt assembly** — prompt fragments are composed with includes and variable substitution
|
||||
3. **LLM call** — the assembled prompt + conversation history is sent to the model
|
||||
4. **Response parsing** — the framework parses the LLM response looking for JSON tool calls
|
||||
5. **Tool execution** — if tool calls are found, each tool's `execute()` method is called and the result is appended to history
|
||||
6. **Loop continues** — steps 3-5 repeat until the agent produces a `response` tool call (which ends the loop) or a loop limit is reached
|
||||
|
||||
Extensions fire at each stage (e.g., `monologue_start`, `before_main_llm_call`, `tool_execute_before`, etc.), allowing plugins to observe and modify behavior at every point.
|
||||
|
||||
---
|
||||
|
||||
## Creating Tools
|
||||
|
||||
Tools are how agents interact with the world. Each tool inherits from the `Tool` base class.
|
||||
|
||||
### Import Path
|
||||
|
||||
```python
|
||||
from helpers.tool import Tool, Response
|
||||
```
|
||||
|
||||
### Tool Base Class
|
||||
|
||||
```python
|
||||
# /a0/helpers/tool.py
|
||||
|
||||
@dataclass
|
||||
class Response:
|
||||
message: str # Text response shown to agent
|
||||
break_loop: bool # True = stop agent message loop
|
||||
additional: dict[str, Any] | None = None # Extra metadata for history
|
||||
|
||||
class Tool:
|
||||
def __init__(self, agent: Agent, name: str, method: str | None,
|
||||
args: dict[str,str], message: str,
|
||||
loop_data: LoopData | None, **kwargs) -> None:
|
||||
self.agent = agent
|
||||
self.name = name
|
||||
self.method = method # For tools with sub-methods (e.g., "skills_tool:load")
|
||||
self.args = args
|
||||
self.loop_data = loop_data
|
||||
self.message = message
|
||||
|
||||
async def execute(self, **kwargs) -> Response:
|
||||
pass # Override this
|
||||
|
||||
# Lifecycle hooks (called automatically):
|
||||
async def before_execution(self, **kwargs): ...
|
||||
async def after_execution(self, response: Response, **kwargs): ...
|
||||
```
|
||||
|
||||
### Where Tools Live
|
||||
|
||||
| Location | Purpose |
|
||||
|---|---|
|
||||
| `/a0/tools/` | Core framework tools (search, response, call_subordinate, etc.) |
|
||||
| `/a0/plugins/<plugin>/tools/` | Plugin-provided tools (code_execution, memory, text_editor) |
|
||||
| `/a0/agents/<profile>/tools/` | Profile-specific tool overrides |
|
||||
| `/a0/usr/plugins/<plugin>/tools/` | User plugin tools |
|
||||
|
||||
### Example: Creating a Tool
|
||||
|
||||
Based on the actual `_example` profile in `/a0/agents/_example/tools/example_tool.py`:
|
||||
|
||||
```python
|
||||
# my_tool.py
|
||||
from helpers.tool import Tool, Response
|
||||
|
||||
class MyTool(Tool):
|
||||
async def execute(self, **kwargs):
|
||||
# Get arguments — kwargs contains the tool_args from the agent's JSON
|
||||
input_data = kwargs.get("input", "")
|
||||
|
||||
# Do something
|
||||
result = f"Processed: {input_data}"
|
||||
|
||||
# Return response
|
||||
return Response(
|
||||
message=result, # Shown to the agent
|
||||
break_loop=False, # Don't stop the agent loop
|
||||
)
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Every tool needs a corresponding **prompt fragment** so the agent knows how to use it. Create a file named `agent.system.tool.<tool_name>.md` in the appropriate `prompts/` directory. See the [Prompt System](#prompt-system) section.
|
||||
|
||||
### Tool Best Practices
|
||||
|
||||
- Always handle errors gracefully — return error messages in `Response`, don't crash
|
||||
- Access agent context via `self.agent.context`
|
||||
- Use `self.method` to support sub-methods (e.g., `my_tool:action1`, `my_tool:action2`)
|
||||
- Use `kwargs.get()` to read arguments with defaults
|
||||
- For long operations, use `self.set_progress()` or `self.add_progress()` to show status
|
||||
- Access `self.loop_data` for loop state (iteration count, timing, etc.) — this is the `LoopData` instance passed during tool dispatch
|
||||
|
||||
---
|
||||
|
||||
## Creating Extensions
|
||||
|
||||
Extensions hook into specific lifecycle points in the agent framework.
|
||||
|
||||
### Import Path
|
||||
|
||||
```python
|
||||
from helpers.extension import Extension
|
||||
```
|
||||
|
||||
### Extension Base Class
|
||||
|
||||
```python
|
||||
class Extension:
|
||||
def __init__(self, agent: "Agent | None", **kwargs):
|
||||
self.agent: "Agent | None" = agent
|
||||
self.kwargs = kwargs
|
||||
|
||||
def execute(self, **kwargs) -> None | Awaitable[None]:
|
||||
pass # Override this — kwargs are hook-point-specific
|
||||
```
|
||||
|
||||
> Extensions can be sync or async. If `execute()` returns an `Awaitable`, the framework will `await` it automatically. The `agent` parameter is nullable because some hook points (like `startup_migration` or `banners`) fire before an agent exists.
|
||||
|
||||
### Extension File Location
|
||||
|
||||
Extensions live in directories named by their hook point. The path structure is:
|
||||
|
||||
```
|
||||
extensions/python/<hook_point>/_NN_name.py
|
||||
```
|
||||
|
||||
Where `_NN_` is a numeric prefix controlling execution order (e.g., `_10_`, `_20_`, `_50_`).
|
||||
|
||||
| Source | Path |
|
||||
|---|---|
|
||||
| Core extensions | `/a0/extensions/python/<hook_point>/` |
|
||||
| Plugin extensions | `/a0/plugins/<plugin>/extensions/python/<hook_point>/` |
|
||||
| User extensions | `/a0/usr/extensions/python/<hook_point>/` |
|
||||
| Agent profile extensions | `/a0/agents/<profile>/extensions/<hook_point>/` |
|
||||
| User plugin extensions | `/a0/usr/plugins/<plugin>/extensions/python/<hook_point>/` |
|
||||
|
||||
### Python Extension Hook Points
|
||||
|
||||
Complete list of available hook points:
|
||||
|
||||
| Hook Point | When It Fires | Common Use |
|
||||
|---|---|---|
|
||||
| `agent_init` | Agent is initialized | Load configs, set defaults |
|
||||
| `system_prompt` | System prompt is being assembled | Inject prompt content |
|
||||
| `monologue_start` | Agent monologue begins | Pre-processing, state setup |
|
||||
| `message_loop_start` | Before message processing loop | Pre-loop setup |
|
||||
| `message_loop_prompts_before` | Before prompt assembly in loop | Modify prompt inputs |
|
||||
| `message_loop_prompts_after` | After prompt assembly in loop | Add context (memory recall lives here) |
|
||||
| `before_main_llm_call` | Before the LLM API call | Modify prompts, add context |
|
||||
| `util_model_call_before` | Before utility model calls | Modify utility prompts |
|
||||
| `response_stream` | When response streaming begins | Initialize stream handlers |
|
||||
| `response_stream_chunk` | Per response chunk received | Transform output, collect data |
|
||||
| `response_stream_end` | Response streaming complete | Finalize, analyze full response |
|
||||
| `reasoning_stream` | Reasoning/thinking stream begins | Monitor reasoning |
|
||||
| `reasoning_stream_chunk` | Per reasoning chunk | Collect reasoning data |
|
||||
| `reasoning_stream_end` | Reasoning stream complete | Analyze reasoning |
|
||||
| `tool_execute_before` | Before a tool runs | Validation, logging, safety checks |
|
||||
| `tool_execute_after` | After a tool runs | Post-process results |
|
||||
| `hist_add_before` | Before adding to history | Modify history entries |
|
||||
| `hist_add_tool_result` | After tool result added to history | Log tool results |
|
||||
| `message_loop_end` | After message processing loop | Post-loop cleanup |
|
||||
| `monologue_end` | Agent monologue complete | Memorization, cleanup |
|
||||
| `process_chain_end` | Entire processing chain done | Final cleanup |
|
||||
| `job_loop` | Background job loop tick | Periodic background tasks |
|
||||
| `error_format` | Error is being formatted | Custom error messages |
|
||||
| `startup_migration` | Framework startup | Data migrations |
|
||||
| `banners` | Startup banners displayed | Add custom banners |
|
||||
| `embedding_model_changed` | Embedding model changed | Reload vector stores (fired programmatically, not a directory-based hook) |
|
||||
| `user_message_ui` | User message from UI | Pre-process user input |
|
||||
| `webui_ws_connect` | WebSocket client connects | Session setup |
|
||||
| `webui_ws_disconnect` | WebSocket client disconnects | Session cleanup |
|
||||
| `webui_ws_event` | WebSocket event received | Handle custom WS events |
|
||||
|
||||
### The `@extensible` Decorator (Implicit Extension Points)
|
||||
|
||||
Any framework function decorated with `@extensible` automatically gets two extension points:
|
||||
|
||||
```
|
||||
_functions/<module_path>/<qualname_path>/start
|
||||
_functions/<module_path>/<qualname_path>/end
|
||||
```
|
||||
|
||||
The path mapping converts Python module paths and qualified names using `/` separators:
|
||||
- Module `agent.py` → `agent`
|
||||
- Class method `Agent.handle_exception` → `Agent/handle_exception`
|
||||
- Full path: `_functions/agent/Agent/handle_exception/start`
|
||||
|
||||
For nested modules like `helpers.history`, a method `History.add` would map to `_functions/helpers/history/History/add/start`.
|
||||
|
||||
For example, a function `Agent.handle_exception` in module `agent` creates:
|
||||
- `_functions/agent/Agent/handle_exception/start`
|
||||
- `_functions/agent/Agent/handle_exception/end`
|
||||
|
||||
Extensions in these directories receive a `data` dict with:
|
||||
- `data["args"]` — positional args (mutable)
|
||||
- `data["kwargs"]` — keyword args (mutable)
|
||||
- `data["result"]` — set this to short-circuit the function
|
||||
- `data["exception"]` — set to a `BaseException` to force-raise
|
||||
|
||||
This is used by plugins like `_error_retry` to wrap core agent methods.
|
||||
|
||||
### WebUI Extensions (JavaScript)
|
||||
|
||||
Client-side extensions live under `extensions/webui/<hook_point>/`:
|
||||
|
||||
| Hook Point | When It Fires |
|
||||
|---|---|
|
||||
| `json_api_call_before` | Before a JSON API request |
|
||||
| `json_api_call_after` | After a JSON API response |
|
||||
| `fetch_api_call_before` | Before a fetch API request |
|
||||
| `fetch_api_call_after` | After a fetch API response |
|
||||
| `get_message_handler` | Register custom message renderers |
|
||||
| `set_messages_before_loop` | Before messages are rendered |
|
||||
| `set_messages_after_loop` | After messages are rendered |
|
||||
| `webui_ws_push` | WebSocket push to client |
|
||||
|
||||
### Example: Creating an Extension
|
||||
|
||||
Based on the actual `_example` profile in `/a0/agents/_example/extensions/agent_init/_10_example_extension.py`:
|
||||
|
||||
```python
|
||||
# extensions/python/agent_init/_15_my_extension.py
|
||||
from helpers.extension import Extension
|
||||
|
||||
class MyExtension(Extension):
|
||||
async def execute(self, **kwargs):
|
||||
# Access the agent
|
||||
agent = self.agent
|
||||
context = agent.context
|
||||
|
||||
# Extension logic — kwargs content depends on the hook point
|
||||
agent.agent_name = "CustomAgent" + str(agent.number)
|
||||
```
|
||||
|
||||
### Extension Execution Order
|
||||
|
||||
Extensions execute in numeric order based on filename prefix:
|
||||
|
||||
```
|
||||
_10_first.py # Runs first
|
||||
_20_second.py # Runs second
|
||||
_50_third.py # Runs third
|
||||
```
|
||||
|
||||
Use 10-number increments to leave room for future extensions.
|
||||
|
||||
---
|
||||
|
||||
## Creating API Endpoints
|
||||
|
||||
API endpoints serve the Web UI and external clients using Flask.
|
||||
|
||||
### Import Path
|
||||
|
||||
```python
|
||||
from helpers.api import ApiHandler
|
||||
from flask import Request, Response
|
||||
```
|
||||
|
||||
### ApiHandler Base Class
|
||||
|
||||
```python
|
||||
class ApiHandler:
|
||||
def __init__(self, app: Flask, thread_lock: ThreadLockType):
|
||||
self.app = app
|
||||
self.thread_lock = thread_lock
|
||||
|
||||
# Override these class methods to configure behavior:
|
||||
@classmethod
|
||||
def requires_loopback(cls) -> bool: return False # Restrict to localhost
|
||||
@classmethod
|
||||
def requires_api_key(cls) -> bool: return False # Require API key
|
||||
@classmethod
|
||||
def requires_auth(cls) -> bool: return True # Require auth session
|
||||
@classmethod
|
||||
def get_methods(cls) -> list[str]: return ["POST"] # HTTP methods
|
||||
@classmethod
|
||||
def requires_csrf(cls) -> bool: return cls.requires_auth() # CSRF protection
|
||||
|
||||
# Implement this:
|
||||
async def process(self, input: dict, request: Request) -> dict | Response:
|
||||
pass
|
||||
|
||||
# Utility: get or create an agent context
|
||||
def use_context(self, ctxid: str, create_if_not_exists: bool = True) -> AgentContext:
|
||||
...
|
||||
```
|
||||
|
||||
### Where API Endpoints Live
|
||||
|
||||
| Location | Purpose |
|
||||
|---|---|
|
||||
| `/a0/api/` | Core API endpoints |
|
||||
| `/a0/plugins/<plugin>/api/` | Plugin API endpoints |
|
||||
| `/a0/usr/plugins/<plugin>/api/` | User plugin API endpoints |
|
||||
|
||||
Endpoints are auto-discovered by filename. The route is derived from the filename (e.g., `my_endpoint.py` -> `/api/my_endpoint`).
|
||||
|
||||
### Example: API Endpoint
|
||||
|
||||
```python
|
||||
# api/my_endpoint.py
|
||||
from helpers.api import ApiHandler
|
||||
from flask import Request, Response
|
||||
from agent import AgentContext
|
||||
|
||||
class MyEndpoint(ApiHandler):
|
||||
@classmethod
|
||||
def get_methods(cls) -> list[str]:
|
||||
return ["GET", "POST"]
|
||||
|
||||
async def process(self, input: dict, request: Request) -> dict:
|
||||
param = input.get("param", "default")
|
||||
|
||||
# Get or create agent context
|
||||
ctxid = input.get("context", "")
|
||||
context = self.use_context(ctxid)
|
||||
|
||||
return {
|
||||
"result": f"processed {param}",
|
||||
"context": context.id,
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Creating Agent Profiles
|
||||
|
||||
Agent profiles define specialized subordinates with custom prompts and behaviors.
|
||||
|
||||
> For a guided, step-by-step wizard (scope selection, `agent.yaml` schema, prompt overrides, tool/extension stubs, test checklist) use the dedicated `/a0/skills/a0-create-agent/SKILL.md` skill.
|
||||
|
||||
### Profile Directory Structure
|
||||
|
||||
```
|
||||
agents/<profile-name>/
|
||||
+-- agent.yaml # Required: profile metadata
|
||||
+-- prompts/ # Optional: prompt overrides
|
||||
| +-- agent.system.main.role.md # Role definition (most common override)
|
||||
| +-- agent.system.main.communication.md # Communication style
|
||||
| +-- agent.system.tool.<name>.md # Tool-specific prompts
|
||||
+-- tools/ # Optional: profile-specific tools
|
||||
| +-- my_tool.py
|
||||
+-- extensions/ # Optional: profile-specific extensions
|
||||
+-- <hook_point>/
|
||||
+-- _NN_extension.py
|
||||
```
|
||||
|
||||
### agent.yaml Format
|
||||
|
||||
The actual format is simple YAML with only three fields:
|
||||
|
||||
```yaml
|
||||
title: Developer
|
||||
description: Agent specialized in complex software development.
|
||||
context: Use this agent for software development tasks, including writing code,
|
||||
debugging, refactoring, and architectural design.
|
||||
```
|
||||
|
||||
| Field | Purpose |
|
||||
|---|---|
|
||||
| `title` | Display name shown in UI and agent selection |
|
||||
| `description` | Brief description of the agent's specialization |
|
||||
| `context` | Instructions for when to delegate to this profile |
|
||||
|
||||
> [!NOTE]
|
||||
> There is **no** model configuration, temperature, or allowed_tools in the profile YAML. `agent.yaml` contains only `title`, `description`, and `context`. Profile-specific Main/Utility model settings are managed by the `_model_config` plugin in `usr/agents/<profile>/plugins/_model_config/config.json`. Tool availability is controlled by plugin activation.
|
||||
|
||||
### Where Profiles Live
|
||||
|
||||
| Location | Purpose |
|
||||
|---|---|
|
||||
| `/a0/agents/` | Core profiles (default, agent0, developer, hacker, researcher) |
|
||||
| `/a0/usr/agents/` | User-created profiles (survives updates) |
|
||||
|
||||
### Prompt Override Mechanism
|
||||
|
||||
Profiles inherit all prompts from the `default/` profile. To customize behavior, place prompt files with the **same name** in your profile's `prompts/` directory. The framework searches profile-specific prompts first, then falls back to the default.
|
||||
|
||||
The most common override is `agent.system.main.role.md` which defines the agent's role and specialization.
|
||||
|
||||
### Example: Creating a Profile
|
||||
|
||||
```yaml
|
||||
# /a0/usr/agents/data-analyst/agent.yaml
|
||||
title: Data Analyst
|
||||
description: Agent specialized in data analysis, visualization, and statistical modeling.
|
||||
context: Use this agent for data analysis tasks, creating visualizations, statistical
|
||||
analysis, and working with datasets in Python.
|
||||
```
|
||||
|
||||
```markdown
|
||||
<!-- /a0/usr/agents/data-analyst/prompts/agent.system.main.role.md -->
|
||||
|
||||
## Your role
|
||||
You are a specialized data analysis agent.
|
||||
Your expertise includes:
|
||||
- Python data analysis (pandas, numpy, scipy)
|
||||
- Data visualization (matplotlib, seaborn, plotly)
|
||||
- Statistical modeling and hypothesis testing
|
||||
- SQL queries and database analysis
|
||||
- Data cleaning and preprocessing
|
||||
|
||||
## Process
|
||||
1. Understand the data and the question
|
||||
2. Choose appropriate tools and methods
|
||||
3. Execute analysis with code_execution_tool
|
||||
4. Visualize results when applicable
|
||||
5. Provide clear interpretation of findings
|
||||
```
|
||||
|
||||
### Reference: The `_example` Profile
|
||||
|
||||
The framework includes a complete example profile at `/a0/agents/_example/` that demonstrates:
|
||||
- Custom tool: `/a0/agents/_example/tools/example_tool.py`
|
||||
- Custom extension: `/a0/agents/_example/extensions/agent_init/_10_example_extension.py`
|
||||
- Tool prompt: `/a0/agents/_example/prompts/agent.system.tool.example_tool.md`
|
||||
- Role prompt: `/a0/agents/_example/prompts/agent.system.main.role.md`
|
||||
|
||||
---
|
||||
|
||||
## Prompt System
|
||||
|
||||
Agent Zero assembles system prompts from **named fragments** using includes and variable substitution.
|
||||
|
||||
### Prompt File Naming Convention
|
||||
|
||||
Prompt files follow a dot-separated naming scheme:
|
||||
|
||||
```
|
||||
agent.system.main.md # Main system prompt (entry point)
|
||||
agent.system.main.role.md # Role definition
|
||||
agent.system.main.communication.md # Communication style
|
||||
agent.system.tool.<name>.md # Tool usage instructions
|
||||
agent.system.tools.md # Tools overview
|
||||
agent.system.projects.main.md # Project system
|
||||
agent.system.secrets.md # Secret handling
|
||||
agent.system.skills.md # Skills listing
|
||||
agent.system.datetime.md # Current date/time
|
||||
agent.context.extras.md # Context extras
|
||||
fw.*.md # Framework messages (errors, hints, etc.)
|
||||
```
|
||||
|
||||
### Where Prompts Live
|
||||
|
||||
| Location | Priority | Purpose |
|
||||
|---|---|---|
|
||||
| `/a0/agents/<profile>/prompts/` | Highest | Profile-specific overrides |
|
||||
| `/a0/usr/agents/<profile>/prompts/` | High | User profile overrides |
|
||||
| `/a0/plugins/<plugin>/prompts/` | Normal | Plugin-provided prompts |
|
||||
| `/a0/usr/plugins/<plugin>/prompts/` | Normal | User plugin prompts |
|
||||
| `/a0/prompts/` | Base | Core framework prompts |
|
||||
|
||||
The framework searches directories in priority order and uses the **first match** found.
|
||||
|
||||
### Include Mechanism
|
||||
|
||||
Prompts can include other fragments using double-brace `include` directives.
|
||||
|
||||
The syntax uses opening double-brace, the keyword, and closing double-brace:
|
||||
|
||||
| Directive | Purpose |
|
||||
|---|---|
|
||||
| `{{include "agent.system.main.role.md"}}` | Include a named prompt fragment |
|
||||
| `{{include "agent.system.main.communication.md"}}` | Include another fragment |
|
||||
| `{{include original}}` | Include the same file from the next lower-priority directory |
|
||||
|
||||
The `include original` directive is particularly useful for **extending** rather than fully **replacing** a prompt — your override can include the base version and add to it.
|
||||
|
||||
### Variable Substitution
|
||||
|
||||
Prompts support `{{variable_name}}` placeholders that are replaced at render time with values passed from the framework or plugin configuration.
|
||||
|
||||
### Conditional Blocks
|
||||
|
||||
Prompts support conditional rendering based on variables.
|
||||
|
||||
### Reading Prompts in Code
|
||||
|
||||
```python
|
||||
# From within an Agent method:
|
||||
content = self.read_prompt("fw.some_message.md", variable1="value1")
|
||||
|
||||
# From helpers:
|
||||
from helpers.files import read_prompt_file
|
||||
content = read_prompt_file("template.md", _directories=[...], var="value")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Creating Skills
|
||||
|
||||
Skills are reusable instruction bundles that the agent loads on demand via the `skills_tool`. Each skill lives in a directory containing a `SKILL.md` file with YAML frontmatter.
|
||||
|
||||
| Location | Purpose |
|
||||
|---|---|
|
||||
| `/a0/skills/` | Core skills (shipped with framework) |
|
||||
| `/a0/usr/skills/` | User-created skills (survives updates) |
|
||||
|
||||
The agent interacts with skills through JSON tool calls:
|
||||
Load references with:
|
||||
|
||||
```json
|
||||
{"tool_name": "skills_tool:list", "tool_args": {}}
|
||||
{"tool_name": "skills_tool:load", "tool_args": {"skill_name": "my-skill"}}
|
||||
{"tool_name": "skills_tool:read_file", "tool_args": {"skill_name": "a0-development", "file_path": "references/<file>.md"}}
|
||||
```
|
||||
|
||||
> For the complete skill creation wizard — including SKILL.md format, frontmatter fields, directory structure, best practices, and examples — load the `build-skill` skill.
|
||||
|
||||
---
|
||||
|
||||
## Working with Projects
|
||||
|
||||
Projects provide isolated workspaces with custom configuration.
|
||||
|
||||
> Projects are typically created and managed via the Web UI. The `.a0proj/` directory and `project.json` are auto-generated when you create a project through the UI.
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
/a0/usr/projects/<project-name>/
|
||||
+-- .a0proj/
|
||||
| +-- project.json # Project configuration
|
||||
| +-- agents.json # Per-project agent overrides
|
||||
| +-- variables.env # Non-sensitive variables
|
||||
| +-- secrets.env # Encrypted secrets
|
||||
| +-- memory/ # Project-specific memory
|
||||
| +-- index.faiss
|
||||
| +-- index.pkl
|
||||
| +-- embedding.json
|
||||
+-- <project-files>/ # Your project files (working directory)
|
||||
```
|
||||
|
||||
### project.json Format
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "My Project",
|
||||
"description": "Project description",
|
||||
"instructions": "Markdown instructions for the agent when this project is active",
|
||||
"color": "#3a86ff",
|
||||
"git_url": "",
|
||||
"memory": "own",
|
||||
"file_structure": {
|
||||
"enabled": true,
|
||||
"max_depth": 5,
|
||||
"max_files": 20,
|
||||
"max_folders": 20,
|
||||
"max_lines": 250,
|
||||
"gitignore": ".a0proj/\nvenv/\n**/__pycache__/\n**/node_modules/\n**/.git/\n"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Purpose |
|
||||
| Need | Read |
|
||||
|---|---|
|
||||
| `title` | Display name |
|
||||
| `description` | Brief description |
|
||||
| `instructions` | Markdown injected into agent system prompt when project is active |
|
||||
| `color` | UI accent color (hex) |
|
||||
| `git_url` | Optional Git repository URL |
|
||||
| `memory` | `"own"` for project-specific memory, or shared |
|
||||
| `file_structure` | Controls the working directory tree shown to the agent |
|
||||
| Runtime split, root layout, discovery order, path and port boundaries | `references/architecture-runtime.md` |
|
||||
| DOX edit workflow, when to update docs, file-level DOX checks | `references/dox-workflow.md` |
|
||||
| Tool contracts, locations, prompts, and verification | `references/tools.md` |
|
||||
| Python/WebUI extension discovery, hook points, ordering, implicit hooks | `references/extensions.md` |
|
||||
| HTTP API, WebSocket handlers, WebUI extension surfaces | `references/api-webui.md` |
|
||||
| Agent profiles, prompts, skills, projects | `references/agents-prompts-skills-projects.md` |
|
||||
| Plugin-first workflow, where to put new work, handoffs to plugin skills | `references/plugins-workflow.md` |
|
||||
|
||||
---
|
||||
## Working Flow
|
||||
|
||||
## Plugin System Overview
|
||||
1. Classify the request: tool, extension, API/WebUI, profile, prompt, skill, project, plugin, runtime, or docs.
|
||||
2. Read the root `AGENTS.md`, then the nearest child `AGENTS.md` files for the target paths.
|
||||
3. Read the focused reference file from this skill.
|
||||
4. Inspect the current source files named by the reference before making a claim or patch.
|
||||
5. Keep changes narrow and in the repo-owned surface. Prefer `usr/` for user-created runtime content, but do not document ignored user state unless requested.
|
||||
6. Update DOX when a durable contract, path, behavior, workflow, responsibility, or verification rule changes.
|
||||
7. Run targeted checks from the relevant DOX file. For skill-only changes, at minimum verify frontmatter parsing, reference paths, and markdown sanity.
|
||||
|
||||
Plugins are the **primary extension mechanism** in Agent Zero. A plugin can bundle tools, extensions, prompts, API endpoints, helpers, and UI components into a self-contained package.
|
||||
## Handoffs
|
||||
|
||||
> For all plugin tasks — creating, reviewing, managing, contributing, or debugging plugins — load the `a0-plugin-router` skill, which routes to the appropriate specialist skill.
|
||||
- Plugin creation: load `a0-create-plugin`.
|
||||
- Plugin management or installation: load `a0-manage-plugin`.
|
||||
- Plugin debugging: load `a0-debug-plugin`.
|
||||
- Plugin review or publishing: load `a0-review-plugin` or `a0-contribute-plugin`.
|
||||
- Agent profile creation: load `a0-create-agent`.
|
||||
- Skill creation or skill format work: load `build-skill`.
|
||||
|
||||
### Core Plugins
|
||||
## Closeout
|
||||
|
||||
The framework ships with these core plugins in `/a0/plugins/`:
|
||||
|
||||
| Plugin | Purpose |
|
||||
|---|---|
|
||||
| `_code_execution` | Terminal, Python, Node.js code execution |
|
||||
| `_memory` | Persistent vector memory system |
|
||||
| `_text_editor` | File read/write/patch with line numbers |
|
||||
| `_model_config` | LLM model selection and configuration |
|
||||
| `_browser` | Direct browser automation and WebUI viewing |
|
||||
| `_infection_check` | Prompt injection safety checks |
|
||||
| `_error_retry` | Retry on critical exceptions |
|
||||
| `_email_integration` | Email communication via IMAP/SMTP |
|
||||
| `_telegram_integration` | Telegram bot integration |
|
||||
| `_chat_branching` | Branch chats from any message |
|
||||
| `_promptinclude` | Persistent behavioral rules (*.promptinclude.md) |
|
||||
| `_plugin_installer` | Install plugins from ZIP/Git/Hub |
|
||||
| `_plugin_scan` | Security scanning for plugins |
|
||||
| `_plugin_validator` | Plugin manifest and code validation |
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns Reference
|
||||
|
||||
### Accessing Agent Context
|
||||
|
||||
```python
|
||||
# Shared across all agents in a conversation
|
||||
context = self.agent.context
|
||||
data = context.data # dict-like shared state
|
||||
|
||||
# Store data
|
||||
data["my_key"] = my_value
|
||||
|
||||
# Retrieve data
|
||||
value = data.get("my_key", default)
|
||||
```
|
||||
|
||||
### Using File Helpers
|
||||
|
||||
```python
|
||||
from helpers import files
|
||||
|
||||
# File operations
|
||||
content = files.read_file("path/to/file")
|
||||
files.write_file("path/to/file", content)
|
||||
exists = files.exists("path/to/file")
|
||||
|
||||
# Read and render a prompt file
|
||||
content = files.read_prompt_file("template.md", _directories=[...], var="value")
|
||||
```
|
||||
|
||||
### Console Output
|
||||
|
||||
```python
|
||||
from helpers.print_style import PrintStyle
|
||||
|
||||
PrintStyle.hint("Informational message")
|
||||
PrintStyle.warning("Warning message")
|
||||
PrintStyle.error("Error message")
|
||||
PrintStyle(font_color="#85C1E9").print("Custom styled output")
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
```python
|
||||
from helpers.tool import Response
|
||||
|
||||
try:
|
||||
result = await risky_operation()
|
||||
except Exception as e:
|
||||
PrintStyle.error(f"Operation failed: {e}")
|
||||
return Response(message=f"Error: {e}", break_loop=False)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Development Workflow
|
||||
|
||||
When building features for Agent Zero:
|
||||
|
||||
### 1. Choose Your Extension Point
|
||||
|
||||
| Want to... | Use |
|
||||
|---|---|
|
||||
| Add a new agent capability | **Tool** (in a plugin) |
|
||||
| Hook into agent lifecycle | **Extension** (in a plugin) |
|
||||
| Add Web UI functionality | **API endpoint** + **WebUI extension** |
|
||||
| Create a specialized agent | **Agent profile** |
|
||||
| Bundle reusable instructions | **Skill** |
|
||||
| Package everything together | **Plugin** (recommended) |
|
||||
|
||||
### 2. Develop in User Space
|
||||
|
||||
- New plugins -> `/a0/usr/plugins/<name>/`
|
||||
- New profiles -> `/a0/usr/agents/<name>/`
|
||||
- New skills -> `/a0/usr/skills/<name>/`
|
||||
- New extensions -> `/a0/usr/extensions/python/<hook_point>/`
|
||||
|
||||
### 3. Test and Iterate
|
||||
|
||||
- **Local dev**: Run `python run_ui.py` (default port 50001 at `http://localhost:50001`)
|
||||
- **Docker**: Restart the container or use the UI restart button; check logs with `docker logs -f <container_name>`
|
||||
- Test with minimal input first
|
||||
- Verify in the Web UI
|
||||
|
||||
### 4. Contributing
|
||||
|
||||
For contribution guidelines, see `/a0/docs/contribution.md`. For plugin contributions to the community Plugin Index, load the `a0-contribute-plugin` skill.
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### DO
|
||||
- Use the **plugin system** for new features (see `a0-create-plugin` skill)
|
||||
- Follow existing code patterns and conventions
|
||||
- Write clear docstrings and comments
|
||||
- Handle errors gracefully in tools and extensions
|
||||
- Create prompt fragments for every tool (`agent.system.tool.<name>.md`)
|
||||
- Develop in `/a0/usr/` directories to survive updates
|
||||
- Test with the `_example` profile as a reference
|
||||
- Use `from helpers.*` imports (not `from python.helpers.*`)
|
||||
|
||||
### DON'T
|
||||
- Modify files in `/a0/plugins/` or `/a0/tools/` directly (use usr/ space)
|
||||
- Hardcode paths or configuration values
|
||||
- Skip creating prompt files for tools
|
||||
- Ignore the plugin system (it's the intended extension mechanism)
|
||||
- Mix sync and async code carelessly
|
||||
- Access internal structures when helpers exist
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference: Key Files
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `/a0/agent.py` | Core `Agent`, `AgentContext`, `AgentConfig` classes |
|
||||
| `/a0/helpers/tool.py` | `Tool` + `Response` base classes |
|
||||
| `/a0/helpers/extension.py` | `Extension` base + `@extensible` decorator |
|
||||
| `/a0/helpers/api.py` | `ApiHandler` base class |
|
||||
| `/a0/helpers/files.py` | File ops + prompt reading |
|
||||
| `/a0/helpers/plugins.py` | Plugin system manager |
|
||||
| `/a0/helpers/print_style.py` | Console output formatting |
|
||||
| `/a0/agents/_example/` | Reference example profile with tool + extension |
|
||||
| `/a0/prompts/agent.system.main.md` | Main system prompt entry point |
|
||||
Report the exact files changed, the grounding checks used, whether DOX was updated or intentionally left unchanged, and what verification ran. If a claim depends on a live Docker runtime, include the runtime proof, not only checkout evidence.
|
||||
|
|
|
|||
38
skills/a0-development/references/AGENTS.md
Normal file
38
skills/a0-development/references/AGENTS.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# A0 Development References DOX
|
||||
|
||||
## Purpose
|
||||
|
||||
- Own focused reference files loaded by the `a0-development` skill on demand.
|
||||
- Keep detailed framework-development guidance grounded in current source files and nearest DOX contracts.
|
||||
|
||||
## Ownership
|
||||
|
||||
- `architecture-runtime.md` owns runtime, path, discovery-order, and port-boundary guidance.
|
||||
- `dox-workflow.md` owns the edit and closeout workflow for DOX-governed changes.
|
||||
- `tools.md` owns core and plugin tool development contracts.
|
||||
- `extensions.md` owns backend and frontend extension contracts.
|
||||
- `api-webui.md` owns HTTP API, WebSocket, and WebUI extension guidance.
|
||||
- `agents-prompts-skills-projects.md` owns profiles, prompt fragments, skills, and project metadata guidance.
|
||||
- `plugins-workflow.md` owns plugin-first placement and handoff guidance.
|
||||
|
||||
## Local Contracts
|
||||
|
||||
- Every reference file must list source anchors or DOX anchors that can be checked in the repository.
|
||||
- Prefer pointing to narrower `AGENTS.md` files instead of copying long subtree contracts.
|
||||
- Keep examples minimal and compatible with the current helper classes.
|
||||
- Do not include hardcoded default WebUI ports or environment-specific credentials.
|
||||
|
||||
## Work Guidance
|
||||
|
||||
- Update the focused reference file when source or DOX changes make its guidance stale.
|
||||
- If a reference starts duplicating a specialist skill, shorten it and hand off to that skill instead.
|
||||
- Treat checked-in examples as examples, not authority, when they conflict with current discovery code.
|
||||
|
||||
## Verification
|
||||
|
||||
- Manually read changed references for broken relative paths, stale source anchors, and duplicated specialist-skill material.
|
||||
- After changing reference names, load `a0-development` and confirm the file tree exposes the new paths through `skills_tool`.
|
||||
|
||||
## Child DOX Index
|
||||
|
||||
No child DOX files.
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
# Agents, Prompts, Skills, And Projects
|
||||
|
||||
## Source Anchors
|
||||
|
||||
- Agent profiles: `/a0/helpers/subagents.py`, `/a0/agents/AGENTS.md`
|
||||
- Prompt rendering: `/a0/agent.py`, `/a0/helpers/files.py`, `/a0/prompts/AGENTS.md`
|
||||
- Skill runtime: `/a0/helpers/skills.py`, `/a0/tools/skills_tool.py`, `/a0/skills/AGENTS.md`
|
||||
- Project metadata: `/a0/helpers/projects.py`, `/a0/api/projects.py`, `/a0/webui/components/projects/`
|
||||
|
||||
## Agent Profiles
|
||||
|
||||
Bundled profiles live under `agents/<profile>/`. User-created profiles live under `usr/agents/<profile>/`. Plugin-distributed profiles live under plugin `agents/` directories.
|
||||
|
||||
The current profile loader accepts `agent.yaml` or `agent.json` and validates through `helpers.subagents.SubAgentListItem` / `SubAgent` fields:
|
||||
|
||||
| Field | Meaning |
|
||||
|---|---|
|
||||
| `title` | Human-readable display name. Defaults to profile name if empty. |
|
||||
| `description` | Brief specialization. |
|
||||
| `context` | Delegation guidance for when to use the profile. |
|
||||
| `enabled` | Optional availability flag in list contexts. |
|
||||
|
||||
Bundled `agent.yaml` files currently use `title`, `description`, and `context`. Model settings are not read from `agent.yaml`; the `_model_config` plugin owns model configuration and scoped overrides.
|
||||
|
||||
Profile folders may contain `prompts/`, `tools/`, `extensions/`, and `skills/`, but verify discovery code before relying on example layout. Source and DOX beat stale examples.
|
||||
|
||||
## Prompt System
|
||||
|
||||
Agents render prompt fragments through `Agent.read_prompt(...)`, which calls `helpers.files.read_prompt_file(...)`.
|
||||
|
||||
Prompt capabilities:
|
||||
|
||||
- Placeholder replacement with `{{variable_name}}`.
|
||||
- Conditional blocks with `{{if ...}} ... {{endif}}`.
|
||||
- Include directives such as `{{include "file.md"}}`.
|
||||
- `{{include original}}` to include the same file from a lower-priority directory.
|
||||
|
||||
Prompt locations include:
|
||||
|
||||
| Location | Use |
|
||||
|---|---|
|
||||
| `prompts/` | Core framework prompts. |
|
||||
| `agents/<profile>/prompts/` | Bundled profile overrides. |
|
||||
| `usr/agents/<profile>/prompts/` | User profile overrides. |
|
||||
| `plugins/<plugin>/prompts/` | Bundled plugin prompt additions or overrides. |
|
||||
| `usr/plugins/<plugin>/prompts/` | User plugin prompts. |
|
||||
|
||||
Prompt changes can change agent behavior. Keep edits narrow and run targeted prompt, budget, snapshot, tool, or behavior tests.
|
||||
|
||||
## Skills
|
||||
|
||||
Skills are directories containing `SKILL.md` frontmatter plus optional `references/`, `scripts/`, or `assets/`.
|
||||
|
||||
Skill roots come from `helpers.skills.get_skill_roots(...)`, including bundled skills, user skills, project metadata, profile skills, and plugin skills.
|
||||
|
||||
`skills_tool` actions:
|
||||
|
||||
| Action | Purpose |
|
||||
|---|---|
|
||||
| `list` | List available skills without full content. |
|
||||
| `search` | Search skill metadata and triggers. |
|
||||
| `load` | Load `SKILL.md` body and show the skill file tree. |
|
||||
| `read_file` | Read a file inside the skill directory, such as `references/foo.md`. |
|
||||
|
||||
Keep always-loaded `SKILL.md` concise. Move long examples, schemas, policies, and variant-specific details into one-level-deep `references/` files and tell the agent when to read them.
|
||||
|
||||
Use `build-skill` for skill creation and skill format work.
|
||||
|
||||
## Projects
|
||||
|
||||
Projects live under `usr/projects/<name>/` and store metadata in `.a0proj/`.
|
||||
|
||||
Important project files and folders:
|
||||
|
||||
| Path | Purpose |
|
||||
|---|---|
|
||||
| `.a0proj/project.json` | Project title, description, instructions, color, git URL, include-AGENTS option, and file-structure settings. |
|
||||
| `.a0proj/instructions/` | Additional text instruction files. |
|
||||
| `.a0proj/knowledge/` | Project knowledge files. |
|
||||
| `.a0proj/variables.env` | Non-sensitive project variables. |
|
||||
| `.a0proj/secrets.env` | Encrypted project secrets. |
|
||||
| `.a0proj/agents/` | Per-project agent profile material. |
|
||||
| `.a0proj/skills/` | Project-scoped skills. |
|
||||
| `.a0proj/mcp_servers.json` | Project MCP server configuration. |
|
||||
|
||||
`helpers.projects.BasicProjectData` currently normalizes `title`, `description`, `instructions`, `include_agents_md`, `color`, `git_url`, and `file_structure`. `EditProjectData` adds runtime/editing fields such as `variables`, `secrets`, `mcp_servers`, `subagents`, and git status.
|
||||
|
||||
Project file-structure injection uses settings for `enabled`, `max_depth`, `max_files`, `max_folders`, `max_lines`, and `gitignore`.
|
||||
|
||||
## Verification
|
||||
|
||||
- Run profile-loading tests when changing agent profile schema or discovery.
|
||||
- Inspect rendered prompts when changing prompt filenames, include behavior, placeholders, or prompt order.
|
||||
- Run skill runtime/catalog tests after changing skill loading, search, active/hidden behavior, or skill format.
|
||||
- For project changes, test create/load/edit paths and project prompt injection when relevant.
|
||||
93
skills/a0-development/references/api-webui.md
Normal file
93
skills/a0-development/references/api-webui.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# API And WebUI
|
||||
|
||||
## Source Anchors
|
||||
|
||||
- HTTP handler base and route registration: `/a0/helpers/api.py`
|
||||
- API DOX: `/a0/api/AGENTS.md`
|
||||
- WebSocket handler base: `/a0/helpers/ws.py`
|
||||
- WebUI shell DOX: `/a0/webui/AGENTS.md`
|
||||
- Component and JS DOX: `/a0/webui/components/AGENTS.md`, `/a0/webui/js/AGENTS.md`
|
||||
- Frontend extension loading: `/a0/webui/js/extensions.js`
|
||||
|
||||
## HTTP API Contract
|
||||
|
||||
HTTP API handlers derive from `helpers.api.ApiHandler`:
|
||||
|
||||
```python
|
||||
from flask import Request, Response
|
||||
from helpers.api import ApiHandler
|
||||
|
||||
class MyEndpoint(ApiHandler):
|
||||
@classmethod
|
||||
def get_methods(cls) -> list[str]:
|
||||
return ["POST"]
|
||||
|
||||
async def process(self, input: dict, request: Request) -> dict | Response:
|
||||
return {"ok": True}
|
||||
```
|
||||
|
||||
Defaults from `ApiHandler`:
|
||||
|
||||
| Method | Default |
|
||||
|---|---|
|
||||
| `requires_loopback()` | `False` |
|
||||
| `requires_api_key()` | `False` |
|
||||
| `requires_auth()` | `True` |
|
||||
| `get_methods()` | `["POST"]` |
|
||||
| `requires_csrf()` | `requires_auth()` |
|
||||
|
||||
Override these only when the endpoint contract requires it. Keep auth and CSRF protection intact for browser-facing state changes.
|
||||
|
||||
## API Routes
|
||||
|
||||
`helpers.api.register_api_route(...)` registers:
|
||||
|
||||
```text
|
||||
/api/<path:path>
|
||||
```
|
||||
|
||||
Resolution:
|
||||
|
||||
- Built-in endpoint `api/<name>.py` becomes `/api/<name>`.
|
||||
- Plugin endpoint `plugins/<plugin>/api/<handler>.py` becomes `/api/plugins/<plugin>/<handler>`.
|
||||
|
||||
Return a Flask `Response` for files, redirects, custom status codes, and plain text. Return a dictionary for JSON success payloads.
|
||||
|
||||
Direct files under `api/*.py` require matching `api/*.py.dox.md`.
|
||||
|
||||
## WebSocket Handlers
|
||||
|
||||
WebSocket handlers live in `api/ws_*.py` or plugin API folders and derive from `helpers.ws.WsHandler`:
|
||||
|
||||
```python
|
||||
from helpers.ws import WsHandler
|
||||
|
||||
class MyHandler(WsHandler):
|
||||
async def process(self, event: str, data: dict, sid: str) -> dict | None:
|
||||
return {"ok": True}
|
||||
```
|
||||
|
||||
`WsHandler` mirrors `ApiHandler` security flags: auth defaults to `True`, CSRF defaults to auth, API-key and loopback default to `False`. Handlers should validate event data before using it and avoid returning secrets or unfiltered exception details.
|
||||
|
||||
## WebUI Work
|
||||
|
||||
Follow the nearest WebUI DOX before changing frontend files:
|
||||
|
||||
- `webui/AGENTS.md` for the shell, CSS, assets, vendor, and extension loader.
|
||||
- `webui/js/AGENTS.md` for stores, modals, API helpers, and JS infrastructure.
|
||||
- `webui/components/AGENTS.md` and child docs for Alpine components.
|
||||
|
||||
Patterns:
|
||||
|
||||
- Store-dependent content should be gated by a `template x-if` guard before using `$store.<name>`.
|
||||
- Stores are registered with `createStore` from `/js/AlpineStore.js`.
|
||||
- Modals use `openModal(path)` and `closeModal()` from `/js/modals.js`.
|
||||
- Plugin settings UIs bind persisted plugin values to `config.*` and modal-only state/actions to `context.*`.
|
||||
- Plugin UI should use the A0 notification system instead of inline success/error boxes.
|
||||
|
||||
## Verification
|
||||
|
||||
- Run endpoint-specific tests or nearest API/WebSocket tests for handler behavior.
|
||||
- For auth, CSRF, upload/download, tunnel, or file endpoints, run security-focused regressions.
|
||||
- For WebUI changes, use targeted component/store tests or a browser smoke check when practical.
|
||||
- Check file-level DOX coverage when touching direct `api/*.py` modules.
|
||||
79
skills/a0-development/references/architecture-runtime.md
Normal file
79
skills/a0-development/references/architecture-runtime.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# Architecture And Runtime
|
||||
|
||||
## Source Anchors
|
||||
|
||||
- Root contract: `/a0/AGENTS.md`
|
||||
- WebUI entry point: `/a0/run_ui.py`
|
||||
- Runtime arguments and WebUI port resolution: `/a0/helpers/runtime.py`
|
||||
- Docker Python runtimes: `/a0/docker/base/fs/ins/install_python.sh`
|
||||
- Docker framework activation: `/a0/docker/run/fs/ins/setup_venv.sh`
|
||||
- Docker UI launch manager: `/a0/docker/run/fs/exe/self_update_manager.py`
|
||||
- Search/discovery roots: `/a0/helpers/subagents.py`, `/a0/helpers/skills.py`, `/a0/helpers/projects.py`
|
||||
|
||||
## Runtime Split
|
||||
|
||||
Agent Zero has two Docker Python runtimes:
|
||||
|
||||
| Runtime | Python | Purpose |
|
||||
|---|---|---|
|
||||
| `/opt/venv-a0` | 3.12.4 | Framework runtime. Runs the WebUI backend, API, scheduler, agent loop, framework imports, plugin hooks, and framework-side tools. |
|
||||
| `/opt/venv` | 3.13 | Agent execution runtime. Use for Python code executed on behalf of the agent or user task dependencies. |
|
||||
|
||||
Use `/opt/venv-a0` for framework import checks, WebUI startup checks, API/plugin hook behavior, and `py_compile` of framework code inside Docker. Use `/opt/venv` only when the feature explicitly targets agent/user code execution.
|
||||
|
||||
Do not claim a package works in the framework because it imports in `/opt/venv`, and do not claim user-code execution works because it imports in `/opt/venv-a0`.
|
||||
|
||||
## Ports And URLs
|
||||
|
||||
Do not hardcode a WebUI default port in guidance. Discover the effective URL from:
|
||||
|
||||
- WebUI startup output.
|
||||
- Launcher or Docker published-port mapping.
|
||||
- Explicit `--host` and `--port` arguments.
|
||||
- `WEB_UI_HOST` and `WEB_UI_PORT` environment configuration.
|
||||
- Live container inspection when the task targets a running runtime.
|
||||
|
||||
`helpers.runtime.get_web_ui_port()` has a code fallback, and the Docker UI manager passes an internal container port. Those are implementation details, not a stable user-facing URL contract.
|
||||
|
||||
## Root Paths
|
||||
|
||||
- `/a0/` means the framework root inside the Docker runtime.
|
||||
- In a local checkout, `/a0/` in documentation maps to the repository root.
|
||||
- `usr/` contains user state, projects, settings, skills, plugins, chats, and workdirs.
|
||||
- `tmp/` contains runtime caches and generated working files.
|
||||
- Do not document ignored `usr/` or `tmp/` changes unless explicitly asked.
|
||||
|
||||
When the user names a live Dockerized runtime, the live `/a0` tree is a separate artifact. Verify the file sync or runtime state directly before treating checkout code as live behavior.
|
||||
|
||||
## Project Layout
|
||||
|
||||
Key root areas:
|
||||
|
||||
| Path | Purpose |
|
||||
|---|---|
|
||||
| `agent.py` | `Agent`, `AgentContext`, `AgentConfig`, prompt reading, tool loop. |
|
||||
| `initialize.py` | Framework initialization and background loop startup. |
|
||||
| `models.py` | Model provider and LiteLLM transport configuration. |
|
||||
| `run_ui.py` | Flask/Socket.IO ASGI WebUI startup. |
|
||||
| `api/` | HTTP API handlers and `ws_*.py` WebSocket handlers. |
|
||||
| `helpers/` | Shared framework utilities and base contracts. |
|
||||
| `tools/` | Core tool implementations. |
|
||||
| `extensions/` | Built-in backend and WebUI extension points. |
|
||||
| `plugins/` | Bundled system plugins. |
|
||||
| `agents/` | Bundled agent profiles. |
|
||||
| `prompts/` | Core prompt fragments. |
|
||||
| `skills/` | Bundled skills. |
|
||||
| `webui/` | Alpine.js frontend shell, components, CSS, assets, and vendor code. |
|
||||
|
||||
## Discovery Order
|
||||
|
||||
Agent-specific path resolution is handled by `helpers.subagents.get_paths(...)`. In broad terms, project and user/profile paths have higher priority than plugin and bundled defaults, then user root/plugin roots, then base defaults. Inspect `helpers/subagents.py` for exact order before changing discovery behavior.
|
||||
|
||||
Skill discovery is handled by `helpers.skills.get_skill_roots(...)`. Skills may come from bundled `skills/`, user `usr/skills/`, project metadata, agent profile folders, and plugin roots. Loaded skills can expose additional files via `skills_tool action=read_file`.
|
||||
|
||||
## Development Bias
|
||||
|
||||
- Prefer plugins for new capabilities.
|
||||
- Prefer `helpers/` only for reusable framework behavior.
|
||||
- Prefer small, source-backed changes over broad rewrites.
|
||||
- If an example conflicts with source discovery code or DOX, treat the example as stale until verified.
|
||||
66
skills/a0-development/references/dox-workflow.md
Normal file
66
skills/a0-development/references/dox-workflow.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# DOX Workflow
|
||||
|
||||
## Source Anchors
|
||||
|
||||
- Root DOX contract: `/a0/AGENTS.md`
|
||||
- Skill parent contract: `/a0/skills/AGENTS.md`
|
||||
- Local skill contract: `/a0/skills/a0-development/AGENTS.md`
|
||||
- Reference-file contract: `/a0/skills/a0-development/references/AGENTS.md`
|
||||
- File-level DOX examples: `/a0/api/*.py.dox.md`, `/a0/tools/*.py.dox.md`, `/a0/helpers/*.py.dox.md`
|
||||
|
||||
## Before Editing
|
||||
|
||||
1. Read the root `AGENTS.md`.
|
||||
2. Identify every path you expect to touch.
|
||||
3. Walk from the root to each target path.
|
||||
4. Read every `AGENTS.md` found on that route.
|
||||
5. If a parent `AGENTS.md` lists a child whose scope contains the path, read that child and continue.
|
||||
6. Use the nearest `AGENTS.md` as the local contract. Parent docs still apply.
|
||||
7. If docs conflict, the closer doc controls local details, but no child weakens DOX.
|
||||
|
||||
Do not rely on memory for DOX. Re-read the current files.
|
||||
|
||||
## When To Update DOX
|
||||
|
||||
Update the nearest owning `AGENTS.md` when a meaningful change affects:
|
||||
|
||||
- Purpose, ownership, responsibilities, or scope.
|
||||
- Durable structure, directories, file contracts, or child indexes.
|
||||
- Runtime behavior, required inputs/outputs, side effects, or verification rules.
|
||||
- User or agent workflow rules.
|
||||
- Creation, deletion, rename, or movement of an `AGENTS.md` file.
|
||||
|
||||
Update parent docs when parent-level structure or child indexes change. Remove stale or contradictory text rather than explaining old history.
|
||||
|
||||
Small implementation edits that do not change contracts may leave DOX unchanged, but still perform the DOX closeout pass and say why docs stayed unchanged.
|
||||
|
||||
Do not create or update DOX under ignored `usr/` or `tmp/` unless explicitly requested.
|
||||
|
||||
## File-Level DOX
|
||||
|
||||
Some directories require per-file `.dox.md` companions:
|
||||
|
||||
| Directory | Requirement |
|
||||
|---|---|
|
||||
| `api/` | Every direct `*.py` endpoint or `ws_*.py` module must have matching `*.py.dox.md`. |
|
||||
| `tools/` | Every direct `*.py` tool module must have matching `*.py.dox.md`. |
|
||||
| `helpers/` | Many helper modules use file-level DOX; follow `helpers/AGENTS.md` before changing helper behavior. |
|
||||
|
||||
When adding, deleting, renaming, or behaviorally changing one of those files, update the companion DOX in the same change.
|
||||
|
||||
## Closeout
|
||||
|
||||
1. Re-check changed paths against the DOX chain.
|
||||
2. Update nearest owning docs and affected parents or children.
|
||||
3. Refresh affected Child DOX Index tables.
|
||||
4. Remove stale or contradictory text.
|
||||
5. Run relevant verification from the nearest DOX.
|
||||
6. Report docs intentionally left unchanged and why.
|
||||
|
||||
## Practical Verification
|
||||
|
||||
- `git diff --check` for whitespace.
|
||||
- Targeted tests named by the relevant DOX file.
|
||||
- Manual read-through for skill/reference link changes.
|
||||
- Shell coverage checks for file-level DOX when touching `api/` or `tools/`.
|
||||
- Runtime or live-container proof when the user asks about the running Dockerized system.
|
||||
150
skills/a0-development/references/extensions.md
Normal file
150
skills/a0-development/references/extensions.md
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
# Extensions
|
||||
|
||||
## Source Anchors
|
||||
|
||||
- Extension base and discovery: `/a0/helpers/extension.py`
|
||||
- Backend extension DOX: `/a0/extensions/AGENTS.md`, `/a0/extensions/python/AGENTS.md`
|
||||
- WebUI extension DOX: `/a0/extensions/webui/AGENTS.md`
|
||||
- Plugin extension contract: `/a0/plugins/AGENTS.md`
|
||||
- Example profile note: `/a0/agents/_example/AGENTS.md`
|
||||
|
||||
## Python Extension Contract
|
||||
|
||||
Backend extensions derive from `helpers.extension.Extension`:
|
||||
|
||||
```python
|
||||
from helpers.extension import Extension
|
||||
|
||||
class MyExtension(Extension):
|
||||
async def execute(self, **kwargs):
|
||||
...
|
||||
```
|
||||
|
||||
`self.agent` may be `None` for startup or non-agent hooks. Match the arguments supplied by the hook point. Keep imports light because many extensions run in hot paths.
|
||||
|
||||
## Python Discovery Layout
|
||||
|
||||
`helpers.extension._get_extension_classes(...)` discovers backend extension classes through:
|
||||
|
||||
```text
|
||||
extensions/python/<extension_point>/
|
||||
```
|
||||
|
||||
using `helpers.subagents.get_paths(agent, "extensions/python", extension_point)`.
|
||||
|
||||
Common locations:
|
||||
|
||||
| Location | Use |
|
||||
|---|---|
|
||||
| `extensions/python/<point>/` | Built-in framework extension. |
|
||||
| `plugins/<plugin>/extensions/python/<point>/` | Bundled plugin extension. |
|
||||
| `usr/plugins/<plugin>/extensions/python/<point>/` | User plugin extension. |
|
||||
| `usr/extensions/python/<point>/` | Standalone user extension. Prefer plugin packaging for durable features. |
|
||||
| Project/profile roots resolved by `helpers.subagents.get_paths(...)` | Scope-specific extension overrides when discovery supports the path. Verify before copying examples. |
|
||||
|
||||
The checked-in `_example` profile contains an older-looking `agents/_example/extensions/agent_init/...` sample. Current discovery code expects `extensions/python/<point>`. Treat source code and DOX as authority before copying profile extension layout.
|
||||
|
||||
## Ordering And Overrides
|
||||
|
||||
- Files are sorted by filename. Numeric prefixes like `_10_`, `_20_`, `_50_` control order.
|
||||
- Use gaps between prefixes so future extensions can fit between them.
|
||||
- Discovery de-duplicates by module filename, preserving the first occurrence by search priority.
|
||||
- Do not bypass secret masking, auth, persistence, or cleanup extensions for convenience.
|
||||
|
||||
## Implicit `@extensible` Hooks
|
||||
|
||||
Functions decorated with `@extensible` emit two implicit hook points:
|
||||
|
||||
```text
|
||||
_functions/<module>/<qualname>/start
|
||||
_functions/<module>/<qualname>/end
|
||||
```
|
||||
|
||||
The path preserves every module segment and nested qualname segment. Example:
|
||||
|
||||
```text
|
||||
helpers.something.Outer.Inner.__init__
|
||||
```
|
||||
|
||||
becomes:
|
||||
|
||||
```text
|
||||
_functions/helpers/something/Outer/Inner/__init__/start
|
||||
_functions/helpers/something/Outer/Inner/__init__/end
|
||||
```
|
||||
|
||||
Extensions receive a mutable `data` dict with `args`, `kwargs`, `result`, and `exception`. They may mutate inputs, short-circuit by setting `result`, or force/clear an exception.
|
||||
|
||||
Do not use retired flattened `_functions` folder names.
|
||||
|
||||
## Current Built-In Python Hook Directories
|
||||
|
||||
Directory-backed built-in hook points currently include:
|
||||
|
||||
```text
|
||||
agent_init
|
||||
banners
|
||||
before_main_llm_call
|
||||
error_format
|
||||
hist_add_before
|
||||
hist_add_tool_result
|
||||
job_loop
|
||||
message_loop_end
|
||||
message_loop_prompts_after
|
||||
message_loop_prompts_before
|
||||
message_loop_start
|
||||
monologue_end
|
||||
monologue_start
|
||||
process_chain_end
|
||||
reasoning_stream
|
||||
reasoning_stream_chunk
|
||||
reasoning_stream_end
|
||||
response_stream
|
||||
response_stream_chunk
|
||||
response_stream_end
|
||||
startup_migration
|
||||
system_prompt
|
||||
tool_execute_after
|
||||
tool_execute_before
|
||||
user_message_ui
|
||||
util_model_call_before
|
||||
webui_ws_connect
|
||||
webui_ws_disconnect
|
||||
webui_ws_event
|
||||
```
|
||||
|
||||
This list comes from the current `extensions/python/` tree. Re-check the tree before claiming the complete current set.
|
||||
|
||||
## WebUI Extension Points
|
||||
|
||||
Frontend extension files live under:
|
||||
|
||||
```text
|
||||
extensions/webui/<point>/
|
||||
plugins/<plugin>/extensions/webui/<point>/
|
||||
usr/plugins/<plugin>/extensions/webui/<point>/
|
||||
```
|
||||
|
||||
Current built-in WebUI extension directories include:
|
||||
|
||||
```text
|
||||
fetch_api_call_after
|
||||
fetch_api_call_before
|
||||
get_message_handler
|
||||
initFw_end
|
||||
json_api_call_after
|
||||
json_api_call_before
|
||||
right-canvas-panels
|
||||
right_canvas_register_surfaces
|
||||
set_messages_after_loop
|
||||
set_messages_before_loop
|
||||
webui_ws_push
|
||||
```
|
||||
|
||||
Plugin frontend HTML extensions should include a root Alpine scope and use `x-move-*` directives when targeting static breakpoints. JS extensions export a default function.
|
||||
|
||||
## Verification
|
||||
|
||||
- Run targeted lifecycle, prompt, stream, WebSocket, or WebUI extension tests for changed hook points.
|
||||
- Smoke-test startup for `agent_init`, `startup_migration`, and `system_prompt` changes when practical.
|
||||
- Check the exact directory path used by `helpers.extension` before adding profile or plugin extension files.
|
||||
91
skills/a0-development/references/plugins-workflow.md
Normal file
91
skills/a0-development/references/plugins-workflow.md
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# Plugins And Development Workflow
|
||||
|
||||
## Source Anchors
|
||||
|
||||
- Plugin contract: `/a0/plugins/AGENTS.md`
|
||||
- Plugin helper code: `/a0/helpers/plugins.py`
|
||||
- Plugin specialist skills: `/a0/skills/a0-plugin-router/SKILL.md`, `/a0/skills/a0-create-plugin/SKILL.md`, `/a0/skills/a0-debug-plugin/SKILL.md`, `/a0/skills/a0-review-plugin/SKILL.md`
|
||||
- Root development contract: `/a0/AGENTS.md`
|
||||
|
||||
## Plugin-First Rule
|
||||
|
||||
Plugins are the primary way to extend Agent Zero. A plugin can bundle:
|
||||
|
||||
- `plugin.yaml`
|
||||
- `default_config.yaml`
|
||||
- `hooks.py`
|
||||
- `execute.py`
|
||||
- `tools/`
|
||||
- `api/`
|
||||
- `helpers/`
|
||||
- `prompts/`
|
||||
- `skills/`
|
||||
- `extensions/python/`
|
||||
- `extensions/webui/`
|
||||
- `webui/`
|
||||
- plugin-local docs and assets
|
||||
|
||||
Use root framework directories only when changing bundled framework behavior itself. For custom or experimental work, use `usr/plugins/<plugin>/` unless the task is explicitly to change a bundled plugin.
|
||||
|
||||
## Imports And Runtime
|
||||
|
||||
- Bundled plugins under `plugins/` may use `plugins.<plugin_name>...` imports.
|
||||
- User plugins under `usr/plugins/` should use `usr.plugins.<plugin_name>...` imports.
|
||||
- Avoid `sys.path` hacks and symlink-dependent imports.
|
||||
- `hooks.py` runs inside the framework runtime (`/opt/venv-a0` in Docker).
|
||||
- If a plugin must prepare the agent execution runtime or system packages, it must explicitly target that environment in a subprocess.
|
||||
|
||||
## Manifest And Configuration
|
||||
|
||||
Every plugin needs `plugin.yaml`. Runtime fields include:
|
||||
|
||||
- `name`
|
||||
- `title`
|
||||
- `description`
|
||||
- `version`
|
||||
- `settings_sections`
|
||||
- `per_project_config`
|
||||
- `per_agent_config`
|
||||
- `always_enabled`
|
||||
|
||||
Defaults belong in `default_config.yaml`. Runtime user settings belong under `usr/`.
|
||||
|
||||
Settings resolution order is project/profile, project, user/profile, user plugin config, then bundled `default_config.yaml`.
|
||||
|
||||
## Activation And Cleanup
|
||||
|
||||
- Global and scoped activation are independent.
|
||||
- Activation files use `.toggle-1` for ON and `.toggle-0` for OFF.
|
||||
- `always_enabled: true` forces ON and disables UI toggles.
|
||||
- Plugin deletion or disablement should not leave unmanaged services, symlinks, or files outside plugin-owned paths unless explicitly documented with cleanup.
|
||||
|
||||
## Routes And UI
|
||||
|
||||
Plugin routes:
|
||||
|
||||
| Route | Purpose |
|
||||
|---|---|
|
||||
| `GET /plugins/<name>/<path>` | Static/plugin web assets. |
|
||||
| `POST /api/plugins/<name>/<handler>` | Plugin API handler. |
|
||||
| `POST /api/plugins` | Plugin management actions. |
|
||||
|
||||
Plugin settings UIs should bind saved values to `config.*` and modal-only state/actions to `context.*` through `$store.pluginSettingsPrototype`.
|
||||
|
||||
Plugin UI errors, warnings, success, and info should use the A0 notification system.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Decide whether the request is plugin-specific. If yes, load `a0-plugin-router`.
|
||||
2. If creating a plugin, load `a0-create-plugin`.
|
||||
3. If debugging a plugin, load `a0-debug-plugin`.
|
||||
4. If reviewing or publishing a plugin, load `a0-review-plugin` or `a0-contribute-plugin`.
|
||||
5. Read `plugins/AGENTS.md` and any plugin-local `AGENTS.md`.
|
||||
6. Keep changes inside the plugin boundary unless shared framework behavior truly belongs in `helpers/` or root code.
|
||||
7. Update plugin docs/DOX when user-visible behavior, configuration, routes, hooks, or cleanup changes.
|
||||
|
||||
## Verification
|
||||
|
||||
- Run plugin-specific tests after changing a bundled plugin.
|
||||
- Run framework tests for touched tools, API handlers, extension points, settings, or WebUI surfaces.
|
||||
- Smoke-test external-service, browser, desktop, or connector integrations when practical.
|
||||
- For discovery banners/cards, verify rendering, dismiss behavior, ordering, and CTA behavior.
|
||||
76
skills/a0-development/references/tools.md
Normal file
76
skills/a0-development/references/tools.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# Tools
|
||||
|
||||
## Source Anchors
|
||||
|
||||
- Tool base class: `/a0/helpers/tool.py`
|
||||
- Core tool contract: `/a0/tools/AGENTS.md`
|
||||
- Tool dispatch path: `/a0/agent.py`
|
||||
- Skills tool reference-file behavior: `/a0/tools/skills_tool.py`
|
||||
- Example profile tool: `/a0/agents/_example/tools/example_tool.py`
|
||||
- Prompt fragments: `/a0/prompts/AGENTS.md`
|
||||
|
||||
## Contract
|
||||
|
||||
All tools derive from `helpers.tool.Tool` and implement:
|
||||
|
||||
```python
|
||||
from helpers.tool import Tool, Response
|
||||
|
||||
class MyTool(Tool):
|
||||
async def execute(self, **kwargs) -> Response:
|
||||
return Response(message="done", break_loop=False)
|
||||
```
|
||||
|
||||
`Response` fields:
|
||||
|
||||
| Field | Meaning |
|
||||
|---|---|
|
||||
| `message` | Text appended as the tool result and shown back to the agent. |
|
||||
| `break_loop` | `True` stops the current message loop. |
|
||||
| `additional` | Optional metadata added with the tool result. |
|
||||
|
||||
`Tool` instances receive `agent`, `name`, `method`, `args`, `message`, and `loop_data`. Use `self.method` for method-style tools such as `skills_tool:load`.
|
||||
|
||||
## Locations
|
||||
|
||||
| Location | Use |
|
||||
|---|---|
|
||||
| `tools/` | Core framework tools. Use only for bundled framework behavior. |
|
||||
| `plugins/<plugin>/tools/` | Bundled plugin tools. |
|
||||
| `usr/plugins/<plugin>/tools/` | User plugin tools. This is the preferred place for custom plugin work. |
|
||||
| `agents/<profile>/tools/` | Profile-local tools. Verify current discovery before relying on profile examples. |
|
||||
|
||||
Most new tools should be packaged in a plugin, not added directly to root `tools/`.
|
||||
|
||||
## Prompt Contract
|
||||
|
||||
Every tool needs an agent-facing prompt fragment so the model knows the tool name, JSON shape, arguments, and when to use it.
|
||||
|
||||
Common locations:
|
||||
|
||||
- Core tool prompt: `prompts/agent.system.tool.<tool_name>.md`
|
||||
- Plugin tool prompt: `plugins/<plugin>/prompts/agent.system.tool.<tool_name>.md`
|
||||
- User plugin prompt: `usr/plugins/<plugin>/prompts/agent.system.tool.<tool_name>.md`
|
||||
- Profile override prompt: `agents/<profile>/prompts/agent.system.tool.<tool_name>.md`
|
||||
|
||||
When changing a tool name, argument shape, output behavior, safety rule, or `break_loop` behavior, update its prompt and tests together.
|
||||
|
||||
## Progress And Interventions
|
||||
|
||||
- Use `await self.set_progress(...)` when progress should be visible through the tool-output update extension.
|
||||
- `self.add_progress(...)` only accumulates local progress text.
|
||||
- For long-running or external-result workflows, follow `tools/AGENTS.md` and use `await self.agent.handle_intervention(...)` where pause/intervention flow matters.
|
||||
- Sanitize and mask secrets before logging or returning outputs.
|
||||
|
||||
## Core Tool DOX
|
||||
|
||||
Direct files under `tools/*.py` require matching `tools/*.py.dox.md`. The companion file owns purpose, arguments, output, `break_loop`, side effects, prompt contract notes, dependencies, and verification.
|
||||
|
||||
Plugin tool documentation belongs in that plugin's docs or DOX contract, not in root `tools/`.
|
||||
|
||||
## Verification
|
||||
|
||||
- Run targeted tests for changed tools.
|
||||
- Run prompt/snapshot tests when tool instructions or output shape changes.
|
||||
- For direct root tools, verify every `tools/*.py` has a matching `.py.dox.md`.
|
||||
- If the tool is plugin-scoped, also run plugin-specific checks from the plugin's `AGENTS.md`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue