# A0 Development

> 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.

- **Type:** Skill
- **Install:** `agentstack add skill-gen-verse-past-bench-a0-development`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Gen-Verse](https://agentstack.voostack.com/s/gen-verse)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [Gen-Verse](https://github.com/Gen-Verse)
- **Source:** https://github.com/Gen-Verse/PAST-Bench/tree/main/agents/agent-zero/skills/a0-development
- **Website:** https://arxiv.org/abs/2608.04003

## Install

```sh
agentstack add skill-gen-verse-past-bench-a0-development
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Agent Zero Development Guide

This skill provides comprehensive, accurate guidance for extending and building features for Agent Zero. Use it when you need to:

- 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 `create-skill` skill for the full wizard)
- Work with **Projects** and workspace configuration

> **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.

> [!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.

Related skills: `a0-plugin-router` (plugin tasks) | `create-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
│   │   ├── /         # e.g., agent_init/, system_prompt/, etc.
│   │   │   └── _NN_name.py       # Numbered extension files
│   │   └── _functions/           # Implicit @extensible decorator extensions
│   └── webui/                    # JavaScript WebUI extensions
│       └── /         # 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//tools/` | Plugin-provided tools (code_execution, memory, text_editor) |
| `/a0/agents//tools/` | Profile-specific tool overrides |
| `/a0/usr/plugins//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..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//_NN_name.py
```

Where `_NN_` is a numeric prefix controlling execution order (e.g., `_10_`, `_20_`, `_50_`).

| Source | Path |
|---|---|
| Core extensions | `/a0/extensions/python//` |
| Plugin extensions | `/a0/plugins//extensions/python//` |
| User extensions | `/a0/usr/extensions/python//` |
| Agent profile extensions | `/a0/agents//extensions//` |
| User plugin extensions | `/a0/usr/plugins//extensions/python//` |

### 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///start
_functions///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 | 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_

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Gen-Verse](https://github.com/Gen-Verse)
- **Source:** [Gen-Verse/PAST-Bench](https://github.com/Gen-Verse/PAST-Bench)
- **License:** Apache-2.0
- **Homepage:** https://arxiv.org/abs/2608.04003

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-gen-verse-past-bench-a0-development
- Seller: https://agentstack.voostack.com/s/gen-verse
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
