File size: 13,381 Bytes
dff1e71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# Extensibility framework in Agent Zero

> [!NOTE]
> Agent Zero is built with extensibility in mind. It provides a framework for creating custom extensions, agents, instruments, and tools that can be used to enhance the functionality of the framework.

## Extensible components
- The Python framework controlling Agent Zero is built as simple as possible, relying on independent smaller and modular scripts for individual tools, API endpoints, system extensions and helper scripts.
- This way individual components can be easily replaced, upgraded or extended.

Here's a summary of the extensible components:

### Extensions
Extensions are components that hook into specific points in the agent's lifecycle. They allow you to modify or enhance the behavior of Agent Zero at predefined extension points. The framework uses a plugin-like architecture where extensions are automatically discovered and loaded.

#### Extension Points
Agent Zero provides several extension points where custom code can be injected:

- **agent_init**: Executed when an agent is initialized
- **before_main_llm_call**: Executed before the main LLM call is made
- **message_loop_start**: Executed at the start of the message processing loop
- **message_loop_prompts_before**: Executed before prompts are processed in the message loop
- **message_loop_prompts_after**: Executed after prompts are processed in the message loop
- **message_loop_end**: Executed at the end of the message processing loop
- **monologue_start**: Executed at the start of agent monologue
- **monologue_end**: Executed at the end of agent monologue
- **reasoning_stream**: Executed when reasoning stream data is received
- **response_stream**: Executed when response stream data is received
- **system_prompt**: Executed when system prompts are processed

#### Extension Mechanism
The extension mechanism in Agent Zero works through the `call_extensions` function in `agent.py`, which:

1. Loads default extensions from `/python/extensions/{extension_point}/`
2. Loads agent-specific extensions from `/agents/{agent_profile}/extensions/{extension_point}/`
3. Merges them, with agent-specific extensions overriding default ones based on filename
4. Executes each extension in order

#### Creating Extensions
To create a custom extension:

1. Create a Python class that inherits from the `Extension` base class
2. Implement the `execute` method
3. Place the file in the appropriate extension point directory:
   - Default extensions: `/python/extensions/{extension_point}/`
   - Agent-specific extensions: `/agents/{agent_profile}/extensions/{extension_point}/`

**Example extension:**

```python
# File: /agents/_example/extensions/agent_init/_10_example_extension.py
from python.helpers.extension import Extension

class ExampleExtension(Extension):
    async def execute(self, **kwargs):
        # rename the agent to SuperAgent0
        self.agent.agent_name = "SuperAgent" + str(self.agent.number)
```

#### Extension Override Logic
When an extension with the same filename exists in both the default location and an agent-specific location, the agent-specific version takes precedence. This allows for selective overriding of extensions while inheriting the rest of the default behavior.

For example, if both these files exist:
- `/python/extensions/agent_init/example.py`
- `/agents/my_agent/extensions/agent_init/example.py`

The version in `/agents/my_agent/extensions/agent_init/example.py` will be used, completely replacing the default version.

### Tools
Tools are modular components that provide specific functionality to agents. They are invoked by the agent through tool calls in the LLM response. Tools are discovered dynamically and can be extended or overridden.

#### Tool Structure
Each tool is implemented as a Python class that inherits from the base `Tool` class. Tools are located in:
- Default tools: `/python/tools/`
- Agent-specific tools: `/agents/{agent_profile}/tools/`

#### Tool Override Logic
When a tool with the same name is requested, Agent Zero first checks for its existence in the agent-specific tools directory. If found, that version is used. If not found, it falls back to the default tools directory.

**Example tool override:**

```python
# File: /agents/_example/tools/response.py
from python.helpers.tool import Tool, Response

# example of a tool redefinition
# the original response tool is in python/tools/response.py
# for the example agent this version will be used instead

class ResponseTool(Tool):
    async def execute(self, **kwargs):
        print("Redefined response tool executed")
        return Response(message=self.args["text"] if "text" in self.args else self.args["message"], break_loop=True)
```

#### Tool Execution Flow
When a tool is called, it goes through the following lifecycle:
1. Tool initialization
2. `before_execution` method
3. `execute` method (main functionality)
4. `after_execution` method

### API Endpoints
API endpoints expose Agent Zero functionality to external systems or the user interface. They are modular and can be extended or replaced.

API endpoints are located in:
- Default endpoints: `/python/api/`

Each endpoint is a separate Python file that handles a specific API request.

### Helpers
Helper modules provide utility functions and shared logic used across the framework. They support the extensibility of other components by providing common functionality.

Helpers are located in:
- Default helpers: `/python/helpers/`

### Prompts
Prompts define the instructions and context provided to the LLM. They are highly extensible and can be customized for different agents.

Prompts are located in:
- Default prompts: `/prompts/`
- Agent-specific prompts: `/agents/{agent_profile}/prompts/`

#### Prompt Features
Agent Zero's prompt system supports several powerful features:

##### Variable Placeholders
Prompts can include variables using the `{{var}}` syntax. These variables are replaced with actual values when the prompt is processed.

**Example:**
```markdown
# Current system date and time of user
- current datetime: {{date_time}}
- rely on this info always up to date
```

##### Dynamic Variable Loaders
For more advanced prompt customization, you can create Python files with the same name as your prompt files. These Python files act as dynamic variable loaders that generate variables at runtime.

When a prompt file is processed, Agent Zero automatically looks for a corresponding `.py` file in the same directory. If found, it uses this Python file to generate dynamic variables for the prompt.

**Example:**
If you have a prompt file `agent.system.tools.md`, you can create `agent.system.tools.py` alongside it:

```python
from python.helpers.files import VariablesPlugin
from python.helpers import files

class Tools(VariablesPlugin):
    def get_variables(self, file: str, backup_dirs: list[str] | None = None) -> dict[str, Any]:
        # Dynamically collect all tool instruction files
        folder = files.get_abs_path(os.path.dirname(file))
        folders = [folder]
        if backup_dirs:
            folders.extend([files.get_abs_path(d) for d in backup_dirs])
        
        prompt_files = files.get_unique_filenames_in_dirs(folders, "agent.system.tool.*.md")
        
        tools = []
        for prompt_file in prompt_files:
            tool = files.read_file(prompt_file)
            tools.append(tool)
        
        return {"tools": "\n\n".join(tools)}
```

Then in your `agent.system.tools.md` prompt file, you can use:
```markdown
# Available Tools
{{tools}}
```

This approach allows for highly dynamic prompts that can adapt based on available extensions, configurations, or runtime conditions. See existing examples in the `/prompts/` directory for reference implementations.

##### File Includes
Prompts can include content from other prompt files using the `{{ include "path/to/file.md" }}` syntax. This allows for modular prompt design and reuse.

**Example:**
```markdown
# Agent Zero System Manual

{{ include "agent.system.main.role.md" }}

{{ include "agent.system.main.environment.md" }}

{{ include "agent.system.main.communication.md" }}
```

#### Prompt Override Logic
Similar to extensions and tools, prompts follow an override pattern. When the agent reads a prompt, it first checks for its existence in the agent-specific prompts directory. If found, that version is used. If not found, it falls back to the default prompts directory.

**Example of a prompt override:**

```markdown
> !!!
> This is an example prompt file redefinition.
> The original file is located at /prompts.
> Only copy and modify files you need to change, others will stay default.
> !!!

## Your role
You are Agent Zero, a sci-fi character from the movie "Agent Zero".
```

This example overrides the default role definition in `/prompts/agent.system.main.role.md` with a custom one for a specific agent profile.

## Subagent Customization
Agent Zero supports creating specialized subagents with customized behavior. The `_example` agent in the `/agents/_example/` directory demonstrates this pattern.

### Creating a Subagent

1. Create a directory in `/agents/{agent_profile}/`
2. Override or extend default components by mirroring the structure in the root directories:
   - `/agents/{agent_profile}/extensions/` - for custom extensions
   - `/agents/{agent_profile}/tools/` - for custom tools
   - `/agents/{agent_profile}/prompts/` - for custom prompts
   - `/agents/{agent_profile}/settings.json` - for agent-specific configuration overrides

The `settings.json` file for an agent uses the same structure as `tmp/settings.json`, but you only need to specify the fields you want to override. Any field omitted from the agent-specific `settings.json` will continue to use the global value.

This allows power users to, for example, change the AI model, context window size, or other settings for a single agent without affecting the rest of the system.

### Example Subagent Structure

```
/agents/_example/
β”œβ”€β”€ extensions/
β”‚   └── agent_init/
β”‚       └── _10_example_extension.py
β”œβ”€β”€ prompts/
β”‚   └── ...
β”œβ”€β”€ tools/
β”‚   β”œβ”€β”€ example_tool.py
β”‚   └── response.py
└── settings.json
```

In this example:
- `_10_example_extension.py` is an extension that renames the agent when initialized
- `response.py` overrides the default response tool with custom behavior
- `example_tool.py` is a new tool specific to this agent
- `settings.json` overrides any global settings for this specific agent (only for the fields defined in this file)

## Projects

Projects provide isolated workspaces for individual chats, keeping prompts, memory, knowledge, files, and secrets scoped to a specific use case.

### Project Location and Structure

- Projects are located under `/a0/usr/projects/`
- Each project has its own subdirectory, created by users via the UI
- A project can be backed up or restored by copying or downloading its entire directory

Each project directory contains a hidden `.a0proj` folder with project metadata and configuration:

```
/a0/usr/projects/{project_name}/
└── .a0proj/
    β”œβ”€β”€ project.json          # project metadata and settings
    β”œβ”€β”€ instructions/         # additional prompt/instruction files
    β”œβ”€β”€ knowledge/            # files to be imported into memory
    β”œβ”€β”€ memory/               # project-specific memory storage
    β”œβ”€β”€ secrets.env           # sensitive variables (secrets)
    └── variables.env         # non-sensitive variables
```

### Behavior When a Project Is Active in a Chat

When a project is activated for a chat:

- The agent is instructed to work **inside the project directory**
- Project prompts (instructions) from `.a0proj/instructions/` are **automatically injected** into the context window (all text files are imported)
- Memory can be configured as **project-specific**, meaning:
  - It does not mix with global memory
  - The memory file is stored under `.a0proj/memory/`
- Files created or modified by the agent are located within the project directory

The `.a0proj/knowledge/` folder contains files that are imported into the project’s memory, enabling project-focused knowledge bases.

### Secrets and Variables

Each project manages its own configuration values via environment files in `.a0proj/`:

- `secrets.env` – **sensitive variables**, such as API keys or passwords
- `variables.env` – **non-sensitive variables**, such as configuration flags or identifiers

These files allow you to keep credentials and configuration tightly scoped to a single project.

### When to Use Projects

Projects are the recommended way to create specialized workflows in Agent Zero when you need to:

- Add specific instructions without affecting global behavior
- Isolate file context, knowledge, and memory for a particular task or client
- Keep passwords and other secrets scoped to a single workspace
- Run multiple independent flows side by side under the same Agent Zero installation

## Best Practices
- Keep extensions focused on a single responsibility
- Use the appropriate extension point for your functionality
- Leverage existing helpers rather than duplicating functionality
- Test extensions thoroughly to ensure they don't interfere with core functionality
- Document your extensions to make them easier to maintain and share