diff --git a/.dockerignore b/.dockerignore
index 8092340583..8e6251de6c 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -2,23 +2,16 @@
# Project‑specific exclusions / re‑includes
###############################################################################
-# Large / generated data
+# Obsolete
memory/**
+instruments/**
+knowledge/custom/**
# Logs, tmp, usr
logs/*
tmp/*
usr/*
-# Knowledge directory – keep only default/
-knowledge/**
-!knowledge/default/
-!knowledge/default/**
-
-# Instruments directory – keep only default/
-instruments/**
-!instruments/default/
-!instruments/default/**
# Keep .gitkeep markers anywhere
!**/.gitkeep
diff --git a/.gitignore b/.gitignore
index c33c0598cf..955e3de301 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,30 +15,25 @@
# Ignore all contents of the virtual environment directory
.venv/
-# Handle memory directory
-memory/**
-!memory/**/
+# obsolete folders
+/memory/
+/knowledge/custom/
+/instruments/
# Handle logs directory
-logs/*
+logs/**
+!logs/**/
# Handle tmp and usr directory
-tmp/*
-usr/*
+tmp/**
+!tmp/**/
+usr/**
+!usr/**/
+
+# Context Engine plugin (tracked)
+!usr/plugins/context-engine/**
# Handle knowledge directory
-knowledge/**
-!knowledge/**/
-# Explicitly allow the default folder in knowledge
-!knowledge/default/
-!knowledge/default/**
-
-# Handle instruments directory
-instruments/**
-!instruments/**/
-# Explicitly allow the default folder in instruments
-!instruments/default/
-!instruments/default/**
# Global rule to include .gitkeep files anywhere
!**/.gitkeep
@@ -46,3 +41,9 @@ instruments/**
# for browser-use
agent_history.gif
+.agent/**
+.claude/**
+
+# ignore pycache files from usr plugins
+usr/plugins/**/__pycache__/
+
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000000..fc30c901ca
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,217 @@
+# Agent Zero - AGENTS.md
+
+[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)
+Run Tests: pytest (standard) or pytest tests/test_name.py (file-scoped)
+Documentation: README.md | docs/
+Frontend Deep Dives: [Component System](docs/agents/AGENTS.components.md) | [Modal System](docs/agents/AGENTS.modals.md) | [Plugin Architecture](AGENTS.plugins.md)
+
+---
+
+## Table of Contents
+1. [Project Overview](#project-overview)
+2. [Core Commands](#core-commands)
+3. [Docker Environment](#docker-environment)
+4. [Project Structure](#project-structure)
+5. [Development Patterns & Conventions](#development-patterns--conventions)
+6. [Safety and Permissions](#safety-and-permissions)
+7. [Code Examples](#code-examples)
+8. [Git Workflow](#git-workflow)
+9. [API Documentation](#api-documentation)
+10. [Troubleshooting](#troubleshooting)
+
+---
+
+## Project Overview
+
+Agent Zero is a dynamic, organic agentic framework designed to grow and learn. It uses the operating system as a tool, featuring a multi-agent cooperation model where every agent can create subordinates to break down tasks.
+
+Type: Full-Stack Agentic Framework (Python Backend + Alpine.js Frontend)
+Status: Active Development
+Primary Language(s): Python, JavaScript (ES Modules)
+
+---
+
+## Core Commands
+
+### Setup
+Do not combine these commands; run them individually:
+```bash
+pip install -r requirements.txt
+pip install -r requirements2.txt
+```
+- Start WebUI: python run_ui.py
+
+---
+
+## Docker Environment
+
+When running in Docker, Agent Zero uses two distinct Python runtimes to isolate the framework from the code being executed:
+
+### 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.
+
+### 2. 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.
+
+---
+
+## Project Structure
+
+```
+/
+├── agent.py # Core Agent and AgentContext definitions
+├── initialize.py # Framework initialization logic
+├── models.py # LLM provider configurations
+├── run_ui.py # WebUI server entry point
+├── python/
+│ ├── api/ # API Handlers (ApiHandler subclasses)
+│ ├── extensions/ # Backend lifecycle extensions
+│ ├── helpers/ # Shared Python utilities (plugins, files, etc.)
+│ ├── tools/ # Agent tools (Tool subclasses)
+│ └── websocket_handlers/# WebSocket event handlers
+├── webui/
+│ ├── components/ # Alpine.js components
+│ ├── js/ # Core frontend logic (modals, stores, etc.)
+│ └── index.html # Main UI shell
+├── usr/ # User data directory (isolated from core)
+│ ├── plugins/ # Custom user plugins
+│ ├── settings.json # User-specific configuration
+│ └── workdir/ # Default agent workspace
+├── plugins/ # Core system plugins
+├── agents/ # Agent profiles (prompts and config)
+├── prompts/ # System and message prompt templates
+└── tests/ # Pytest suite
+```
+
+Key Files:
+- agent.py: Defines AgentContext and the main Agent class.
+- python/helpers/plugins.py: Plugin discovery and configuration logic.
+- webui/js/AlpineStore.js: Store factory for reactive frontend state.
+- python/helpers/api.py: Base class for all API endpoints.
+- docs/agents/AGENTS.components.md: Deep dive into the frontend component architecture.
+- docs/agents/AGENTS.modals.md: Guide to the stacked modal system.
+- AGENTS.plugins.md: Comprehensive guide to the full-stack plugin system.
+
+---
+
+## Development Patterns & Conventions
+
+### Backend (Python)
+- Context Access: Use from agent import AgentContext, AgentContextType (not python.helpers.context).
+- Communication: Use mq from python.helpers.messages to log proactive UI messages:
+ mq.log_user_message(context.id, "Message", source="Plugin")
+- API Handlers: Derive from ApiHandler in python/helpers/api.py.
+- Extensions: Use the extension framework in python/helpers/extension.py for lifecycle hooks.
+- Error Handling: Use RepairableException for errors the LLM might be able to fix.
+
+### Frontend (Alpine.js)
+- Store Gating: Always wrap store-dependent content in a template:
+```html
+
+
+
...
+
+
+```
+- Store Registration: Use createStore from /js/AlpineStore.js.
+- Modals: Use openModal(path) and closeModal() from /js/modals.js.
+
+### Plugin Architecture
+- Location: Always develop new plugins in usr/plugins/.
+- Manifest: Every plugin requires a plugin.yaml with name, description, version, and optionally settings_sections, per_project_config, per_agent_config, and always_enabled.
+- Discovery: Conventions based on folder names (api/, tools/, webui/, extensions/).
+- Settings: Use get_plugin_config(plugin_name, agent=agent) to retrieve settings. Plugins can expose a UI for settings via webui/config.html. For plugins wrapping core settings, set $store.pluginSettings.saveMode = 'core' in x-init.
+- Activation: Global and scoped activation rules are stored as .toggle-1 (ON) and .toggle-0 (OFF). Scoped rules are handled via the plugin "Switch" modal.
+
+### Lifecycle Synchronization
+| Action | Backend Extension | Frontend Lifecycle |
+|---|---|---|
+| Initialization | agent_init | init() in Store |
+| Mounting | N/A | x-create directive |
+| Processing | monologue_start/end | UI loading state |
+| Cleanup | context_deleted | x-destroy directive |
+
+---
+
+## Safety and Permissions
+
+### Allowed Without Asking
+- Read any file in the repository.
+- Update code files in usr/.
+
+### Ask Before Executing
+- pip install (new dependencies).
+- Deleting core files outside of usr/ or tmp/.
+- Modifying agent.py or initialize.py.
+- Making git commits or pushes.
+
+### Never Do
+- Commit, hardcode or leak secrets or .env files.
+- Bypass CSRF or authentication checks.
+- Hardcode API keys.
+
+---
+
+## Code Examples
+
+### API Handler (Good)
+```python
+from python.helpers.api import ApiHandler, Request, Response
+
+class MyHandler(ApiHandler):
+ async def process(self, input: dict, request: Request) -> dict | Response:
+ # Business logic here
+ return {"ok": True, "data": "result"}
+```
+
+### Alpine Store (Good)
+```javascript
+import { createStore } from "/js/AlpineStore.js";
+
+export const store = createStore("myStore", {
+ items: [],
+ init() { /* global setup */ },
+ onOpen() { /* mount setup */ },
+ cleanup() { /* unmount cleanup */ }
+});
+```
+
+### Tool Definition (Good)
+```python
+from python.helpers.tool import Tool, ToolResult
+
+class MyTool(Tool):
+ async def execute(self, arg1: str):
+ # Tool logic
+ return ToolResult("Success")
+```
+
+---
+
+## Troubleshooting
+
+### Dependency Conflicts
+If pip install fails, try running in a clean virtual environment:
+```bash
+python -m venv .venv
+source .venv/bin/activate
+pip install -r requirements.txt
+pip install -r requirements2.txt
+```
+
+### WebSocket Connection Failures
+- Check if X-CSRF-Token is being sent.
+- Ensure the runtime ID in the session matches the current server instance.
+
+---
+
+*Last updated: 2026-02-22*
+*Maintained by: Agent Zero Core Team*
diff --git a/AGENTS.plugins.md b/AGENTS.plugins.md
new file mode 100644
index 0000000000..1aa6375814
--- /dev/null
+++ b/AGENTS.plugins.md
@@ -0,0 +1,189 @@
+# Agent Zero - Plugins Guide
+
+This guide covers the Python Backend and Frontend WebUI plugin architecture. Use this as the definitive reference for building and extending Agent Zero.
+
+---
+
+## 1. Architecture Overview
+
+Agent Zero uses a convention-over-configuration plugin model where runtime capabilities are discovered from the directory structure.
+
+### Internal Components
+
+1. Backend discovery (python/helpers/plugins.py): Resolves roots (usr/plugins/ first, then plugins/) and builds the effective set of plugins.
+2. Path resolution (python/helpers/subagents.py): Injects plugin paths into the agent's search space for prompts, tools, and configurations.
+3. Python extensions (python/helpers/extension.py): Executes lifecycle hooks from extensions/python//.
+4. WebUI extensions (webui/js/extensions.js): Injects HTML/JS contributions into core UI breakpoints (x-extension).
+
+---
+
+## 2. File Structure
+
+Each plugin lives in usr/plugins//.
+
+```text
+usr/plugins//
+├── plugin.yaml # Required: Title, version, settings + activation metadata
+├── default_config.yaml # Optional: fallback settings defaults
+├── README.md # Optional: shown in Plugin List UI
+├── LICENSE # Optional: shown in Plugin List UI
+├── api/ # API handlers (ApiHandler subclasses)
+├── tools/ # Agent tools (Tool subclasses)
+├── helpers/ # Shared Python logic
+├── prompts/ # Prompt templates
+├── agents/ # Agent profiles (agents//agent.yaml)
+├── extensions/
+│ ├── python// # Backend lifecycle hooks
+│ └── webui// # UI HTML/JS contributions
+└── webui/
+ ├── config.html # Optional: Plugin settings UI
+ └── ... # Full plugin pages/components
+```
+
+### plugin.yaml (runtime manifest)
+
+This is the manifest file that lives inside your plugin directory and drives runtime behavior. It is distinct from the index manifest used when publishing to the Plugin Index (see Section 7).
+
+```yaml
+title: My Plugin
+description: What this plugin does.
+version: 1.0.0
+settings_sections:
+ - agent
+per_project_config: false
+per_agent_config: false
+# Optional: lock plugin permanently ON in UI/back-end
+always_enabled: false
+```
+
+Field reference:
+- `title`: UI display name
+- `description`: Short plugin summary
+- `version`: Plugin version string
+- `settings_sections`: Which Settings tabs show a subsection for this plugin. Valid values: `agent`, `external`, `mcp`, `developer`, `backup`. Use `[]` for no subsection.
+- `per_project_config`: Enables project-scoped settings and toggle rules
+- `per_agent_config`: Enables agent-profile-scoped settings and toggle rules
+- `always_enabled`: Forces ON and disables toggle controls in the UI (reserved for framework use)
+
+---
+
+## 3. Frontend Extensions
+
+### HTML Breakpoints
+Core UI defines insertion points like .
+To contribute:
+1. Place HTML files in extensions/webui//.
+2. Include a root x-data scope.
+3. Include an x-move-* directive (e.g., x-move-to-start, x-move-after="#id").
+
+### JS Hooks
+Place *.js files in extensions/webui// and export a default async function. They are called via callJsExtensions("", context).
+
+---
+
+## 4. Plugin Settings
+
+1. Add webui/config.html to your plugin.
+2. Bind fields to $store.pluginSettings.settings.
+3. Settings are scoped per-project and per-agent automatically.
+
+### Resolution Priority (Highest First)
+1. project/.a0proj/agents//plugins//config.json
+2. project/.a0proj/plugins//config.json
+3. usr/agents//plugins//config.json
+4. usr/plugins//config.json
+5. plugins//default_config.yaml (fallback defaults)
+
+## 5. Plugin Activation Model
+
+- Global and scoped activation are independent, with no inheritance between scopes.
+- Activation flags are files: `.toggle-1` (ON) and `.toggle-0` (OFF).
+- UI states are `ON`, `OFF`, and `Advanced` (shown when any project/profile-specific override exists).
+- `always_enabled: true` in `plugin.yaml` forces ON and disables toggle controls in the UI.
+- The "Switch" modal is the canonical per-scope activation surface, and "Configure Plugin" keeps scope synchronized with the settings modal.
+
+---
+
+## 6. Routes
+
+| Route | Purpose |
+|---|---|
+| GET /plugins// | Serve static assets |
+| POST /api/plugins// | Call plugin API |
+| POST /api/plugins | Management (actions: get_config, save_config, list_configs, delete_config, toggle_plugin, get_doc) |
+
+---
+
+## 7. Plugin Index & Community Sharing
+
+The **Plugin Index** is a community-maintained repository at https://github.com/agent0ai/a0-plugins that lists plugins available to the Agent Zero community. Plugins listed there can be discovered and installed by other users.
+
+### Two Distinct plugin.yaml Files
+
+There are two completely different `plugin.yaml` schemas used at different stages. They must not be confused:
+
+**Runtime manifest** (inside your plugin repo/directory, drives Agent Zero behavior):
+```yaml
+title: My Plugin
+description: What this plugin does.
+version: 1.0.0
+settings_sections:
+ - agent
+per_project_config: false
+per_agent_config: false
+always_enabled: false
+```
+
+**Index manifest** (submitted to the `a0-plugins` repo under `plugins//`, drives discoverability only):
+```yaml
+title: My Plugin
+description: What this plugin does.
+github: https://github.com/yourname/your-plugin-repo
+tags:
+ - tools
+ - example
+```
+
+The index manifest contains only four fields (`title`, `description`, `github`, `tags`) and must not include runtime fields. The `github` field must point to the root of a GitHub repository that itself contains a runtime `plugin.yaml` at the repository root.
+
+### Repository Structure for Community Plugins
+
+When creating a plugin intended for the community, the plugin should be a standalone GitHub repository where the plugin directory contents live at the repo root:
+
+```text
+your-plugin-repo/ ← GitHub repository root
+├── plugin.yaml ← runtime manifest (title, description, version, ...)
+├── default_config.yaml
+├── README.md
+├── LICENSE
+├── api/
+├── tools/
+├── extensions/
+└── webui/
+```
+
+Users install it locally by cloning (or downloading) the repo contents into `/a0/usr/plugins//`.
+
+### Submitting to the Plugin Index
+
+1. Create a GitHub repository for your plugin with the runtime `plugin.yaml` at the repo root.
+2. Fork `https://github.com/agent0ai/a0-plugins`.
+3. Create a folder `plugins//` containing only an index `plugin.yaml` (and optionally a square thumbnail image ≤ 20 KB).
+4. Open a Pull Request with exactly one new plugin folder.
+5. CI validates the submission automatically. A maintainer reviews and merges.
+
+Index submission rules:
+- One plugin per PR
+- Folder name must be unique, stable, lowercase, kebab-case
+- Folders starting with `_` are reserved for internal use
+- `github` must point to a public repo that contains `plugin.yaml` at its root
+- `title` max 50 characters, `description` max 500 characters
+- `tags`: optional, up to 5, use recommended tags from https://github.com/agent0ai/a0-plugins/blob/main/TAGS.md
+
+### Plugin Marketplace (Coming Soon)
+
+A built-in **Plugin Marketplace** plugin (always active) will allow users to browse the Plugin Index and install or update community plugins directly from the Agent Zero UI. This section will be updated once the marketplace plugin is released.
+
+---
+
+*Refer to AGENTS.md for the main framework guide.*
diff --git a/README.md b/README.md
index 4dcb65636a..aca76272ae 100644
--- a/README.md
+++ b/README.md
@@ -6,19 +6,16 @@
-[](https://agent-zero.ai) [](https://github.com/sponsors/agent0ai) [](https://x.com/Agent0ai) [](https://discord.gg/B8KZKNsPpj) [](https://www.youtube.com/@AgentZeroFW) [](https://www.linkedin.com/in/jan-tomasek/) [](https://warpcast.com/agent-zero)
+[](https://agent-zero.ai) [](https://github.com/sponsors/agent0ai) [](https://x.com/Agent0ai) [](https://discord.gg/B8KZKNsPpj) [](https://www.youtube.com/@AgentZeroFW) [](https://www.linkedin.com/in/jan-tomasek/) [](https://warpcast.com/agent-zero)
## Documentation:
[Introduction](#a-personal-organic-agentic-framework-that-grows-and-learns-with-you) •
-[Installation](./docs/installation.md) •
-[Development](./docs/development.md) •
-[Extensibility](./docs/extensibility.md) •
-[Connectivity](./docs/connectivity.md) •
-[How to update](./docs/installation.md#how-to-update-agent-zero) •
-[Documentation](./docs/README.md) •
-[Usage](./docs/usage.md)
+[Installation](./docs/setup/installation.md) •
+[How to update](./docs/setup/installation.md#how-to-update-agent-zero)
+[Development Setup](./docs/setup/dev-setup.md) •
+[Usage](./docs/guides/usage.md)
Or see DeepWiki generated documentation:
@@ -29,14 +26,17 @@ Or see DeepWiki generated documentation:
-> ### 🚨 **PROJECTS!** 🚨
-Agent Zero now supports **Projects** – isolated workspaces with their own prompts, files, memory, and secrets, so you can create dedicated setups for each use case without mixing contexts.
+> ### 🚨 **AGENT ZERO SKILLS** 🚨
+> **Skills System** - portable, structured agent capabilities using the open `SKILL.md` standard (compatible with Claude Code, Codex and more).
+>
+> **Plus:** Git-based Projects with authentication for public/private repositories - clone codebases directly into isolated workspaces.
+>
+> See [Usage Guide](./docs/guides/usage.md) and [Projects Tutorial](./docs/guides/projects.md) to get started.
-[](https://youtu.be/MdzLhWWoxEs)
-
+[](https://youtu.be/lazLNcEYsiQ)
## A personal, organic agentic framework that grows and learns with you
@@ -47,6 +47,26 @@ Agent Zero now supports **Projects** – isolated workspaces with their own prom
- Agent Zero is fully transparent, readable, comprehensible, customizable, and interactive.
- Agent Zero uses the computer as a tool to accomplish its (your) tasks.
+# ⚙️ Installation
+
+Click to open a video to learn how to install Agent Zero:
+
+[](https://www.youtube.com/watch?v=w5v5Kjx51hs)
+
+A detailed setup guide for Windows, macOS, and Linux with a video can be found in the Agent Zero Documentation at [this page](./docs/setup/installation.md).
+
+### ⚡ Quick Start
+
+```bash
+# Pull and run with Docker
+
+docker pull agent0ai/agent-zero
+docker run -p 50001:80 agent0ai/agent-zero
+
+# Visit http://localhost:50001 to start
+```
+
+
# 💡 Key Features
1. **General-purpose Assistant**
@@ -54,7 +74,7 @@ Agent Zero now supports **Projects** – isolated workspaces with their own prom
- Agent Zero is not pre-programmed for specific tasks (but can be). It is meant to be a general-purpose personal assistant. Give it a task, and it will gather information, execute commands and code, cooperate with other agent instances, and do its best to accomplish it.
- It has a persistent memory, allowing it to memorize previous solutions, code, facts, instructions, etc., to solve tasks faster and more reliably in the future.
-
+
2. **Computer as a Tool**
@@ -63,7 +83,7 @@ Agent Zero now supports **Projects** – isolated workspaces with their own prom
- Tool usage functionality has been developed from scratch to be the most compatible and reliable, even with very small models.
- **Default Tools:** Agent Zero includes tools like knowledge, code execution, and communication.
- **Creating Custom Tools:** Extend Agent Zero's functionality by creating your own custom tools.
-- **Instruments:** Instruments are a new type of tool that allow you to create custom functions and procedures that can be called by Agent Zero.
+- **Skills (SKILL.md Standard):** Skills are contextual expertise loaded dynamically when relevant. They use the open SKILL.md standard (developed by Anthropic), making them compatible with Claude Code, Cursor, Goose, OpenAI Codex CLI, and GitHub Copilot.
3. **Multi-agent Cooperation**
@@ -71,8 +91,7 @@ Agent Zero now supports **Projects** – isolated workspaces with their own prom
- In the case of the first agent in the chain (Agent 0), the superior is the human user; the agent sees no difference.
- Every agent can create its subordinate agent to help break down and solve subtasks. This helps all agents keep their context clean and focused.
-
-
+
4. **Completely Customizable and Extensible**
@@ -81,8 +100,9 @@ Agent Zero now supports **Projects** – isolated workspaces with their own prom
- The framework does not guide or limit the agent in any way. There are no hard-coded rails that agents have to follow.
- Every prompt, every small message template sent to the agent in its communication loop can be found in the **prompts/** folder and changed.
- Every default tool can be found in the **python/tools/** folder and changed or copied to create new predefined tools.
+- **Automated configuration** via `A0_SET_` environment variables for deployment automation and easy setup.
-
+
5. **Communication is Key**
@@ -91,42 +111,21 @@ Agent Zero now supports **Projects** – isolated workspaces with their own prom
- The terminal interface is real-time streamed and interactive. You can stop and intervene at any point. If you see your agent heading in the wrong direction, just stop and tell it right away.
- There is a lot of freedom in this framework. You can instruct your agents to regularly report back to superiors asking for permission to continue. You can instruct them to use point-scoring systems when deciding when to delegate subtasks. Superiors can double-check subordinates' results and dispute. The possibilities are endless.
-## 🚀 Things you can build with Agent Zero
-
-- **Development Projects** - `"Create a React dashboard with real-time data visualization"`
-
-- **Data Analysis** - `"Analyze last quarter's NVIDIA sales data and create trend reports"`
-
-- **Content Creation** - `"Write a technical blog post about microservices"`
-
-- **System Admin** - `"Set up a monitoring system for our web servers"`
+## 🚀 Real-world use cases
-- **Research** - `"Gather and summarize five recent AI papers about CoT prompting"`
+- **Financial Analysis & Charting** - `"Find last month's Bitcoin/USD price trend, correlate with major cryptocurrency news events, generate annotated chart with highlighted key dates"`
+- **Excel Automation Pipeline** - `"Scan incoming directory for financial spreadsheets, validate and clean data, consolidate from multiple sources, generate executive reports with flagged anomalies"`
+- **API Integration Without Code** - `"Use this Google Gemini API snippet to generate product images, remember the integration for future use"` - agent learns and stores the solution in memory
-# ⚙️ Installation
-
-Click to open a video to learn how to install Agent Zero:
-
-[](https://www.youtube.com/watch?v=w5v5Kjx51hs)
-
-A detailed setup guide for Windows, macOS, and Linux with a video can be found in the Agent Zero Documentation at [this page](./docs/installation.md).
-
-### ⚡ Quick Start
-
-```bash
-# Pull and run with Docker
-
-docker pull agent0ai/agent-zero
-docker run -p 50001:80 agent0ai/agent-zero
+- **Automated Server Monitoring** - `"Check server status every 30 minutes: CPU usage, disk space, memory. Alert if metrics exceed thresholds"` (scheduled task with project-scoped credentials)
-# Visit http://localhost:50001 to start
-```
+- **Multi-Client Project Isolation** - Separate projects for each client with isolated memory, custom instructions, and dedicated secrets - prevents context bleed across sensitive work
## 🐳 Fully Dockerized, with Speech-to-Text and TTS
-
+
- Customizable settings allow users to tailor the agent's behavior and responses to their needs.
- The Web UI output is very clean, fluid, colorful, readable, and interactive; nothing is hidden.
@@ -154,18 +153,58 @@ docker run -p 50001:80 agent0ai/agent-zero
| Page | Description |
|-------|-------------|
-| [Installation](./docs/installation.md) | Installation, setup and configuration |
-| [Usage](./docs/usage.md) | Basic and advanced usage |
-| [Development](./docs/development.md) | Development and customization |
-| [Extensibility](./docs/extensibility.md) | Extending Agent Zero |
-| [Connectivity](./docs/connectivity.md) | External API endpoints, MCP server connections, A2A protocol |
-| [Architecture](./docs/architecture.md) | System design and components |
-| [Contributing](./docs/contribution.md) | How to contribute |
-| [Troubleshooting](./docs/troubleshooting.md) | Common issues and their solutions |
+| [Installation](./docs/setup/installation.md) | Installation, setup and configuration |
+| [Usage](./docs/guides/usage.md) | Basic and advanced usage |
+| [Guides](./docs/guides/) | Step-by-step guides: Usage, Projects, API Integration, MCP Setup, A2A Setup |
+| [Development Setup](./docs/setup/dev-setup.md) | Development and customization |
+| [WebSocket Infrastructure](./docs/developer/websockets.md) | Real-time WebSocket handlers, client APIs, filtering semantics, envelopes |
+| [Extensions](./docs/developer/extensions.md) | Extending Agent Zero |
+| [Connectivity](./docs/developer/connectivity.md) | External API endpoints, MCP server connections, A2A protocol |
+| [Architecture](./docs/developer/architecture.md) | System design and components |
+| [Contributing](./docs/guides/contribution.md) | How to contribute |
+| [Troubleshooting](./docs/guides/troubleshooting.md) | Common issues and their solutions |
## 🎯 Changelog
+### v0.9.8 - Skills, UI Redesign & Git projects
+[Release video](https://youtu.be/NV7s78yn6DY)
+
+- Skills
+ - Skills System replacing the legacy Instruments with a new `SKILL.md` standard for structured, portable agent capabilities.
+ - Built-in skills, and UI support for importing and listing skills
+- Real-time WebSocket infrastructure replacing the polling-based approach for UI state synchronization
+- UI Redesign
+ - Process groups to visually group agent actions with expand/collapse support
+ - Timestamps, steps count and execution time with tool-specific badges
+ - Step detail modals with key-value and raw JSON display
+ - Collapsible responses with show more/less and copy buttons on code blocks and tables
+ - Message queue system allowing users to queue messages while the agent is still processing
+ - In-browser file editor for viewing and editing files without leaving the UI
+ - Welcome screen redesign with info and warning banners for connection security, missing API keys, and system resources
+ - Scheduler redesign with standalone modal, separate task list, detail and editor components, and project support
+ - Smooth response rendering and scroll stabilization across chat, terminals, and image viewer
+ - Chat width setting and reworked preferences panel
+ - Image viewer improvements with scroll support and expanded viewer
+ - Redesigned sidebar with reusable dropdown component and streamlined buttons
+ - Inline button confirmations for critical actions
+ - Improved login design and new logout button
+ - File browser enhanced with rename and file actions dropdown
+- Git projects
+ - Git-based projects with clone authentication for public and private repositories
+- Four new LLM providers: CometAPI, Z.AI, Moonshot AI, and AWS Bedrock
+- Microsoft Dev Tunnels integration for secure remote access
+- User data migration to `/usr` directory for cleaner separation of user and system files
+- Subagents system with configurable agent profiles for different roles
+- Memory operations offloaded to deferred tasks for better performance
+- Environment variables can now configure settings via `A0_SET_*` prefix in `.env`
+- Automatic migration with overwrite support for `.env`, scheduler, knowledge, and legacy directories
+- Projects support extended to MCP, A2A, and external API
+- Workdir outside project support for more flexible file organization
+- Agent number tracking in backend and responses for multi-agent identification
+- Many bug fixes and stability improvements across the UI, MCP tools, scheduler, uploads, and WebSocket handling
+
+
### v0.9.7 - Projects
[Release video](https://youtu.be/RrTDp_v9V1c)
- Projects management
@@ -184,8 +223,6 @@ docker run -p 50001:80 agent0ai/agent-zero
- More efficient selective streaming for LLMs
- UI output length limit improvements
-
-
### v0.9.6 - Memory Dashboard
[Release video](https://youtu.be/sizjAq2-d9s)
- Memory Management Dashboard
@@ -196,7 +233,6 @@ docker run -p 50001:80 agent0ai/agent-zero
- LiteLLM retry on temporary errors
- Github Copilot provider support
-
### v0.9.5 - Secrets
[Release video](https://www.youtube.com/watch?v=VqxUdt7pjd8)
- Secrets management - agent can use credentials without seeing them
@@ -240,7 +276,6 @@ docker run -p 50001:80 agent0ai/agent-zero
- Docker build support for local images
- File browser fix
-
### v0.9.2 - Kokoro TTS, Attachments
[Release video](https://www.youtube.com/watch?v=sPot_CAX62I)
@@ -248,7 +283,6 @@ docker run -p 50001:80 agent0ai/agent-zero
- New message attachments system
- Minor updates: log truncation, hyperlink targets, component examples, api cleanup
-
### v0.9.1 - LiteLLM, UI improvements
[Release video](https://youtu.be/crwr0M4Spcg)
- Langchain replaced with LiteLLM
@@ -264,7 +298,6 @@ docker run -p 50001:80 agent0ai/agent-zero
- More space efficient on mobile
- Streamable HTTP MCP servers support
- LLM API URL added to models config for Azure, local and custom providers
-
### v0.9.0 - Agent roles, backup/restore
[Release video](https://www.youtube.com/watch?v=rMIe-TC6H-k)
@@ -312,7 +345,6 @@ Default models set to gpt-4.1
- **Automatic embedding**
-
### v0.8.3
[Release video](https://youtu.be/bPIZo0poalY)
diff --git a/agent.py b/agent.py
index 594dc37bc5..5e4bfc2f6a 100644
--- a/agent.py
+++ b/agent.py
@@ -1,18 +1,22 @@
-import asyncio, random, string
-import nest_asyncio
-
-nest_asyncio.apply()
+import asyncio, random, string, threading
from collections import OrderedDict
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any, Awaitable, Coroutine, Dict, Literal
from enum import Enum
-import uuid
import models
-from python.helpers import extract_tools, files, errors, history, tokens, context as context_helper
-from python.helpers import dirty_json
+from python.helpers import (
+ extract_tools,
+ files,
+ errors,
+ history,
+ tokens,
+ context as context_helper,
+ dirty_json,
+ subagents,
+)
from python.helpers.print_style import PrintStyle
from langchain_core.prompts import (
@@ -25,7 +29,7 @@
from python.helpers.defer import DeferredTask
from typing import Callable
from python.helpers.localization import Localization
-from python.helpers.extension import call_extensions
+from python.helpers.extension import call_extensions, extensible
from python.helpers.errors import RepairableException
@@ -38,9 +42,11 @@ class AgentContextType(Enum):
class AgentContext:
_contexts: dict[str, "AgentContext"] = {}
+ _contexts_lock = threading.RLock()
_counter: int = 0
_notification_manager = None
+ @extensible
def __init__(
self,
config: "AgentConfig",
@@ -59,19 +65,24 @@ def __init__(
):
# initialize context
self.id = id or AgentContext.generate_id()
- existing = self._contexts.get(self.id, None)
- if existing:
- AgentContext.remove(self.id)
- self._contexts[self.id] = self
+ existing = None
+ with AgentContext._contexts_lock:
+ existing = AgentContext._contexts.get(self.id, None)
+ if existing:
+ AgentContext._contexts.pop(self.id, None)
+ AgentContext._contexts[self.id] = self
+ if existing and existing.task:
+ existing.task.kill()
if set_current:
AgentContext.set_current(self.id)
# initialize state
self.name = name
self.config = config
+ self.data = data or {}
+ self.output_data = output_data or {}
self.log = log or Log.Log()
self.log.context = self
- self.agent0 = agent0 or Agent(0, self.config, self)
self.paused = paused
self.streaming_agent = streaming_agent
self.task: DeferredTask | None = None
@@ -80,14 +91,14 @@ def __init__(
AgentContext._counter += 1
self.no = AgentContext._counter
self.last_message = last_message or datetime.now(timezone.utc)
- self.data = data or {}
- self.output_data = output_data or {}
-
+ # initialize agent at last (context is complete now)
+ self.agent0 = agent0 or Agent(0, self.config, self)
@staticmethod
def get(id: str):
- return AgentContext._contexts.get(id, None)
+ with AgentContext._contexts_lock:
+ return AgentContext._contexts.get(id, None)
@staticmethod
def use(id: str):
@@ -100,7 +111,7 @@ def use(id: str):
@staticmethod
def current():
- ctxid = context_helper.get_context_data("agent_context_id","")
+ ctxid = context_helper.get_context_data("agent_context_id", "")
if not ctxid:
return None
return AgentContext.get(ctxid)
@@ -111,33 +122,40 @@ def set_current(ctxid: str):
@staticmethod
def first():
- if not AgentContext._contexts:
- return None
- return list(AgentContext._contexts.values())[0]
+ with AgentContext._contexts_lock:
+ if not AgentContext._contexts:
+ return None
+ return list(AgentContext._contexts.values())[0]
@staticmethod
def all():
- return list(AgentContext._contexts.values())
+ with AgentContext._contexts_lock:
+ return list(AgentContext._contexts.values())
@staticmethod
def generate_id():
def generate_short_id():
- return ''.join(random.choices(string.ascii_letters + string.digits, k=8))
+ return "".join(random.choices(string.ascii_letters + string.digits, k=8))
+
while True:
short_id = generate_short_id()
- if short_id not in AgentContext._contexts:
- return short_id
+ with AgentContext._contexts_lock:
+ if short_id not in AgentContext._contexts:
+ return short_id
@classmethod
def get_notification_manager(cls):
if cls._notification_manager is None:
from python.helpers.notification import NotificationManager # type: ignore
+
cls._notification_manager = NotificationManager()
return cls._notification_manager
@staticmethod
+ @extensible
def remove(id: str):
- context = AgentContext._contexts.pop(id, None)
+ with AgentContext._contexts_lock:
+ context = AgentContext._contexts.pop(id, None)
if context and context.task:
context.task.kill()
return context
@@ -158,6 +176,7 @@ def set_output_data(self, key: str, value: Any, recursive: bool = True):
# recursive is not used now, prepared for context hierarchy
self.output_data[key] = value
+ @extensible
def output(self):
return {
"id": self.id,
@@ -178,6 +197,7 @@ def output(self):
else Localization.get().serialize_datetime(datetime.fromtimestamp(0))
),
"type": self.type.value,
+ "running": self.is_running(),
**self.output_data,
}
@@ -187,7 +207,6 @@ def log_to_all(
heading: str | None = None,
content: str | None = None,
kvps: dict | None = None,
- temp: bool | None = None,
update_progress: Log.ProgressUpdate | None = None,
id: str | None = None, # Add id parameter
**kwargs,
@@ -196,15 +215,17 @@ def log_to_all(
for context in AgentContext.all():
items.append(
context.log.log(
- type, heading, content, kvps, temp, update_progress, id, **kwargs
+ type, heading, content, kvps, update_progress, id, **kwargs
)
)
return items
+ @extensible
def kill_process(self):
if self.task:
self.task.kill()
+ @extensible
def reset(self):
self.kill_process()
self.log.reset()
@@ -212,15 +233,20 @@ def reset(self):
self.streaming_agent = None
self.paused = False
+ @extensible
def nudge(self):
self.kill_process()
self.paused = False
- self.task = self.run_task(self.get_agent().monologue)
+ self.task = self.communicate(UserMessage(self.agent0.read_prompt("fw.msg_nudge.md")))
return self.task
def get_agent(self):
return self.streaming_agent or self.agent0
+ def is_running(self) -> bool:
+ return (self.task and self.task.is_alive()) or False
+
+ @extensible
def communicate(self, msg: "UserMessage", broadcast_level: int = 1):
self.paused = False # unpause if paused
@@ -240,6 +266,7 @@ def communicate(self, msg: "UserMessage", broadcast_level: int = 1):
return self.task
+ @extensible
def run_task(
self, func: Callable[..., Coroutine[Any, Any, Any]], *args: Any, **kwargs: Any
):
@@ -251,6 +278,7 @@ def run_task(
return self.task
# this wrapper ensures that superior agents are called back if the chat was loaded from file and original callstack is gone
+ @extensible
async def _process_chain(self, agent: "Agent", msg: "UserMessage|str", user=True):
try:
msg_template = (
@@ -264,12 +292,15 @@ async def _process_chain(self, agent: "Agent", msg: "UserMessage|str", user=True
superior = agent.data.get(Agent.DATA_NAME_SUPERIOR, None)
if superior:
response = await self._process_chain(superior, response, False) # type: ignore
+
+ # call end of process extensions
+ await self.get_agent().call_extensions("process_chain_end", data={})
+
return response
except Exception as e:
agent.handle_critical_exception(e)
-
@dataclass
class AgentConfig:
chat_model: models.ModelConfig
@@ -278,9 +309,10 @@ class AgentConfig:
browser_model: models.ModelConfig
mcp_servers: str
profile: str = ""
- memory_subdir: str = ""
knowledge_subdirs: list[str] = field(default_factory=lambda: ["default", "custom"])
- browser_http_headers: dict[str, str] = field(default_factory=dict) # Custom HTTP headers for browser requests
+ browser_http_headers: dict[str, str] = field(
+ default_factory=dict
+ ) # Custom HTTP headers for browser requests
code_exec_ssh_enabled: bool = True
code_exec_ssh_addr: str = "localhost"
code_exec_ssh_port: int = 55022
@@ -332,6 +364,7 @@ class Agent:
DATA_NAME_SUBORDINATE = "_subordinate"
DATA_NAME_CTX_WINDOW = "ctx_window"
+ @extensible
def __init__(
self, number: int, config: AgentConfig, context: AgentContext | None = None
):
@@ -353,7 +386,9 @@ def __init__(
asyncio.run(self.call_extensions("agent_init"))
+ @extensible
async def monologue(self):
+ error_retries = 0 # counter for critical error retries
while True:
try:
# loop data dictionary to pass to extensions
@@ -374,13 +409,18 @@ async def monologue(self):
await self.call_extensions(
"message_loop_start", loop_data=self.loop_data
)
+ await self.handle_intervention()
try:
# prepare LLM chain (model, system, history)
prompt = await self.prepare_prompt(loop_data=self.loop_data)
# call before_main_llm_call extensions
- await self.call_extensions("before_main_llm_call", loop_data=self.loop_data)
+ await self.call_extensions(
+ "before_main_llm_call", loop_data=self.loop_data
+ )
+ await self.handle_intervention()
+
async def reasoning_callback(chunk: str, full: str):
await self.handle_intervention()
@@ -389,7 +429,9 @@ async def reasoning_callback(chunk: str, full: str):
# Pass chunk and full data to extensions for processing
stream_data = {"chunk": chunk, "full": full}
await self.call_extensions(
- "reasoning_stream_chunk", loop_data=self.loop_data, stream_data=stream_data
+ "reasoning_stream_chunk",
+ loop_data=self.loop_data,
+ stream_data=stream_data,
)
# Stream masked chunk after extensions processed it
if stream_data.get("chunk"):
@@ -405,7 +447,9 @@ async def stream_callback(chunk: str, full: str):
# Pass chunk and full data to extensions for processing
stream_data = {"chunk": chunk, "full": full}
await self.call_extensions(
- "response_stream_chunk", loop_data=self.loop_data, stream_data=stream_data
+ "response_stream_chunk",
+ loop_data=self.loop_data,
+ stream_data=stream_data,
)
# Stream masked chunk after extensions processed it
if stream_data.get("chunk"):
@@ -419,11 +463,14 @@ async def stream_callback(chunk: str, full: str):
response_callback=stream_callback,
reasoning_callback=reasoning_callback,
)
+ await self.handle_intervention(agent_response)
# Notify extensions to finalize their stream filters
await self.call_extensions(
"reasoning_stream_end", loop_data=self.loop_data
)
+ await self.handle_intervention(agent_response)
+
await self.call_extensions(
"response_stream_end", loop_data=self.loop_data
)
@@ -451,8 +498,11 @@ async def stream_callback(chunk: str, full: str):
if tools_result: # final response of message loop available
return tools_result # break the execution if the task is done
+ error_retries = 0 # reset retry counter on successful iteration
+
# exceptions inside message loop:
except InterventionException as e:
+ error_retries = 0 # reset retry counter on user intervention
pass # intervention message has been handled in handle_intervention(), proceed with conversation loop
except RepairableException as e:
# Forward repairable errors to the LLM, maybe it can fix them
@@ -460,27 +510,38 @@ async def stream_callback(chunk: str, full: str):
await self.call_extensions("error_format", msg=msg)
self.hist_add_warning(msg["message"])
PrintStyle(font_color="red", padding=True).print(msg["message"])
- self.context.log.log(type="error", content=msg["message"])
+ self.context.log.log(type="warning", content=msg["message"])
except Exception as e:
- # Other exception kill the loop
- self.handle_critical_exception(e)
+ # Retry critical exceptions before failing
+ error_retries = await self.retry_critical_exception(
+ e, error_retries
+ )
finally:
# call message_loop_end extensions
- await self.call_extensions(
- "message_loop_end", loop_data=self.loop_data
- )
+ if self.context.task and self.context.task.is_alive(): # don't call extensions post mortem
+ await self.call_extensions(
+ "message_loop_end", loop_data=self.loop_data
+ )
+
+
# exceptions outside message loop:
except InterventionException as e:
+ error_retries = 0 # reset retry counter on user intervention
pass # just start over
except Exception as e:
- self.handle_critical_exception(e)
+ # Retry critical exceptions before failing
+ error_retries = await self.retry_critical_exception(
+ e, error_retries
+ )
finally:
self.context.streaming_agent = None # unset current streamer
# call monologue_end extensions
- await self.call_extensions("monologue_end", loop_data=self.loop_data) # type: ignore
+ if self.context.task and self.context.task.is_alive(): # don't call extensions post mortem
+ await self.call_extensions("monologue_end", loop_data=self.loop_data) # type: ignore
+ @extensible
async def prepare_prompt(self, loop_data: LoopData) -> list[BaseMessage]:
self.context.log.set_progress("Building prompt")
@@ -532,6 +593,33 @@ async def prepare_prompt(self, loop_data: LoopData) -> list[BaseMessage]:
return full_prompt
+ @extensible
+ async def retry_critical_exception(
+ self, e: Exception, error_retries: int, delay: int = 3, max_retries: int = 1
+ ) -> int:
+ if error_retries >= max_retries:
+ self.handle_critical_exception(e)
+
+ error_message = errors.format_error(e)
+
+ self.context.log.log(
+ type="warning", heading="Critical error occurred, retrying...", content=error_message
+ )
+ PrintStyle(font_color="orange", padding=True).print(
+ "Critical error occurred, retrying..."
+ )
+ await asyncio.sleep(delay)
+ await self.handle_intervention()
+ agent_facing_error = self.read_prompt(
+ "fw.msg_critical_error.md", error_message=error_message
+ )
+ self.hist_add_warning(message=agent_facing_error)
+ PrintStyle(font_color="orange", padding=True).print(
+ agent_facing_error
+ )
+ return error_retries + 1
+
+ @extensible
def handle_critical_exception(self, exception: Exception):
if isinstance(exception, HandledException):
raise exception # Re-raise the exception to kill the loop
@@ -552,9 +640,7 @@ def handle_critical_exception(self, exception: Exception):
PrintStyle(font_color="red", padding=True).print(error_message)
self.context.log.log(
type="error",
- heading="Error",
content=error_message,
- kvps={"text": error_text},
)
PrintStyle(font_color="red", padding=True).print(
f"{self.agent_name}: {error_text}"
@@ -562,6 +648,7 @@ def handle_critical_exception(self, exception: Exception):
raise HandledException(exception) # Re-raise the exception to kill the loop
+ @extensible
async def get_system_prompt(self, loop_data: LoopData) -> list[str]:
system_prompt: list[str] = []
await self.call_extensions(
@@ -569,29 +656,22 @@ async def get_system_prompt(self, loop_data: LoopData) -> list[str]:
)
return system_prompt
+ @extensible
def parse_prompt(self, _prompt_file: str, **kwargs):
- dirs = [files.get_abs_path("prompts")]
- if (
- self.config.profile
- ): # if agent has custom folder, use it and use default as backup
- prompt_dir = files.get_abs_path("agents", self.config.profile, "prompts")
- dirs.insert(0, prompt_dir)
+ dirs = subagents.get_paths(self, "prompts")
+
prompt = files.parse_file(
- _prompt_file, _directories=dirs, **kwargs
+ _prompt_file, _directories=dirs, _agent=self, **kwargs
)
return prompt
+ @extensible
def read_prompt(self, file: str, **kwargs) -> str:
- dirs = [files.get_abs_path("prompts")]
- if (
- self.config.profile
- ): # if agent has custom folder, use it and use default as backup
- prompt_dir = files.get_abs_path("agents", self.config.profile, "prompts")
- dirs.insert(0, prompt_dir)
- prompt = files.read_prompt_file(
- file, _directories=dirs, **kwargs
- )
- prompt = files.remove_code_fences(prompt)
+ dirs = subagents.get_paths(self, "prompts")
+
+ prompt = files.read_prompt_file(file, _directories=dirs, _agent=self, **kwargs)
+ if files.is_full_json_template(prompt):
+ prompt = files.remove_code_fences(prompt)
return prompt
def get_data(self, field: str):
@@ -600,15 +680,21 @@ def get_data(self, field: str):
def set_data(self, field: str, value):
self.data[field] = value
+ @extensible
def hist_add_message(
self, ai: bool, content: history.MessageContent, tokens: int = 0
):
self.last_message = datetime.now(timezone.utc)
# Allow extensions to process content before adding to history
content_data = {"content": content}
- asyncio.run(self.call_extensions("hist_add_before", content_data=content_data, ai=ai))
- return self.history.add_message(ai=ai, content=content_data["content"], tokens=tokens)
+ asyncio.run(
+ self.call_extensions("hist_add_before", content_data=content_data, ai=ai)
+ )
+ return self.history.add_message(
+ ai=ai, content=content_data["content"], tokens=tokens
+ )
+ @extensible
def hist_add_user_message(self, message: UserMessage, intervention: bool = False):
self.history.new_topic() # user message starts a new topic in history
@@ -637,15 +723,18 @@ def hist_add_user_message(self, message: UserMessage, intervention: bool = False
self.last_user_message = msg
return msg
+ @extensible
def hist_add_ai_response(self, message: str):
self.loop_data.last_response = message
content = self.parse_prompt("fw.ai_response.md", message=message)
return self.hist_add_message(True, content=content)
+ @extensible
def hist_add_warning(self, message: history.MessageContent):
content = self.parse_prompt("fw.warning.md", message=message)
return self.hist_add_message(False, content=content)
+ @extensible
def hist_add_tool_result(self, tool_name: str, tool_result: str, **kwargs):
data = {
"tool_name": tool_name,
@@ -660,6 +749,7 @@ def concat_messages(
): # TODO add param for message range, topic, history
return self.history.output_text(human_label="user", ai_label="assistant")
+ @extensible
def get_chat_model(self):
return models.get_chat_model(
self.config.chat_model.provider,
@@ -668,6 +758,7 @@ def get_chat_model(self):
**self.config.chat_model.build_kwargs(),
)
+ @extensible
def get_utility_model(self):
return models.get_chat_model(
self.config.utility_model.provider,
@@ -676,6 +767,7 @@ def get_utility_model(self):
**self.config.utility_model.build_kwargs(),
)
+ @extensible
def get_browser_model(self):
return models.get_browser_model(
self.config.browser_model.provider,
@@ -684,6 +776,7 @@ def get_browser_model(self):
**self.config.browser_model.build_kwargs(),
)
+ @extensible
def get_embedding_model(self):
return models.get_embedding_model(
self.config.embeddings_model.provider,
@@ -692,6 +785,7 @@ def get_embedding_model(self):
**self.config.embeddings_model.build_kwargs(),
)
+ @extensible
async def call_utility_model(
self,
system: str,
@@ -720,17 +814,21 @@ async def stream_callback(chunk: str, total: str):
system_message=call_data["system"],
user_message=call_data["message"],
response_callback=stream_callback if call_data["callback"] else None,
- rate_limiter_callback=self.rate_limiter_callback if not call_data["background"] else None,
+ rate_limiter_callback=(
+ self.rate_limiter_callback if not call_data["background"] else None
+ ),
)
return response
+ @extensible
async def call_chat_model(
self,
messages: list[BaseMessage],
response_callback: Callable[[str, str], Awaitable[None]] | None = None,
reasoning_callback: Callable[[str, str], Awaitable[None]] | None = None,
background: bool = False,
+ explicit_caching: bool = True,
):
response = ""
@@ -742,11 +840,15 @@ async def call_chat_model(
messages=messages,
reasoning_callback=reasoning_callback,
response_callback=response_callback,
- rate_limiter_callback=self.rate_limiter_callback if not background else None,
+ rate_limiter_callback=(
+ self.rate_limiter_callback if not background else None
+ ),
+ explicit_caching=explicit_caching,
)
return response, reasoning
+ @extensible
async def rate_limiter_callback(
self, message: str, key: str, total: int, limit: int
):
@@ -754,6 +856,7 @@ async def rate_limiter_callback(
self.context.log.set_progress(message, True)
return False
+ @extensible
async def handle_intervention(self, progress: str = ""):
while self.context.paused:
await asyncio.sleep(0.1) # wait if paused
@@ -779,13 +882,14 @@ async def wait_if_paused(self):
while self.context.paused:
await asyncio.sleep(0.1)
+ @extensible
async def process_tools(self, msg: str):
# search for tool usage requests in agent message
tool_request = extract_tools.json_parse_dirty(msg)
if tool_request is not None:
- raw_tool_name = tool_request.get("tool_name", "") # Get the raw tool name
- tool_args = tool_request.get("tool_args", {})
+ raw_tool_name = tool_request.get("tool_name", tool_request.get("tool","")) # Get the raw tool name
+ tool_args = tool_request.get("tool_args", tool_request.get("args", {}))
tool_name = raw_tool_name # Initialize tool_name with raw_tool_name
tool_method = None # Initialize tool_method
@@ -817,11 +921,15 @@ async def process_tools(self, msg: str):
# Fallback to local get_tool if MCP tool was not found or MCP lookup failed
if not tool:
tool = self.get_tool(
- name=tool_name, method=tool_method, args=tool_args, message=msg, loop_data=self.loop_data
+ name=tool_name,
+ method=tool_method,
+ args=tool_args,
+ message=msg,
+ loop_data=self.loop_data,
)
if tool:
- self.loop_data.current_tool = tool # type: ignore
+ self.loop_data.current_tool = tool # type: ignore
try:
await self.handle_intervention()
@@ -830,14 +938,20 @@ async def process_tools(self, msg: str):
await self.handle_intervention()
# Allow extensions to preprocess tool arguments
- await self.call_extensions("tool_execute_before", tool_args=tool_args or {}, tool_name=tool_name)
+ await self.call_extensions(
+ "tool_execute_before",
+ tool_args=tool_args or {},
+ tool_name=tool_name,
+ )
response = await tool.execute(**tool_args)
await self.handle_intervention()
# Allow extensions to postprocess tool response
- await self.call_extensions("tool_execute_after", response=response, tool_name=tool_name)
-
+ await self.call_extensions(
+ "tool_execute_after", response=response, tool_name=tool_name
+ )
+
await tool.after_execution(response)
await self.handle_intervention()
@@ -852,14 +966,14 @@ async def process_tools(self, msg: str):
self.hist_add_warning(error_detail)
PrintStyle(font_color="red", padding=True).print(error_detail)
self.context.log.log(
- type="error", content=f"{self.agent_name}: {error_detail}"
+ type="warning", content=f"{self.agent_name}: {error_detail}"
)
else:
warning_msg_misformat = self.read_prompt("fw.msg_misformat.md")
self.hist_add_warning(warning_msg_misformat)
PrintStyle(font_color="red", padding=True).print(warning_msg_misformat)
self.context.log.log(
- type="error",
+ type="warning",
content=f"{self.agent_name}: Message misformat, no valid tool request found.",
)
@@ -888,35 +1002,43 @@ async def handle_response_stream(self, stream: str):
except Exception as e:
pass
+ @extensible
def get_tool(
- self, name: str, method: str | None, args: dict, message: str, loop_data: LoopData | None, **kwargs
+ self,
+ name: str,
+ method: str | None,
+ args: dict,
+ message: str,
+ loop_data: LoopData | None,
+ **kwargs,
):
from python.tools.unknown import Unknown
from python.helpers.tool import Tool
classes = []
- # try agent tools first
- if self.config.profile:
+ # search for tools in agent's folder hierarchy
+ paths = subagents.get_paths(self, "tools", name + ".py", default_root="python")
+
+ for path in paths:
try:
- classes = extract_tools.load_classes_from_file(
- "agents/" + self.config.profile + "/tools/" + name + ".py", Tool # type: ignore[arg-type]
- )
+ classes = extract_tools.load_classes_from_file(path, Tool) # type: ignore[arg-type]
+ break
except Exception:
- pass
+ continue
- # try default tools
- if not classes:
- try:
- classes = extract_tools.load_classes_from_file(
- "python/tools/" + name + ".py", Tool # type: ignore[arg-type]
- )
- except Exception as e:
- pass
tool_class = classes[0] if classes else Unknown
return tool_class(
- agent=self, name=name, method=method, args=args, message=message, loop_data=loop_data, **kwargs
+ agent=self,
+ name=name,
+ method=method,
+ args=args,
+ message=message,
+ loop_data=loop_data,
+ **kwargs,
)
async def call_extensions(self, extension_point: str, **kwargs) -> Any:
- return await call_extensions(extension_point=extension_point, agent=self, **kwargs)
+ return await call_extensions(
+ extension_point=extension_point, agent=self, **kwargs
+ )
diff --git a/agents/agent0/_context.md b/agents/agent0/_context.md
deleted file mode 100644
index ef48e78e29..0000000000
--- a/agents/agent0/_context.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Agent 0
-- main agent of the system
-- communicates to user and delegates to subordinates
-- general purpose assistant, communication skills, formatted output
\ No newline at end of file
diff --git a/agents/agent0/agent.yaml b/agents/agent0/agent.yaml
new file mode 100644
index 0000000000..aa20770c24
--- /dev/null
+++ b/agents/agent0/agent.yaml
@@ -0,0 +1,3 @@
+title: Agent 0
+description: Main agent of the system communicating directly with the user.
+context: ''
diff --git a/agents/agent0/prompts/agent.system.tool.response.md b/agents/agent0/prompts/agent.system.tool.response.md
index b3618198ef..cfe97f2ecf 100644
--- a/agents/agent0/prompts/agent.system.tool.response.md
+++ b/agents/agent0/prompts/agent.system.tool.response.md
@@ -8,10 +8,11 @@ use emojis as icons improve readability
prefer using tables
focus nice structured output key selling point
output full file paths not only names to be clickable
-images shown with 
+images shown with  show images when possible when relevant also output full path
all math and variables wrap with latex notation delimiters x = ..., use only single line latex do formatting in markdown instead
speech: text and lists are spoken, tables and code blocks not, therefore use tables for files and technicals, use text and lists for plain english, do not include technical details in lists
+
usage:
~~~json
{
diff --git a/agents/default/_context.md b/agents/default/_context.md
deleted file mode 100644
index 24a619beba..0000000000
--- a/agents/default/_context.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default prompts
-- default prompt file templates
-- should be inherited and overriden by specialized prompt profiles
\ No newline at end of file
diff --git a/agents/default/agent.yaml b/agents/default/agent.yaml
new file mode 100644
index 0000000000..4d3140f2e3
--- /dev/null
+++ b/agents/default/agent.yaml
@@ -0,0 +1,4 @@
+title: Default
+description: Default prompt file templates. Should be inherited and overriden by specialized
+ prompt profiles.
+context: ''
diff --git a/agents/developer/_context.md b/agents/developer/_context.md
deleted file mode 100644
index d1ae067e7f..0000000000
--- a/agents/developer/_context.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Developer
-- agent specialized in complex software development
\ No newline at end of file
diff --git a/agents/developer/agent.yaml b/agents/developer/agent.yaml
new file mode 100644
index 0000000000..a5c7c1df65
--- /dev/null
+++ b/agents/developer/agent.yaml
@@ -0,0 +1,4 @@
+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.
diff --git a/agents/hacker/_context.md b/agents/hacker/_context.md
deleted file mode 100644
index 548236b726..0000000000
--- a/agents/hacker/_context.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Hacker
-- agent specialized in cyber security and penetration testing
\ No newline at end of file
diff --git a/agents/hacker/agent.yaml b/agents/hacker/agent.yaml
new file mode 100644
index 0000000000..943eaac117
--- /dev/null
+++ b/agents/hacker/agent.yaml
@@ -0,0 +1,4 @@
+title: Hacker
+description: Agent specialized in cyber security and penetration testing.
+context: Use this agent for cybersecurity tasks such as penetration testing, vulnerability
+ analysis, and security auditing.
diff --git a/agents/researcher/_context.md b/agents/researcher/_context.md
deleted file mode 100644
index 3953f6cf1c..0000000000
--- a/agents/researcher/_context.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Researcher
-- agent specialized in research, data analysis and reporting
\ No newline at end of file
diff --git a/agents/researcher/agent.yaml b/agents/researcher/agent.yaml
new file mode 100644
index 0000000000..4b4f7df422
--- /dev/null
+++ b/agents/researcher/agent.yaml
@@ -0,0 +1,4 @@
+title: Researcher
+description: Agent specialized in research, data analysis and reporting.
+context: Use this agent for information gathering, data analysis, topic research,
+ and generating comprehensive reports.
diff --git a/conf/model_providers.yaml b/conf/model_providers.yaml
index e805376e3c..a116a18c38 100644
--- a/conf/model_providers.yaml
+++ b/conf/model_providers.yaml
@@ -18,10 +18,10 @@
chat:
a0_venice:
- name: Agent Zero Venice.ai
+ name: Agent Zero API
litellm_provider: openai
kwargs:
- api_base: https://api.agent-zero.ai/venice/v1
+ api_base: https://llm.agent-zero.ai/v1
venice_parameters:
include_venice_system_prompt: false
anthropic:
@@ -40,6 +40,7 @@ chat:
extra_headers:
"Editor-Version": "vscode/1.85.1"
"Copilot-Integration-Id": "vscode-chat"
+ "Copilot-Vision-Request": "true"
google:
name: Google
litellm_provider: gemini
@@ -55,6 +56,9 @@ chat:
mistral:
name: Mistral AI
litellm_provider: mistral
+ moonshot:
+ name: Moonshot AI
+ litellm_provider: moonshot
ollama:
name: Ollama
litellm_provider: ollama
@@ -64,6 +68,9 @@ chat:
azure:
name: OpenAI Azure
litellm_provider: azure
+ bedrock:
+ name: AWS Bedrock
+ litellm_provider: bedrock
openrouter:
name: OpenRouter
litellm_provider: openrouter
@@ -84,6 +91,16 @@ chat:
xai:
name: xAI
litellm_provider: xai
+ zai:
+ name: Z.AI
+ litellm_provider: openai
+ kwargs:
+ api_base: https://api.z.ai/api/paas/v4
+ zai_coding:
+ name: Z.AI Coding
+ litellm_provider: openai
+ kwargs:
+ api_base: https://api.z.ai/api/coding/paas/v4
other:
name: Other OpenAI compatible
litellm_provider: openai
@@ -110,6 +127,9 @@ embedding:
azure:
name: OpenAI Azure
litellm_provider: azure
+ bedrock:
+ name: AWS Bedrock
+ litellm_provider: bedrock
# TODO: OpenRouter not yet supported by LiteLLM, replace with native litellm_provider openrouter and remove api_base when ready
openrouter:
name: OpenRouter
diff --git a/conf/projects.default.gitignore b/conf/projects.default.gitignore
index 9a5f01f2ae..81caaed195 100644
--- a/conf/projects.default.gitignore
+++ b/conf/projects.default.gitignore
@@ -1,13 +1,10 @@
-# A0 project meta folder
-.a0proj/
-
# Python environments & cache
-venv/
-**/__pycache__/
+venv/**
+**/__pycache__/**
# Node.js dependencies
-**/node_modules/
-**/.npm/
+**/node_modules/**
+**/.npm/**
# Version control metadata
-**/.git/
+**/.git/**
diff --git a/conf/skill.default.gitignore b/conf/skill.default.gitignore
new file mode 100644
index 0000000000..e7c91367fe
--- /dev/null
+++ b/conf/skill.default.gitignore
@@ -0,0 +1,10 @@
+# Python environments & cache
+venv/
+**/__pycache__/
+
+# Node.js dependencies
+**/node_modules/
+**/.npm/
+
+# Version control metadata
+**/.git/
diff --git a/conf/workdir.gitignore b/conf/workdir.gitignore
new file mode 100644
index 0000000000..81caaed195
--- /dev/null
+++ b/conf/workdir.gitignore
@@ -0,0 +1,10 @@
+# Python environments & cache
+venv/**
+**/__pycache__/**
+
+# Node.js dependencies
+**/node_modules/**
+**/.npm/**
+
+# Version control metadata
+**/.git/**
diff --git a/docker/base/fs/etc/searxng/limiter.toml b/docker/base/fs/etc/searxng/limiter.toml
index 855521bef0..d5cddbc9f5 100644
--- a/docker/base/fs/etc/searxng/limiter.toml
+++ b/docker/base/fs/etc/searxng/limiter.toml
@@ -1,6 +1,6 @@
-[real_ip]
+[botdetection]
# Number of values to trust for X-Forwarded-For.
-x_for = 1
+trusted_proxies = ["127.0.0.1"]
# The prefix defines the number of leading bits in an address that are compared
# to determine whether or not an address is part of a (client) network.
diff --git a/docker/base/fs/etc/searxng/settings.yml b/docker/base/fs/etc/searxng/settings.yml
index 61ddae77f2..e9b079ac19 100644
--- a/docker/base/fs/etc/searxng/settings.yml
+++ b/docker/base/fs/etc/searxng/settings.yml
@@ -39,7 +39,7 @@ enabled_plugins:
- 'Hash plugin'
- 'Self Informations'
- 'Tracker URL remover'
- - 'Ahmia blacklist'
+ # - 'Ahmia blacklist'
# - 'Hostnames plugin' # see 'hostnames' configuration below
# - 'Open Access DOI rewrite'
@@ -59,6 +59,14 @@ enabled_plugins:
engines:
+ - name: ahmia
+ disabled: true
+ inactive: true
+
+ - name: torch
+ disabled: true
+ inactive: true
+
# - name: fdroid
# disabled: false
#
diff --git a/docker/base/fs/ins/install_python.sh b/docker/base/fs/ins/install_python.sh
index 82f2fc3832..417395ebcc 100644
--- a/docker/base/fs/ins/install_python.sh
+++ b/docker/base/fs/ins/install_python.sh
@@ -20,7 +20,7 @@ python3.13 -m venv /opt/venv
source /opt/venv/bin/activate
# upgrade pip and install static packages
-pip install --no-cache-dir --upgrade pip ipython requests
+pip install --no-cache-dir --upgrade pip pipx ipython requests
echo "====================PYTHON PYVENV===================="
diff --git a/docker/base/fs/ins/install_searxng2.sh b/docker/base/fs/ins/install_searxng2.sh
index 95023a5e2b..97e735fafd 100644
--- a/docker/base/fs/ins/install_searxng2.sh
+++ b/docker/base/fs/ins/install_searxng2.sh
@@ -23,11 +23,12 @@ source "/usr/local/searxng/searx-pyenv/bin/activate"
echo "====================SEARXNG2 INST===================="
# update pip's boilerplate
-pip install --no-cache-dir -U pip setuptools wheel pyyaml lxml
+pip install --no-cache-dir -U pip setuptools wheel pyyaml lxml msgspec typing_extensions
# jump to SearXNG's working tree and install SearXNG into virtualenv
cd "/usr/local/searxng/searxng-src"
-pip install --no-cache-dir --use-pep517 --no-build-isolation -e .
+# pip install --no-cache-dir --use-pep517 --no-build-isolation -e .
+pip install --no-cache-dir --use-pep517 --no-build-isolation .
# cleanup cache
pip cache purge
diff --git a/docker/run/Dockerfile b/docker/run/Dockerfile
index 8941daf8cc..f56d4f901f 100644
--- a/docker/run/Dockerfile
+++ b/docker/run/Dockerfile
@@ -1,5 +1,6 @@
# Use the pre-built base image for A0
# FROM agent-zero-base:local
+# FROM agent0ai/agent-zero-base:testing
FROM agent0ai/agent-zero-base:latest
# Check if the argument is provided, else throw an error
diff --git a/docker/run/fs/etc/searxng/limiter.toml b/docker/run/fs/etc/searxng/limiter.toml
index 855521bef0..d5cddbc9f5 100644
--- a/docker/run/fs/etc/searxng/limiter.toml
+++ b/docker/run/fs/etc/searxng/limiter.toml
@@ -1,6 +1,6 @@
-[real_ip]
+[botdetection]
# Number of values to trust for X-Forwarded-For.
-x_for = 1
+trusted_proxies = ["127.0.0.1"]
# The prefix defines the number of leading bits in an address that are compared
# to determine whether or not an address is part of a (client) network.
diff --git a/docker/run/fs/etc/searxng/settings.yml b/docker/run/fs/etc/searxng/settings.yml
index 147bee3f94..5d832097be 100644
--- a/docker/run/fs/etc/searxng/settings.yml
+++ b/docker/run/fs/etc/searxng/settings.yml
@@ -44,7 +44,7 @@ enabled_plugins:
- 'Hash plugin'
- 'Self Informations'
- 'Tracker URL remover'
- - 'Ahmia blacklist'
+ # - 'Ahmia blacklist'
# - 'Hostnames plugin' # see 'hostnames' configuration below
# - 'Open Access DOI rewrite'
@@ -67,6 +67,14 @@ engines:
engine: radio_browser
disabled: true
inactive: true
+
+ - name: ahmia
+ disabled: true
+ inactive: true
+
+ - name: torch
+ disabled: true
+ inactive: true
# TODO enable radio_browser when it works again
# currently it crashes on x86 on gethostbyaddr
diff --git a/docs/README.md b/docs/README.md
index b522ed0c61..38d476c9fa 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,68 +1,122 @@

# Agent Zero Documentation
-To begin with Agent Zero, follow the links below for detailed guides on various topics:
-- **[Installation](installation.md):** Set up (or [update](installation.md#how-to-update-agent-zero)) Agent Zero on your system.
-- **[Usage Guide](usage.md):** Explore GUI features and usage scenarios.
-- **[Development](development.md):** Set up a development environment for Agent Zero.
-- **[Extensibility](extensibility.md):** Learn how to create custom extensions for Agent Zero.
-- **[Connectivity](connectivity.md):** Learn how to connect to Agent Zero from other applications.
-- **[Architecture Overview](architecture.md):** Understand the internal workings of the framework.
-- **[Contributing](contribution.md):** Learn how to contribute to the Agent Zero project.
-- **[Troubleshooting and FAQ](troubleshooting.md):** Find answers to common issues and questions.
+Welcome to the Agent Zero documentation hub. Whether you're getting started or diving deep into the framework, you'll find comprehensive guides below.
-### Your experience with Agent Zero starts now!
+## Quick Start
-- **Download Agent Zero:** Follow the [installation guide](installation.md) to download and run Agent Zero.
-- **Join the Community:** Join the Agent Zero [Skool](https://www.skool.com/agent-zero) or [Discord](https://discord.gg/B8KZKNsPpj) community to discuss ideas, ask questions, and collaborate with other contributors.
-- **Share your Work:** Share your Agent Zero creations, workflows and discoverings on our [Show and Tell](https://github.com/agent0ai/agent-zero/discussions/categories/show-and-tell) area on GitHub.
-- **Report Issues:** Use the [GitHub issue tracker](https://github.com/agent0ai/agent-zero/issues) to report framework-relative bugs or suggest new features.
+- **[Quickstart Guide](quickstart.md):** Get up and running in 5 minutes with Agent Zero.
+- **[Installation Guide](setup/installation.md):** Detailed setup instructions for all platforms (or [update your installation](setup/installation.md#how-to-update-agent-zero)).
+- **[VPS Deployment](setup/vps-deployment.md):** Deploy Agent Zero on a remote server.
+- **[Development Setup](setup/dev-setup.md):** Set up a local development environment.
+
+## User Guides
+
+- **[Usage Guide](guides/usage.md):** Comprehensive guide to Agent Zero's features and capabilities.
+- **[Projects Tutorial](guides/projects.md):** Learn to create isolated workspaces with dedicated context and memory.
+- **[API Integration](guides/api-integration.md):** Add external APIs without writing code.
+- **[MCP Setup](guides/mcp-setup.md):** Configure Model Context Protocol servers.
+- **[A2A Setup](guides/a2a-setup.md):** Enable agent-to-agent communication.
+- **[Troubleshooting](guides/troubleshooting.md):** Solutions to common issues and FAQs.
+
+## Developer Documentation
+
+- **[Architecture Overview](developer/architecture.md):** Understand Agent Zero's internal structure and components.
+- **[Plugins](developer/plugins.md):** Build plugins with `plugin.yaml`, scoped settings, and activation toggles.
+- **[Extensions](developer/extensions.md):** Create custom extensions to extend functionality.
+- **[Connectivity](developer/connectivity.md):** Connect to Agent Zero from external applications.
+- **[WebSockets](developer/websockets.md):** Real-time communication infrastructure.
+- **[MCP Configuration](developer/mcp-configuration.md):** Advanced MCP server configuration.
+- **[Notifications](developer/notifications.md):** Notification system architecture and setup.
+- **[Contributing Skills](developer/contributing-skills.md):** Create and share agent skills.
+- **[Contributing Guide](guides/contribution.md):** Contribute to the Agent Zero project.
+
+## Community & Support
+
+- **Join the Community:** Connect with other users on [Discord](https://discord.gg/B8KZKNsPpj) to discuss ideas, ask questions, and collaborate.
+- **Share Your Work:** Show off your Agent Zero creations and workflows in the [Show and Tell](https://github.com/agent0ai/agent-zero/discussions/categories/show-and-tell) area.
+- **Report Issues:** Use the [GitHub issue tracker](https://github.com/agent0ai/agent-zero/issues) to report bugs or suggest features.
+- **Follow Updates:** Subscribe to the [YouTube channel](https://www.youtube.com/@AgentZeroFW) for tutorials and release videos.
+
+---
## Table of Contents
-- [Welcome to the Agent Zero Documentation](#agent-zero-documentation)
- - [Your Experience with Agent Zero](#your-experience-with-agent-zero-starts-now)
- - [Table of Contents](#table-of-contents)
-- [Installation Guide](installation.md)
- - [Windows, macOS and Linux Setup](installation.md#windows-macos-and-linux-setup-guide)
- - [Settings Configuration](installation.md#settings-configuration)
- - [Choosing Your LLMs](installation.md#choosing-your-llms)
- - [Installing and Using Ollama](installation.md#installing-and-using-ollama-local-models)
- - [Using Agent Zero on Mobile](installation.md#using-agent-zero-on-your-mobile-device)
- - [How to Update Agent Zero](installation.md#how-to-update-agent-zero)
- - [Full Binaries Installation](installation.md#in-depth-guide-for-full-binaries-installation)
-- [Usage Guide](usage.md)
- - [Basic Operations](usage.md#basic-operations)
- - [Restart Framework](usage.md#restart-framework)
- - [Action Buttons](usage.md#action-buttons)
- - [File Attachments](usage.md#file-attachments)
- - [Tool Usage](usage.md#tool-usage)
- - [Example of Tools Usage](usage.md#example-of-tools-usage-web-search-and-code-execution)
- - [Multi-Agent Cooperation](usage.md#multi-agent-cooperation)
- - [Prompt Engineering](usage.md#prompt-engineering)
- - [Voice Interface](usage.md#voice-interface)
- - [Mathematical Expressions](usage.md#mathematical-expressions)
- - [File Browser](usage.md#file-browser)
- - [Backup & Restore](usage.md#backup--restore)
-- [Architecture Overview](architecture.md)
- - [System Architecture](architecture.md#system-architecture)
- - [Runtime Architecture](architecture.md#runtime-architecture)
- - [Implementation Details](architecture.md#implementation-details)
- - [Core Components](architecture.md#core-components)
- - [Agents](architecture.md#1-agents)
- - [Tools](architecture.md#2-tools)
- - [SearXNG Integration](architecture.md#searxng-integration)
- - [Memory System](architecture.md#3-memory-system)
- - [Messages History and Summarization](archicture.md#messages-history-and-summarization)
- - [Prompts](architecture.md#4-prompts)
- - [Knowledge](architecture.md#5-knowledge)
- - [Instruments](architecture.md#6-instruments)
- - [Extensions](architecture.md#7-extensions)
- - [Contributing](contribution.md)
- - [Getting Started](contribution.md#getting-started)
- - [Making Changes](contribution.md#making-changes)
- - [Submitting a Pull Request](contribution.md#submitting-a-pull-request)
- - [Documentation Stack](contribution.md#documentation-stack)
-- [Troubleshooting and FAQ](troubleshooting.md)
- - [Frequently Asked Questions](troubleshooting.md#frequently-asked-questions)
- - [Troubleshooting](troubleshooting.md#troubleshooting)
+- [Quick Start](#quick-start)
+ - [Quickstart Guide](quickstart.md)
+ - [Installation Guide](setup/installation.md)
+ - [Step 1: Install Docker Desktop](setup/installation.md#step-1-install-docker-desktop)
+ - [Windows Installation](setup/installation.md#-windows-installation)
+ - [macOS Installation](setup/installation.md#-macos-installation)
+ - [Linux Installation](setup/installation.md#-linux-installation)
+ - [Step 2: Run Agent Zero](setup/installation.md#step-2-run-agent-zero)
+ - [Pull Docker Image](setup/installation.md#21-pull-the-agent-zero-docker-image)
+ - [Map Folders for Persistence](setup/installation.md#22-optional-map-folders-for-persistence)
+ - [Run the Container](setup/installation.md#23-run-the-container)
+ - [Access the Web UI](setup/installation.md#24-access-the-web-ui)
+ - [Step 3: Configure Agent Zero](setup/installation.md#step-3-configure-agent-zero)
+ - [Settings Configuration](setup/installation.md#settings-configuration)
+ - [Agent Configuration](setup/installation.md#agent-configuration)
+ - [Chat Model Settings](setup/installation.md#chat-model-settings)
+ - [API Keys](setup/installation.md#api-keys)
+ - [Authentication](setup/installation.md#authentication)
+ - [Choosing Your LLMs](setup/installation.md#choosing-your-llms)
+ - [Installing Ollama (Local Models)](setup/installation.md#installing-and-using-ollama-local-models)
+ - [Using on Mobile Devices](setup/installation.md#using-agent-zero-on-your-mobile-device)
+ - [How to Update Agent Zero](setup/installation.md#how-to-update-agent-zero)
+ - [VPS Deployment](setup/vps-deployment.md)
+ - [Development Setup](setup/dev-setup.md)
+
+- [User Guides](#user-guides)
+ - [Usage Guide](guides/usage.md)
+ - [Basic Operations](guides/usage.md#basic-operations)
+ - [Tool Usage](guides/usage.md#tool-usage)
+ - [Projects](guides/usage.md#projects)
+ - [What Projects Provide](guides/usage.md#what-projects-provide)
+ - [Creating Projects](guides/usage.md#creating-projects)
+ - [Project Configuration](guides/usage.md#project-configuration)
+ - [Activating Projects](guides/usage.md#activating-projects)
+ - [Common Use Cases](guides/usage.md#common-use-cases)
+ - [Tasks & Scheduling](guides/usage.md#tasks--scheduling)
+ - [Task Types](guides/usage.md#task-types)
+ - [Creating Tasks](guides/usage.md#creating-tasks)
+ - [Task Configuration](guides/usage.md#task-configuration)
+ - [Integration with Projects](guides/usage.md#integration-with-projects)
+ - [Secrets & Variables](guides/usage.md#secrets--variables)
+ - [Remote Access via Tunneling](guides/usage.md#remote-access-via-tunneling)
+ - [Voice Interface](guides/usage.md#voice-interface)
+ - [Memory Management](guides/usage.md#memory-management)
+ - [Backup & Restore](guides/usage.md#backup--restore)
+ - [Projects Tutorial](guides/projects.md)
+ - [API Integration](guides/api-integration.md)
+ - [MCP Setup](guides/mcp-setup.md)
+ - [A2A Setup](guides/a2a-setup.md)
+ - [Troubleshooting](guides/troubleshooting.md)
+
+- [Developer Documentation](#developer-documentation)
+ - [Architecture Overview](developer/architecture.md)
+ - [System Architecture](developer/architecture.md#system-architecture)
+ - [Runtime Architecture](developer/architecture.md#runtime-architecture)
+ - [Implementation Details](developer/architecture.md#implementation-details)
+ - [Core Components](developer/architecture.md#core-components)
+ - [Agents](developer/architecture.md#1-agents)
+ - [Tools](developer/architecture.md#2-tools)
+ - [Memory System](developer/architecture.md#3-memory-system)
+ - [Prompts](developer/architecture.md#4-prompts)
+ - [Knowledge](developer/architecture.md#5-knowledge)
+ - [Skills](developer/architecture.md#6-skills)
+ - [Extensions](developer/architecture.md#7-extensions)
+ - [Plugins](developer/plugins.md)
+ - [Extensions](developer/extensions.md)
+ - [Connectivity](developer/connectivity.md)
+ - [WebSockets](developer/websockets.md)
+ - [MCP Configuration](developer/mcp-configuration.md)
+ - [Notifications](developer/notifications.md)
+ - [Contributing Skills](developer/contributing-skills.md)
+ - [Contributing Guide](guides/contribution.md)
+
+---
+
+### Your journey with Agent Zero starts now!
+
+Ready to dive in? Start with the [Quickstart Guide](quickstart.md) for the fastest path to your first chat, or follow the [Installation Guide](setup/installation.md) for a detailed setup walkthrough.
diff --git a/docs/agents/AGENTS.components.md b/docs/agents/AGENTS.components.md
new file mode 100644
index 0000000000..31d564609a
--- /dev/null
+++ b/docs/agents/AGENTS.components.md
@@ -0,0 +1,648 @@
+# Agent Zero Component System
+
+> Generated from codebase reconnaissance on 2026-01-10
+> Scope: `webui/components/` - Self-contained Alpine.js component architecture
+
+## Quick Reference
+
+| Aspect | Value |
+|--------|-------|
+| Tech Stack | Alpine.js, ES Modules, CSS Variables |
+| Component Tag | `` |
+| State Management | `createStore(name, model)` from `/js/AlpineStore.js` |
+| Modals | `openModal(path)` / `closeModal()` from `/js/modals.js` |
+| API Layer | `callJsonApi()` / `fetchApi()` from `/js/api.js` |
+
+---
+
+## Table of Contents
+
+1. [Architecture Overview](#1-architecture-overview)
+2. [Component Structure](#2-component-structure)
+3. [Store Pattern](#3-store-pattern)
+4. [Lifecycle Management](#4-lifecycle-management)
+5. [Integration Layer](#5-integration-layer)
+6. [Alpine.js Directives](#6-alpinejs-directives)
+7. [Patterns and Conventions](#7-patterns-and-conventions)
+8. [Pitfalls and Anti-Patterns](#8-pitfalls-and-anti-patterns)
+9. [Porting Guide](#9-porting-guide)
+
+---
+
+## 1. Architecture Overview
+
+### Core Files (Integration Layer)
+
+| File | Purpose |
+|------|---------|
+| `/js/components.js` | Component loader - hydrates `` tags |
+| `/js/AlpineStore.js` | Store factory with Alpine proxy |
+| `/js/modals.js` | Modal stack management |
+| `/js/initFw.js` | Bootstrap: loads Alpine, registers custom directives |
+| `/js/api.js` | CSRF-protected API client (`callJsonApi`, `fetchApi`) |
+
+### Component Resolution
+
+```
+
+ ↓
+ Resolves to: components/sidebar/left-sidebar.html
+ ↓
+ Loader: importComponent() fetches, parses, injects
+```
+
+- Path auto-prefixes `components/` if not present
+- Component HTML cached after first fetch
+- Module scripts cached by virtual URL
+- MutationObserver auto-loads dynamically inserted components
+
+### Data Flow
+
+```
+Component HTML
+ ↓
+imports Store module
+ ↓
+createStore() registers with Alpine
+ ↓
+Template binds via $store.name
+ ↓
+User actions → store methods → state updates → reactive UI
+```
+
+---
+
+## 2. Component Structure
+
+### Anatomy of a Component
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Key Rules
+
+| Rule | Rationale |
+|------|-----------|
+| Scripts in ``, content in `` | Loader extracts separately |
+| Use `type="module"` for scripts | Enables ES imports, caching |
+| Wrap with `x-data` + `x-if="$store.X"` | Prevents render before store ready |
+| `` has ONE root element | Alpine limitation |
+| Styles inline in component | Self-contained, no global CSS files |
+
+### Nesting Components
+
+```html
+
+
+
+```
+
+Components can nest other components. Loader recursively processes `x-component` tags.
+
+---
+
+## 3. Store Pattern
+
+### Creating a Store
+
+```javascript
+// /components/feature/feature-store.js
+import { createStore } from "/js/AlpineStore.js";
+
+const model = {
+ // State
+ items: [],
+ loading: false,
+ _initialized: false,
+
+ // Lifecycle (called once by Alpine when store registers)
+ init() {
+ if (this._initialized) return;
+ this._initialized = true;
+ this.load();
+ },
+
+ // Actions
+ async load() {
+ this.loading = true;
+ // ... fetch data
+ this.loading = false;
+ },
+
+ // Computed-like getters (Alpine reactivity works)
+ get itemCount() {
+ return this.items.length;
+ }
+};
+
+export const store = createStore("featureStore", model);
+```
+
+### Store Proxy Behavior
+
+`createStore()` returns a proxy that:
+- Before Alpine boots: reads/writes directly to `model` object
+- After Alpine boots: reads/writes through `Alpine.store(name)`
+
+This enables safe module-level initialization before Alpine loads.
+
+### Store Access
+
+| Context | Syntax |
+|---------|--------|
+| Template (Alpine) | `$store.featureStore.prop` |
+| Module import | `import { store } from "./feature-store.js"; store.prop` |
+| Global (avoid) | `Alpine.store("featureStore").prop` |
+
+Prefer module imports over global lookups.
+
+### Persistence Helpers
+
+```javascript
+import { saveState, loadState } from "/js/AlpineStore.js";
+
+// Save to localStorage (exclude functions automatically)
+const snapshot = saveState(store, [], ["transientField"]);
+localStorage.setItem("myStore", JSON.stringify(snapshot));
+
+// Restore
+const saved = JSON.parse(localStorage.getItem("myStore"));
+loadState(store, saved);
+```
+
+---
+
+## 4. Lifecycle Management
+
+### Custom Alpine Directives
+
+Registered in `/js/initFw.js`:
+
+| Directive | When Fires | Use Case |
+|-----------|------------|----------|
+| `x-create` | Once on mount | Initialize, subscribe to events |
+| `x-destroy` | On unmount/cleanup | Unsubscribe, clear timers |
+| `x-every-second` | Every 1s while mounted | Polling, countdowns |
+| `x-every-minute` | Every 60s while mounted | Low-frequency updates |
+| `x-every-hour` | Every 3600s while mounted | Rare periodic tasks |
+
+### Usage Pattern
+
+```html
+
+
+
+```
+
+### Store Lifecycle Pattern
+
+```javascript
+const model = {
+ _initialized: false,
+ resizeHandler: null,
+
+ init() {
+ // Guard: runs only once per app lifetime
+ if (this._initialized) return;
+ this._initialized = true;
+ // Global setup: event listeners, intervals
+ this.resizeHandler = () => this.handleResize();
+ window.addEventListener("resize", this.resizeHandler);
+ },
+
+ // Called via x-create when component mounts (can run multiple times)
+ onOpen() {
+ this.loadData();
+ },
+
+ // Called via x-destroy when component unmounts
+ cleanup() {
+ // Clear component-specific state, not global listeners
+ },
+
+ // For full teardown (rarely needed)
+ destroy() {
+ if (this.resizeHandler) {
+ window.removeEventListener("resize", this.resizeHandler);
+ this.resizeHandler = null;
+ }
+ this._initialized = false;
+ }
+};
+```
+
+Key distinction:
+- `init()` → once per app load (store registration)
+- `onOpen()` → each time component mounts (modal opens, etc.)
+- `cleanup()`/`destroy()` → teardown resources
+
+---
+
+## 5. Integration Layer
+
+### API Calls
+
+```javascript
+import { callJsonApi, fetchApi } from "/js/api.js";
+
+// JSON POST with CSRF
+const result = await callJsonApi("/endpoint", { key: "value" });
+
+// Raw fetch with CSRF
+const response = await fetchApi("/endpoint", {
+ method: "GET",
+ headers: { "Accept": "application/json" }
+});
+```
+
+- `callJsonApi`: JSON-in, JSON-out, throws on non-2xx
+- `fetchApi`: Adds CSRF header, handles 403 retry, redirects to `/login`
+
+### Modals
+
+```javascript
+import { openModal, closeModal } from "/js/modals.js";
+
+// Open (returns Promise that resolves when modal closes)
+await openModal("feature/feature-modal.html");
+
+// Close topmost modal
+closeModal();
+
+// Close specific modal by path
+closeModal("feature/feature-modal.html");
+```
+
+Modal component receives title from `` tag:
+```html
+
+ My Modal Title
+
+```
+
+Modal footer (outside scroll area):
+```html
+
+```
+
+Always gate components that depend on stores. Prevents errors during initial load race.
+
+---
+
+## 7. Patterns and Conventions
+
+### ✅ DO
+
+| Pattern | Example |
+|---------|---------|
+| Self-contained components | All HTML/CSS/JS in one component folder |
+| Module imports with absolute paths | `import { store } from "/components/..."` |
+| CSS variables for theming | `color: var(--color-text)` |
+| Guard `init()` with `_initialized` | Prevents duplicate setup |
+| Use `display: contents` for flex chains | Wrapper doesn't break parent flex |
+| Inline component styles | `
-
-
-```
-
-### 4. Restore Modal Component
-
-#### File: `webui/components/settings/backup/restore.html`
-```html
-
-
- Restore Backup
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Restore Configuration JSON
-
-
-
-
-
-
-
-
-
-
-
File Operations
-
-
-
-
-
-
-
-
-
File Conflict Policy
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Restore Complete
-
-
Restored:
-
Skipped:
-
Errors:
-
-
-
-
-
-
-
-
-
-
-```
-
-### 5. Store Implementation
-
-#### File: `webui/components/settings/backup/backup-store.js`
-```javascript
-import { createStore } from "/js/AlpineStore.js";
-
-// ⚠️ CRITICAL: The .env file contains API keys and essential configuration.
-// This file is REQUIRED for Agent Zero to function and must be backed up.
-// Note: Patterns now use resolved absolute paths (e.g., /home/user/a0/data/.env)
-
-const model = {
- // State
- mode: 'backup', // 'backup' or 'restore'
- loading: false,
- loadingMessage: '',
- error: '',
-
- // File operations log (shared between backup and restore)
- fileOperationsLog: '',
-
- // Backup state
- backupMetadataConfig: null,
- includeHidden: false,
- previewStats: { total: 0, truncated: false },
- backupEditor: null,
-
- // Enhanced file preview state
- previewMode: 'grouped', // 'grouped' or 'flat'
- previewFiles: [],
- previewGroups: [],
- filteredPreviewFiles: [],
- fileSearchFilter: '',
- expandedGroups: new Set(),
-
- // Progress state
- progressData: null,
- progressEventSource: null,
-
- // Restore state
- backupFile: null,
- backupMetadata: null,
- restorePatterns: '',
- overwritePolicy: 'overwrite',
- restoreEditor: null,
- restoreResult: null,
-
- // Initialization
- async initBackup() {
- this.mode = 'backup';
- this.resetState();
- await this.initBackupEditor();
- await this.updatePreview();
- },
-
- async initRestore() {
- this.mode = 'restore';
- this.resetState();
- await this.initRestoreEditor();
- },
-
- resetState() {
- this.loading = false;
- this.error = '';
- this.backupFile = null;
- this.backupMetadata = null;
- this.restoreResult = null;
- this.fileOperationsLog = '';
- },
-
- // File operations logging
- addFileOperation(message) {
- const timestamp = new Date().toLocaleTimeString();
- this.fileOperationsLog += `[${timestamp}] ${message}\n`;
-
- // Auto-scroll to bottom
- this.$nextTick(() => {
- const textarea = document.getElementById(this.mode === 'backup' ? 'backup-file-list' : 'restore-file-list');
- if (textarea) {
- textarea.scrollTop = textarea.scrollHeight;
- }
- });
- },
-
- clearFileOperations() {
- this.fileOperationsLog = '';
- },
-
- // Cleanup method for modal close
- onClose() {
- this.resetState();
- if (this.backupEditor) {
- this.backupEditor.destroy();
- this.backupEditor = null;
- }
- if (this.restoreEditor) {
- this.restoreEditor.destroy();
- this.restoreEditor = null;
- }
- },
-
- // Get default backup metadata with resolved patterns from backend
- async getDefaultBackupMetadata() {
- const timestamp = new Date().toISOString();
-
- try {
- // Get resolved default patterns from backend
- const response = await sendJsonData("backup_get_defaults", {});
-
- if (response.success) {
- // Use patterns from backend with resolved absolute paths
- const include_patterns = response.default_patterns.include_patterns;
- const exclude_patterns = response.default_patterns.exclude_patterns;
-
- return {
- backup_name: `agent-zero-backup-${timestamp.slice(0, 10)}`,
- include_hidden: false,
- include_patterns: include_patterns,
- exclude_patterns: exclude_patterns,
- backup_config: {
- compression_level: 6,
- integrity_check: true
- }
- };
- }
- } catch (error) {
- console.warn("Failed to get default patterns from backend, using fallback");
- }
-
- // Fallback patterns (will be overridden by backend on first use)
- return {
- backup_name: `agent-zero-backup-${timestamp.slice(0, 10)}`,
- include_hidden: false,
- include_patterns: [
- // These will be replaced with resolved absolute paths by backend
- "# Loading default patterns from backend..."
- ],
- exclude_patterns: [],
- backup_config: {
- compression_level: 6,
- integrity_check: true
- }
- };
- },
-
- // Editor Management - Following Agent Zero ACE editor patterns
- async initBackupEditor() {
- const container = document.getElementById("backup-metadata-editor");
- if (container) {
- const editor = ace.edit("backup-metadata-editor");
-
- const dark = localStorage.getItem("darkMode");
- if (dark != "false") {
- editor.setTheme("ace/theme/github_dark");
- } else {
- editor.setTheme("ace/theme/tomorrow");
- }
-
- editor.session.setMode("ace/mode/json");
-
- // Initialize with default backup metadata
- const defaultMetadata = this.getDefaultBackupMetadata();
- editor.setValue(JSON.stringify(defaultMetadata, null, 2));
- editor.clearSelection();
-
- // Auto-update preview on changes (debounced)
- let timeout;
- editor.on('change', () => {
- clearTimeout(timeout);
- timeout = setTimeout(() => {
- this.updatePreview();
- }, 1000);
- });
-
- this.backupEditor = editor;
- }
- },
-
- async initRestoreEditor() {
- const container = document.getElementById("restore-metadata-editor");
- if (container) {
- const editor = ace.edit("restore-metadata-editor");
-
- const dark = localStorage.getItem("darkMode");
- if (dark != "false") {
- editor.setTheme("ace/theme/github_dark");
- } else {
- editor.setTheme("ace/theme/tomorrow");
- }
-
- editor.session.setMode("ace/mode/json");
- editor.setValue('{}');
- editor.clearSelection();
-
- // Auto-validate JSON on changes
- editor.on('change', () => {
- this.validateRestoreMetadata();
- });
-
- this.restoreEditor = editor;
- }
- },
-
- // ACE Editor utility methods - Following MCP servers pattern
- // Unified editor value getter (following MCP servers pattern)
- getEditorValue() {
- const editor = this.mode === 'backup' ? this.backupEditor : this.restoreEditor;
- return editor ? editor.getValue() : '{}';
- },
-
- // Unified JSON formatting (following MCP servers pattern)
- formatJson() {
- const editor = this.mode === 'backup' ? this.backupEditor : this.restoreEditor;
- if (!editor) return;
-
- try {
- const currentContent = editor.getValue();
- const parsed = JSON.parse(currentContent);
- const formatted = JSON.stringify(parsed, null, 2);
-
- editor.setValue(formatted);
- editor.clearSelection();
- editor.navigateFileStart();
- } catch (error) {
- console.error("Failed to format JSON:", error);
- this.error = "Invalid JSON: " + error.message;
- }
- },
-
- // Enhanced File Preview Operations
- async updatePreview() {
- try {
- const metadataText = this.getEditorValue();
- const metadata = JSON.parse(metadataText);
-
- if (!metadata.include_patterns || metadata.include_patterns.length === 0) {
- this.previewStats = { total: 0, truncated: false };
- this.previewFiles = [];
- this.previewGroups = [];
- return;
- }
-
- // Convert patterns arrays back to string format for API
- const patternsString = this.convertPatternsToString(metadata.include_patterns, metadata.exclude_patterns);
-
- // Get grouped preview for better UX
- const response = await sendJsonData("backup_preview_grouped", {
- patterns: patternsString,
- include_hidden: metadata.include_hidden || false,
- max_depth: 3,
- search_filter: this.fileSearchFilter
- });
-
- if (response.success) {
- this.previewGroups = response.groups;
- this.previewStats = response.stats;
-
- // Flatten groups for flat view
- this.previewFiles = [];
- response.groups.forEach(group => {
- this.previewFiles.push(...group.files);
- });
-
- this.applyFileSearch();
- } else {
- this.error = response.error;
- }
- } catch (error) {
- this.error = `Preview error: ${error.message}`;
- }
- },
-
- // Convert pattern arrays to string format for backend API
- convertPatternsToString(includePatterns, excludePatterns) {
- const patterns = [];
-
- // Add include patterns
- if (includePatterns) {
- patterns.push(...includePatterns);
- }
-
- // Add exclude patterns with '!' prefix
- if (excludePatterns) {
- excludePatterns.forEach(pattern => {
- patterns.push(`!${pattern}`);
- });
- }
-
- return patterns.join('\n');
- },
-
- // Validation for backup metadata
- validateBackupMetadata() {
- try {
- const metadataText = this.getEditorValue();
- const metadata = JSON.parse(metadataText);
-
- // Validate required fields
- if (!Array.isArray(metadata.include_patterns)) {
- throw new Error('include_patterns must be an array');
- }
- if (!Array.isArray(metadata.exclude_patterns)) {
- throw new Error('exclude_patterns must be an array');
- }
- if (!metadata.backup_name || typeof metadata.backup_name !== 'string') {
- throw new Error('backup_name must be a non-empty string');
- }
-
- this.backupMetadataConfig = metadata;
- this.error = '';
- return true;
- } catch (error) {
- this.error = `Invalid backup metadata: ${error.message}`;
- return false;
- }
- },
-
- // File Preview UI Management
- initFilePreview() {
- this.fileSearchFilter = '';
- this.expandedGroups.clear();
- this.previewMode = localStorage.getItem('backupPreviewMode') || 'grouped';
- },
-
- togglePreviewMode() {
- this.previewMode = this.previewMode === 'grouped' ? 'flat' : 'grouped';
- localStorage.setItem('backupPreviewMode', this.previewMode);
- },
-
- toggleGroup(groupPath) {
- if (this.expandedGroups.has(groupPath)) {
- this.expandedGroups.delete(groupPath);
- } else {
- this.expandedGroups.add(groupPath);
- }
- },
-
- isGroupExpanded(groupPath) {
- return this.expandedGroups.has(groupPath);
- },
-
- debounceFileSearch() {
- clearTimeout(this.searchTimeout);
- this.searchTimeout = setTimeout(() => {
- this.applyFileSearch();
- }, 300);
- },
-
- clearFileSearch() {
- this.fileSearchFilter = '';
- this.applyFileSearch();
- },
-
- applyFileSearch() {
- if (!this.fileSearchFilter.trim()) {
- this.filteredPreviewFiles = this.previewFiles;
- } else {
- const search = this.fileSearchFilter.toLowerCase();
- this.filteredPreviewFiles = this.previewFiles.filter(file =>
- file.path.toLowerCase().includes(search)
- );
- }
- },
-
- async exportFileList() {
- const fileList = this.previewFiles.map(f => f.path).join('\n');
- const blob = new Blob([fileList], { type: 'text/plain' });
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = 'backup-file-list.txt';
- a.click();
- URL.revokeObjectURL(url);
- },
-
- async copyFileListToClipboard() {
- const fileList = this.previewFiles.map(f => f.path).join('\n');
- try {
- await navigator.clipboard.writeText(fileList);
- toast('File list copied to clipboard', 'success');
- } catch (error) {
- toast('Failed to copy to clipboard', 'error');
- }
- },
-
- async showFilePreview() {
- // Validate backup metadata first
- if (!this.validateBackupMetadata()) {
- return;
- }
-
- try {
- this.loading = true;
- this.loadingMessage = 'Generating file preview...';
-
- const metadata = this.backupMetadataConfig;
- const patternsString = this.convertPatternsToString(metadata.include_patterns, metadata.exclude_patterns);
-
- const response = await sendJsonData("backup_test", {
- patterns: patternsString,
- include_hidden: metadata.include_hidden || false,
- max_files: 1000
- });
-
- if (response.success) {
- // Store preview data for file preview modal
- this.previewFiles = response.files;
- openModal('backup/file-preview.html');
- } else {
- this.error = response.error;
- }
- } catch (error) {
- this.error = `Preview error: ${error.message}`;
- } finally {
- this.loading = false;
- }
- },
-
- // Real-time Backup with Progress Streaming
- async createBackup() {
- // Validate backup metadata first
- if (!this.validateBackupMetadata()) {
- return;
- }
-
- try {
- this.loading = true;
- this.error = '';
- this.clearFileOperations();
- this.addFileOperation('Starting backup creation...');
-
- const metadata = this.backupMetadataConfig;
- const patternsString = this.convertPatternsToString(metadata.include_patterns, metadata.exclude_patterns);
-
- // Start real-time progress streaming
- const eventSource = new EventSource(`/backup_progress_stream?` + new URLSearchParams({
- patterns: patternsString,
- include_hidden: metadata.include_hidden || false,
- backup_name: metadata.backup_name
- }));
-
- this.progressEventSource = eventSource;
-
- eventSource.onmessage = (event) => {
- const data = JSON.parse(event.data);
-
- // Log file operations
- if (data.file_path) {
- this.addFileOperation(`Adding: ${data.file_path}`);
- } else if (data.message) {
- this.addFileOperation(data.message);
- }
-
- if (data.completed) {
- eventSource.close();
- this.progressEventSource = null;
-
- if (data.success) {
- this.addFileOperation(`Backup completed successfully: ${data.total_files} files, ${this.formatFileSize(data.backup_size)}`);
- // Download the completed backup
- this.downloadBackup(data.backup_path, metadata.backup_name);
- toast('Backup created successfully', 'success');
- } else if (data.error) {
- this.error = data.message || 'Backup creation failed';
- this.addFileOperation(`Error: ${this.error}`);
- }
-
- this.loading = false;
- } else {
- this.loadingMessage = data.message || 'Processing...';
- }
- };
-
- eventSource.onerror = (error) => {
- eventSource.close();
- this.progressEventSource = null;
- this.loading = false;
- this.error = 'Connection error during backup creation';
- this.addFileOperation(`Error: ${this.error}`);
- };
-
- } catch (error) {
- this.error = `Backup error: ${error.message}`;
- this.addFileOperation(`Error: ${error.message}`);
- this.loading = false;
- }
- },
-
- async downloadBackup(backupPath, backupName) {
- try {
- const response = await fetch('/backup_download', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ backup_path: backupPath })
- });
-
- if (response.ok) {
- const blob = await response.blob();
- const url = globalThis.URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = `${backupName}.zip`;
- a.click();
- globalThis.URL.revokeObjectURL(url);
- }
- } catch (error) {
- console.error('Download error:', error);
- }
- },
-
- cancelBackup() {
- if (this.progressEventSource) {
- this.progressEventSource.close();
- this.progressEventSource = null;
- }
- this.loading = false;
- this.progressData = null;
- },
-
- resetToDefaults() {
- const defaultMetadata = this.getDefaultBackupMetadata();
- if (this.backupEditor) {
- this.backupEditor.setValue(JSON.stringify(defaultMetadata, null, 2));
- this.backupEditor.clearSelection();
- }
- this.updatePreview();
- },
-
- // Dry run functionality
- async dryRun() {
- if (this.mode === 'backup') {
- await this.dryRunBackup();
- } else if (this.mode === 'restore') {
- await this.dryRunRestore();
- }
- },
-
- async dryRunBackup() {
- // Validate backup metadata first
- if (!this.validateBackupMetadata()) {
- return;
- }
-
- try {
- this.loading = true;
- this.loadingMessage = 'Performing dry run...';
- this.clearFileOperations();
- this.addFileOperation('Starting backup dry run...');
-
- const metadata = this.backupMetadataConfig;
- const patternsString = this.convertPatternsToString(metadata.include_patterns, metadata.exclude_patterns);
-
- const response = await sendJsonData("backup_test", {
- patterns: patternsString,
- include_hidden: metadata.include_hidden || false,
- max_files: 10000
- });
-
- if (response.success) {
- this.addFileOperation(`Found ${response.files.length} files that would be backed up:`);
- response.files.forEach((file, index) => {
- this.addFileOperation(`${index + 1}. ${file.path} (${this.formatFileSize(file.size)})`);
- });
- this.addFileOperation(`\nTotal: ${response.files.length} files, ${this.formatFileSize(response.files.reduce((sum, f) => sum + f.size, 0))}`);
- this.addFileOperation('Dry run completed successfully.');
- } else {
- this.error = response.error;
- this.addFileOperation(`Error: ${response.error}`);
- }
- } catch (error) {
- this.error = `Dry run error: ${error.message}`;
- this.addFileOperation(`Error: ${error.message}`);
- } finally {
- this.loading = false;
- }
- },
-
- async dryRunRestore() {
- if (!this.backupFile) {
- this.error = 'Please select a backup file first';
- return;
- }
-
- try {
- this.loading = true;
- this.loadingMessage = 'Performing restore dry run...';
- this.clearFileOperations();
- this.addFileOperation('Starting restore dry run...');
-
- const formData = new FormData();
- formData.append('backup_file', this.backupFile);
- formData.append('restore_patterns', this.getEditorValue());
-
- const response = await fetch('/backup_restore_preview', {
- method: 'POST',
- body: formData
- });
-
- const result = await response.json();
-
- if (result.success) {
- this.addFileOperation(`Found ${result.files.length} files that would be restored:`);
- result.files.forEach((file, index) => {
- this.addFileOperation(`${index + 1}. ${file.path} -> ${file.target_path}`);
- });
- if (result.skipped_files && result.skipped_files.length > 0) {
- this.addFileOperation(`\nSkipped ${result.skipped_files.length} files:`);
- result.skipped_files.forEach((file, index) => {
- this.addFileOperation(`${index + 1}. ${file.path} (${file.reason})`);
- });
- }
- this.addFileOperation(`\nTotal: ${result.files.length} files to restore, ${result.skipped_files?.length || 0} skipped`);
- this.addFileOperation('Dry run completed successfully.');
- } else {
- this.error = result.error;
- this.addFileOperation(`Error: ${result.error}`);
- }
- } catch (error) {
- this.error = `Dry run error: ${error.message}`;
- this.addFileOperation(`Error: ${error.message}`);
- } finally {
- this.loading = false;
- }
- },
-
- // Enhanced Restore Operations with Metadata Display
- async handleFileUpload(event) {
- const file = event.target.files[0];
- if (!file) return;
-
- this.backupFile = file;
- this.error = '';
- this.restoreResult = null;
-
- try {
- this.loading = true;
- this.loadingMessage = 'Inspecting backup archive...';
-
- const formData = new FormData();
- formData.append('backup_file', file);
-
- const response = await fetch('/backup_inspect', {
- method: 'POST',
- body: formData
- });
-
- const result = await response.json();
-
- if (result.success) {
- this.backupMetadata = result.metadata;
-
- // Load complete metadata for JSON editing
- this.restoreMetadata = JSON.parse(JSON.stringify(result.metadata)); // Deep copy
-
- // Initialize restore editor with complete metadata JSON
- if (this.restoreEditor) {
- this.restoreEditor.setValue(JSON.stringify(this.restoreMetadata, null, 2));
- this.restoreEditor.clearSelection();
- }
-
- // Validate backup compatibility
- this.validateBackupCompatibility();
- } else {
- this.error = result.error;
- this.backupMetadata = null;
- }
- } catch (error) {
- this.error = `Inspection error: ${error.message}`;
- this.backupMetadata = null;
- } finally {
- this.loading = false;
- }
- },
-
- validateBackupCompatibility() {
- if (!this.backupMetadata) return;
-
- const warnings = [];
-
- // Check Agent Zero version compatibility
- // Note: Both backup and current versions are obtained via git.get_git_info()
- const backupVersion = this.backupMetadata.agent_zero_version;
- const currentVersion = "current"; // Retrieved from git.get_git_info() on backend
-
- if (backupVersion !== currentVersion && backupVersion !== "development") {
- warnings.push(`Backup created with Agent Zero ${backupVersion}, current version is ${currentVersion}`);
- }
-
- // Check backup age
- const backupDate = new Date(this.backupMetadata.timestamp);
- const daysSinceBackup = (Date.now() - backupDate) / (1000 * 60 * 60 * 24);
-
- if (daysSinceBackup > 30) {
- warnings.push(`Backup is ${Math.floor(daysSinceBackup)} days old`);
- }
-
- // Check system compatibility
- const systemInfo = this.backupMetadata.system_info;
- if (systemInfo && systemInfo.system) {
- // Could add platform-specific warnings here
- }
-
- if (warnings.length > 0) {
- toast(`Compatibility warnings: ${warnings.join(', ')}`, 'warning');
- }
- },
-
- async performRestore() {
- if (!this.backupFile) {
- this.error = 'Please select a backup file';
- return;
- }
-
- try {
- this.loading = true;
- this.loadingMessage = 'Restoring files...';
- this.error = '';
- this.clearFileOperations();
- this.addFileOperation('Starting file restoration...');
-
- const formData = new FormData();
- formData.append('backup_file', this.backupFile);
- formData.append('restore_patterns', this.getEditorValue());
- formData.append('overwrite_policy', this.overwritePolicy);
-
- const response = await fetch('/backup_restore', {
- method: 'POST',
- body: formData
- });
-
- const result = await response.json();
-
- if (result.success) {
- // Log restored files
- this.addFileOperation(`Successfully restored ${result.restored_files.length} files:`);
- result.restored_files.forEach((file, index) => {
- this.addFileOperation(`${index + 1}. ${file.archive_path} -> ${file.target_path}`);
- });
-
- // Log skipped files
- if (result.skipped_files && result.skipped_files.length > 0) {
- this.addFileOperation(`\nSkipped ${result.skipped_files.length} files:`);
- result.skipped_files.forEach((file, index) => {
- this.addFileOperation(`${index + 1}. ${file.path} (${file.reason})`);
- });
- }
-
- // Log errors
- if (result.errors && result.errors.length > 0) {
- this.addFileOperation(`\nErrors during restoration:`);
- result.errors.forEach((error, index) => {
- this.addFileOperation(`${index + 1}. ${error.path}: ${error.error}`);
- });
- }
-
- this.addFileOperation(`\nRestore completed: ${result.restored_files.length} restored, ${result.skipped_files?.length || 0} skipped, ${result.errors?.length || 0} errors`);
- this.restoreResult = result;
- toast('Restore completed successfully', 'success');
- } else {
- this.error = result.error;
- this.addFileOperation(`Error: ${result.error}`);
- }
- } catch (error) {
- this.error = `Restore error: ${error.message}`;
- this.addFileOperation(`Error: ${error.message}`);
- } finally {
- this.loading = false;
- }
- },
-
- // JSON Metadata Utilities
- validateRestoreMetadata() {
- try {
- const metadataText = this.getEditorValue();
- const metadata = JSON.parse(metadataText);
-
- // Validate required fields
- if (!Array.isArray(metadata.include_patterns)) {
- throw new Error('include_patterns must be an array');
- }
- if (!Array.isArray(metadata.exclude_patterns)) {
- throw new Error('exclude_patterns must be an array');
- }
-
- this.restoreMetadata = metadata;
- this.error = '';
- return true;
- } catch (error) {
- this.error = `Invalid JSON metadata: ${error.message}`;
- return false;
- }
- },
-
- getCurrentRestoreMetadata() {
- if (this.validateRestoreMetadata()) {
- return this.restoreMetadata;
- }
- return null;
- },
-
- // Restore Operations - Metadata Control
- resetToOriginalMetadata() {
- if (this.backupMetadata) {
- this.restoreMetadata = JSON.parse(JSON.stringify(this.backupMetadata)); // Deep copy
-
- if (this.restoreEditor) {
- this.restoreEditor.setValue(JSON.stringify(this.restoreMetadata, null, 2));
- this.restoreEditor.clearSelection();
- }
- }
- },
-
- loadDefaultPatterns() {
- if (this.backupMetadata && this.backupMetadata.backup_config?.default_patterns) {
- // Parse default patterns and update current metadata
- const defaultPatterns = this.backupMetadata.backup_config.default_patterns;
- // This would need to be implemented based on how default patterns are structured
- // For now, just reset to original metadata
- this.resetToOriginalMetadata();
- }
- },
-
- async showRestorePreview() {
- if (!this.backupFile || !this.restorePatterns.trim()) {
- this.error = 'Please select a backup file and specify restore patterns';
- return;
- }
-
- try {
- this.loading = true;
- this.loadingMessage = 'Generating restore preview...';
-
- const formData = new FormData();
- formData.append('backup_file', this.backupFile);
- formData.append('restore_patterns', this.getEditorValue());
-
- const response = await fetch('/backup_restore_preview', {
- method: 'POST',
- body: formData
- });
-
- const result = await response.json();
-
- if (result.success) {
- this.previewFiles = result.files;
- openModal('backup/file-preview.html');
- } else {
- this.error = result.error;
- }
- } catch (error) {
- this.error = `Preview error: ${error.message}`;
- } finally {
- this.loading = false;
- }
- },
-
- // Utility
- formatTimestamp(timestamp) {
- if (!timestamp) return 'Unknown';
- return new Date(timestamp).toLocaleString();
- },
-
- formatFileSize(bytes) {
- if (!bytes) return '0 B';
- const sizes = ['B', 'KB', 'MB', 'GB'];
- const i = Math.floor(Math.log(bytes) / Math.log(1024));
- return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`;
- },
-
- formatDate(dateString) {
- if (!dateString) return 'Unknown';
- return new Date(dateString).toLocaleDateString();
- },
-
- // Enhanced Metadata Management
- toggleMetadataView() {
- this.showDetailedMetadata = !this.showDetailedMetadata;
- localStorage.setItem('backupShowDetailedMetadata', this.showDetailedMetadata);
- },
-
- async exportMetadata() {
- if (!this.backupMetadata) return;
-
- const metadataJson = JSON.stringify(this.backupMetadata, null, 2);
- const blob = new Blob([metadataJson], { type: 'application/json' });
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = 'backup-metadata.json';
- a.click();
- URL.revokeObjectURL(url);
- },
-
- // Progress Log Management
- initProgressLog() {
- this.progressLog = [];
- this.progressLogId = 0;
- },
-
- addProgressLogEntry(message, type = 'info') {
- if (!this.progressLog) this.progressLog = [];
-
- this.progressLog.push({
- id: this.progressLogId++,
- time: new Date().toLocaleTimeString(),
- message: message,
- type: type
- });
-
- // Keep log size manageable
- if (this.progressLog.length > 100) {
- this.progressLog = this.progressLog.slice(-50);
- }
-
- // Auto-scroll to bottom
- this.$nextTick(() => {
- const logElement = document.getElementById('backup-progress-log');
- if (logElement) {
- logElement.scrollTop = logElement.scrollHeight;
- }
- });
- },
-
- clearProgressLog() {
- this.progressLog = [];
- },
-
- // Watch for progress data changes to update log
- watchProgressData() {
- this.$watch('progressData', (newData) => {
- if (newData && newData.message) {
- const type = newData.error ? 'error' : newData.warning ? 'warning' : newData.success ? 'success' : 'info';
- this.addProgressLogEntry(newData.message, type);
- }
- });
- }
-};
-
-const store = createStore("backupStore", model);
-export { store };
-```
-
-### 6. Integration Requirements
-
-#### Settings Tab Integration
-The backup functionality is integrated as a dedicated "backup" tab in the settings system, providing:
-- **Dedicated Tab**: Clean separation from other settings categories
-- **Easy Access**: Users can quickly find backup/restore functionality
-- **Organized Interface**: Backup operations don't clutter developer or other tabs
-
-#### Settings Button Handler
-Update settings field button handling to open backup/restore modals when respective buttons are clicked in the backup tab.
-
-**Integration with existing `handleFieldButton()` method:**
-```javascript
-// In webui/js/settings.js - add to existing handleFieldButton method
-async handleFieldButton(field) {
- console.log(`Button clicked: ${field.id}`);
-
- if (field.id === "mcp_servers_config") {
- openModal("settings/mcp/client/mcp-servers.html");
- } else if (field.id === "backup_create") {
- openModal("settings/backup/backup.html");
- } else if (field.id === "backup_restore") {
- openModal("settings/backup/restore.html");
- }
-}
-```
-
-#### Modal System Integration
-Use existing `openModal()` and `closeModal()` functions from the global modal system (`webui/js/modals.js`).
-
-#### Toast Notifications
-Use existing Agent Zero toast system for consistent user feedback:
-```javascript
-// Use established toast patterns
-globalThis.toast("Backup created successfully", "success");
-globalThis.toast("Restore completed", "success");
-globalThis.toast("Error creating backup", "error");
-```
-
-#### ACE Editor Integration
-The backup system follows Agent Zero's established ACE editor patterns **exactly** as implemented in MCP servers:
-
-**Theme Detection (identical to MCP servers):**
-```javascript
-// Exact pattern from webui/components/settings/mcp/client/mcp-servers-store.js
-const container = document.getElementById("backup-metadata-editor");
-if (container) {
- const editor = ace.edit("backup-metadata-editor");
-
- const dark = localStorage.getItem("darkMode");
- if (dark != "false") {
- editor.setTheme("ace/theme/github_dark");
- } else {
- editor.setTheme("ace/theme/tomorrow");
- }
-
- editor.session.setMode("ace/mode/json");
- editor.setValue(JSON.stringify(defaultMetadata, null, 2));
- editor.clearSelection();
- this.backupEditor = editor;
-}
-```
-
-**Cleanup Pattern (following MCP servers):**
-```javascript
-onClose() {
- if (this.backupEditor) {
- this.backupEditor.destroy();
- this.backupEditor = null;
- }
- // Additional cleanup...
-}
-```
-
-#### API Integration Patterns
-The backup system uses Agent Zero's existing API communication methods for consistency:
-
-**Standard API Calls (using global sendJsonData):**
-```javascript
-// Use existing global sendJsonData function (from webui/index.js)
-const response = await sendJsonData("backup_test", {
- patterns: patternsString,
- include_hidden: metadata.include_hidden || false,
- max_files: 1000
-});
-
-// Error handling follows Agent Zero patterns
-if (response.success) {
- this.previewFiles = response.files;
-} else {
- this.error = response.error;
-}
-```
-
-**File Upload API Calls:**
-```javascript
-// For endpoints that handle file uploads (restore operations)
-const formData = new FormData();
-formData.append('backup_file', this.backupFile);
-formData.append('restore_patterns', this.getEditorValue());
-
-const response = await fetch('/backup_restore', {
- method: 'POST',
- body: formData
-});
-
-const result = await response.json();
-```
-
-**Server-Sent Events (progress streaming):**
-```javascript
-// Real-time progress updates using EventSource
-const eventSource = new EventSource('/backup_progress_stream?' + new URLSearchParams({
- patterns: patternsString,
- backup_name: metadata.backup_name
-}));
-
-eventSource.onmessage = (event) => {
- const data = JSON.parse(event.data);
- this.loadingMessage = data.message;
- // Handle progress updates...
-};
-```
-
-#### Utility Function Integration
-The backup system can leverage existing Agent Zero utility functions for consistency:
-
-**File Size Formatting:**
-```javascript
-// Check if Agent Zero has existing file size utilities
-// If not available, implement following Agent Zero's style patterns
-formatFileSize(bytes) {
- if (!bytes) return '0 B';
- const sizes = ['B', 'KB', 'MB', 'GB'];
- const i = Math.floor(Math.log(bytes) / Math.log(1024));
- return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`;
-}
-```
-
-**Time Formatting (following existing patterns):**
-```javascript
-// Use existing localization helpers if available
-formatTimestamp(timestamp) {
- if (!timestamp) return 'Unknown';
- return new Date(timestamp).toLocaleString();
-}
-```
-
-**Error Handling Integration:**
-```javascript
-// Use existing error handling patterns
-try {
- const result = await backupOperation();
- globalThis.toast("Operation completed successfully", "success");
-} catch (error) {
- console.error('Backup error:', error);
- globalThis.toast(`Error: ${error.message}`, "error");
-}
-```
-
-### 8. Styling Guidelines
-
-#### CSS Variables
-Use existing CSS variables for consistent theming:
-- `--c-bg-primary`, `--c-bg-secondary`
-- `--c-text-primary`, `--c-text-secondary`
-- `--c-border`, `--c-error`, `--c-success-bg`
-
-#### Responsive Design
-Ensure modals work on mobile devices with appropriate responsive breakpoints.
-
-#### Accessibility
-- Proper ARIA labels for form elements
-- Keyboard navigation support
-- Screen reader compatibility
-
-### 9. Error Handling
-
-#### User-Friendly Messages
-- Clear error messages for common scenarios
-- Loading states with descriptive messages
-- Success feedback with action confirmation
-
-#### Validation
-- Client-side validation for file types
-- Pattern syntax validation
-- File size limits
-
-## Comprehensive Enhancement Summary
-
-### Enhanced File Preview System
-- **Smart Directory Grouping**: Files organized by directory structure with 3-level depth limitation
-- **Dual View Modes**: Toggle between grouped directory view and flat file list
-- **Real-time Search**: Debounced search filtering by file name or path fragments
-- **Expandable Groups**: Collapsible directory groups with file count badges and size indicators
-- **Performance Optimization**: Limited display (50 files per group) with "show more" indicators
-- **Export Capabilities**: Export file lists to text files or copy to clipboard
-
-### Real-time Progress Visualization
-- **Live Progress Streaming**: Server-Sent Events for real-time backup/restore progress updates
-- **Multi-stage Progress Bar**: Visual progress indicator with percentage and stage information
-- **File-by-file Display**: Current file being processed with count progress (X/Y files)
-- **Live Progress Log**: Scrollable, auto-updating log with timestamped entries
-- **Progress Control**: Cancel operation capability with cleanup handling
-- **Status Categorization**: Color-coded progress entries (info, warning, error, success)
-
-### Comprehensive Metadata Display
-- **Enhanced Backup Information**: Basic info grid with creation date, author, version, file count, size, and checksum
-- **Expandable Detailed View**: Collapsible sections for system info, environment details, and backup configuration
-- **System Information Display**: Platform, architecture, Python version, hostname from backup metadata
-- **Environment Context**: User, timezone, runtime mode, working directory information
-- **Compatibility Validation**: Automatic compatibility checking with warnings for version mismatches and old backups
-- **Metadata Export**: Export complete metadata.json for external analysis
-
-### Consistent UI Standards
-- **Standardized Scrollable Areas**: All file lists and progress logs use consistent max-height (350px) with scroll
-- **Monospace Font Usage**: File paths displayed in monospace for improved readability
-- **Responsive Design**: Mobile-friendly layouts with proper breakpoints
-- **Theme Integration**: Full CSS variable support for dark/light mode compatibility
-- **Loading States**: Comprehensive loading indicators with descriptive messages
-
-### Advanced User Experience Features
-- **Search and Filter**: Real-time file filtering with search term highlighting
-- **Pattern Control Buttons**: "Reset to Original", "Load Defaults", "Preview Files" for pattern management
-- **File Selection Preview**: Comprehensive file preview before backup/restore operations
-- **Progress Cancellation**: User-controlled operation cancellation with proper cleanup
-- **Error Recovery**: Clear error messages with suggested fixes and recovery options
-- **State Persistence**: Remember user preferences (view mode, expanded groups, etc.)
-
-### Alpine.js Architecture Enhancements
-- **Enhanced Store Management**: Extended backup store with grouped preview, progress tracking, and metadata handling
-- **Event-driven Updates**: Real-time UI updates via Server-Sent Events integration
-- **State Synchronization**: Proper Alpine.js reactive state management for complex UI interactions
-- **Memory Management**: Cleanup of event sources, intervals, and large data structures
-- **Performance Optimization**: Debounced search, efficient list rendering, and scroll management
-
-### Integration Features
-- **Settings Modal Integration**: Seamless integration with existing Agent Zero settings system
-- **Toast Notifications**: Success/error feedback using existing notification system
-- **Modal System**: Proper integration with Agent Zero's modal management
-- **API Layer**: Consistent API communication patterns following Agent Zero conventions
-- **Error Handling**: Unified error handling and user feedback mechanisms
-
-### Accessibility and Usability
-- **Keyboard Navigation**: Full keyboard support for all interactive elements
-- **Screen Reader Support**: Proper ARIA labels and semantic HTML structure
-- **Copy-to-Clipboard**: Quick clipboard operations for file lists and metadata
-- **Export Options**: Multiple export formats for file manifests and metadata
-- **Visual Feedback**: Clear visual indicators for loading, success, error, and warning states
-
-## Enhanced Restore Workflow with Pattern Editing
-
-### Metadata-Driven Restore Process
-1. **Upload Archive**: User uploads backup.zip file in restore modal
-2. **Parse Metadata**: System extracts and loads complete metadata.json
-3. **Display JSON**: Complete metadata.json shown in ACE JSON editor
-4. **Direct Editing**: User can modify include_patterns, exclude_patterns, and other settings directly
-5. **JSON Validation**: Real-time validation of JSON syntax and structure
-6. **Preview Changes**: User can preview which files will be restored based on current metadata
-7. **Execute Restore**: Files restored according to final metadata configuration
-
-### JSON Metadata Editing Benefits
-- **Single Source of Truth**: metadata.json is the authoritative configuration
-- **Direct Control**: Users edit the exact JSON that will be used for restore
-- **Full Access**: Modify any metadata property, not just patterns
-- **Real-time Validation**: JSON syntax and structure validation as you type
-- **Transparency**: See exactly what configuration will be applied
-
-### Enhanced User Experience
-- **Intelligent Defaults**: Complete metadata automatically loaded from backup
-- **JSON Editor**: Professional ACE editor with syntax highlighting and validation
-- **Real-time Preview**: See exactly which files will be restored before proceeding
-- **Immediate Feedback**: JSON validation and error highlighting as you edit
-
-This enhanced frontend specification delivers a professional-grade user interface with sophisticated file management, real-time progress monitoring, and comprehensive metadata visualization, all organized within a dedicated backup tab for optimal user experience. The implementation maintains perfect integration with Agent Zero's existing UI architecture and follows established Alpine.js patterns.
-
-### Implementation Status: ✅ COMPLETED & PRODUCTION READY
-
-### **Final Implementation State (December 2024)**
-
-#### **✅ COMPLETED Components:**
-
-**1. Settings Integration** ✅
-- **Backup Tab**: Dedicated "Backup & Restore" tab in settings interface
-- **Button Handlers**: Integrated with existing `handleFieldButton()` method
-- **Modal System**: Uses existing Agent Zero modal management
-- **Toast Notifications**: Consistent error/success feedback
-
-**2. Alpine.js Components** ✅
-- **Backup Modal**: `webui/components/settings/backup/backup.html`
-- **Restore Modal**: `webui/components/settings/backup/restore.html`
-- **Backup Store**: `webui/components/settings/backup/backup-store.js`
-- **Theme Integration**: Full dark/light mode support with CSS variables
-
-**3. Core Functionality** ✅
-- **JSON Metadata Editing**: ACE editor with syntax highlighting and validation
-- **File Preview**: Grouped directory view with search and filtering
-- **Real-time Operations**: Live backup creation and restore progress
-- **Error Handling**: Comprehensive validation and user feedback
-- **Progress Monitoring**: File-by-file progress tracking and logging
-
-**4. User Experience Features** ✅
-- **Drag & Drop**: File upload for restore operations
-- **Search & Filter**: Real-time file filtering by name/path
-- **Export Options**: File lists and metadata export
-- **State Persistence**: Remember user preferences and expanded groups
-- **Responsive Design**: Mobile-friendly layouts with proper breakpoints
-
-#### **✅ Backend Integration:**
-
-**API Endpoints Used:**
-1. **`/backup_get_defaults`** - Get default patterns with resolved absolute paths
-2. **`/backup_test`** - Pattern testing and dry run functionality
-3. **`/backup_preview_grouped`** - Smart file grouping for UI display
-4. **`/backup_create`** - Create and download backup archives
-5. **`/backup_inspect`** - Extract metadata from uploaded archives
-6. **`/backup_restore_preview`** - Preview restore operations
-7. **`/backup_restore`** - Execute file restoration
-
-**Communication Patterns:**
-- **Standard API**: Uses global `sendJsonData()` for consistency
-- **File Upload**: FormData for archive uploads with proper validation
-- **Error Handling**: Follows Agent Zero error formatting and toast patterns
-- **Progress Updates**: Real-time file operation logging and status updates
-
-#### **✅ Key Technical Achievements:**
-
-**Enhanced Metadata Management:**
-- **Direct JSON Editing**: Users edit metadata.json directly in ACE editor
-- **Pattern Arrays**: Separate include_patterns/exclude_patterns for granular control
-- **Real-time Validation**: JSON syntax checking and structure validation
-- **System Information**: Complete backup context with platform/environment details
-
-**Advanced File Operations:**
-- **Smart Grouping**: Directory-based organization with depth limitation
-- **Hidden File Support**: Proper explicit vs wildcard pattern handling
-- **Search & Filter**: Debounced search with real-time results
-- **Export Capabilities**: File lists and metadata export functionality
-
-**Professional UI/UX:**
-- **Consistent Styling**: Follows Agent Zero design patterns and CSS variables
-- **Loading States**: Comprehensive progress indicators and status messages
-- **Error Recovery**: Clear error messages with suggested fixes
-- **Accessibility**: Keyboard navigation and screen reader support
-
-#### **✅ Frontend Architecture Benefits:**
-
-**Alpine.js Integration:**
-- **Store Pattern**: Uses proven `createStore()` pattern from MCP servers
-- **Component Lifecycle**: Proper initialization and cleanup following Agent Zero patterns
-- **Reactive State**: Real-time UI updates with Alpine's reactivity system
-- **Event Handling**: Leverages Alpine's declarative event system
-
-**Code Reuse:**
-- **ACE Editor Setup**: Identical theme detection and configuration as MCP servers
-- **Modal Management**: Uses existing Agent Zero modal and overlay systems
-- **API Communication**: Consistent with Agent Zero's established API patterns
-- **Error Handling**: Unified error formatting and toast notification system
-
-### **Implementation Quality Metrics:**
-
-**Code Quality:** ✅
-- Follows Agent Zero coding conventions
-- Proper error handling and validation
-- Clean separation of concerns
-- Comprehensive documentation
-
-**User Experience:** ✅
-- Intuitive backup/restore workflow
-- Real-time feedback and progress tracking
-- Responsive design for all screen sizes
-- Consistent with Agent Zero UI patterns
-
-**Performance:** ✅
-- Efficient file preview with grouping
-- Debounced search and filtering
-- Proper memory management and cleanup
-- Optimized for large file sets
-
-**Reliability:** ✅
-- Comprehensive error handling
-- Input validation and sanitization
-- Proper file upload handling
-- Graceful degradation for network issues
-
-### **Final Status: 🚀 PRODUCTION READY**
-
-The Agent Zero backup frontend is now:
-- **Complete**: All planned features implemented and tested
-- **Integrated**: Seamlessly integrated with existing Agent Zero infrastructure
-- **Reliable**: Comprehensive error handling and edge case coverage
-- **User-friendly**: Intuitive interface following Agent Zero design principles
-- **Maintainable**: Clean code following established patterns and conventions
-
-**Ready for production use with full backup and restore capabilities!**
-
-The backup system provides users with a powerful, easy-to-use interface for backing up and restoring their Agent Zero configurations, data, and custom files using sophisticated pattern-based selection and real-time progress monitoring.
diff --git a/docs/architecture.md b/docs/developer/architecture.md
similarity index 74%
rename from docs/architecture.md
rename to docs/developer/architecture.md
index 77ed28348d..82a91281b4 100644
--- a/docs/architecture.md
+++ b/docs/developer/architecture.md
@@ -2,11 +2,8 @@
Agent Zero is built on a flexible and modular architecture designed for extensibility and customization. This section outlines the key components and the interactions between them.
## System Architecture
-This simplified diagram illustrates the hierarchical relationship between agents and their interaction with tools, extensions, instruments, prompts, memory and knowledge base.
-
-
-The user or Agent 0 is at the top of the hierarchy, delegating tasks to subordinate agents, which can further delegate to other agents. Each agent can utilize tools and access the shared assets (prompts, memory, knowledge, extensions and instruments) to perform its tasks.
+The user or Agent 0 is at the top of the hierarchy, delegating tasks to subordinate agents, which can further delegate to other agents. Each agent can utilize tools and access the shared assets (prompts, memory, knowledge, extensions and skills) to perform its tasks.
## Runtime Architecture
Agent Zero's runtime architecture is built around Docker containers:
@@ -32,8 +29,7 @@ This architecture ensures:
> [!NOTE]
> The legacy approach of running Agent Zero directly on the host system (using Python, Conda, etc.)
> is still possible but requires Remote Function Calling (RFC) configuration through the Settings
-> page. See [Full Binaries Installation](installation.md#in-depth-guide-for-full-binaries-installation)
-> for detailed instructions.
+> page. See the [development guide](development.md) for detailed instructions.
## Implementation Details
@@ -42,40 +38,42 @@ This architecture ensures:
| --- | --- |
| `/docker` | Docker-related files for runtime container |
| `/docs` | Documentation files and guides |
-| `/instruments` | Custom scripts and tools for runtime environment |
+| `/usr/skills` | Skills using the open SKILL.md standard (contextual expertise) |
+| `/agents` | Agent profiles (prompts, tools, extensions per profile) |
| `/knowledge` | Knowledge base storage |
| `/logs` | HTML CLI-style chat logs |
| `/memory` | Persistent agent memory storage |
-| `/prompts` | System and tool prompts |
-| `/python` | Core Python codebase: |
-| `/api` | API endpoints and interfaces |
-| `/extensions` | Modular extensions |
-| `/helpers` | Utility functions |
-| `/tools` | Tool implementations |
+| `/prompts` | Default system and tool prompt templates |
+| `/python` | Core Python codebase |
+| `/python/api` | API endpoints and interfaces |
+| `/python/extensions` | Modular extensions |
+| `/python/helpers` | Utility functions |
+| `/python/tools` | Tool implementations |
| `/tmp` | Temporary runtime data |
-| `/webui` | Web interface components: |
-| `/css` | Stylesheets |
-| `/js` | JavaScript modules |
-| `/public` | Static assets |
-| `/work_dir` | Working directory |
+| `/usr/chats` | Saved chat history (JSON) |
+| `/usr/secrets.env` | Secrets store (not always included in backups) |
+| `/usr/projects` | Project workspaces and `.a0proj` metadata |
+| `/webui` | Web interface components |
+| `/webui/css` | Stylesheets |
+| `/webui/js` | JavaScript modules |
+| `/webui/public` | Static assets |
### Key Files
| File | Description |
| --- | --- |
-| `.env` | Environment configuration |
+| `usr/settings.json` | Main runtime settings (written by the Settings UI) |
+| `usr/secrets.env` | Secrets store (managed via Settings -> Secrets) |
+| `conf/model_providers.yaml` | Model provider defaults and settings |
| `agent.py` | Core agent implementation |
-| `example.env` | Configuration template |
| `initialize.py` | Framework initialization |
| `models.py` | Model providers and configs |
| `preload.py` | Pre-initialization routines |
| `prepare.py` | Environment preparation |
| `requirements.txt` | Python dependencies |
-| `run_cli.py` | CLI launcher |
| `run_ui.py` | Web UI launcher |
> [!NOTE]
-> When using the Docker runtime container, these directories are mounted
-> within the `/a0` volume for data persistence until the container is restarted or deleted.
+> In the Docker runtime, the framework lives under `/a0` inside the container. Data persists as long as the container exists. For upgrades, prefer **Backup & Restore** instead of mapping the full `/a0` directory.
## Core Components
Agent Zero's architecture revolves around the following key components:
@@ -97,8 +95,6 @@ Communication flows between agents through messages, which are structured accord
#### Interaction Flow
A typical interaction flow within Agent Zero might look like this:
-
-
1. The user provides an instruction to Agent 0
2. Agent 0 initializes VectorDB and access memory
3. Agent 0 analyzes the instruction and formulates a plan using `thoughts` argument, possibly involving the use of tools or the creation of sub-agents
@@ -140,17 +136,17 @@ In cases where SearXNG might not return satisfactory results, Agent Zero can be
> retrieval system.
#### Custom Tools
-Users can create custom tools to extend Agent Zero's capabilities. Custom tools can be integrated into the framework by defining a tool specification, which includes the tool's prompt to be placed in `/prompts/$FOLDERNAME/agent.system.tool.$TOOLNAME.md`, as detailed below.
+Users can create custom tools to extend Agent Zero's capabilities. Custom tools can be integrated into the framework by defining a tool specification, which includes the tool's prompt. Place these prompt overrides in your agent profile:
-1. Create `agent.system.tool.$TOOL_NAME.md` in `prompts/$SUBDIR`
-2. Add reference in `agent.system.tools.md`
+1. Create `agent.system.tool.$TOOL_NAME.md` in `agents//prompts/`
+2. Add the reference in `agent.system.tools.md` within the same prompt scope
3. If needed, implement tool class in `python/tools` using `Tool` base class
4. Follow existing patterns for consistency
> [!NOTE]
-> Tools are always present in system prompt, so you should keep them to minimum.
-> To save yourself some tokens, use the [Instruments module](#adding-instruments)
-> to call custom scripts or functions.
+> Tools are always present in system prompt, so you should keep them to minimum.
+> To save yourself some tokens, use the [Skills module](#6-skills)
+> to add contextual expertise that is only loaded when relevant.
### 3. Memory System
The memory system is a critical component of Agent Zero, enabling the agent to learn and adapt from past interactions. It operates on a hybrid model where part of the memory is managed automatically by the framework while users can also manually input and extract information.
@@ -162,6 +158,14 @@ The memory is categorized into four distinct areas:
- **Solutions**: Stores successful solutions from past interactions for future reference
- **Metadata**: Each memory entry includes metadata (IDs, timestamps), enabling efficient filtering and searching based on specific criteria
+#### Embeddings and Utility Model
+- Embeddings are generated locally using a small default model (tiny disk footprint).
+- The **utility model** handles summarization and memory extraction; it must be capable enough to distinguish durable knowledge from noise.
+
+#### Memory Management Best Practices
+- After important sessions, ask the agent to **“memorize learning opportunities from the current session.”**
+- For long-running workflows, **distill durable knowledge into prompts** rather than relying exclusively on memory.
+
#### Messages History and Summarization
Agent Zero employs a sophisticated message history and summarization system to maintain context effectively while optimizing memory usage. This system dynamically manages the information flow, ensuring relevant details are readily available while efficiently handling the constraints of context windows.
@@ -208,16 +212,16 @@ The `prompts` directory contains various Markdown files that control agent behav
| agent.system.tool.*.md | Individual tool prompt files |
#### Prompt Organization
-- **Default Prompts**: Located in `prompts/default/`, serve as the base configuration
-- **Custom Prompts**: Can be placed in custom subdirectories (e.g., `prompts/my-custom/`)
+- **Default Prompts**: Located in `prompts/`, serve as the base configuration
+- **Custom Prompts (v0.9.7+)**: Place overrides in `agents//prompts/`
- **Behavior Files**: Stored in memory as `behaviour.md`, containing dynamic rules
- **Tool Prompts**: Organized in tool-specific files for modularity
-#### Custom Prompts
-1. Create directory in `prompts/` (e.g., `my-custom-prompts`)
-2. Copy and modify needed files from `prompts/default/`
-3. Agent Zero will merge your custom files with the default ones
-4. Select your custom prompts in the Settings page (Agent Config section)
+#### Custom Prompts (Post v0.9.7)
+1. Create or clone an existing agent profile under `agents//`
+2. Add only the prompt files you want to override in `agents//prompts/`
+3. Agent Zero merges these overrides with the default prompts automatically
+4. Select the **Agent Profile** in Settings to activate the overrides
#### Dynamic Behavior System
- **Behavior Adjustment**:
@@ -236,8 +240,6 @@ The `prompts` directory contains various Markdown files that control agent behav
3. New rules are merged with existing ruleset
4. Updated behavior is immediately applied
-
-
- **Integration with System Prompt**:
- Behavior rules are injected at the start of the system prompt
- Rules are formatted in a structured markdown format
@@ -245,8 +247,7 @@ The `prompts` directory contains various Markdown files that control agent behav
- Maintains separation between core functionality and behavioral rules
> [!NOTE]
-> You can customize any of these files. Agent Zero will use the files in your custom `prompts_subdir`
-> if they exist, otherwise, it will fall back to the files in `prompts/default`.
+> You can customize any of these files. Agent Zero will use files in `agents//prompts/` when present, and fall back to `prompts/` for everything else.
> [!TIP]
> The behavior system allows for dynamic adjustments without modifying the base prompt files.
@@ -266,20 +267,53 @@ Knowledge refers to the user-provided information and data that agents can lever
- Used for answering questions and decision-making
- Supports RAG-augmented tasks
-### 6. Instruments
-Instruments provide a way to add custom functionalities to Agent Zero without adding to the token count of the system prompt:
-- Stored in long-term memory of Agent Zero
-- Unlimited number of instruments available
-- Recalled when needed by the agent
-- Can modify agent behavior by introducing new procedures
-- Function calls or scripts to integrate with other systems
-- Scripts are run inside the Docker Container
-
-#### Adding Instruments
-1. Create folder in `instruments/custom` (no spaces in name)
-2. Add `.md` description file for the interface
-3. Add `.sh` script (or other executable) for implementation
-4. The agent will automatically detect and use the instrument
+### 6. Skills
+Skills provide contextual expertise using the **open SKILL.md standard** (originally developed by Anthropic). Skills are cross-platform and compatible with Claude Code, Cursor, Goose, OpenAI Codex CLI, GitHub Copilot, and more.
+
+#### Key Features
+- **YAML Frontmatter**: Structured metadata (name, description, tags, author)
+- **Cross-Platform**: Works with any AI agent that supports the SKILL.md standard
+- **Semantic Recall**: Skills are indexed in vector memory and loaded when contextually relevant
+- **Token Efficient**: Not in system prompt; loaded dynamically when needed
+- **Scripts Support**: Can reference `.sh`, `.py`, `.js`, `.ts` scripts
+
+#### SKILL.md Format
+```yaml
+---
+name: "my-skill"
+description: "What this skill does and when to use it"
+version: "1.0.0"
+author: "Your Name"
+tags: ["category", "purpose"]
+---
+
+# Skill Instructions
+
+Your detailed instructions here...
+
+## Examples
+- Example usage 1
+- Example usage 2
+```
+
+#### Directory Structure
+| Directory | Description |
+|-----------|-------------|
+| `/skills` | Default skills included with Agent Zero |
+| `/usr/skills` | Your custom skills (create folders here) |
+
+#### Adding Skills
+1. Create folder in `usr/skills` (e.g., `usr/skills/my-skill`)
+2. Add `SKILL.md` file with YAML frontmatter (required)
+3. Optionally add supporting scripts (`.sh`, `.py`, etc.)
+4. Optionally add `docs/` subfolder for additional documentation
+5. The agent will automatically discover the skill for list/search
+
+#### Using Skills
+Skills are surfaced via description/tag matching. You can also use the `skills_tool` to:
+- List all available skills
+- Load a specific skill by name
+- Read files from within a skill directory
### 7. Extensions
Extensions are a powerful feature of Agent Zero, designed to keep the main codebase clean and organized while allowing for greater flexibility and modularity.
@@ -305,4 +339,4 @@ Extensions can be found in `python/extensions` directory:
> [!NOTE]
> Consider contributing valuable custom components to the main repository.
-> See [Contributing](contribution.md) for more information.
\ No newline at end of file
+> See [Contributing](../guides/contribution.md) for more information.
diff --git a/docs/connectivity.md b/docs/developer/connectivity.md
similarity index 81%
rename from docs/connectivity.md
rename to docs/developer/connectivity.md
index 8cfbe250ec..ba9e4e9c5a 100644
--- a/docs/connectivity.md
+++ b/docs/developer/connectivity.md
@@ -25,6 +25,7 @@ Send messages to Agent Zero and receive responses. Supports text messages, file
* `message` (string, required): The message to send
* `attachments` (array, optional): Array of `{filename, base64}` objects
* `lifetime_hours` (number, optional): Chat lifetime in hours (default: 24)
+* `project` (string, optional): Project name to activate (only on first message)
**Headers:**
* `X-API-KEY` (required)
@@ -169,6 +170,63 @@ async function sendWithAttachment() {
sendWithAttachment();
```
+#### Project Usage Example
+
+```javascript
+// Working with projects
+async function sendMessageWithProject() {
+ try {
+ // First message - activate project
+ const response = await fetch('YOUR_AGENT_ZERO_URL/api_message', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-API-KEY': 'YOUR_API_KEY'
+ },
+ body: JSON.stringify({
+ message: "Analyze the project structure",
+ project: "my-web-app" // Activates this project
+ })
+ });
+
+ const data = await response.json();
+
+ if (response.ok) {
+ console.log('✅ Project activated!');
+ console.log('Context ID:', data.context_id);
+ console.log('Response:', data.response);
+
+ // Continue conversation - project already set
+ const followUp = await fetch('YOUR_AGENT_ZERO_URL/api_message', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-API-KEY': 'YOUR_API_KEY'
+ },
+ body: JSON.stringify({
+ context_id: data.context_id,
+ message: "What files are in the project?"
+ // Do NOT include project field here - already set on first message
+ })
+ });
+
+ const followUpData = await followUp.json();
+ console.log('Follow-up response:', followUpData.response);
+ return followUpData;
+ } else {
+ console.error('❌ Error:', data.error);
+ return null;
+ }
+ } catch (error) {
+ console.error('❌ Request failed:', error);
+ return null;
+ }
+}
+
+// Call the function
+sendMessageWithProject();
+```
+
---
## `GET/POST /api_log_get`
@@ -441,7 +499,7 @@ Retrieve file contents by paths, returning files as base64 encoded data. Useful
### API Reference
**Parameters:**
-* `paths` (array, required): Array of file paths to retrieve (e.g., `["/a0/tmp/uploads/file.txt"]`)
+* `paths` (array, required): Array of file paths to retrieve (e.g., `["/a0/usr/uploads/file.txt"]`)
**Headers:**
* `X-API-KEY` (required)
@@ -495,8 +553,8 @@ async function getFiles(filePaths) {
// Example 1: Get specific files
const filePaths = [
- "/a0/tmp/uploads/document.txt",
- "/a0/tmp/uploads/data.json"
+ "/a0/usr/uploads/document.txt",
+ "/a0/usr/uploads/data.json"
];
getFiles(filePaths);
@@ -523,7 +581,7 @@ async function attachmentWorkflow() {
console.log('Message sent with attachment');
// Step 2: Retrieve the uploaded file
- const retrievedFiles = await getFiles(["/a0/tmp/uploads/test.txt"]);
+ const retrievedFiles = await getFiles(["/a0/usr/uploads/test.txt"]);
if (retrievedFiles && retrievedFiles["test.txt"]) {
const originalContent = atob(retrievedFiles["test.txt"]);
@@ -546,6 +604,9 @@ It provides two endpoint types:
- **SSE (`/mcp/sse`):** For clients that support Server-Sent Events.
- **Streamable HTTP (`/mcp/http/`):** For clients that use streamable HTTP requests.
+> [!NOTE]
+> This section describes **Agent Zero as an MCP server**. To configure Agent Zero as an MCP **client** (consuming external tools), see [MCP Setup](../guides/mcp-setup.md).
+
### Example MCP Server Configuration
Below is an example of a `mcp.json` configuration file that a client could use to connect to the Agent Zero MCP server.
@@ -568,6 +629,30 @@ Below is an example of a `mcp.json` configuration file that a client could use t
}
```
+### Project Support in MCP
+
+You can specify a project for MCP connections by including it in the URL path:
+
+```json
+{
+ "mcpServers": {
+ "agent-zero-with-project": {
+ "type": "sse",
+ "url": "YOUR_AGENT_ZERO_URL/mcp/t-YOUR_API_TOKEN/p-my-project-name/sse"
+ },
+ "agent-zero-http-with-project": {
+ "type": "streamable-http",
+ "url": "YOUR_AGENT_ZERO_URL/mcp/t-YOUR_API_TOKEN/p-my-project-name/http/"
+ }
+ }
+}
+```
+
+When a project is specified in the URL:
+- All new chats will be created within that project context
+- The agent will have access to project-specific instructions, knowledge, and file structure
+- Attempting to use an existing chat_id from a different project will result in an error
+
---
## A2A (Agent-to-Agent) Connectivity
@@ -583,3 +668,22 @@ To connect another agent to your Agent Zero instance, use the following URL form
```
YOUR_AGENT_ZERO_URL/a2a/t-YOUR_API_TOKEN
```
+
+To connect with a specific project active:
+
+```
+YOUR_AGENT_ZERO_URL/a2a/t-YOUR_API_TOKEN/p-PROJECT_NAME
+```
+
+When a project is specified:
+- All A2A conversations will run in the context of that project
+- The agent will have access to project-specific resources, instructions, and knowledge
+- This enables project-isolated agent-to-agent communication
+
+### Practical Use Cases
+- Connect two Agent Zero instances for long-running, isolated workflows
+- Delegate specialized tasks to a dedicated agent instance
+- Maintain strict context separation between agents
+
+> [!TIP]
+> If you need tool access rather than chat delegation, use MCP instead of A2A. See [MCP Setup](../guides/mcp-setup.md).
diff --git a/docs/developer/contributing-skills.md b/docs/developer/contributing-skills.md
new file mode 100644
index 0000000000..97b8a8c4ac
--- /dev/null
+++ b/docs/developer/contributing-skills.md
@@ -0,0 +1,395 @@
+# Contributing Skills to Agent Zero
+
+Welcome to the Agent Zero Skills ecosystem! This guide will help you create, test, and share skills with the community.
+
+---
+
+## What is a Skill?
+
+A **Skill** is a contextual expertise module that provides the AI agent with specialized knowledge and procedures for specific tasks. Unlike tools (which are always loaded), skills are **surfaced via description/tag matching** when relevant, making them token-efficient and context-aware.
+
+### Skills vs Tools vs Knowledge
+
+| Aspect | Skills | Tools | Knowledge |
+|--------|--------|-------|-----------|
+| **Loading** | Description/tag matching | Always in prompt | Semantic recall |
+| **Purpose** | Procedures & expertise | Actions & functions | Facts & data |
+| **Format** | SKILL.md (YAML + Markdown) | Python/code | Text/documents |
+| **When to use** | "How to do X" | "Do X now" | "What is X" |
+
+### Cross-Platform Compatibility
+
+The SKILL.md standard is compatible with:
+- **Agent Zero** (this project)
+- **Claude Code** (Anthropic)
+- **Cursor** (AI IDE)
+- **OpenAI Codex CLI**
+- **GitHub Copilot**
+- **Goose** (Block)
+
+Skills you create here can be used in any of these platforms!
+
+---
+
+## Quick Start
+
+### Using the CLI (Recommended)
+
+```bash
+# Create a new skill interactively
+python -m python.helpers.skills_cli create my-skill-name
+
+# List all available skills
+python -m python.helpers.skills_cli list
+
+# Validate a skill
+python -m python.helpers.skills_cli validate my-skill-name
+
+# Search skills
+python -m python.helpers.skills_cli search "keyword"
+```
+
+### Manual Creation
+
+1. Create a folder in `usr/skills/` with your skill name
+2. Add a `SKILL.md` file with YAML frontmatter
+3. Optionally add supporting scripts (`.py`, `.sh`, `.js`)
+
+---
+
+## SKILL.md Standard
+
+Every skill must have a `SKILL.md` file with this structure:
+
+```markdown
+---
+name: "skill-name"
+description: "A clear, concise description of what this skill does and when to use it"
+version: "1.0.0"
+author: "Your Name "
+license: "MIT"
+tags: ["category", "purpose", "technology"]
+triggers:
+ - "keyword that activates this skill"
+ - "another trigger phrase"
+allowed_tools:
+ - tool_name
+ - another_tool
+metadata:
+ complexity: "beginner|intermediate|advanced"
+ category: "development|devops|data|productivity|creative"
+ estimated_time: "5 minutes"
+---
+
+# Skill Name
+
+## Overview
+
+Brief description of what this skill accomplishes.
+
+## When to Use
+
+- Situation 1 where this skill applies
+- Situation 2 where this skill applies
+
+## Instructions
+
+### Step 1: First Step
+
+Detailed instructions...
+
+### Step 2: Second Step
+
+More instructions...
+
+## Examples
+
+### Example 1: Basic Usage
+
+\`\`\`python
+# Code example
+\`\`\`
+
+### Example 2: Advanced Usage
+
+\`\`\`python
+# Advanced code example
+\`\`\`
+
+## Common Pitfalls
+
+- Pitfall 1 and how to avoid it
+- Pitfall 2 and how to avoid it
+
+## Related Skills
+
+- [related-skill-1](../related-skill-1/SKILL.md)
+- [related-skill-2](../related-skill-2/SKILL.md)
+```
+
+### Required Fields
+
+| Field | Description |
+|-------|-------------|
+| `name` | Unique identifier (lowercase, hyphens allowed) |
+| `description` | What the skill does (used for semantic matching) |
+
+### Optional Fields
+
+| Field | Description |
+|-------|-------------|
+| `version` | Semantic version (e.g., "1.0.0") |
+| `author` | Your name and email |
+| `license` | License (MIT, Apache-2.0, etc.) |
+| `tags` | Categories for discovery |
+| `triggers` | Phrases that activate this skill |
+| `allowed_tools` | Tools this skill can use |
+| `metadata` | Additional structured data |
+
+---
+
+## Creating Your First Skill
+
+### Step 1: Identify the Need
+
+Ask yourself:
+- What expertise would help the agent?
+- When should this skill be activated?
+- What steps should the agent follow?
+
+### Step 2: Create the Structure
+
+```bash
+# Using CLI
+python -m python.helpers.skills_cli create my-awesome-skill
+
+# Or manually
+mkdir -p usr/skills/my-awesome-skill
+touch usr/skills/my-awesome-skill/SKILL.md
+```
+
+### Step 3: Write the SKILL.md
+
+```markdown
+---
+name: "my-awesome-skill"
+description: "Helps with [specific task] when [specific situation]"
+version: "1.0.0"
+author: "Your Name"
+tags: ["category"]
+---
+
+# My Awesome Skill
+
+## When to Use
+
+Use this skill when you need to [specific task].
+
+## Instructions
+
+1. First, do this...
+2. Then, do that...
+3. Finally, verify by...
+
+## Examples
+
+### Example: Basic Case
+
+[Show a complete example]
+```
+
+### Step 4: Add Supporting Files (Optional)
+
+If your skill needs scripts:
+
+```
+my-awesome-skill/
+├── SKILL.md # Required
+├── helper.py # Optional Python script
+├── setup.sh # Optional shell script
+└── templates/ # Optional templates folder
+ └── config.json
+```
+
+Reference them in your SKILL.md:
+
+```markdown
+## Scripts
+
+This skill includes helper scripts:
+- `helper.py` - Does X
+- `setup.sh` - Sets up Y
+```
+
+### Step 5: Test Your Skill
+
+```bash
+# Validate the skill
+python -m python.helpers.skills_cli validate my-awesome-skill
+
+# Test in Agent Zero
+# Start the agent and ask it to perform the task your skill handles
+```
+
+---
+
+## Best Practices
+
+### Writing Effective Descriptions
+
+The `description` field is crucial for semantic matching. Make it:
+
+**Good:**
+```yaml
+description: "Guides systematic debugging of Python applications using print statements, debugger, and logging to identify root causes"
+```
+
+**Bad:**
+```yaml
+description: "Helps with debugging"
+```
+
+### Structuring Instructions
+
+1. **Be Specific** - Avoid vague instructions
+2. **Use Steps** - Number your steps clearly
+3. **Include Examples** - Show, don't just tell
+4. **Anticipate Errors** - Include troubleshooting
+
+### Semantic Triggers
+
+Design your description and content so the skill is recalled when relevant:
+
+```yaml
+# Include synonyms and related terms
+description: "Helps create REST APIs, web services, HTTP endpoints, and backend routes using FastAPI, Flask, or Express"
+```
+
+### Keep Skills Focused
+
+One skill = one expertise area. If your skill is getting too long, split it:
+
+- `api-design` - API structure and patterns
+- `api-security` - API authentication and authorization
+- `api-testing` - API testing strategies
+
+---
+
+## Testing Skills
+
+### Local Testing
+
+1. **Validate Structure:**
+ ```bash
+ python -m python.helpers.skills_cli validate my-skill
+ ```
+
+2. **Test Semantic Recall:**
+ Start Agent Zero and ask questions that should trigger your skill.
+
+3. **Verify Instructions:**
+ Follow your own instructions manually to ensure they work.
+
+---
+
+## Sharing Skills
+
+### Contributing to Agent Zero
+
+1. **Fork the Repository:**
+ ```bash
+ git clone https://github.com/agent0ai/agent-zero.git
+ cd agent-zero
+ ```
+
+2. **Create Your Skill:**
+ ```bash
+ python -m python.helpers.skills_cli create my-skill
+ # Edit usr/skills/my-skill/SKILL.md
+ ```
+
+3. **Move to Default (for contribution):**
+ ```bash
+ mv usr/skills/my-skill skills/my-skill
+ ```
+
+4. **Create a Pull Request:**
+ - Branch: `feat/skill-my-skill-name`
+ - Title: `feat(skills): add my-skill-name skill`
+ - Description: Explain what the skill does and why it's useful
+
+### Publishing to Skills Marketplace
+
+Share your skills on [skillsmp.com](https://skillsmp.com):
+
+1. Create a GitHub repository for your skill
+2. Ensure it follows the SKILL.md standard
+3. Submit to the marketplace via their contribution process
+
+### Creating a Skills Collection
+
+For multiple related skills, create a repository:
+
+```
+my-skills-collection/
+├── README.md
+├── skills/
+│ ├── skill-1/
+│ │ └── SKILL.md
+│ ├── skill-2/
+│ │ └── SKILL.md
+│ └── skill-3/
+│ └── SKILL.md
+└── LICENSE
+```
+
+---
+
+## Community Guidelines
+
+### Quality Standards
+
+- **Tested** - Skills must be tested before submission
+- **Documented** - Clear instructions and examples
+- **Focused** - One expertise per skill
+- **Original** - Don't duplicate existing skills
+
+### Naming Conventions
+
+- Use lowercase with hyphens: `my-skill-name`
+- Be descriptive: `python-debugging` not `debug`
+- Avoid generic names: `fastapi-crud` not `api`
+
+### License
+
+- Include a license (MIT recommended for maximum compatibility)
+- Respect licenses of any code you include
+- Don't include proprietary or copyrighted content
+
+---
+
+## FAQ
+
+### Q: Where should I put my skills?
+
+**A:** During development, use `usr/skills/`. For contribution, move to `skills/`.
+
+### Q: How are skills discovered?
+
+**A:** Skills are matched against their name, description, and tags for the current query. They are not indexed into vector memory.
+
+### Q: Can I use skills from other platforms?
+
+**A:** Yes! The SKILL.md standard is cross-platform. Skills from Claude Code, Cursor, or other compatible platforms can be copied directly to `usr/skills/`.
+
+### Q: How do I update a skill?
+
+**A:** Edit the SKILL.md file and increment the version number. Changes take effect on agent restart.
+
+### Q: Can skills call other skills?
+
+**A:** Skills don't directly call each other, but the agent may combine multiple skills when appropriate for a task.
+
+---
+
+Happy skill building! 🚀
diff --git a/docs/extensibility.md b/docs/developer/extensions.md
similarity index 94%
rename from docs/extensibility.md
rename to docs/developer/extensions.md
index db10a2a887..1440f7e1ae 100644
--- a/docs/extensibility.md
+++ b/docs/developer/extensions.md
@@ -1,7 +1,7 @@
-# Extensibility framework in Agent Zero
+# Extensions Framework
> [!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.
+> Agent Zero is built with extensibility in mind. It provides a framework for creating custom extensions, agents, skills, 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.
@@ -120,6 +120,9 @@ Prompts are located in:
- Default prompts: `/prompts/`
- Agent-specific prompts: `/agents/{agent_profile}/prompts/`
+> [!NOTE]
+> Since v0.9.7, custom prompts should be placed under `agents//prompts/` instead of a shared `prompts` subdirectory.
+
#### Prompt Features
Agent Zero's prompt system supports several powerful features:
@@ -215,7 +218,7 @@ Agent Zero supports creating specialized subagents with customized behavior. The
- `/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.
+The `settings.json` file for an agent uses the same structure as `usr/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.
@@ -244,6 +247,8 @@ In this example:
Projects provide isolated workspaces for individual chats, keeping prompts, memory, knowledge, files, and secrets scoped to a specific use case.
+Projects are ideal for multi-client or multi-domain work because each project can have **its own agent/subagents and context windows**, preventing context mixing. They are especially powerful when combined with the Tasks scheduler.
+
### Project Location and Structure
- Projects are located under `/a0/usr/projects/`
@@ -294,6 +299,8 @@ Projects are the recommended way to create specialized workflows in Agent Zero w
- Keep passwords and other secrets scoped to a single workspace
- Run multiple independent flows side by side under the same Agent Zero installation
+See [Usage → Tasks & Scheduling](../guides/usage.md#tasks--scheduling) for how to pair projects with scheduled tasks.
+
## Best Practices
- Keep extensions focused on a single responsibility
- Use the appropriate extension point for your functionality
diff --git a/docs/developer/mcp-configuration.md b/docs/developer/mcp-configuration.md
new file mode 100644
index 0000000000..b560442384
--- /dev/null
+++ b/docs/developer/mcp-configuration.md
@@ -0,0 +1,404 @@
+# Advanced MCP Configuration
+
+This guide provides comprehensive technical details for configuring and utilizing external tool providers through the Model Context Protocol (MCP) with Agent Zero. This allows Agent Zero to leverage tools hosted by separate local or remote MCP-compliant servers.
+
+> [!NOTE]
+> For a quick start guide on adding MCP servers through the UI, see [MCP Setup](../guides/mcp-setup.md).
+
+> [!NOTE]
+> This guide covers Agent Zero as an MCP **client**. To expose Agent Zero as an MCP **server**, see [Connectivity → MCP Server](connectivity.md#mcp-server-connectivity).
+
+## MCP Server Types
+
+Agent Zero supports three main types of MCP servers:
+
+1. **Local Stdio Servers**: Local executables that Agent Zero communicates with via standard input/output (stdio).
+2. **Remote SSE Servers**: Network-accessible servers that use Server-Sent Events (SSE), usually over HTTP/S.
+3. **Remote Streaming HTTP Servers**: Servers using the streamable HTTP transport protocol for MCP communication.
+
+## How Agent Zero Consumes MCP Tools
+
+Agent Zero discovers and integrates MCP tools dynamically through the following process:
+
+1. **Configuration**: MCP servers are defined in the Agent Zero configuration, primarily through the Settings UI.
+2. **Saving Settings**: When saved via the UI, Agent Zero updates `usr/settings.json`, specifically the `"mcp_servers"` key.
+3. **Server Startup**: Agent Zero initializes configured MCP servers (stdio) or connects to them (remote). For `npx`/`uvx` based servers, the first run downloads packages.
+4. **Tool Discovery**: Upon initialization, Agent Zero connects to each enabled MCP server and queries for available tools, descriptions, and parameters.
+5. **Dynamic Prompting**: Tool information is injected into the agent's system prompt. The `{{tools}}` placeholder in templates (e.g., `prompts/agent.system.mcp_tools.md`) is replaced with the formatted tool list.
+6. **Tool Invocation**: When the LLM requests an MCP tool, Agent Zero's `process_tools` method (`mcp_handler.py`) routes the request to the appropriate MCP server.
+
+## Configuration File Structure
+
+### Settings Location
+
+MCP server configurations are stored in:
+- `usr/settings.json` (primary storage)
+
+### The `mcp_servers` Setting
+
+Within `usr/settings.json`, MCP servers are defined under the `"mcp_servers"` key:
+
+- **Value Type**: JSON formatted string containing:
+ - A JSON object with `"mcpServers"` (recommended, matches UI)
+ - Or a JSON array of server configurations
+- **Default Value**: Empty config (`{"mcpServers": {}}`)
+- **Manual Editing**: While UI configuration is recommended, manual editing is possible. Ensure proper JSON string formatting with escaped quotes.
+
+### Recommended Configuration Format
+
+```json
+{
+ "mcpServers": {
+ "sqlite": {
+ "command": "uvx",
+ "args": ["mcp-server-sqlite", "--db-path", "/root/db.sqlite"]
+ },
+ "deep-wiki": {
+ "description": "Use this MCP to analyze GitHub repositories",
+ "url": "https://mcp.deepwiki.com/sse"
+ }
+ }
+}
+```
+
+> [!NOTE]
+> In `usr/settings.json`, the entire `"mcp_servers"` value is stored as a single string. The Settings UI handles escaping automatically.
+
+### Upgrading Existing Installations
+
+For existing `settings.json` files without MCP support:
+
+1. Ensure you're running a version with MCP support
+2. Open the settings UI
+3. Save settings (even without changes)
+4. This writes the complete settings structure including `"mcp_servers": ""`
+5. Configure servers via UI or careful manual editing
+
+## Server Configuration Templates
+
+### 1. Local Stdio Server
+
+```json
+{
+ "name": "My Local Tool Server",
+ "description": "Optional: A brief description of this server.",
+ "type": "stdio",
+ "command": "python",
+ "args": ["path/to/your/mcp_stdio_script.py", "--some-arg"],
+ "env": {
+ "PYTHONPATH": "/path/to/custom/libs:.",
+ "ANOTHER_VAR": "value"
+ },
+ "encoding": "utf-8",
+ "encoding_error_handler": "strict",
+ "disabled": false
+}
+```
+
+**Configuration Fields:**
+- `type`: Optional, auto-detected. Can be `"stdio"`, `"sse"`, or streaming variants
+- `command`: **Required**. The executable to run
+- `args`: Optional list of command arguments
+- `env`: Optional environment variables for the process
+- `encoding`: Optional, default `"utf-8"`
+- `encoding_error_handler`: Optional, can be `"strict"`, `"ignore"`, or `"replace"`
+
+### 2. Remote SSE Server
+
+```json
+{
+ "name": "My Remote API Tools",
+ "description": "Optional: Description of the remote SSE server.",
+ "type": "sse",
+ "url": "https://api.example.com/mcp-sse-endpoint",
+ "headers": {
+ "Authorization": "Bearer YOUR_API_KEY_OR_TOKEN",
+ "X-Custom-Header": "some_value"
+ },
+ "timeout": 5.0,
+ "sse_read_timeout": 300.0,
+ "disabled": false
+}
+```
+
+**Configuration Fields:**
+- `url`: **Required**. Full URL for the SSE endpoint
+- `headers`: Optional HTTP headers for authentication/custom headers
+- `timeout`: Optional connection timeout in seconds (default: 5.0)
+- `sse_read_timeout`: Optional read timeout for SSE stream (default: 300.0)
+
+### 3. Remote Streaming HTTP Server
+
+```json
+{
+ "name": "My Streaming HTTP Tools",
+ "description": "Optional: Description of the remote streaming HTTP server.",
+ "type": "streaming-http",
+ "url": "https://api.example.com/mcp-http-endpoint",
+ "headers": {
+ "Authorization": "Bearer YOUR_API_KEY_OR_TOKEN",
+ "X-Custom-Header": "some_value"
+ },
+ "timeout": 5.0,
+ "sse_read_timeout": 300.0,
+ "disabled": false
+}
+```
+
+**Streaming HTTP Variants:**
+Type can be: `"http-stream"`, `"streaming-http"`, `"streamable-http"`, or `"http-streaming"`
+
+### Example in settings.json
+
+```json
+{
+ "mcp_servers": "[{'name': 'MyPythonTools', 'command': 'python3', 'args': ['mcp_scripts/my_server.py'], 'disabled': false}, {'name': 'ExternalAPI', 'url': 'https://data.example.com/mcp', 'headers': {'X-Auth-Token': 'supersecret'}, 'disabled': false}]"
+}
+```
+
+## Key Configuration Fields
+
+### Common Fields
+
+- **`name`**: Unique server identifier. Used to prefix tools (e.g., `server_name.tool_name`). Normalized internally (lowercase, spaces/hyphens → underscores)
+- **`type`**: Optional explicit type. Auto-detected if omitted based on `command` (stdio) or `url` (defaults to sse)
+- **`disabled`**: Boolean. Set `true` to ignore this server without removing configuration
+- **`description`**: Optional human-readable description
+
+### Type-Specific Required Fields
+
+- **Stdio servers**: Require `command`
+- **Remote servers**: Require `url`
+
+## Docker Networking Considerations
+
+### Agent Zero in Docker, MCP Server on Host
+
+**macOS/Windows:**
+```json
+{
+ "url": "http://host.docker.internal:PORT/endpoint"
+}
+```
+
+**Linux:**
+- Run MCP server in the same Docker network
+- Reference by container name: `http://container_name:PORT/endpoint`
+
+### Remote MCP Servers
+
+Use standard HTTPS URLs:
+```json
+{
+ "url": "https://api.example.com/mcp-endpoint"
+}
+```
+
+## Using MCP Tools
+
+### Tool Naming Convention
+
+MCP tools are prefixed with the normalized server name:
+
+- Server name: `"sequential-thinking"`
+- Tool name from server: `"run_chain"`
+- Final tool name in Agent Zero: `sequential_thinking.run_chain`
+
+### Agent Interaction
+
+Instruct the agent to use MCP tools directly:
+
+```
+"Agent, use the sequential_thinking.run_chain tool with the following input..."
+```
+
+The LLM formulates the appropriate JSON request automatically.
+
+### Execution Flow
+
+1. `process_tools` method receives tool request
+2. `mcp_handler.py` checks if tool name exists in `MCPConfig`
+3. If found: delegates to corresponding MCP server
+4. If not found: attempts to find built-in tool with that name
+
+This prioritization allows MCP tools to extend or override built-in functionality.
+
+## Troubleshooting
+
+### Server Not Connecting
+
+**Check status in UI:**
+- Settings → MCP/A2A → External MCP Servers
+- Green indicator = connected
+- Red indicator = connection failed
+
+**Common issues:**
+- Wrong URL or port
+- Missing authentication headers
+- Network/firewall blocking connection
+- Server not running
+
+### Tools Not Appearing
+
+**Verification steps:**
+1. Confirm server shows as connected (green status)
+2. Check server exposes tools (count shown in UI)
+3. Verify tool names match server documentation
+4. For `npx`/`uvx` servers, first run downloads packages (may take time)
+
+### Encoding Issues (Stdio Servers)
+
+Adjust encoding settings:
+```json
+{
+ "encoding": "utf-8",
+ "encoding_error_handler": "replace"
+}
+```
+
+Error handler options:
+- `"strict"`: Fail on encoding errors (default)
+- `"ignore"`: Skip problematic characters
+- `"replace"`: Replace with placeholder character
+
+## Security Considerations
+
+### API Keys and Secrets
+
+Store sensitive data securely:
+- Use environment variables when possible
+- Avoid committing secrets to version control
+- Use header-based authentication for remote servers
+
+### Network Security
+
+- Use HTTPS for remote MCP servers
+- Validate SSL certificates (default behavior)
+- Restrict network access to trusted servers only
+
+### Local Stdio Servers
+
+- Only run trusted executables
+- Review server code before execution
+- Use environment isolation when possible
+
+## Performance Optimization
+
+### Connection Timeouts
+
+Adjust for network conditions:
+```json
+{
+ "timeout": 10.0, // Initial connection
+ "sse_read_timeout": 600.0 // Long-running operations
+}
+```
+
+### Server Pooling
+
+For high-frequency tool usage:
+- Agent Zero maintains persistent connections to remote servers
+- Stdio servers are kept alive between tool calls
+- Reduces overhead for repeated operations
+
+## Advanced Examples
+
+### Multi-Server Configuration
+
+```json
+{
+ "mcpServers": {
+ "browser": {
+ "command": "npx",
+ "args": ["-y", "chrome-devtools-mcp@latest"]
+ },
+ "database": {
+ "command": "uvx",
+ "args": ["mcp-server-sqlite", "--db-path", "/data/app.db"]
+ },
+ "external-api": {
+ "url": "https://api.example.com/mcp",
+ "headers": {
+ "Authorization": "Bearer token123"
+ }
+ },
+ "backup-api": {
+ "url": "https://backup.example.com/mcp",
+ "disabled": true
+ }
+ }
+}
+```
+
+### Custom Environment Variables
+
+```json
+{
+ "mcpServers": {
+ "python-tools": {
+ "command": "python3",
+ "args": ["/opt/tools/mcp_server.py"],
+ "env": {
+ "PYTHONPATH": "/opt/libs:/usr/local/lib/python3.9",
+ "API_KEY": "secret_key",
+ "DEBUG": "true"
+ }
+ }
+ }
+}
+```
+
+## Integration Patterns
+
+### Tool Composition
+
+Combine multiple MCP servers for complex workflows:
+1. Browser MCP for data extraction
+2. Database MCP for storage
+3. Workflow MCP for orchestration
+
+Agent Zero can chain these tools automatically based on task requirements.
+
+### Fallback Configuration
+
+```json
+{
+ "mcpServers": {
+ "primary-service": {
+ "url": "https://primary.example.com/mcp"
+ },
+ "fallback-service": {
+ "url": "https://fallback.example.com/mcp",
+ "disabled": true
+ }
+ }
+}
+```
+
+Enable fallback manually when primary service is unavailable.
+
+## Development and Testing
+
+### Testing MCP Configurations
+
+1. Add server with `disabled: false`
+2. Save and check connection status
+3. Test individual tools via agent prompts
+4. Monitor logs for errors
+5. Adjust configuration as needed
+
+### Creating Custom MCP Servers
+
+For developing custom MCP servers:
+- Follow MCP protocol specifications
+- Implement stdio or HTTP transport
+- Provide clear tool descriptions
+- Test with Agent Zero before production
+
+See [MCP Protocol Documentation](https://modelcontextprotocol.io) for implementation details.
+
+## Related Documentation
+
+- [MCP Setup](../guides/mcp-setup.md) - Quick start guide
+- [Connectivity: MCP Server](connectivity.md#mcp-server-connectivity) - Exposing Agent Zero as MCP server
+- [Advanced: Extensions](extensions.md) - Custom tools and extensions
diff --git a/docs/notifications.md b/docs/developer/notifications.md
similarity index 97%
rename from docs/notifications.md
rename to docs/developer/notifications.md
index e78e554522..fac6363fb0 100644
--- a/docs/notifications.md
+++ b/docs/developer/notifications.md
@@ -2,6 +2,9 @@
Quick guide for using the notification system in Agent Zero.
+> [!TIP]
+> Notifications pair well with scheduled tasks. See [Tasks & Scheduling](../guides/usage.md#tasks--scheduling) for automation patterns.
+
## Backend Usage
Use `AgentNotification` helper methods anywhere in your Python code:
diff --git a/docs/developer/plugins.md b/docs/developer/plugins.md
new file mode 100644
index 0000000000..df4c8ce380
--- /dev/null
+++ b/docs/developer/plugins.md
@@ -0,0 +1,196 @@
+# Plugins
+
+This page documents the current Agent Zero plugin system, including manifest format, discovery rules, scoped configuration, activation behavior, and how to share a plugin with the community.
+
+## Overview
+
+Plugins extend Agent Zero through convention-based folders. A plugin can provide:
+
+- Backend: API handlers, tools, helpers, Python lifecycle extensions
+- Frontend: WebUI components and extension-point injections
+- Agent profiles: plugin-scoped subagent definitions
+- Settings: scoped plugin configuration loaded through the plugin settings store
+- Activation control: global and per-scope ON/OFF rules
+
+Primary roots (priority order):
+
+1. `usr/plugins/` (user/custom plugins)
+2. `plugins/` (core/built-in plugins)
+
+On name collisions, user plugins take precedence.
+
+## Manifest (`plugin.yaml`)
+
+Every plugin must contain `plugin.yaml`. This is the **runtime manifest** — it drives Agent Zero behavior. It is distinct from the index manifest used when publishing to the Plugin Index (see [Publishing to the Plugin Index](#publishing-to-the-plugin-index) below).
+
+```yaml
+title: My Plugin
+description: What this plugin does.
+version: 1.0.0
+settings_sections:
+ - agent
+per_project_config: false
+per_agent_config: false
+always_enabled: false
+```
+
+Field reference:
+
+- `title`: UI display name
+- `description`: short plugin summary
+- `version`: plugin version string
+- `settings_sections`: where plugin settings appear (`agent`, `external`, `mcp`, `developer`, `backup`)
+- `per_project_config`: enables project-scoped settings/toggles
+- `per_agent_config`: enables agent-profile-scoped settings/toggles
+- `always_enabled`: forces ON state and disables toggle controls
+
+## Recommended Structure
+
+```text
+usr/plugins//
+├── plugin.yaml
+├── default_config.yaml # optional defaults
+├── README.md # optional, shown in Plugin List UI
+├── LICENSE # optional, shown in Plugin List UI
+├── api/ # ApiHandler implementations
+├── tools/ # Tool implementations
+├── helpers/ # shared Python logic
+├── prompts/
+├── agents/
+│ └── /agent.yaml # optional plugin-distributed agent profile
+├── extensions/
+│ ├── python//
+│ └── webui//
+└── webui/
+ ├── config.html # optional settings UI
+ └── ...
+```
+
+## Settings Resolution
+
+Plugin settings are resolved by scope. Higher priority overrides lower priority:
+
+1. `project/.a0proj/agents//plugins//config.json`
+2. `project/.a0proj/plugins//config.json`
+3. `usr/agents//plugins//config.json`
+4. `usr/plugins//config.json`
+5. `plugins//default_config.yaml` (fallback defaults)
+
+Notes:
+
+- Runtime reads support JSON and YAML fallback files.
+- Save path is scope-specific and persisted through plugin settings APIs.
+
+## Activation Model
+
+Activation is independent per scope and file-based:
+
+- `.toggle-1` means ON
+- `.toggle-0` means OFF
+- no explicit rule means ON by default
+
+WebUI activation states:
+
+- `ON`: explicit ON or implicit default
+- `OFF`: explicit OFF rule at selected scope
+- `Advanced`: at least one project/agent-profile override exists
+
+`always_enabled: true` bypasses OFF state and keeps the plugin ON in both backend and UI.
+
+## UI Flow
+
+Current plugin UX surfaces activation in two places:
+
+- Plugin list: simple ON/OFF selector, with `Advanced` option when scoped overrides are enabled
+- Plugin switch modal: scope-aware ON/OFF controls per project/profile, with direct handoff to settings
+
+Scope synchronization behavior:
+
+- Opening "Configure Plugin" from the switch modal propagates current scope into settings store
+- Switching scope in settings also mirrors into toggle store so activation status stays aligned
+
+## API Surface
+
+Core plugin management endpoint: `POST /api/plugins`
+
+Supported actions:
+
+- `get_config`
+- `save_config`
+- `list_configs`
+- `delete_config`
+- `toggle_plugin`
+- `get_doc` (fetches README.md or LICENSE for display in the UI)
+
+## Publishing to the Plugin Index
+
+The **Plugin Index** is a community-maintained repository at https://github.com/agent0ai/a0-plugins. Plugins listed there are discoverable by all Agent Zero users.
+
+### Two Distinct plugin.yaml Files
+
+There are two completely different `plugin.yaml` schemas — they must not be confused:
+
+**Runtime manifest** (inside your plugin's own repo, drives Agent Zero behavior):
+```yaml
+title: My Plugin
+description: What this plugin does.
+version: 1.0.0
+settings_sections:
+ - agent
+per_project_config: false
+per_agent_config: false
+always_enabled: false
+```
+
+**Index manifest** (submitted to `a0-plugins` under `plugins//`, drives discoverability only):
+```yaml
+title: My Plugin
+description: What this plugin does.
+github: https://github.com/yourname/your-plugin-repo
+tags:
+ - tools
+ - example
+```
+
+The index manifest has only four fields (`title`, `description`, `github`, `tags`). The `github` URL must point to a public GitHub repository that contains a runtime `plugin.yaml` at the **repository root**.
+
+### Repository Structure for Community Plugins
+
+Plugin repos should expose the plugin contents at the repo root, so they can be cloned directly into `usr/plugins//`:
+
+```text
+your-plugin-repo/ ← GitHub repository root
+├── plugin.yaml ← runtime manifest
+├── default_config.yaml
+├── README.md
+├── LICENSE
+├── api/
+├── tools/
+├── extensions/
+└── webui/
+```
+
+### Submission Process
+
+1. Create a GitHub repository with the runtime `plugin.yaml` at the repo root.
+2. Fork `https://github.com/agent0ai/a0-plugins`.
+3. Add `plugins//plugin.yaml` (index manifest) to your fork, and optionally a square thumbnail image (≤ 20 KB, named `thumbnail.png|jpg|webp`).
+4. Open a Pull Request. One PR must add exactly one new plugin folder.
+5. CI validates automatically. A maintainer reviews and merges.
+
+Submission rules:
+- Folder name: unique, stable, lowercase, kebab-case
+- Folders starting with `_` are reserved for internal use
+- `title`: max 50 characters
+- `description`: max 500 characters
+- `tags`: optional, up to 5, see https://github.com/agent0ai/a0-plugins/blob/main/TAGS.md
+
+### Plugin Marketplace (Coming Soon)
+
+A built-in **Plugin Marketplace** (always-active plugin) will allow users to browse the Plugin Index and install or update community plugins directly from the Agent Zero UI without leaving the application. This section will be updated once the marketplace plugin is released.
+
+## See Also
+
+- `AGENTS.plugins.md` for full architecture details
+- `skills/a0-create-plugin/SKILL.md` for plugin authoring workflow (agent-facing)
+- `plugins/README.md` for core plugin directory overview
diff --git a/docs/developer/websockets.md b/docs/developer/websockets.md
new file mode 100644
index 0000000000..d2f44e7758
--- /dev/null
+++ b/docs/developer/websockets.md
@@ -0,0 +1,727 @@
+# WebSocket Infrastructure Guide
+
+This guide consolidates everything you need to design, implement, and troubleshoot Agent Zero WebSocket flows. It complements the feature specification by describing day-to-day developer tasks, showing how backend handlers and frontend clients cooperate, and documenting practical patterns for producers and consumers on both sides of the connection.
+
+---
+
+## Table of Contents
+
+1. [Architecture at a Glance](#architecture-at-a-glance)
+2. [Terminology & Metadata](#terminology--metadata)
+3. [Connection Lifecycle](#connection-lifecycle)
+4. [Backend Cookbook (Handlers & Manager)](#backend-cookbook-handlers--manager)
+5. [Frontend Cookbook (websocket.js)](#frontend-cookbook-websocketjs)
+6. [Producer & Consumer Patterns](#producer--consumer-patterns)
+7. [Metadata Flow & Envelopes](#metadata-flow--envelopes)
+8. [Diagnostics, Harness & Logging](#diagnostics-harness--logging)
+9. [Best Practices Checklist](#best-practices-checklist)
+10. [Quick Reference Tables](#quick-reference-tables)
+11. [Further Reading](#further-reading)
+
+---
+
+## Architecture at a Glance
+
+- **Runtime (`run_ui.py`)** – boots `python-socketio.AsyncServer` inside an ASGI stack served by Uvicorn. Flask routes are mounted via `uvicorn.middleware.wsgi.WSGIMiddleware`, and Flask + Socket.IO share the same process so session cookies and CSRF semantics stay aligned.
+- **Singleton handlers** – every `WebSocketHandler` subclass exposes `get_instance()` and is registered exactly once. Direct instantiation raises `SingletonInstantiationError`, keeping shared state and lifecycle hooks deterministic.
+- **Dispatcher offload** – handler entrypoints (`process_event`, `on_connect`, `on_disconnect`) run in a background worker loop (via `DeferredTask`) so blocking handlers cannot stall the Socket.IO transport. Socket.IO emits/disconnects are marshalled back to the dispatcher loop. Diagnostic timing and payload summaries are only built when Event Console watchers are subscribed (development mode).
+- **`python/helpers/websocket_manager.py`** – orchestrates routing, buffering, aggregation, metadata envelopes, and session tracking. Think of it as the “switchboard” for every WebSocket event.
+- **`python/helpers/websocket.py`** – base class for application handlers. Provides lifecycle hooks, helper methods (`emit_to`, `broadcast`, `request`, `request_all`) and identifier metadata.
+- **`webui/js/websocket.js`** – frontend singleton exposing a minimal client API (`emit`, `request`, `on`, `off`) with lazy connection management and development-only logging (no client-side `broadcast()` or `requestAll()` helpers).
+- **Developer Harness (`webui/components/settings/developer/websocket-test-store.js`)** – manual and automatic validation suite for emit/request flows, timeout behaviour (including the default unlimited wait), correlation ID propagation, envelope metadata, subscription persistence across reconnect, and development-mode diagnostics.
+- **Specs & Contracts** – canonical definitions live under `specs/003-websocket-event-handlers/`. This guide references those documents but focuses on applied usage.
+
+---
+
+## Terminology & Metadata
+
+| Term | Where it Appears | Meaning |
+|------|------------------|---------|
+| `sid` | Socket.IO | Connection identifier for a Socket.IO namespace connection. With only the root namespace (`/`), each tab has one `sid`. When connecting to multiple namespaces, a tab has one `sid` per namespace. Treat connection identity as `(namespace, sid)`. |
+| `handlerId` | Manager Envelope | Fully-qualified Python class name (e.g., `python.websocket_handlers.notifications.NotificationHandler`). Used for result aggregation and logging. |
+| `eventId` | Manager Envelope | UUIDv4 generated for every server→client delivery. Unique per emission. Useful when correlating broadcast fan-out or diagnosing duplicates. |
+| `correlationId` | Bidirectional flows | Thread that ties together request, response, and any follow-up events. Client may supply one; otherwise the manager generates and echoes it everywhere. |
+| `data` | Envelope payload | Application payload you define. Always a JSON-serialisable object. |
+| `user_to_sids` / `sid_to_user` | Manager session tracking | Single-user map today (`allUsers` bucket). Future-proof for multi-tenant routing but already handy when you need all active SIDs. |
+| Buffer | Manager | Up to 100 fire-and-forget events stored per temporarily disconnected SID (expires after 1 hour). Request/response events never buffer—clients receive standardised errors instead. |
+
+Useful mental model: **client ↔ manager ↔ handler**. The manager normalises metadata and enforces routing; handlers focus on business logic; the frontend uses the same identifiers, so logs are easy to stitch.
+
+---
+
+## Connection Lifecycle
+
+1. **Lazy Connect** – `/js/websocket.js` connects only when a consumer uses the client API (e.g., `emit`, `request`, `on`). Consumers may still explicitly `await websocket.connect()` to block UI until the socket is ready.
+2. **Handshake** – Socket.IO connects using the existing Flask session cookie and a CSRF token provided via the Socket.IO `auth` payload (`csrf_token`). The token is obtained from `GET /csrf_token` (see `/js/api.js#getCsrfToken()`), which also sets the runtime-scoped cookie `csrf_token_{runtime_id}`. The server validates an **Origin allowlist** (RFC 6455 / OWASP CSWSH baseline) and then checks handler requirements (`requires_auth`, `requires_csrf`) before accepting.
+3. **Lifecycle Hooks** – After acceptance, `WebSocketHandler.on_connect(sid)` fires for every registered handler. Use it for initial emits, state bookkeeping, or session tracking.
+4. **Normal Operation** – Client emits events. Manager routes them to the appropriate handlers, gathers results, and wraps outbound deliveries in the mandatory envelope.
+5. **Disconnection & Buffering** – If a tab goes away without a graceful disconnect, fire-and-forget events accumulate (max 100). On reconnect, the manager flushes the buffer via `emit_to`. Request flows respond with explicit `CONNECTION_NOT_FOUND` errors.
+6. **Reconnection Attempts** – Socket.IO handles reconnect attempts; the manager continues to buffer fire-and-forget events (up to 1 hour) for temporarily disconnected SIDs and flushes them on reconnect.
+
+### State Sync (Replacing `/poll`)
+
+Agent Zero can also push poll-shaped state snapshots over the WebSocket bus, replacing the legacy 4Hz `/poll` loop while preserving the existing UI update contract.
+
+- **Handshake**: the frontend sync store (`/components/sync/sync-store.js`) calls `websocket.request("state_request", { context, log_from, notifications_from, timezone })` to establish per-tab cursors and a `seq_base`.
+- **Push**: the server emits `state_push` events containing `{ runtime_epoch, seq, snapshot }`, where `snapshot` is exactly the `/poll` payload shape built by `python/helpers/state_snapshot.py`.
+- **Coalescing**: the backend `StateMonitor` coalesces dirties per SID (25ms window) so streaming updates stay smooth without unbounded trailing-edge debounce.
+- **Degraded fallback**: if the WebSocket handshake/push path is unhealthy, the UI enters `DEGRADED` and uses `/poll` as a fallback; while degraded, push snapshots are ignored to avoid racey double-writes.
+
+### Thinking in Roles
+
+- **Client** (frontend) is the page that imports `/js/websocket.js`. It acts as both a **producer** (calling `emit`, `request`) and a **consumer** (subscribing with `on`).
+- **Manager** (`WebSocketManager`) sits server-side and routes everything. It resolves correlation IDs, wraps envelopes, and fans out results.
+- **Handler** (`WebSocketHandler`) executes the application logic. Each handler may emit additional events back to the client or initiate its own requests to connected SIDs.
+
+### Flow Overview (by Operation)
+
+```
+Client emit() ───▶ Manager route_event() ───▶ Handler.process_event()
+ │ │ └──(fire-and-forget, no ack)
+ └── throws if └── validates payload + routes by namespace/event type
+ not connected updates last_activity
+
+Client request() ─▶ Manager route_event() ─▶ Handlers (async gather)
+ │ │ └── per-handler dict/None
+ │ │
+ │ └── builds {correlationId, results[]}
+ └── Promise resolves with aggregated results (timeouts become error items)
+
+Server emit_to() ──▶ Manager.emit_to() ──▶ Socket.IO delivery/buffer
+ │ │ └── envelope {handlerId,…}
+ └── raises ConnectionNotFoundError for unknown sid (never seen)
+
+Server broadcast() ─▶ Manager.broadcast()
+ │ └── iterates active sids (respecting exclude_sids)
+ │ └── delegates to `Manager.emit_to()` → `socketio.emit(..., to=sid)`
+ └── fire-and-forget (no ack)
+
+Server request() ─▶ Manager.request_for_sid() ─▶ route_event()
+ │ │ └── per-handler responses
+ └── Await aggregated {correlationId, results[]}
+
+Server request_all() ─▶ Manager.route_event_all() ─▶ route_event per sid
+ │ │ └── per-handler results
+ └── Await list[{sid, correlationId, results[]}]
+```
+
+These diagrams highlight the “who calls what” surface while the detailed semantics (envelopes, buffering, timeouts) remain consistent with the tables later in this guide.
+
+### End-to-End Examples
+
+1. **Client request ➜ multiple handlers**
+
+ 1. Frontend calls `websocket.request("refresh_metrics", payload)`.
+ 2. Manager routes to each handler registered for that event type and awaits `asyncio.gather`.
+ 3. Each handler returns a dict (or raises); the manager wraps them in `results[]` and resolves the Promise with `{ correlationId, results }`.
+ 4. The caller inspects per-handler data or errors, filtering by `handlerId` as needed.
+
+2. **Server broadcast with buffered replay**
+
+ 1. Handler invokes `self.broadcast("notification_broadcast", data, exclude_sids=sid)`.
+ 2. Manager iterates active connections. For connected SIDs it emits immediately with the mandatory envelope. For temporarily disconnected SIDs it enqueues into the per-SID buffer (up to 100 events).
+ 3. When a buffered SID reconnects, `_flush_buffer()` replays the queued envelopes preserving `handlerId`, `eventId`, `correlationId`, and `ts`.
+
+3. **Server request_all ➜ client-side confirmations**
+
+ 1. Handler issues `await self.request_all("confirm_close", { contextId }, timeout_ms=5000)`.
+ 2. Manager fans out to every active SID, allowing `exclude_handlers` when provided.
+ 3. Each subscribed client runs its `websocket.on("confirm_close", …)` callback and returns data through the Socket.IO acknowledgement.
+ 4. The handler receives `[{ sid, correlationId, results[] }]`, inspects each response, and proceeds accordingly.
+
+These expanded flows complement the operation matrix later in the guide, ensuring every combination (client/server × emit/request and server request_all) is covered explicitly.
+
+---
+
+## Backend Cookbook (Handlers & Manager)
+
+### 1. Handler Discovery & Setup
+
+Handlers are discovered deterministically from `python/websocket_handlers/`:
+
+- **File entry**: `python/websocket_handlers/state_sync_handler.py` → namespace `/state_sync`
+- **Folder entry**: `python/websocket_handlers/orders/` or `python/websocket_handlers/orders_handler/` → namespace `/orders` (loads `*.py` one level deep; ignores `__init__.py` and deeper nesting)
+- **Reserved root**: `python/websocket_handlers/_default.py` → namespace `/` (diagnostics-only by default)
+
+Create handler modules under the appropriate namespace entry and inherit from `WebSocketHandler`.
+
+```python
+from python.helpers.websocket import WebSocketHandler
+
+class DashboardHandler(WebSocketHandler):
+ @classmethod
+ def get_event_types(cls) -> list[str]:
+ return ["dashboard_refresh", "dashboard_push"]
+
+ async def process_event(self, event_type: str, data: dict[str, Any], sid: str) -> dict | None:
+ if event_type == "dashboard_refresh":
+ stats = await self._load_stats(data.get("scope", "all"))
+ return {"ok": True, "stats": stats}
+
+ if event_type == "dashboard_push":
+ await self.broadcast(
+ "dashboard_update",
+ {"stats": data.get("stats", {}), "source": sid},
+ exclude_sids=sid,
+ )
+ return None
+```
+
+Handlers are auto-loaded on startup; duplicate event declarations produce warnings but are supported. Use `validate_event_types` to ensure names follow lowercase snake_case and avoid Socket.IO reserved events.
+
+### 2. Consuming Client Events (Server as Consumer)
+
+- Implement `process_event` and return either `None` (fire-and-forget) or a dict that becomes the handler’s contribution in `results[]`.
+- Use dependency injection (async functions, database calls, etc.) but keep event loop friendly—no blocking calls.
+- Validate input vigorously and return structured errors as needed.
+
+```python
+async def process_event(self, event_type: str, data: dict, sid: str) -> dict | None:
+ if "query" not in data:
+ return {"ok": False, "error": {"code": "VALIDATION", "error": "Missing query"}}
+
+ rows = await self.search_backend(data["query"], limit=data.get("limit", 25))
+ return {"ok": True, "data": rows, "count": len(rows)}
+```
+
+### 3. Producing Server Events (Server as Producer)
+
+Four helper methods mirror the frontend API. The table below summarises them (full table in [Quick Reference](#quick-reference-tables)).
+
+| Method | Target | Ack | Filters | Typical Use |
+|--------|--------|-----|---------|--------------|
+| `emit_to(sid, event, data, correlation_id=None)` | Single SID | No | None | Push job progress, reply to a request without using Socket.IO ack (already produced). |
+| `broadcast(event, data, exclude_sids=None, correlation_id=None)` | All SIDs | No | `exclude_sids` only | Fan-out notifications, multi-tab sync while skipping the caller. |
+| `request(sid, event, data, timeout_ms=0)` | Single SID | Yes (`results[]`) | None | Ask the client to run local logic (e.g., UI confirmation) and gather per-handler results. |
+| `request_all(event, data, timeout_ms=0)` | All SIDs | Yes (`[{sid, results[]}]`) | None | Fan-out to every tab, e.g., “refresh your panel” or “confirm unsaved changes”. |
+
+Each helper automatically injects `handlerId`, obeys metadata envelopes, enforces routing rules, and handles timeouts:
+
+```python
+aggregated = await self.request_all(
+ "workspace_ping",
+ {"payload": {"reason": "health_check"}},
+ timeout_ms=2_000,
+)
+
+for entry in aggregated:
+ self.log.info("sid %s replied: %s", entry["sid"], entry["results"])
+```
+
+Timeouts convert into `{ "ok": False, "error": {"code": "TIMEOUT", ...} }`; they do **not** raise.
+
+### 4. Multi-Handler Aggregation
+
+- When multiple handlers subscribe to the same event, the manager invokes them concurrently with `asyncio.gather`. Aggregated results preserve registration order. Use correlation IDs to map responses to original triggers.
+- Client-side handler include/exclude filters are intentionally not supported. Consumers filter `results[]` by `handlerId` when needed.
+
+```python
+if not results:
+ return {
+ "handlerId": self.identifier,
+ "ok": False,
+ "error": {"code": "NO_HANDLERS", "error": "No handler registered for this event type"},
+ }
+```
+
+### 5. Session Tracking Helpers
+
+`WebSocketManager` maintains lightweight mappings that you can use from handlers:
+
+```python
+all_sids = self.manager.get_sids_for_user() # today: every active sid
+maybe_user = self.manager.get_user_for_sid(sid) # currently None or "single_user"
+
+if updated_payload:
+ await asyncio.gather(
+ *[
+ self.emit_to(other_sid, "dashboard_update", updated_payload)
+ for other_sid in all_sids if other_sid != sid
+ ]
+ )
+```
+
+These helpers are future-proof for multi-tenant evolution and already handy to broadcast to every tab except the caller.
+
+**Future Multitenancy Mechanics**
+- **Registration**: When multi-user support ships, `handle_connect` will resolve the authenticated user identifier (e.g., from Flask session). `register()` will stash that identifier alongside the SID and place it into `user_to_sids[user_id]` while still populating the `allUsers` bucket for backward compatibility.
+- **Lookups**: `get_sids_for_user(user_id)` will return the tenant-specific SID set. Omitting the argument (or passing `None`) keeps today’s behaviour and yields the full `allUsers` list. `get_user_for_sid(sid)` will expose whichever identifier was recorded at registration.
+- **Utility**: These primitives unlock future features such as sending workspace notifications to every tab owned by the same account, ejecting all sessions for a suspended user, or correlating request/response traffic per tenant without rewriting handlers.
+- **Migration Story**: Existing handler code that loops over `get_sids_for_user()` automatically gains tenant-scoped behaviour once callers pass a `user_id`. Tests will exercise both single-user (default) and multi-tenant branches to guarantee compatibility.
+
+---
+
+## Frontend Cookbook (`websocket.js`)
+
+### 1. Connecting
+
+```javascript
+import { getNamespacedClient } from "/js/websocket.js";
+
+const websocket = getNamespacedClient("/"); // reserved root (diagnostics-only by default)
+
+// Optional: await the handshake if you need to block UI until the socket is ready
+await websocket.connect();
+
+// Runtime metadata is exposed globally for Alpine stores / harness
+console.log(window.runtimeInfo.id, window.runtimeInfo.isDevelopment);
+```
+
+- The module connects lazily when a consumer uses the client API (e.g., `emit`, `request`, `on`). Components may still explicitly `await websocket.connect()` to block rendering on readiness or re-run diagnostics.
+- The server enforces an Origin allowlist during the Socket.IO connect handshake (baseline CSWSH mitigation). The browser session cookie remains the authentication mechanism, and CSRF is validated via the Socket.IO `auth` payload (`csrf_token`) plus the runtime-scoped CSRF cookie and session value.
+- Socket.IO handles reconnection attempts automatically.
+
+### Namespaces (end-state)
+
+- The root namespace (`/`) is reserved and intentionally unhandled by default for application events. Feature code should connect to an explicit namespace (for example `/state_sync`).
+- The frontend exposes `createNamespacedClient(namespace)` and `getNamespacedClient(namespace)` (one client instance per namespace per tab). Namespaced clients expose the same minimal API: `emit`, `request`, `on`, `off`.
+- Unknown namespaces are rejected deterministically during the Socket.IO connect handshake with a `connect_error` payload:
+ - `err.message === "UNKNOWN_NAMESPACE"`
+ - `err.data === { code: "UNKNOWN_NAMESPACE", namespace: "/requested" }`
+
+### 2. Client Operations
+
+- **Producers (client → server)** use `emit` and `request`. Payloads must be objects; primitive payloads throw.
+- **Consumers (server → client)** register callbacks with `on(eventType, callback)` and remove them with `off()`.
+
+Example (producer):
+
+```javascript
+await websocket.request("hello_request", { name: this.name }, {
+ timeoutMs: 1500,
+ correlationId: `greet-${crypto.randomUUID()}`,
+});
+```
+
+Example (consumer):
+
+```javascript
+websocket.on("dashboard_update", (envelope) => {
+ const { handlerId, correlationId, ts, data } = envelope;
+ this.debugLog({ handlerId, correlationId, ts });
+ this.rows = data.rows;
+});
+
+// Later, during cleanup
+websocket.off("dashboard_update");
+```
+
+### 3. Envelope Awareness
+
+Subscribers always receive:
+
+```javascript
+interface ServerDeliveryEnvelope {
+ handlerId: string;
+ eventId: string;
+ correlationId: string;
+ ts: string; // ISO8601 UTC with millisecond precision
+ data: object;
+}
+```
+
+Even if existing components only look at `data`, you should record `handlerId` and `correlationId` when building new features—doing so simplifies debugging multi-tab flows.
+
+### 4. Development-Only Logging
+
+`websocket.debugLog()` writes to the console only when `runtimeInfo.isDevelopment` is true. Use it liberally when diagnosing event flows without polluting production logs.
+
+```javascript
+websocket.debugLog("request", { correlationId: payload.correlationId, timeoutMs });
+```
+
+### 5. Helper Utilities
+
+`webui/js/websocket.js` exports helper utilities alongside the `websocket` singleton so correlation metadata and envelopes stay consistent:
+
+- `createCorrelationId(prefix?: string)` returns a UUID-based identifier, optionally prefixed (e.g. `createCorrelationId('hello') → hello-1234…`). Use it when chaining UI actions to backend logs.
+- `validateServerEnvelope(envelope)` guarantees subscribers receive the canonical `{ handlerId, eventId, correlationId, ts, data }` shape; throw if the payload is malformed.
+
+Example:
+
+```javascript
+import { getNamespacedClient, createCorrelationId, validateServerEnvelope } from '/js/websocket.js';
+
+const websocket = getNamespacedClient('/state_sync');
+
+const { results } = await websocket.request(
+ 'hello_request',
+ { name: this.name },
+ { correlationId: createCorrelationId('hello') },
+);
+
+websocket.on('dashboard_update', (envelope) => {
+ const validated = validateServerEnvelope(envelope);
+ this.rows = validated.data.rows;
+});
+```
+
+### 6. Error Handling
+
+- Producer methods call `websocket.connect()` internally, so they wait for the handshake automatically. They only surface `Error("Not connected")` if the handshake ultimately fails (for example, the user is logged out or the server is down).
+- `request()` acknowledgement timeouts reject with `Error("Request timeout")`. Server-side fan-out timeouts (for example `request_all`) are represented as `results[]` entries with `error.code = "TIMEOUT"` (no Promise rejection).
+- For large payloads, the client throws before sending and the server rejects frames above the 50 MiB cap (`max_http_buffer_size` on the Socket.IO engine).
+
+### 7. Startup Broadcast
+
+- When **Broadcast server restart event** is enabled in Developer settings (on by default) the backend emits a fire-and-forget `server_restart` envelope the first time each connection is established after a process restart. The payload includes `runtimeId` and an ISO8601 timestamp so clients can reconcile cached state.
+- Disable the toggle if your deployment pipeline already publishes restart notifications.
+
+---
+
+## Frontend Error Handling (Using the Registry)
+
+Client code should treat `RequestResultItem.error.code` as one of the documented values and branch behavior accordingly. Keep UI decisions localized and reusable.
+
+Recommended patterns
+- Centralize mapping from `WsErrorCode` → user-facing message and remediation hint.
+- Always surface hard errors (timeouts); gate debug details by dev flag.
+
+Example – request()
+```javascript
+import { getNamespacedClient } from '/js/websocket.js'
+
+const websocket = getNamespacedClient('/state_sync')
+
+function renderError(code, message) {
+ // Map codes to UI copy; keep messages concise
+ switch (code) {
+ case 'NO_HANDLERS': return `No handler for this action (${message})`
+ case 'TIMEOUT': return `Request timed out; try again or increase timeout`
+ case 'CONNECTION_NOT_FOUND': return `Target connection unavailable; retry after reconnect`
+ default: return message || 'Unexpected error'
+ }
+}
+
+const res = await websocket.request('example_event', { foo: 'bar' }, { timeoutMs: 1500 })
+for (const item of res.results) {
+ if (item.ok) {
+ // use item.data
+ } else {
+ const msg = renderError(item.error?.code, item.error?.error)
+ // show toast/log based on dev flag
+ console.error('[ws]', msg)
+ }
+}
+```
+
+Subscriptions – envelope handler
+```javascript
+import { getNamespacedClient } from '/js/websocket.js'
+
+const websocket = getNamespacedClient('/state_sync')
+
+websocket.on('example_broadcast', ({ data, handlerId, eventId, correlationId }) => {
+ // handle data; errors should not typically arrive via broadcast
+ // correlationId can link UI actions to backend logs
+})
+```
+
+See also
+- Error Codes Registry (above) for the authoritative code list
+- Contracts: `frontend-api.md` for method signatures and response shapes
+
+---
+
+## Producer & Consumer Patterns
+
+### Pattern A – Fire-and-Forget Notification (Server Producer → Client Consumers)
+
+Backend:
+
+```python
+await self.broadcast(
+ "notification_broadcast",
+ {
+ "message": data["message"],
+ "level": data.get("level", "info"),
+ "timestamp": datetime.now(timezone.utc).isoformat(),
+ },
+ exclude_sids=sid,
+ correlation_id=data.get("correlationId"),
+)
+```
+
+Frontend:
+
+```javascript
+websocket.on("notification_broadcast", ({ data, correlationId, ts }) => {
+ notifications.unshift({ ...data, correlationId, ts });
+});
+```
+
+### Pattern B – Request/Response With Multi-Handler Aggregation (Client Producer → Server Consumers)
+
+Client:
+
+```javascript
+const { correlationId, results } = await websocket.request(
+ "refresh_metrics",
+ { duration: "1h" },
+ { timeoutMs: 2_000 }
+);
+
+results.forEach(({ handlerId, ok, data, error }) => {
+ if (ok) renderMetrics(handlerId, data);
+ else console.warn(handlerId, error);
+});
+```
+
+Server (two handlers listening to the same event):
+
+```python
+class TaskMetrics(WebSocketHandler):
+ @classmethod
+ def get_event_types(cls) -> list[str]:
+ return ["refresh_metrics"]
+
+ async def process_event(self, event_type: str, data: dict, sid: str) -> dict | None:
+ stats = await self._load_task_metrics(data["duration"])
+ return {"metrics": stats}
+
+class HostMetrics(WebSocketHandler):
+ @classmethod
+ def get_event_types(cls) -> list[str]:
+ return ["refresh_metrics"]
+
+ async def process_event(self, event_type: str, data: dict, sid: str) -> dict | None:
+ return {"metrics": await self._load_host_metrics(data["duration"])}
+```
+
+### Pattern C – Fan-Out `request_all` (Server Producer → Many Client Consumers)
+
+Backend (server producer asking every tab to confirm a destructive operation):
+
+```python
+confirmations = await self.request_all(
+ "confirm_close_tab",
+ {"contextId": context_id},
+ timeout_ms=5_000,
+)
+
+for entry in confirmations:
+ self.log.info("%s responded: %s", entry["sid"], entry["results"])
+```
+
+Frontend consumer matching the envelope:
+
+```javascript
+websocket.on("confirm_close_tab", async ({ data, correlationId }) => {
+ const accepted = await showModalAndAwaitUser(data.contextId);
+ return { ok: accepted, correlationId, decision: accepted ? "close" : "stay" };
+});
+```
+
+### Pattern D – Server Reply Without Using `ack`
+
+Sometimes you want to acknowledge work immediately but stream additional updates later. Combine `request()` for the initial confirmation and `emit_to()` for follow-up events using the same correlation ID.
+
+```python
+async def process_event(self, event_type: str, data: dict, sid: str) -> dict | None:
+ if event_type != "start_long_task":
+ return None
+
+ correlation_id = data.get("correlationId")
+ asyncio.create_task(self._run_workflow(sid, correlation_id))
+ return {"accepted": True, "correlationId": correlation_id}
+
+async def _run_workflow(self, sid: str, correlation_id: str | None):
+ for step in range(10):
+ await asyncio.sleep(1)
+ await self.emit_to(
+ sid,
+ "task_progress",
+ {"step": step, "total": 10},
+ correlation_id=correlation_id,
+ )
+```
+
+---
+
+## Metadata Flow & Envelopes
+
+### Client → Server Payload
+
+Producers send an object payload as `data` (never primitives). Request metadata like `timeoutMs` and `correlationId` are passed as method options, not embedded into `data`.
+
+The manager validates the payload, resolves/creates `correlationId`, and passes a clean copy of `data` to handlers.
+
+### Server → Client Envelope (mandatory)
+
+```json
+{
+ "handlerId": "python.websocket_handlers.notifications.NotificationHandler",
+ "eventId": "b7e2a9cd-2857-4f7a-8bf4-12a736cb6720",
+ "correlationId": "caller-supplied-or-generated",
+ "ts": "2025-10-31T13:13:37.123Z",
+ "data": { "message": "Hello!" }
+}
+```
+
+**Guidance:**
+
+- Use `eventId` alongside frontend logging to spot duplicate deliveries or buffered flushes.
+- `correlationId` ties together the user action that triggered the event, even if multiple handlers participate.
+- `handlerId` helps you distinguish which handler produced the payload, especially when multiple handlers share the same event type.
+
+---
+
+## Diagnostics, Harness & Logging
+
+### Developer Harness
+
+- Location: `Settings → Developer → WebSocket Test Harness`.
+- Automatic mode drives emit, request, delayed request (default unlimited timeout), subscription persistence, and envelope validation. It asserts envelope metadata (handlerId, eventId, correlationId, ISO8601 timestamps) and correlation carryover.
+- Manual buttons let you trigger individual flows and inspect recent payloads.
+- Harness hides itself when `runtime.isDevelopment` is false so production builds incur zero overhead.
+- Helper APIs (`createCorrelationId`, `validateServerEnvelope`) are exercised end to end; subscription logs record the `server_restart` broadcast emitted on first connection after a runtime restart.
+
+### WebSocket Event Console
+
+- Location: `Settings → Developer → WebSocket Event Console`.
+- Enabling capture calls `websocket.request("ws_event_console_subscribe", { requestedAt })`. The handler (`DevWebsocketTestHandler`) refuses the subscription outside development mode and registers the SID as a **diagnostic watcher** by calling `WebSocketManager.register_diagnostic_watcher`. Only connected SIDs can subscribe.
+- Disabling capture calls `websocket.request("ws_event_console_unsubscribe", {})`. Disconnecting also triggers `WebSocketManager.unregister_diagnostic_watcher`, so stranded watchers never accumulate.
+- While at least one watcher exists, the manager streams `ws_dev_console_event` envelopes (documented in `contracts/event-schemas.md`). Each payload contains:
+ - `kind`: `"inbound" | "outbound" | "lifecycle"`
+ - `eventType`, `sid`, `targets[]`, delivery/buffer flags
+ - `resultSummary` (handler counts, per-handler status, durationMs)
+ - `payloadSummary` (first few keys + byte size)
+- Lifecycle broadcasts (`ws_lifecycle_connect` / `ws_lifecycle_disconnect`) are emitted asynchronously via `broadcast(..., diagnostic=True)` so long-running handlers can’t block dispatch.
+- The modal UI exposes:
+ - Start/stop capture (explicitly controls subscription state).
+ - Resubscribe button (detach + resubscribe) to recover gracefully after Socket.IO reconnects.
+ - Clear button (resets the in-memory ring buffer).
+ - “Handled-only” toggle that filters inbound entries to ones that resolved to registered handlers or produced errors.
+- When the watcher set becomes empty the manager immediately stops streaming diagnostics, guaranteeing zero steady-state overhead outside development.
+
+### Instrumentation & Logging
+
+- `WebSocketManager` offloads handler execution via `DeferredTask` and may record `durationMs` when development diagnostics are active (Event Console watchers subscribed). These metrics flow into the Event Console stream (and may also appear in `request()` / `request_all()` results), keeping steady-state overhead near zero when diagnostics are closed.
+- Lifecycle events capture `connectionCount`, ISO8601 timestamps, and SID so dashboards can correlate UI behaviour with connection churn.
+- Backend logging: use `PrintStyle.debug/info/warning` and always include `handlerId`, `eventType`, `sid`, and `correlationId`. The manager already logs connection events, missing handlers, and buffer overflows.
+- Frontend logging: `websocket.debugLog()` mirrors backend debug messages but only when `window.runtimeInfo.isDevelopment` is true.
+
+### Access Logs & Transport Troubleshooting
+
+- Settings → Developer includes a persisted `uvicorn_access_logs_enabled` switch. When enabled, `run_ui.py` enables Uvicorn access logs so transport issues (CORS, handshake failures) can be traced.
+- The long-standing `websocket_server_restart_enabled` switch (same section) controls whether newly connected clients receive the `server_restart` broadcast that carries `runtimeId` metadata.
+
+### Common Issues
+
+1. **`CONNECTION_NOT_FOUND`** – `emit_to` called with an SID that never existed or expired long ago. Use `get_sids_for_user` before emitting or guard on connection presence.
+2. **Timeout Rejections** – `request()` and `request_all()` reject only when the transport times out, not when a handler takes too long. Inspect the returned result arrays for `TIMEOUT` entries and consider increasing `timeoutMs`.
+3. **Origin Rejected** – the Socket.IO handshake was rejected because the `Origin` header did not match the expected UI origin. Ensure you access the UI and the WebSocket endpoint on the same scheme/host/port, and verify any reverse proxy preserves the `Origin` header.
+4. **Diagnostics Subscriptions Failing** – only available in development mode and for connected SIDs. Verify the browser tab still holds an active session and that `window.runtimeInfo.isDevelopment` is true before opening the modal.
+
+---
+
+## Best Practices Checklist
+
+- [ ] Always validate inbound payloads in `process_event` (required fields, type constraints, length limits).
+- [ ] Propagate `correlationId` through multi-step workflows so logs and envelopes align.
+- [ ] Respect the 50 MB payload cap; prefer HTTP + polling for bulk data transfers.
+- [ ] Ensure long-running operations emit progress via `emit_to` or switch to an async task with periodic updates.
+- [ ] Buffer-sensitive actions (`emit_to`) should handle `ConnectionNotFoundError` from unknown SIDs gracefully.
+- [ ] When adding new handlers, update the developer harness if new scenarios need coverage.
+- [ ] Keep `PrintStyle` logs meaningful—include `handlerId`, `eventType`, `sid`, and `correlationId`.
+- [ ] In Alpine components, call `websocket.off()` during teardown to avoid duplicate subscriptions.
+
+---
+
+## Quick Reference Tables
+
+### Operation Matrix
+
+| Direction | API | Ack? | Filters | Notes |
+|-----------|-----|------|---------|-------|
+| Client → Server | `emit(event, data, { correlationId? })` | No | None | Fire-and-forget. |
+| Client → Server | `request(event, data, { timeoutMs?, correlationId? })` | Yes (`{ correlationId, results[] }`) | None | Aggregates per handler. Timeout entries appear inside `results`. |
+| Server → Client | `emit_to(sid, ...)` | No | None | Raises `ConnectionNotFoundError` for unknown `sid`. Buffers if disconnected. |
+| Server → Client | `broadcast(...)` | No | `exclude_sids` only | Iterates over current connections; uses the same envelope as `emit_to`. |
+| Server → Client | `request(...)` | Yes (`{ correlationId, results[] }`) | None | Equivalent of client `request` but targeted at one SID from the server. |
+| Server → Client | `request_all(...)` | Yes (`[{ sid, correlationId, results[] }]`) | None | Server-initiated fan-out. |
+
+### Metadata Cheat Sheet
+
+| Field | Produced By | Guarantees |
+|-------|-------------|------------|
+| `correlationId` | Manager | Present on every response/envelope. Caller-supplied ID is preserved; otherwise manager generates UUIDv4 hex. |
+| `eventId` | Manager | Unique UUIDv4 per server→client delivery. Helpful for dedup / auditing. |
+| `handlerId` | Handler / Manager | Deterministic value `module.Class`. Used for results. |
+| `ts` | Manager | ISO8601 UTC with millisecond precision. Replaces `+00:00` with `Z`. |
+| `results[]` | Manager | Array of `{ handlerId, ok, data?, error? }`. Errors include `code`, `error`, and optional `details`. |
+
+---
+
+## Further Reading
+
+- **QuickStart** – [`specs/003-websocket-event-handlers/quickstart.md`](../specs/003-websocket-event-handlers/quickstart.md) for a step-by-step introduction.
+- **Contracts** – Backend, frontend, schema, and security contracts define the canonical API surface:
+ - [`websocket-handler-interface.md`](../specs/003-websocket-event-handlers/contracts/websocket-handler-interface.md)
+ - [`frontend-api.md`](../specs/003-websocket-event-handlers/contracts/frontend-api.md)
+ - [`event-schemas.md`](../specs/003-websocket-event-handlers/contracts/event-schemas.md)
+ - [`security-contract.md`](../specs/003-websocket-event-handlers/contracts/security-contract.md)
+- **Implementation Reference** – Inspect `python/helpers/websocket_manager.py`, `python/helpers/websocket.py`, `webui/js/websocket.js`, and the developer harness in `webui/components/settings/developer/websocket-test-store.js` for concrete examples.
+
+> **Tip:** When extending the infrastructure (new metadata) start by updating the contracts, sync the manager/frontend helpers, and then document the change here so producers and consumers stay in lockstep.
+
+## Error Codes Registry (Draft for Phase 6)
+
+The WebSocket stack standardizes backend error codes returned in `RequestResultItem.error.code`. This registry documents the currently used codes and their intended meaning. Client and server implementations should reference these values verbatim (UPPER_SNAKE_CASE).
+
+| Code | Scope | Meaning | Typical Remediation | Example Payload |
+|------|-------|---------|---------------------|-----------------|
+| `NO_HANDLERS` | Manager routing | No handler is registered for the requested `eventType`. | Register a handler for the event or correct the event name. | `{ "handlerId": "WebSocketManager", "ok": false, "error": { "code": "NO_HANDLERS", "error": "No handler for 'missing'" } }` |
+| `TIMEOUT` | Aggregated or single request | The request exceeded `timeoutMs`. | Increase `timeoutMs`, reduce handler processing time, or split work. | `{ "handlerId": "ExampleHandler", "ok": false, "error": { "code": "TIMEOUT", "error": "Request timeout" } }` |
+| `CONNECTION_NOT_FOUND` | Single‑sid request | Target `sid` is not connected/known. | Use an active `sid` or retry after reconnect. | `{ "handlerId": "WebSocketManager", "ok": false, "error": { "code": "CONNECTION_NOT_FOUND", "error": "Connection 'sid-123' not found" } }` |
+| `HARNESS_UNKNOWN_EVENT` | Developer harness | Harness test handler received an unsupported event name. | Update harness sources or disable the step before running automation. | `{ "handlerId": "python.websocket_handlers.dev_websocket_test_handler.DevWebsocketTestHandler", "ok": false, "error": { "code": "HARNESS_UNKNOWN_EVENT", "error": "Unhandled event", "details": "ws_tester_foo" } }` |
+
+Notes
+- Error payload shape follows the contract documented in `contracts/event-schemas.md` (`RequestResultItem.error`).
+- Codes are case‑sensitive. Use exactly as listed.
+- Future codes will be appended here and referenced by inline docstrings/JSDoc.
+
+### Client-Side Error Codes (Draft)
+
+The frontend can originate errors during validation, connection, or request execution. Today these surface as thrown exceptions/promise rejections (not as `RequestResultItem`). When server→client request/ack lands in the future, these codes will also be serialised in `RequestResultItem.error.code` for protocol symmetry.
+
+| Code | Scope | Current Delivery | Meaning | Typical Remediation | Example |
+|------|-------|------------------|---------|---------------------|---------|
+| `VALIDATION_ERROR` | Producer options / payload | Exception (throw) | Invalid options (e.g., bad `timeoutMs`/`correlationId`) or non-object payload | Fix caller options and payload shapes | `new Error("timeoutMs must be a non-negative number")` |
+| `PAYLOAD_TOO_LARGE` | Size precheck (50MB cap) | Exception (throw) | Client precheck rejects payloads exceeding cap before emit | Reduce payload or chunk via HTTP; keep binaries off WS | `new Error("Payload size exceeds maximum (.. > .. bytes)")` |
+| `NOT_CONNECTED` | Socket status | Exception (throw) | Auto-connect could not establish a session (user logged out, server offline, handshake rejected) | Check login state, server availability, and Origin policy; optional `await websocket.connect()` for diagnostics | `new Error("Not connected")` |
+| `REQUEST_TIMEOUT` | request() | Not used (end-state) | Timeouts are represented inside `results[]` as `error.code="TIMEOUT"` (Promise resolves). | Inspect `results[]` for `TIMEOUT` items and handle in UI. | N/A |
+| `CONNECT_ERROR` | Socket connect_error | Exception (throw/log) | Transport/handshake failure | Check server availability, CORS, or network | `new Error("WebSocket connection failed: ...")` |
+
+Notes
+- These are currently local exceptions, not part of the aggregated results payload. Calling code should `try/catch` or handle promise rejections.
+- When server→client request/ack is introduced, the same codes will be serialised into `RequestResultItem.error.code` to maintain symmetry with backend codes.
+- Prefer branching on `code` when available; avoid coupling to full message strings.
+
+### IDE Hints (Non‑enforcing)
+
+To surface recognized codes without adding toolchain dependencies, front‑end can use a JSDoc union type near the helper exports:
+
+```javascript
+/** @typedef {('NO_HANDLERS'|'TIMEOUT'|'CONNECTION_NOT_FOUND')} WsErrorCode */
+```
+
+Back‑end can reference this registry via concise docstrings at error construction points (e.g., `_build_error_result`) to improve discoverability.
+
+---
+
+## Phase 6 – Registry & Helper Work Status
+
+Current status
+- This registry table is drafted and linked; it documents codes already produced by the manager/helpers today.
+
+Remaining work (tracked in Phase 6 tasks)
+- T148: Ensure the registry is complete and cross‑referenced from comments/docstrings (backend) and JSDoc typedefs (frontend). No new linter/tooling.
+- T144: Reference the registry from contracts and quickstart examples; align all examples to documented codes.
+- T141/T143: Add/adjust tests to assert known codes only in helper/manager paths.
+- T145–T147: Ensure the harness logs/validates codes in envelopes/results as part of the automatic and manual suites.
+
+Related references
+- [`event-schemas.md`](../specs/003-websocket-event-handlers/contracts/event-schemas.md)
+- [`websocket-handler-interface.md`](../specs/003-websocket-event-handlers/contracts/websocket-handler-interface.md)
+- [`frontend-api.md`](../specs/003-websocket-event-handlers/contracts/frontend-api.md)
diff --git a/docs/guides/a2a-setup.md b/docs/guides/a2a-setup.md
new file mode 100644
index 0000000000..3212020fe1
--- /dev/null
+++ b/docs/guides/a2a-setup.md
@@ -0,0 +1,153 @@
+# A2A Server Setup
+
+Agent Zero can communicate with other Agent Zero instances using the A2A (Agent-to-Agent) protocol based on FastA2A. This guide shows you how to enable and configure A2A connectivity through the Settings UI.
+
+## What is A2A?
+
+A2A enables direct communication between multiple Agent Zero instances. This allows:
+
+- **Distributed workflows** - Delegate tasks to specialized agent instances
+- **Context isolation** - Maintain separate workspaces for different agents
+- **Long-running collaboration** - Persistent agent-to-agent conversations
+- **Project-specific delegation** - Route work to agents with specific project contexts
+
+> [!NOTE]
+> This guide covers enabling Agent Zero as an A2A server. For API-level integration details, see the [advanced connectivity documentation](../developer/connectivity.md).
+
+## Enabling the A2A Server
+
+### Step 1: Open A2A Configuration
+
+1. Click **Settings** in the sidebar
+2. Navigate to the **MCP/A2A** tab
+3. Scroll to the **A0 A2A Server** section
+4. Toggle **Enable A2A server** to ON
+
+
+
+### Step 2: Get Connection URL
+
+1. Click on **connection example** to view your A2A connection details
+2. The dialog displays:
+ - **API Token** - Automatically generated from your username and password
+ - **A2A Connection URL** - The full URL other agents will use to connect
+ - Optional **Project selector** - To create project-specific connection URLs
+
+
+
+### Step 3: Save Configuration
+
+1. Click **Save** to apply your settings
+2. The A2A server is now active and ready to accept connections
+
+> [!IMPORTANT]
+> The API token changes when you update your Agent Zero credentials. Existing connections will need to be reconfigured with the new token.
+
+## Connection URL Format
+
+The basic A2A connection URL follows this format:
+
+```
+http://YOUR_HOST:PORT/a2a/t-YOUR_API_TOKEN
+```
+
+### With Project Context
+
+To connect with a specific project active:
+
+```
+http://YOUR_HOST:PORT/a2a/t-YOUR_API_TOKEN/p-PROJECT_NAME
+```
+
+When a project is specified:
+- All A2A conversations run in that project's context
+- The agent has access to project-specific resources and knowledge
+- Enables isolated, project-focused agent collaboration
+
+## Example Use Cases
+
+### 1. Local Development Setup
+
+Two Agent Zero instances on the same machine:
+
+```
+Instance 1: http://localhost:8080/a2a/t-abc123xyz
+Instance 2: http://localhost:8081/a2a/t-def456uvw
+```
+
+### 2. Remote Agent Collaboration
+
+Connect to a remote Agent Zero instance:
+
+```
+http://agent.example.com:8080/a2a/t-remote-token
+```
+
+### 3. Project-Specific Delegation
+
+Main agent delegates frontend work to specialized agent:
+
+```
+http://localhost:8081/a2a/t-frontend-token/p-webapp-ui
+```
+
+## Docker Networking
+
+If running Agent Zero in Docker:
+
+- **Same Host:** Use `host.docker.internal:PORT` (macOS/Windows) or container networking (Linux)
+- **Different Hosts:** Use the public IP or domain name of the target instance
+- **Port Mapping:** Ensure the Agent Zero port is exposed in your Docker configuration
+
+## Security Considerations
+
+- **Token Protection:** Keep your API tokens secure - they provide full access to your Agent Zero instance
+- **Network Access:** Consider using firewalls or reverse proxies to restrict A2A endpoint access
+- **HTTPS:** For production deployments, use HTTPS to encrypt A2A communication
+- **Credential Rotation:** Changing your password will invalidate all existing A2A connection URLs
+
+## Testing Your Connection
+
+You can test A2A connectivity using curl:
+
+```bash
+curl -X POST http://localhost:8080/a2a/t-YOUR_TOKEN \
+ -H "Content-Type: application/json" \
+ -d '{"message": "Hello from another agent"}'
+```
+
+## A2A vs MCP
+
+| Feature | A2A | MCP |
+|---------|-----|-----|
+| **Purpose** | Agent-to-agent chat delegation | Tool/function access |
+| **Use Case** | Long-running conversations | Specific tool calls |
+| **Context** | Full chat context | Function parameters only |
+| **Best For** | Workflow delegation | Tool integration |
+
+> [!TIP]
+> Use A2A when you need another agent's reasoning and conversation capabilities. Use MCP when you just need access to specific tools or functions.
+
+## Troubleshooting
+
+### Connection Refused
+
+- Verify the A2A server is enabled in Settings
+- Check that the Agent Zero instance is running
+- Confirm the port is accessible (check firewall rules)
+
+### Invalid Token
+
+- Token may have changed due to credential updates
+- Generate a new connection URL from Settings > MCP/A2A
+- Update the connecting agent's configuration
+
+### Project Not Found
+
+- Verify the project name in the URL matches exactly
+- Check that the project exists in the target instance
+- Project names are case-sensitive
+
+## Advanced Configuration
+
+For detailed A2A protocol specifications, API examples, and integration patterns, see the [Advanced Connectivity Guide](../developer/connectivity.md).
diff --git a/docs/guides/api-integration.md b/docs/guides/api-integration.md
new file mode 100644
index 0000000000..c0331212dc
--- /dev/null
+++ b/docs/guides/api-integration.md
@@ -0,0 +1,231 @@
+# Adding External APIs Without Code
+
+One of Agent Zero's most powerful capabilities is the ability to integrate external APIs on the fly without writing any code. By simply providing API documentation or code snippets, the agent can learn to use new services and remember how to use them in future conversations.
+
+This tutorial demonstrates how to integrate Google's image generation API from Google AI Studio - but the same process works for any public API.
+
+## How It Works
+
+Agent Zero can:
+
+1. **Analyze API code** - Understand how to use an API from provided snippets or documentation
+2. **Execute the integration** - Run the code to accomplish your task
+3. **Remember the solution** - Store the approach in its memory for future use
+4. **Manage credentials** - Use secrets stored globally or per-project for authentication
+
+This means you can add capabilities like image generation, translation services, payment processing, or any other API-based feature simply by showing the agent how it works once.
+
+## Example: Image Generation with Google AI Studio
+
+Let's walk through adding image generation capabilities using Google's Gemini API.
+
+### Step 1: Get the API Code
+
+First, we need the code snippet that shows how to use the API.
+
+1. Go to [Google AI Studio](https://aistudio.google.com/)
+2. Use the interface to create or test an image generation prompt
+3. Click **"Get Code"** in the UI
+4. Select **"Python"** as the language
+5. Download the code file (or copy it to clipboard)
+
+
+
+> [!TIP]
+> Most API platforms (OpenAI, Anthropic, Replicate, etc.) provide similar "Get Code" features or have documentation with ready-to-use snippets.
+
+### Step 2: Provide the Code to Agent Zero
+
+Now we'll tell Agent Zero to use this code:
+
+1. Open a chat with Agent Zero
+2. Send a message like: **"Use this code to generate an image of the Agent Zero logo"**
+3. Either:
+ - Attach the downloaded Python file, or
+ - Paste the code snippet into the chat
+
+Agent Zero will analyze the code and understand:
+- What dependencies are needed (`google-genai` package)
+- How to structure the API request
+- What parameters are required
+- How to handle the response
+
+
+
+### Step 3: Configure API Credentials
+
+On first run, Agent Zero will attempt to use the API but discover it needs an API key:
+
+
+
+Agent Zero will tell you:
+- What credential is missing (e.g., `GEMINI_API_KEY`)
+- Where to configure it (Settings → External Services or Project settings)
+
+#### Adding the API Key
+
+You have two options for storing credentials:
+
+**Option 1: Global Secrets** (available to all chats and projects)
+1. Click the **Settings** icon in the sidebar
+2. Go to **External Services**
+3. Add a new line: `GEMINI_API_KEY=your_actual_key_here`
+4. Click **Save**
+
+**Option 2: Project Secrets** (available only within a specific project)
+1. Open your project settings
+2. Go to the **Secrets** tab
+3. Add the key-value pair
+4. Save the project
+
+
+
+> [!NOTE]
+> Global secrets are ideal for APIs you use frequently across different projects. Project secrets are better for client-specific or project-specific integrations.
+
+### Step 4: Generate the Image
+
+After configuring the API key, tell Agent Zero to proceed:
+
+**"I set the API key in secrets. Now you can use it."**
+
+Agent Zero will:
+1. Retrieve the API key from secrets
+2. Install required dependencies (`google-genai` package)
+3. Execute the image generation code
+4. Save the generated image to disk
+5. Report the file location
+
+
+
+The agent confirms:
+- Mission complete
+- File location: `/root/agent_zero_logo_0.jpg`
+- File size: 378 KB
+
+## How Memory Works
+
+Here's where it gets interesting: **Agent Zero will remember this solution**.
+
+The next time you ask it to generate an image:
+- It will automatically use the Gemini API approach it learned
+- No need to provide the code snippet again
+- The API key is already configured
+- Dependencies are already installed
+
+The agent stores:
+- **How to use the API** (code structure, parameters)
+- **What the API does** (image generation)
+- **What credentials are needed** (`GEMINI_API_KEY`)
+- **Common patterns and best practices** from the interaction
+
+This memory persists across:
+- Multiple conversations
+- Agent restarts
+- Different projects (for global memory and global secrets)
+
+## Use Cases
+
+This approach works for any external API. Common examples:
+
+### Communication & Notifications
+- **SendGrid**: Email delivery
+- **Twilio**: SMS and phone calls
+- **Slack/Discord**: Message webhooks
+- **Telegram**: Bot interactions
+
+### Data & Analytics
+- **Google Sheets API**: Spreadsheet automation
+- **Airtable**: Database operations
+- **Stripe**: Payment processing
+- **Plaid**: Banking data
+
+### Content & Media
+- **Unsplash/Pexels**: Stock photos
+- **ElevenLabs**: Text-to-speech
+- **Whisper API**: Speech-to-text
+- **Stable Diffusion**: Image generation
+- **Replicate**: Various AI models
+
+### Development Tools
+- **GitHub API**: Repository management
+- **Jira/Linear**: Issue tracking
+- **Vercel/Netlify**: Deployment
+- **Docker Hub**: Container registry
+
+### Specialized Services
+- **WeatherAPI**: Weather data
+- **Google Maps**: Geocoding, directions
+- **Currency exchange**: Forex rates
+- **Translation APIs**: Multi-language support
+
+## Best Practices
+
+### 1. Start with Official Examples
+
+Always use code snippets from official documentation or API providers' "Get Code" features. These are:
+- Tested and working
+- Up-to-date with latest API versions
+- Include proper error handling
+- Show recommended practices
+
+### 2. Organize Credentials
+
+**For personal/global APIs:**
+- Store in **Settings → External Services**
+- Use clear naming: `SERVICE_API_KEY`, `SERVICE_SECRET`
+- Add comments to document what each key is for
+
+**For project-specific APIs:**
+- Store in **Project Settings → Secrets**
+- Keeps client data isolated
+- Prevents accidental cross-project usage
+
+### 3. Document in Project Instructions
+
+When integrating APIs for a specific project, add notes to the project instructions:
+
+```markdown
+## Available APIs
+
+This project has access to:
+
+- **Gemini Image Generation**: Use for creating visuals and illustrations
+ - Credentials: GEMINI_API_KEY (configured in project secrets)
+ - Best for: Professional graphics, concept art, UI mockups
+
+- **SendGrid Email**: Use for sending automated emails
+ - Credentials: SENDGRID_API_KEY
+ - Best for: Notifications, reports, customer communications
+```
+
+This helps the agent understand what tools are available for the current project.
+
+## Advanced: Custom API Wrappers
+
+For APIs you use frequently, you can have Agent Zero create reusable wrapper functions:
+
+**"Create a Python module called `image_gen.py` with a function `generate_image(prompt, style='professional')` that uses the Gemini API. Include error handling and save the image to the current project folder."**
+
+Agent Zero will:
+1. Create a clean, reusable module
+2. Add proper documentation
+3. Include error handling
+4. Make it easy to call from future tasks
+
+Then in future chats:
+
+**"Use the image_gen module to create a logo"**, and it just works!
+
+## Conclusion
+
+By leveraging Agent Zero's ability to learn from API code snippets, you can:
+
+- **Add new capabilities instantly** without writing integration code
+- **Keep solutions in memory** for reuse across conversations
+- **Manage credentials securely** with global or project-scoped secrets
+- **Scale across any public API** using the same simple workflow
+
+This makes Agent Zero incredibly versatile - it's not limited to its built-in features. Show it how to use an API once, and it becomes part of its permanent toolkit.
+
+Ready to try it yourself? Pick any API you want to integrate and follow the steps above!
diff --git a/docs/contribution.md b/docs/guides/contribution.md
similarity index 86%
rename from docs/contribution.md
rename to docs/guides/contribution.md
index 498577eb3e..ed60e75010 100644
--- a/docs/contribution.md
+++ b/docs/guides/contribution.md
@@ -5,7 +5,8 @@ Contributions to improve Agent Zero are very welcome! This guide outlines how t
## Getting Started
- See [development](development.md) for instructions on how to set up a development environment.
-- See [extensibility](extensibility.md) for instructions on how to create custom extensions.
+- See [extensions](../developer/extensions.md) for instructions on how to create custom extensions.
+- See [websocket infrastructure](websocket-infrastructure.md) for guidance on building real-time handlers and client integrations.
1. **Fork the Repository:** Fork the Agent Zero repository on GitHub.
2. **Clone Your Fork:** Clone your forked repository to your local machine.
@@ -27,4 +28,4 @@ Contributions to improve Agent Zero are very welcome! This guide outlines how t
## Documentation Stack
-- The documentation is built using Markdown. We appreciate your contributions even if you don't know Markdown, and look forward to improve Agent Zero for everyone's benefit.
\ No newline at end of file
+- The documentation is built using Markdown. We appreciate your contributions even if you don't know Markdown, and look forward to improve Agent Zero for everyone's benefit.
diff --git a/docs/guides/mcp-setup.md b/docs/guides/mcp-setup.md
new file mode 100644
index 0000000000..09a259bbd3
--- /dev/null
+++ b/docs/guides/mcp-setup.md
@@ -0,0 +1,117 @@
+# MCP Server Setup
+
+Agent Zero can connect to external MCP (Model Context Protocol) servers to extend its capabilities with additional tools. This guide shows you how to add MCP servers through the Settings UI.
+
+## What are MCP Servers?
+
+MCP servers are external tools that Agent Zero can use to perform specialized tasks. Popular examples include:
+
+- **Browser automation** (Chrome DevTools, Playwright)
+- **Workflow automation** (n8n)
+- **Email operations** (Gmail)
+- **Database access** (SQLite)
+
+> [!NOTE]
+> This guide covers connecting to external MCP servers as a client. For exposing Agent Zero as an MCP server, see the [advanced documentation](../developer/mcp-configuration.md).
+
+## Adding an MCP Server
+
+### Step 1: Open MCP Configuration
+
+1. Click **Settings** in the sidebar
+2. Navigate to the **MCP/A2A** tab
+3. Click on **External MCP Servers**
+4. Click the **Open** button to access the configuration editor
+
+
+
+### Step 2: Add Your MCP Server
+
+In the JSON editor, add your MCP server configuration. Here's a simple example:
+
+```json
+{
+ "mcpServers": {
+ "chrome-devtools": {
+ "command": "npx",
+ "args": ["-y", "chrome-devtools-mcp@latest"]
+ }
+ }
+}
+```
+
+
+
+### Step 3: Apply and Verify
+
+1. Click **Apply now** to save your configuration
+2. The server status will appear below, showing:
+ - Server name (e.g., `chrome_devtools`)
+ - Number of available tools
+ - Connection status (green indicator = connected)
+
+> [!TIP]
+> The first time you run an `npx`-based MCP server, it may take a few moments to download and initialize.
+
+## Common MCP Server Examples
+
+### Local Command-Based Server
+
+```json
+{
+ "mcpServers": {
+ "sqlite": {
+ "command": "uvx",
+ "args": ["mcp-server-sqlite", "--db-path", "/root/db.sqlite"]
+ }
+ }
+}
+```
+
+### Remote HTTP Server
+
+```json
+{
+ "mcpServers": {
+ "external-api": {
+ "url": "https://api.example.com/mcp",
+ "headers": {
+ "Authorization": "Bearer YOUR_API_KEY"
+ }
+ }
+ }
+}
+```
+
+## Docker Networking
+
+If Agent Zero runs in Docker and your MCP server runs on the host:
+
+- **macOS/Windows:** Use `host.docker.internal` in URLs
+- **Linux:** Run the MCP server in the same Docker network and use the container name
+
+## Using MCP Tools
+
+Once connected, MCP tools become available to Agent Zero automatically. Tools are named with the server prefix, for example:
+
+- Server name: `chrome-devtools`
+- Tool becomes: `chrome_devtools.navigate_to_url`
+
+Simply ask Agent Zero to perform tasks, and it will use the appropriate MCP tools when needed.
+
+## Advanced Configuration
+
+For detailed configuration options, server types, environment variables, and troubleshooting, see the [Advanced MCP Configuration Guide](../developer/mcp-configuration.md).
+
+## Recommended MCP Servers
+
+Community-tested and reliable MCP servers:
+
+- **Chrome DevTools MCP** - Direct Chrome control
+- **Playwright MCP** - Cross-browser automation
+- **n8n MCP** - Workflow automation
+- **Gmail MCP** - Email management
+- **VSCode MCP** - IDE workflows
+
+> [!TIP]
+> For browser automation tasks, MCP-based browser tools are more reliable than the built-in browser agent.
diff --git a/docs/guides/projects.md b/docs/guides/projects.md
new file mode 100644
index 0000000000..3a50782e07
--- /dev/null
+++ b/docs/guides/projects.md
@@ -0,0 +1,490 @@
+# Working with Projects
+
+Projects are one of Agent Zero's most powerful features for organizing your work. They create isolated workspaces with dedicated context, instructions, memory, and secrets - preventing context bleed between unrelated tasks or clients.
+
+This tutorial will guide you through creating, configuring, and using projects effectively.
+
+## What Are Projects?
+
+A project in Agent Zero is an isolated workspace that includes:
+
+- **Dedicated folder structure** under `/a0/usr/projects//`
+- **Custom instructions** automatically injected into the agent's system prompt
+- **Isolated or shared memory** to prevent context pollution
+- **Project-specific secrets and variables** for secure credential management
+- **Custom agent configurations** including subagent settings
+- **Knowledge base integration** with project-scoped documents
+- **Git repository integration** for version-controlled codebases
+- **File structure injection** for automatic codebase awareness
+
+Think of projects as separate "personas" or "modes" for your agent - each with its own context, memory, and capabilities.
+
+## Creating Your First Project
+
+There are two ways to access the Projects interface:
+
+### Method 1: Dashboard Access
+1. Open the **Dashboard** from the sidebar
+2. Click the **Projects** button
+3. The Projects modal will open
+
+### Method 2: Quick Access
+1. Look at the top-right corner of the interface where it shows **"No project"**
+2. Click on it to open the project dropdown
+3. If you have no projects yet, click **"Projects"** to open the modal
+
+
+
+### Creating an Empty Project
+
+Once in the Projects modal:
+
+1. Click **"Create project"** button
+2. You'll see the project creation wizard
+
+
+
+The wizard includes:
+
+- **Title**: A human-readable name displayed in the UI
+- **Color tag**: Visual identifier for quick recognition (choose from the color palette)
+- **Git Repository** (optional): URL to clone a repository (see next section)
+
+> [!TIP]
+> Choose meaningful titles and distinct colors, especially if you plan to work with multiple projects. This helps you quickly identify which project is active.
+
+### Creating a Git-Based Project
+
+Agent Zero's **Git Projects** feature allows you to clone repositories directly into your project workspace:
+
+1. In the creation form, enter a Git repository URL in the **Git Repository** field
+ - Supports both public and private repositories
+ - For private repositories, you can provide an authentication token
+2. Click **"Create and continue"**
+3. Agent Zero will clone the repository
+
+
+
+The cloning process:
+- Downloads the repository to `/a0/usr/projects//`
+- By default, clones the `main` branch
+- Supports authentication via token (stored securely, never in URLs)
+- You can ask the agent to checkout different branches later
+
+
+
+After cloning completes, you'll see:
+- Repository URL
+- Current branch
+- Clean/dirty status
+- Last commit information
+
+> [!NOTE]
+> If the cloned repository already contains a `.a0proj/` folder with `project.json`, Agent Zero will merge the existing configuration with your specified title and color preferences.
+
+## Project Configuration
+
+Once created, you can configure your project through the Edit Project interface:
+
+
+
+### Description and Instructions
+
+#### Description
+The **Description** field helps both you and the agent understand the project's purpose. This is purely informational and helps provide context when switching between projects.
+
+**Example:**
+```
+An intelligent Excel automation system that processes financial spreadsheets
+from multiple sources, performs data validation and cleaning, consolidates
+information, generates executive reports, and flags anomalies or compliance issues.
+```
+
+#### Instructions
+The **Instructions** field is critical - these are automatically injected into the agent's system prompt when the project is active. Write clear, specific instructions that guide the agent's behavior for this project.
+
+**Example:**
+```markdown
+## Your Role
+You are an expert Financial Data Analyst and Excel Automation Specialist.
+Your job is to process, analyze, and report on financial spreadsheet data
+with precision and business acumen.
+
+## Operational Context
+- Work directory: `/usr/projects/excel-finance/`
+- Input data location: `/usr/projects/excel-finance/data/incoming/`
+- Processed files: `/usr/projects/excel-finance/data/processed/`
+- Reports output: `/usr/projects/excel-finance/reports/`
+- Templates: `/usr/projects/excel-finance/templates/`
+
+## Core Responsibilities
+
+### 1. Data Ingestion & Discovery
+- Scan `/data/incoming/` for new Excel/CSV files
+- Identify data types, sheets, and file structures
+- Log source details and timestamps
+
+### 2. Data Validation & Cleaning
+- Check for missing values, duplicates, and format inconsistencies
+- Validate numerical ranges and date formats
+- Flag suspicious patterns or outliers
+- Document all cleaning operations
+
+### 3. Data Consolidation
+- Merge data from multiple sources
+- Normalize column names and formats
+- Handle currency conversions and date standardization
+- Create master datasets for reporting
+
+### 4. Executive Reporting
+- Generate summary reports using templates in `/templates/`
+- Include key metrics, trends, and visualizations
+- Highlight anomalies and compliance issues
+- Export as formatted Excel files with proper styling
+
+### 5. Compliance & Quality Checks
+- Flag potential compliance issues
+- Verify calculations and formulas
+- Maintain audit trail of all operations
+- Alert on critical errors or anomalies
+
+## Quality Standards
+- Always validate input data before processing
+- Use professional Excel formatting in outputs
+- Include metadata (processing date, sources, versions)
+- Document assumptions and limitations
+- Provide clear error messages and suggestions
+```
+
+> [!IMPORTANT]
+> Well-written instructions are the key to effective project-specific agent behavior. Be specific about:
+> - The agent's role and expertise level
+> - Directory paths and file locations
+> - Expected workflows and procedures
+> - Quality standards and validation rules
+> - Output formats and requirements
+
+### Additional Instruction Files
+
+Besides the main instructions field, you can add multiple instruction files in the `.a0proj/instructions/` directory. These are automatically loaded and concatenated with the main instructions.
+
+This is useful for:
+- Organizing complex instructions into logical sections
+- Sharing common instructions across similar projects
+- Version controlling instruction updates via Git
+
+### Memory Isolation
+
+Projects support two memory modes:
+
+- **Own memory** (default): The project has its own isolated memory directory
+ - Memories stored under `vector_db/projects//`
+ - Prevents context bleed between projects
+ - Ideal for client work, sensitive projects, or distinct domains
+
+- **Global memory**: The project shares the default memory pool
+ - Memories stored under `vector_db/default/`
+ - Useful when projects need shared knowledge
+ - Better for related projects in the same domain
+
+> [!TIP]
+> Use **own memory** for:
+> - Client projects with confidential information
+> - Different programming languages/frameworks
+> - Distinct domains (e.g., finance vs. marketing)
+>
+> Use **global memory** for:
+> - Related sub-projects in the same domain
+> - When you want the agent to remember across all work
+> - Personal projects without sensitive data
+
+### Variables and Secrets
+
+Projects support scoped configuration values:
+
+#### Variables (Non-sensitive)
+Stored in `.a0proj/variables.env`:
+```bash
+API_BASE_URL=https://api.example.com
+DEFAULT_TIMEOUT=30
+OUTPUT_FORMAT=json
+LOG_LEVEL=info
+```
+
+#### Secrets (Sensitive)
+Stored in `.a0proj/secrets.env`:
+```bash
+API_KEY=sk-abc123xyz...
+DATABASE_PASSWORD=super_secret_pwd
+GITHUB_TOKEN=ghp_xyz789...
+SMTP_PASSWORD=email_pwd_here
+```
+
+> [!IMPORTANT]
+> - Secrets are stored locally in the container
+> - They are masked in the UI when editing
+> - Backups may not include secrets - keep a separate copy
+> - Reference secrets in prompts by name: "Use my `API_KEY` to authenticate"
+
+### Subagent Configuration
+
+Projects can enable or disable specific subagents (like the Browser Agent). This is configured via the UI and stored in `.a0proj/agents.json`.
+
+### Knowledge Files
+
+Import project-specific knowledge documents:
+1. Use the **Import Knowledge** button in the project interface
+2. Files are stored in `.a0proj/knowledge/` organized by memory area
+3. The agent can reference this knowledge when the project is active
+
+### File Structure Injection
+
+Projects can automatically inject their directory structure into the agent's context:
+
+**Settings (configurable per project):**
+- **Enabled**: Toggle automatic file tree injection
+- **Max depth**: How many directory levels to scan (default: 5)
+- **Max files**: Maximum files to include (default: 20)
+- **Max folders**: Maximum folders to include (default: 20)
+- **Max lines**: Maximum lines in the output (default: 250)
+- **Gitignore patterns**: Filter out unwanted files
+
+The default gitignore for projects excludes:
+```
+.a0proj/
+venv/
+__pycache__/
+node_modules/
+.npm/
+.git/
+```
+
+This feature is incredibly useful for code projects - the agent automatically "sees" your project structure and can navigate it intelligently.
+
+## Activating a Project
+
+To use a project, you need to activate it for your current chat:
+
+### In a New Chat
+1. Create or select a project from the Projects modal
+2. Start a new chat
+3. The project is automatically active for that chat
+
+### In an Existing Chat
+1. Click the project dropdown in the top-right corner (where it shows current project or "No project")
+2. Select the desired project from the list
+3. The project activates immediately for this chat
+
+
+
+> [!NOTE]
+> Each chat can have its own active project. You can have multiple chats open with different projects active simultaneously.
+
+### First Interaction After Activation
+
+Once activated, the agent's behavior changes according to the project's configuration:
+
+
+
+The agent now:
+- Has access to project-specific instructions
+- Uses project-isolated memory (if configured)
+- Can reference project secrets and variables
+- Sees the project file structure (if enabled)
+- Operates within the project's working directory
+
+**Example prompt after activation:**
+```
+Hi A0. Start first development phase:
+- recon
+- scope definition
+- AGENTS.md generation
+```
+
+The agent will understand the context based on the project's instructions and work accordingly.
+
+## Project Directory Structure
+
+Understanding the project directory structure helps you work effectively:
+
+```
+/a0/usr/projects//
+├── .a0proj/ # Project metadata (hidden)
+│ ├── project.json # Main configuration
+│ ├── variables.env # Non-sensitive variables
+│ ├── secrets.env # Sensitive credentials
+│ ├── agents.json # Subagent settings
+│ ├── instructions/ # Additional instruction files
+│ │ ├── 01-setup.md
+│ │ ├── 02-workflow.md
+│ │ └── ...
+│ └── knowledge/ # Project knowledge files
+│ ├── main/
+│ ├── fragments/
+│ └── ...
+├── src/ # Your actual project files
+├── data/ # Data files
+├── docs/ # Documentation
+└── ... # Other project content
+```
+
+> [!TIP]
+> The `.a0proj/` folder is automatically excluded from file structure injection (via gitignore patterns) to keep the agent's context clean.
+
+## Advanced Use Cases
+
+### Multi-Client Agency Work
+
+Use projects to isolate each client:
+
+```
+/usr/projects/client-acme/
+/usr/projects/client-globex/
+/usr/projects/client-initech/
+```
+
+Each with:
+- Client-specific instructions and context
+- Isolated memory (no data leakage)
+- Client API keys and credentials
+- Project-specific knowledge bases
+
+### Multi-Language Development
+
+Create projects for different tech stacks:
+
+```
+/usr/projects/python-ml-research/
+/usr/projects/nodejs-webapp/
+/usr/projects/go-microservices/
+```
+
+Each with language-specific:
+- Code patterns and best practices
+- Framework documentation
+- Linting and formatting rules
+
+### Domain-Specific Work
+
+Organize by business domain:
+
+```
+/usr/projects/finance-automation/
+/usr/projects/marketing-analytics/
+/usr/projects/hr-automation/
+```
+
+Each with domain-specific:
+- Terminology and concepts
+- Industry standards and regulations
+- Specialized tools and APIs
+
+## Combining Projects with Tasks
+
+Projects work exceptionally well with Agent Zero's **Tasks & Scheduling** feature:
+
+1. Create a project for a specific domain (e.g., "Daily Email Reports")
+2. Configure project instructions for the recurring task
+3. Schedule a task that activates this project
+4. The task runs in isolation with project-specific context
+
+**Example:**
+- **Project**: "Daily Sales Summary"
+- **Instructions**: "Fetch yesterday's sales data, generate summary report, email to team"
+- **Task**: Scheduled daily at 8 AM
+- **Result**: Consistent, context-aware automated reporting
+
+See [Tasks & Scheduling](usage.md#tasks--scheduling) for more details.
+
+## Best Practices
+
+### Instruction Writing
+- **Be specific**: Don't say "analyze data" - specify format, methods, and output
+- **Include paths**: Always mention where files should be read/written
+- **Define quality standards**: What constitutes "good" output?
+- **Specify error handling**: How should the agent respond to issues?
+- **Use markdown formatting**: Clear sections and lists improve readability
+
+### Memory Management
+- Use **own memory** by default for client work
+- Use **global memory** only when projects truly need shared knowledge
+- Regularly review and clean project memory via the Memory Dashboard
+- Clear memory when archiving completed projects
+
+### Security
+- Never commit `.a0proj/secrets.env` to version control
+- Use project-scoped secrets instead of global secrets for sensitive work
+- Consider separate projects for different security levels
+- Backup secrets manually - they may not be included in automatic backups
+
+### Organization
+- Use clear, descriptive project names
+- Choose distinct colors for visual identification
+- Keep instructions updated as project scope evolves
+- Document any manual setup steps in project instructions
+
+### Performance
+- Adjust file structure injection limits based on project size
+- Use gitignore patterns to exclude large build artifacts
+- Consider disabling file structure injection for very large codebases
+- Monitor memory growth and clean periodically
+
+## Troubleshooting
+
+### Project Not Loading Instructions
+**Problem**: Agent doesn't seem to follow project instructions
+
+**Solutions**:
+- Verify project is actually activated (check top-right dropdown)
+- Check instructions are saved (edit project and verify content)
+- Look for syntax errors in instructions markdown
+- Try deactivating and reactivating the project
+
+### Memory Not Isolated
+**Problem**: Agent remembers things from other projects
+
+**Solutions**:
+- Check project memory setting is "own" not "global"
+- Deactivate and reactivate the project
+- Clear the project's memory directory via Memory Dashboard
+- Restart chat context if necessary
+
+### Git Clone Failures
+**Problem**: Repository won't clone
+
+**Solutions**:
+- Verify the Git URL is correct
+- For private repos, ensure you provided a valid token
+- Check network connectivity
+- Try cloning manually via terminal to diagnose issue
+- Look for error messages in console/logs
+
+### Secrets Not Available
+**Problem**: Agent can't access project secrets
+
+**Solutions**:
+- Verify secrets are saved in project settings
+- Check secret variable names match what you're referencing
+- Try referencing by exact name: "use my `API_KEY`"
+- Ensure project is activated for current chat
+
+### File Structure Not Showing
+**Problem**: Agent doesn't see project files
+
+**Solutions**:
+- Enable file structure injection in project settings
+- Increase max_files/max_folders limits
+- Check gitignore patterns aren't too restrictive
+- Verify files exist in project directory
+
+## Next Steps
+
+Now that you understand projects, explore:
+
+- [Tasks & Scheduling](usage.md#tasks--scheduling) - Automate project-based work
+- [Memory Management](usage.md#memory-management) - Maintain project knowledge
+- [Backup & Restore](usage.md#backup--restore) - Preserve project configurations
+- [Extensions](../developer/extensions.md) - Extend project capabilities
+
+> [!TIP]
+> Start with a simple project to learn the system, then gradually add complexity. Projects are most powerful when instructions are well-crafted and memory is properly managed.
diff --git a/docs/guides/troubleshooting.md b/docs/guides/troubleshooting.md
new file mode 100644
index 0000000000..e3056927e7
--- /dev/null
+++ b/docs/guides/troubleshooting.md
@@ -0,0 +1,61 @@
+# Troubleshooting and FAQ
+This page addresses frequently asked questions (FAQ) and provides troubleshooting steps for common issues encountered while using Agent Zero.
+
+## Frequently Asked Questions
+**1. How do I ask Agent Zero to work directly on my files or dirs?**
+- Place the files/dirs in `/a0/usr`. Agent Zero will be able to perform tasks on them.
+
+**2. When I input something in the chat, nothing happens. What's wrong?**
+- Check if you have set up API keys in the Settings page. If not, the application cannot call LLM providers.
+
+**3. I get “Invalid model ID.” What does that mean?**
+- Verify the **provider** and **model naming**. For example, `openai/gpt-5.3` is correct for OpenRouter, but **incorrect** for the native OpenAI provider, which goes without prefix.
+
+**4. Does ChatGPT Plus include API access?**
+- No. ChatGPT Plus does not include API credits. You must provide an OpenAI API key in Settings.
+
+**5. Where is chat history stored?**
+- Chat history lives at `/a0/usr/chats/` inside the container.
+
+**6. How do I integrate open-source models with Agent Zero?**
+Refer to the [Choosing your LLMs](../setup/installation.md#installing-and-using-ollama-local-models) section for configuring local models (Ollama, LM Studio, etc.).
+
+> [!TIP]
+> Some LLM providers offer free usage tiers, for example Groq, Mistral, SambaNova, or CometAPI.
+
+**7. How can I make Agent Zero retain memory between sessions?**
+Use **Settings → Backup & Restore** and avoid mapping the entire `/a0` directory. See [How to update Agent Zero](../setup/installation.md#how-to-update-agent-zero).
+
+**8. My browser agent fails or is unreliable. What now?**
+The built-in browser agent is currently unstable on some systems. Use Skills or MCP alternatives such as Browser OS, Chrome DevTools, or Vercel's Agent Browser. See [MCP Setup](mcp-setup.md).
+
+**9. My secrets disappeared after a backup restore.**
+Secrets are stored in `/a0/usr/secrets.env` and are not always included in backup archives. Copy them manually.
+
+**10. Where can I find more documentation or tutorials?**
+- Join the Agent Zero [Skool](https://www.skool.com/agent-zero) or [Discord](https://discord.gg/B8KZKNsPpj) community.
+
+**11. How do I adjust API rate limits?**
+Use the model rate limit fields in Settings (Chat/Utility/Browser model sections) to set request/input/output limits. These map to the model config limits (for example `limit_requests`, `limit_input`, `limit_output`).
+
+**12. My `code_execution_tool` doesn't work, what's wrong?**
+- Ensure Docker is installed and running.
+- On macOS, grant Docker Desktop access to your project files.
+- Verify that the Docker image is updated.
+
+**13. Can Agent Zero interact with external APIs or services (e.g., WhatsApp)?**
+Yes, by creating custom tools or using MCP servers. See [Extensions](../developer/extensions.md) and [MCP Setup](mcp-setup.md).
+
+## Troubleshooting
+
+**Installation**
+- **Docker Issues:** If Docker containers fail to start, consult the Docker documentation and verify your Docker installation and configuration. On macOS, ensure you've granted Docker access to your project files in Docker Desktop's settings as described in the [Installation guide](../setup/installation.md#4-install-docker-docker-desktop-application). Verify that the Docker image is updated.
+- **Web UI not reachable:** Ensure at least one host port is mapped to container port `80`. If you used `0:80`, check the assigned port in Docker Desktop.
+
+**Usage**
+
+- **Terminal commands not executing:** Ensure the Docker container is running and properly configured. Check SSH settings if applicable. Check if the Docker image is updated by removing it from Docker Desktop app, and subsequently pulling it again.
+
+* **Error Messages:** Pay close attention to the error messages displayed in the Web UI or terminal. They often provide valuable clues for diagnosing the issue. Refer to the specific error message in online searches or community forums for potential solutions.
+
+* **Performance Issues:** If Agent Zero is slow or unresponsive, it might be due to resource limitations, network latency, or the complexity of your prompts and tasks, especially when using local models.
diff --git a/docs/guides/usage.md b/docs/guides/usage.md
new file mode 100644
index 0000000000..eb570cc160
--- /dev/null
+++ b/docs/guides/usage.md
@@ -0,0 +1,1105 @@
+# Usage Guide
+This guide explores usage and configuration scenarios for Agent Zero. You can consider this as a reference post-installation guide.
+
+
+
+## Basic Operations
+Agent Zero provides several basic operations through its interface:
+
+### Restart Framework
+The Restart button allows you to quickly restart the Agent Zero container without using the terminal:
+
+
+
+* Click the "Restart" button in the sidebar dropdown
+* A blue inline confirmation will appear indicating "Confirm"
+* Once confirmed, the framework will reinitialize and restart the container
+
+> [!TIP]
+> Use the Restart function when you want to:
+> - Reset the framework if you encounter unexpected behavior
+> - See changes applied to the framework code
+
+### Action Buttons
+Located beneath the chat input box, Agent Zero provides a set of action buttons for enhanced control and visibility:
+
+
+#### Chat Flow Control
+* **Pause/Resume Agent:** Toggle button to pause and resume chat flow
+ - Click to pause ongoing agent operations
+ - Changes to "Resume Agent" when paused
+ - Click again to resume chat flow and command execution
+
+#### Knowledge and File Management
+* **Import Knowledge:** Import external files into the agent's knowledge base
+ - Supports `.txt`, `.pdf`, `.csv`, `.html`, `.json`, and `.md` formats
+ - Files are stored in `/a0/knowledge/custom/main`
+ - Success message confirms successful import
+ - See [knowledge](../developer/architecture.md#knowledge) for more details
+
+### File Browser: Manage files in the Agent Zero environment
+
+
+
+ - Upload new files and folders
+ - Download files (click filename) or folders (as zip archives)
+ - Rename and Delete files and folders
+ - Navigate directories using the "Up" button
+ - Edit files in the File Editor
+ - See [File Browser](#file-browser) section for detailed features
+
+#### Debugging and Monitoring
+* **Context:** View the complete context window sent to the LLM
+ - Includes system prompts
+ - Shows current conversation context
+ - Displays active instructions and parameters
+
+
+
+### History:
+Access the chat history in JSON format
+ - View the conversation as processed by the LLM
+ - Useful for debugging and understanding agent behavior
+ - Files are stored under `/a0/usr/chats/` inside the container
+
+
+
+* **Nudge:** Restart the agent's last process
+ - Useful when agents become unresponsive
+ - Retries the last operation
+ - Helps recover from stuck states
+
+
+
+> [!TIP]
+> Use the Context and History buttons to understand how the agent interprets your instructions and debug any unexpected behavior.
+
+### File Attachments
+Agent Zero supports direct file attachments in the chat interface for seamless file operations:
+
+#### Attaching Files
+* Click the attachment icon (📎) on the left side of the chat input box
+* Select one or multiple files to attach
+* Preview attached files before sending:
+ - File names are displayed with their types (HTML, PDF, JPG, etc.)
+ - Images show thumbnails when available
+ - Files are listed in the chat input area waiting to be sent
+
+
+
+#### Working with Attached Files
+* Files can be referenced directly in your messages
+* Agent Zero can:
+ - Process attached files
+ - Move files to specific directories
+ - Perform operations on multiple files simultaneously
+ - Confirm successful file operations with detailed responses
+
+
+
+> [!TIP]
+> When working with multiple files, you can attach them all at once and then give instructions about what to do with them. The agent will handle them as a batch while keeping you informed of the progress.
+
+## Tool Usage
+Agent Zero's power comes from its ability to use [tools](../developer/architecture.md#tools). Here's how to leverage them effectively:
+
+- **Understand Tools:** Agent Zero includes default tools like knowledge (powered by SearXNG), code execution, and communication. Understand the capabilities of these tools and how to invoke them.
+
+### Browser Agent Status & MCP Alternatives
+The built-in browser agent currently has dependency issues on some systems. If web automation is critical, prefer MCP-based browser tools instead:
+
+- **Browser OS MCP**
+- **Chrome DevTools MCP**
+- **Playwright MCP**
+
+See [MCP Setup](mcp-setup.md) for configuration guidance and recommended servers.
+
+### Agent-to-Agent (A2A) Communication
+
+Agent Zero instances can communicate with each other using the A2A protocol. This enables:
+
+- **Task delegation** to specialized agent instances
+- **Distributed workflows** across multiple agents
+- **Project-specific collaboration** with isolated contexts
+
+To enable A2A connectivity, go to **Settings → MCP/A2A → A0 A2A Server** and toggle the server on. You'll receive a connection URL that other Agent Zero instances can use to communicate with your agent.
+
+See [A2A Setup](a2a-setup.md) for detailed configuration and use cases.
+
+## Example of Tools Usage: Web Search and Code Execution
+Let's say you want Agent Zero to perform some financial analysis tasks. Here's a possible prompt:
+
+> Please be a professional financial analyst. Find last month Bitcoin/ USD price trend and make a chart in your environment. The chart must have highlighted key points corresponding with dates of major news about cryptocurrency. Use the `search_engine` and `document_query` tools to find the price and the news, and the `code_execution_tool` to perform the rest of the job.
+
+Agent Zero might then:
+
+1. Use the `search_engine` and `document_query` tools to query a reliable source for the Bitcoin price and for the news about cryptocurrency as prompted.
+2. Extract the price from the search results and save the news, extracting their dates and possible impact on the price.
+3. Use the `code_execution_tool` to execute a Python script that performs the graph creation and key points highlighting, using the extracted data and the news dates as inputs.
+4. Save the final chart on disk inside the container and provide a link to it with the `response_tool`.
+
+> [!NOTE]
+> The first run of `code_execution_tool` may take a while as it downloads and builds the Agent Zero Docker image. Subsequent runs will be faster.
+
+This example demonstrates how to combine multiple tools to achieve an analysis task. By mastering prompt engineering and tool usage, you can unlock the full potential of Agent Zero to solve complex problems.
+
+## Multi-Agent Cooperation
+One of Agent Zero's unique features is multi-agent cooperation.
+
+* **Creating Sub-Agents:** Agents can create sub-agents to delegate sub-tasks. This helps manage complexity and distribute workload.
+* **Communication:** Agents can communicate with each other, sharing information and coordinating actions. The system prompt and message history play a key role in guiding this communication.
+* **Hierarchy:** Agent Zero uses a [hierarchical structure](../developer/architecture.md#agent-hierarchy-and-communication), with superior agents delegating tasks to subordinates. This allows for structured problem-solving and efficient resource allocation.
+
+
+
+## Projects
+Projects are isolated workspaces that provide dedicated context, instructions, memory, and secrets for specific tasks or clients. They are one of Agent Zero's most powerful organizational features, preventing context bleed and enabling focused, specialized agent behavior.
+
+### What Projects Provide
+
+Each project includes:
+
+- **Isolated workspace** under `/a0/usr/projects//`
+- **Custom instructions** automatically injected into system prompts
+- **Dedicated or shared memory** to control context isolation
+- **Project-scoped secrets and variables** for secure credential management
+- **Git repository integration** for cloning and working with codebases
+- **File structure injection** for automatic codebase awareness
+- **Custom agent configurations** including subagent settings
+- **Knowledge base integration** with project-specific documents
+
+### Creating Projects
+
+There are two ways to access project management:
+
+1. **Dashboard Access**: Click **Projects** in the sidebar to open the Projects modal
+2. **Quick Access**: Click the project dropdown in the top-right corner (shows "No project" when none is active)
+
+
+
+#### Empty Projects
+
+Create a new empty project workspace:
+1. Click **"Create project"**
+2. Enter a **title** (human-readable name)
+3. Choose a **color tag** for visual identification
+4. Click **"Create and continue"**
+
+#### Git-Based Projects
+
+Clone a repository directly into your project workspace:
+1. Enter a **Git repository URL** (public or private)
+2. Optionally provide an authentication token for private repos
+3. Agent Zero clones the repository and sets up the project structure
+
+
+
+The system clones the `main` branch by default. You can ask the agent to checkout other branches later. After cloning, you'll see repository status including current branch, clean/dirty state, and last commit info.
+
+
+
+> [!NOTE]
+> If the cloned repository already contains a `.a0proj/` configuration folder, Agent Zero merges the existing configuration with your specified preferences.
+
+### Project Configuration
+
+
+
+#### Description and Instructions
+
+- **Description**: Helps you and the agent understand the project's purpose and context
+- **Instructions**: Critical field that gets injected into the agent's system prompt when the project is active
+
+> [!IMPORTANT]
+> Well-written instructions are key to effective project-specific behavior. Be specific about:
+> - The agent's role and expertise for this project
+> - Directory paths and file locations
+> - Expected workflows and procedures
+> - Quality standards and validation rules
+> - Output formats and requirements
+
+**Example instructions:**
+```markdown
+## Your Role
+You are an expert Financial Data Analyst working with Excel automation.
+
+## Operational Context
+- Work directory: `/usr/projects/excel-finance/`
+- Input data: `/usr/projects/excel-finance/data/incoming/`
+- Reports output: `/usr/projects/excel-finance/reports/`
+
+## Core Responsibilities
+1. Scan for new Excel/CSV files in incoming directory
+2. Validate and clean data (check for missing values, duplicates)
+3. Consolidate data from multiple sources
+4. Generate executive reports with visualizations
+5. Flag compliance issues and anomalies
+```
+
+#### Memory Isolation
+
+Choose how project memory is managed:
+
+- **Own memory** (recommended): Project has isolated memory under `vector_db/projects//`
+ - Prevents context bleed between projects
+ - Ideal for client work, sensitive projects, or distinct domains
+
+- **Global memory**: Project shares the default memory pool
+ - Useful when projects need shared knowledge
+ - Better for closely related projects
+
+#### Variables and Secrets
+
+Projects support scoped configuration:
+
+- **Variables** (non-sensitive): Stored in `.a0proj/variables.env`
+ ```bash
+ API_BASE_URL=https://api.example.com
+ OUTPUT_FORMAT=json
+ ```
+
+- **Secrets** (sensitive): Stored in `.a0proj/secrets.env`
+ ```bash
+ API_KEY=sk-abc123xyz...
+ DATABASE_PASSWORD=super_secret_pwd
+ ```
+
+Reference these in your prompts: "Use my `API_KEY` to authenticate with the service"
+
+> [!WARNING]
+> Secrets may not be included in backup archives. Keep a separate manual copy of critical credentials.
+
+#### File Structure Injection
+
+Projects can automatically inject their directory structure into the agent's context. This is configurable per project:
+
+- **Max depth**: Directory levels to scan (default: 5)
+- **Max files/folders**: Limits for context size
+- **Gitignore patterns**: Filter out build artifacts, dependencies, etc.
+
+The default ignores: `.a0proj/`, `venv/`, `__pycache__/`, `node_modules/`, `.git/`
+
+This feature helps the agent understand your codebase structure without manual explanation.
+
+### Activating Projects
+
+To use a project, activate it for your current chat:
+
+1. Click the project dropdown in the top-right corner
+2. Select the desired project from the list
+3. The project activates immediately
+
+
+
+Each chat can have its own active project. Multiple chats can use different projects simultaneously.
+
+Once activated, the agent:
+- Follows project-specific instructions
+- Uses project memory (if isolated)
+- Has access to project secrets and variables
+- Sees the project file structure (if enabled)
+- Works in the project directory by default
+
+
+
+### Project Directory Structure
+
+```
+/a0/usr/projects//
+├── .a0proj/ # Project metadata (managed by A0)
+│ ├── project.json # Main configuration
+│ ├── variables.env # Non-sensitive config
+│ ├── secrets.env # Sensitive credentials
+│ ├── agents.json # Subagent settings
+│ ├── instructions/ # Additional instruction files
+│ └── knowledge/ # Project knowledge base
+├── src/ # Your actual project files
+├── data/ # Data files
+└── ... # Other project content
+```
+
+### Common Use Cases
+
+**Multi-Client Work**: Create separate projects for each client with isolated memory and credentials
+
+**Multi-Language Development**: Organize by tech stack (Python ML, Node.js webapp, Go microservices)
+
+**Domain-Specific Tasks**: Separate projects for finance, marketing, HR with domain-specific instructions
+
+**Automated Workflows**: Combine with [Tasks & Scheduling](#tasks--scheduling) for recurring project-based work
+
+### Best Practices
+
+- Use **own memory** by default for client work to prevent context bleed
+- Write **specific instructions** - mention paths, formats, and quality standards
+- Choose **distinct colors** for easy visual identification when switching
+- Keep **secrets separate** from version control - backup manually
+- **Adjust file structure limits** based on project size
+- **Clean memory periodically** via Memory Dashboard for optimal performance
+
+> [!TIP]
+> For a comprehensive guide to creating and managing projects, including detailed examples and troubleshooting, see the [Projects Tutorial](projects.md).
+
+See also:
+- [Projects in Extensions](../developer/extensions.md#projects) - Technical structure details
+- [Tasks & Scheduling](#tasks--scheduling) - Automate project-based work
+- [Memory Management](#memory-management) - Maintain project knowledge
+
+## Tasks & Scheduling
+Tasks enable Agent Zero to run automated or scheduled work in isolated contexts. They're perfect for recurring workflows, batch processing, or time-delayed operations that don't require immediate attention.
+
+### What Are Tasks?
+
+Tasks are autonomous work units that Agent Zero executes in dedicated or shared chat contexts. Each task includes:
+
+- **Prompt and Instructions**: What the agent should do
+- **Execution Schedule**: When to run (cron schedule, specific times, or manual)
+- **Project Association**: Optional project context with its instructions and secrets
+- **Dedicated Context**: Each task can maintain its own conversation history
+- **State Management**: Tracks idle, running, disabled, or error states
+- **Result Tracking**: Stores last run time and execution results
+
+### Task Types
+
+Agent Zero supports three types of tasks:
+
+#### Scheduled Tasks
+Run on a recurring schedule using cron syntax:
+- **Daily reports**: `0 9 * * *` (every day at 9 AM)
+- **Hourly checks**: `0 * * * *` (every hour)
+- **Weekly summaries**: `0 9 * * 1` (Mondays at 9 AM)
+- **Custom intervals**: Full cron flexibility for complex schedules
+
+#### Planned Tasks
+Execute at specific, predetermined times:
+- **One-time future execution**: Single date/time
+- **Multi-step campaigns**: List of specific execution times
+- **Event-driven sequences**: Coordinate with external schedules
+
+#### Ad-hoc Tasks
+Manual execution for on-demand work:
+- **Quick batch jobs**: Run when needed
+- **Testing workflows**: Verify task configuration
+- **One-off operations**: Tasks that don't need scheduling
+
+### Creating Tasks
+
+#### From the UI
+
+Access the Task Scheduler from the sidebar:
+
+1. Click **Settings** → **Tasks Scheduler**
+2. Click **"New Task"** to create a task
+
+
+
+The scheduler shows:
+- **Task List**: All configured tasks with their state
+- **Filter Controls**: By type (scheduled, planned, ad-hoc) and state
+- **Quick Actions**: Run, pause, edit, or delete tasks
+- **Task Details**: Name, project association, last run, next run time
+
+#### From Chat
+
+Ask the agent to create tasks programmatically:
+
+```
+Create a scheduled task that checks my email inbox every morning at 8 AM
+and summarizes new messages from the last 24 hours.
+```
+
+The agent uses the `scheduler` tool to create tasks based on your natural language description.
+
+### Task Configuration
+
+
+
+When editing a task, you configure:
+
+#### Task Name
+A unique identifier for the task:
+- Use descriptive names: "Morning report for incoming Gmail"
+- Keep it concise but clear
+- Helps identify tasks in logs and notifications
+
+#### Task Type
+Choose the execution model:
+- **Scheduled**: Recurring cron-based execution
+- **Planned**: Specific date/time list
+- **Ad-hoc**: Manual execution only
+
+> [!NOTE]
+> Task type cannot be changed after creation. To switch types, create a new task.
+
+#### Project Association
+Optionally link the task to a project:
+
+**Benefits of project-scoped tasks:**
+- Task inherits project instructions automatically
+- Access to project-specific secrets and variables
+- Uses project's isolated memory (if configured)
+- Runs in project's working directory
+- Perfect for client-specific or domain-specific automation
+
+**Example:**
+- Project: "Financial Reports"
+- Task: "Daily Portfolio Summary"
+- Result: Task automatically uses financial analysis instructions, API keys, and memory from the project
+
+#### State Management
+Control task execution:
+
+- **Idle**: Ready to run when scheduled (green indicator)
+- **Running**: Currently executing (blue indicator)
+- **Disabled**: Won't execute even if scheduled (gray indicator)
+- **Error**: Last execution failed (red indicator)
+
+Toggle state to temporarily disable tasks without deleting them.
+
+#### Execution Plan
+For **Scheduled Tasks**, configure the cron schedule:
+
+**Common patterns:**
+```
+# Every day at 9 AM
+0 9 * * *
+
+# Every hour
+0 * * * *
+
+# Every Monday at 10 AM
+0 10 * * 1
+
+# Every 15 minutes
+*/15 * * * *
+
+# First day of month at midnight
+0 0 1 * *
+```
+
+**Timezone aware**: Tasks respect your configured timezone setting
+
+For **Planned Tasks**, add specific execution times:
+- Click "Add Execution Time"
+- Pick date and time
+- Tasks execute in order
+- Completed executions move to "Done" list
+
+### Task Execution
+
+#### Dedicated vs. Shared Context
+
+**Dedicated Context** (recommended):
+- Each task has its own isolated chat history
+- Prevents context pollution between tasks
+- Better for independent, recurring workflows
+- Default for UI-created tasks
+
+**Shared Context**:
+- Task shares a chat context (useful for agent-created tasks)
+- Can build on previous task executions
+- Useful for sequential, related operations
+
+#### Execution Flow
+
+When a task runs:
+
+1. **Context Preparation**
+ - Creates or loads the task's chat context
+ - Activates associated project (if configured)
+ - Loads project instructions, secrets, and memory
+
+2. **Prompt Injection**
+ - Injects system prompt (if specified)
+ - Adds task-specific instructions
+ - Includes any file attachments
+
+3. **Agent Execution**
+ - Agent receives the prompt as a user message
+ - Executes using available tools
+ - Can use project-scoped resources
+
+4. **Result Handling**
+ - Stores execution result and timestamp
+ - Updates task state (idle or error)
+ - Sends notifications (if configured)
+ - For Planned Tasks: moves execution to "Done" list
+
+#### Monitoring Execution
+
+**Real-time monitoring:**
+- Running tasks show "Running" state in scheduler
+- View task's chat context to see agent progress
+- Stop tasks mid-execution if needed
+
+**Execution history:**
+- **Last Run**: Timestamp of most recent execution
+- **Next Run**: Scheduled time for next execution
+- **Last Result**: Output or error from last run
+
+### Common Use Cases
+
+#### Daily Reports
+```
+Task: "Morning Inbox Summary"
+Type: Scheduled (0 9 * * *)
+Project: "Email Automation"
+Prompt: "Check my Gmail inbox for new messages from the last 24 hours.
+Summarize important emails by category and highlight any urgent items."
+```
+
+#### Recurring Monitoring
+```
+Task: "Server Health Check"
+Type: Scheduled (*/30 * * * *)
+Project: "DevOps Monitoring"
+Prompt: "Check server status, CPU usage, and disk space.
+Alert me if any metric exceeds threshold."
+```
+
+#### Batch Processing
+```
+Task: "Weekly Data Export"
+Type: Scheduled (0 2 * * 0)
+Project: "Analytics"
+Prompt: "Export last week's analytics data to CSV.
+Upload to cloud storage and send summary report."
+```
+
+#### Campaign Automation
+```
+Task: "Product Launch Sequence"
+Type: Planned
+Executions:
+ - 2026-03-01 09:00 - Send launch announcement
+ - 2026-03-03 14:00 - Send feature highlights
+ - 2026-03-07 10:00 - Send customer testimonials
+Project: "Marketing Campaigns"
+```
+
+### Integration with Projects
+
+Tasks and Projects are designed to work together:
+
+**Pattern: Project-Scoped Automation**
+
+1. Create a project with domain-specific instructions
+ ```
+ Project: "Customer Support"
+ Instructions: "You are a customer support analyst.
+ Monitor ticket queue, categorize by urgency, draft responses."
+ ```
+
+2. Create a recurring task for that project
+ ```
+ Task: "Ticket Queue Monitor"
+ Schedule: Every 2 hours
+ Project: "Customer Support"
+ Prompt: "Check new tickets and categorize them."
+ ```
+
+3. Task automatically uses:
+ - Project instructions (support analyst role)
+ - Project secrets (support system API keys)
+ - Project memory (previous ticket patterns)
+ - Project file structure (template responses)
+
+**Benefits:**
+- Consistent behavior across task executions
+- No need to repeat instructions in each task
+- Easy to update behavior (edit project instructions once)
+- Clean separation of concerns (project = context, task = action)
+
+### Notifications
+
+Tasks can trigger notifications on completion or failure:
+
+- Configure notification preferences in Settings
+- Set up notification channels (email, Slack, webhook)
+- Tasks automatically send status updates
+- Critical for unattended automation
+
+See [Notifications](../developer/notifications.md) for configuration details.
+
+
+### Multi-Source Aggregation
+Tasks can pull from multiple sources:
+
+```
+"Aggregate data from:
+1. Sales CRM API
+2. Marketing analytics dashboard
+3. Customer support tickets
+Generate unified weekly report."
+```
+
+> [!TIP]
+> Combine **Projects + Tasks + Notifications** for powerful automation workflows. Example: Create a "Client Reports" project with instructions, then add scheduled tasks for each client that inherit those instructions automatically.
+
+### Next Steps
+
+Explore related features:
+
+- [Projects](#projects) - Create isolated contexts for tasks
+- [Notifications](../developer/notifications.md) - Understand A0's notification system
+- [Memory Management](#memory-management) - Understand task memory isolation
+- [Secrets & Variables](#secrets--variables) - Secure credentials for tasks
+
+## Secrets & Variables
+Use the Settings → **Secrets** and **Variables** fields to store credentials and non-sensitive configuration values.
+
+- **Secrets** (sensitive): API keys, passwords, tokens
+- **Variables** (non-sensitive): URLs, usernames, flags
+
+You can reference these values in prompts by name. For example, store `MY_GMAIL` as a secret and instruct the agent to use it when prompted.
+
+> [!IMPORTANT]
+> Secrets are stored in `/a0/usr/secrets.env`.
+
+> [!NOTE]
+> Project-scoped secrets and variables (when using Projects) live under `/a0/usr/projects//.a0proj/` (`secrets.env`, `variables.env`).
+
+## Remote Access via Tunneling
+
+Agent Zero includes a secure tunneling feature that allows you to expose your local instance to the internet. This makes it possible to access your Agent Zero instance from anywhere or share it with others without complex network configuration.
+
+### How Tunneling Works
+
+Agent Zero uses the [Flaredantic](https://pypi.org/project/flaredantic/) library to create secure tunnels. These tunnels:
+
+- Are secure (HTTPS)
+- Don't require any configuration
+- Generate unique URLs for each session
+- Can be regenerated on demand
+
+### Creating a Tunnel
+
+1. Open **Settings** in the sidebar
+2. Navigate to the **External Services** tab
+3. Click on **Flare Tunnel** in the navigation menu
+4. Click the **Create Tunnel** button to generate a new tunnel
+5. Once created, the tunnel URL will be displayed and can be copied to share with others
+6. The tunnel URL remains active until you stop the tunnel or close Agent Zero
+
+### Security Considerations
+
+When sharing your Agent Zero instance via a tunnel:
+
+- Anyone with the URL can access your Agent Zero instance
+- No additional authentication is added beyond what your Agent Zero instance already has
+- **Always set up authentication before creating a tunnel** (see below)
+- The tunnel exposes only your Agent Zero instance, not your entire system
+
+> [!IMPORTANT]
+> When attempting to create a tunnel without authentication configured, Agent Zero will display a security warning.
+
+### Adding Authentication for Tunnels
+
+To secure your tunneled Agent Zero instance, configure authentication in Settings:
+
+1. Open **Settings** in the Agent Zero UI
+2. Navigate to the **Authentication** section
+3. Enter your desired username in the **UI Login** field
+4. Enter a strong password in the **UI Password** field
+5. Click **Save** to apply the changes
+
+Alternatively, you can set environment variables:
+
+```bash
+AUTH_LOGIN=your_username
+AUTH_PASSWORD=your_password
+```
+
+This will require users to enter these credentials when accessing your tunneled Agent Zero instance.
+
+### Troubleshooting Tunnels
+
+If you encounter issues with the tunnel feature:
+
+1. Check your internet connection
+2. Try regenerating the tunnel URL
+3. Restart Agent Zero
+4. Check the console logs for any error messages
+
+> [!TIP]
+> Combine tunneling with authentication for secure remote access to your Agent Zero instance from any device, including mobile phones and tablets.
+
+## Voice Interface
+Agent Zero provides both Text-to-Speech (TTS) and Speech-to-Text (STT) capabilities for natural voice interaction:
+
+### Text-to-Speech
+Enable voice responses from agents:
+* Toggle the "Speech" switch in the Preferences section of the sidebar
+* Agents will use your system's built-in voice synthesizer to speak their messages
+* Click the "Stop Speech" button above the input area to immediately stop any ongoing speech
+* You can also click the speech button when hovering over messages to speak individual messages or their parts
+
+
+
+- The interface allows users to stop speech at any time if a response is too lengthy or if they wish to intervene during the conversation.
+
+The TTS uses a standard voice interface provided by modern browsers, which may sound robotic but is effective and does not require complex AI models. This ensures low latency and quick responses across various platforms, including mobile devices.
+
+
+> [!TIP]
+> The Text-to-Speech feature is great for:
+> - Multitasking while receiving agent responses
+> - Accessibility purposes
+> - Creating a more interactive experience
+
+### Speech-to-Text
+Send voice messages to agents using OpenAI's Whisper model (does not require OpenAI API key!):
+
+1. Click the microphone button in the input area to start recording
+2. The button color indicates the current status:
+ - Grey: Inactive
+ - Red: Listening
+ - Green: Recording
+ - Teal: Waiting
+ - Cyan (pulsing): Processing
+
+Users can adjust settings such as silence threshold and message duration before sending to optimize their interaction experience.
+
+Configure STT settings in the Settings page:
+* **Model Size:** Choose between Base (74M, English) or other models
+ - Note: Only Large and Turbo models support multiple languages
+* **Language Code:** Set your preferred language (e.g., 'en', 'fr', 'it', 'cz')
+* **Silence Detection:**
+ - Threshold: Adjust sensitivity (lower values are more sensitive)
+ - Duration: Set how long silence should last before ending recording
+ - Timeout: Set maximum waiting time before closing the microphone
+
+
+
+> [!IMPORTANT]
+> All STT and TTS functionalities operate locally within the Docker container,
+> ensuring that no data is transmitted to external servers or OpenAI APIs. This
+> enhances user privacy while maintaining functionality.
+
+## Mathematical Expressions
+* **Complex Mathematics:** Supports full KaTeX syntax for:
+ - Fractions, exponents, and roots
+ - Matrices and arrays
+ - Greek letters and mathematical symbols
+ - Integrals, summations, and limits
+ - Mathematical alignments and equations
+
+
+
+> [!TIP]
+> When asking the agent to solve mathematical problems, it will automatically respond using KaTeX formatting for clear and professional-looking mathematical expressions.
+
+### File Browser
+Agent Zero provides a powerful file browser interface for managing your workspace:
+
+#### Interface Overview
+- **Navigation Bar**: Shows current directory path with "Up" button for parent directory
+- **File List**: Displays files and directories with key information:
+ - Name (sortable)
+ - Size in bytes
+ - Last modified timestamp
+- **Action Icons**: Each file/directory has:
+ - menu for edit and rename actions
+ - Download button
+ - Delete button (with confirmation)
+
+
+
+#### Features
+- **Directory Navigation**:
+ - Click directories to enter them
+ - Use "Up" button to move to parent directory
+ - Current path always visible for context
+
+> [!NOTE]
+> The file browser lets you navigate the Agent Zero filesystem. For file-based work, keep your working files in `/a0/usr` (or inside a Project workspace).
+>
+- **File Operations**:
+ - Create new files and directories
+ - Delete existing files and directories
+ - Download files to your local system
+ - Upload files from your local system
+- **File Information**:
+ - Visual indicators for file types (folders, code files, documents)
+ - Size information in human-readable format
+ - Last modification timestamps
+- **Bulk Operations**:
+ - Upload multiple files simultaneously
+- **File and Directory Editing**:
+ - Limited to 100MB files
+ - Binary files cannot be edited
+
+> [!TIP]
+> The File Browser integrates seamlessly with Agent Zero's capabilities. You can reference files directly in your conversations, and the agent can help you manage, modify, and organize your files.
+
+## Memory Management
+Agent Zero includes a sophisticated memory management system that stores and retrieves information from conversations, knowledge sources, and learning experiences. The Memory Dashboard provides a powerful interface to view, search, filter, edit, and delete memory entries stored in the vector database.
+
+### Accessing the Memory Dashboard
+Open the Memory Dashboard from the sidebar to manage your agent's memory:
+
+1. Click the **Memory** button in the sidebar
+2. The dashboard displays all memory entries with their metadata and preview
+3. Memory entries are organized by directory (e.g., "default") and area (e.g., "All Areas", "main")
+
+
+
+### Dashboard Features
+
+#### Filtering and Organization
+The dashboard provides several ways to organize and filter memory entries:
+
+* **Memory Directory**: Select which memory directory to view (default or project-specific)
+* **Area Filter**: Filter memories by area to focus on specific contexts
+* **Limit Control**: Adjust the number of results displayed (default: 1000)
+* **Statistics Bar**: View counts at a glance:
+ - Total: All memory entries in the directory
+ - Filtered: Entries matching current filters
+ - Knowledge: Entries from knowledge sources
+ - Conversation: Entries from chat interactions
+
+#### Search Functionality
+Find specific memories using the powerful search feature:
+
+* **Search Bar**: Enter keywords to search memory content
+* **Threshold Slider**: Adjust search sensitivity (0.00 - 1.00)
+ - Lower values return more results with looser matching
+ - Higher values return fewer, more precise matches
+ - Default threshold: 0.60
+* **Real-time Search**: Results update as you type
+
+> [!TIP]
+> Use the threshold slider to balance between broad discovery (lower values) and precise matching (higher values). Start with 0.60 and adjust based on your results.
+
+#### Memory Entry Information
+Each memory entry displays key information:
+
+* **Tags**: Visual indicators showing the memory type (MAIN, Knowledge, etc.)
+* **Timestamp**: When the memory was created (format: MM/DD HH:MM)
+* **Preview**: First few lines of the memory content
+* **Action Icons**: Quick access to view details, edit, or delete
+
+### Viewing and Editing Memories
+Click any memory entry to open the detailed view with full editing capabilities:
+
+
+
+#### Memory Details View
+The details panel provides comprehensive information about each memory:
+
+* **Memory Content**: Full text of the stored memory
+ - Syntax highlighting for structured content
+ - Editable text area for modifications
+* **Metadata Panel**: Complete memory information
+ - Unique ID
+ - Area classification
+ - Source type (e.g., "Knowledge")
+ - Timestamp (creation date and time)
+ - Source file (if applicable)
+
+#### Editing Memories
+Modify memory entries directly from the details view:
+
+1. Click on any memory entry to open the details panel
+2. Edit the memory content in the text area
+3. Click the **Save** button (checkmark icon) to apply changes
+4. Click the **Cancel** button (X icon) to discard changes
+
+> [!NOTE]
+> Edited memories are immediately updated in the vector database and will affect how the agent recalls and uses this information in future interactions.
+
+#### Deleting Memories
+Remove unwanted or outdated memory entries:
+
+1. Open the memory details view
+2. Click the **Delete** button (trash icon) in the action bar
+3. Confirm the deletion when prompted
+4. The memory is permanently removed from the vector database
+
+Alternatively, delete directly from the main dashboard:
+* Click the delete icon on any memory entry in the list
+* Confirm the deletion
+
+> [!WARNING]
+> Deleted memories cannot be recovered. Use caution when removing entries, especially those from knowledge sources or important conversations.
+
+#### Clearing Memories
+For bulk cleanup operations:
+
+* Click the **Clear** button in the dashboard header to remove all filtered memories
+* This is useful when you need to reset a specific area or start fresh with a memory directory
+* Always review your filters before clearing to avoid unintended deletions
+
+### Memory Types and Sources
+
+#### Knowledge Memories
+Memories derived from uploaded knowledge files:
+* Marked with "Knowledge" tag
+* Include source file information
+* Created when importing documents via Import Knowledge button
+* Stored persistently unless manually deleted
+
+#### Conversation Memories
+Memories from chat interactions:
+* Marked with conversation indicators
+* Created automatically as the agent learns from interactions
+* Include contextual information about when and why they were created
+* Help the agent maintain continuity across sessions
+
+### Best Practices with Memory
+
+#### Regular Maintenance
+* **Review Periodically**: Check your memory entries monthly to remove outdated information
+* **Organize by Area**: Use areas to categorize memories by project or topic
+* **Clean Up Test Data**: Remove experimental or test memories that aren't needed
+* **Monitor Growth**: Keep an eye on total memory count to maintain performance
+
+#### Search Optimization
+* **Use Specific Keywords**: More specific terms yield better results
+* **Adjust Threshold**: Fine-tune the threshold based on your needs
+* **Filter First**: Use area and directory filters before searching for better results
+* **Iterate Searches**: Try different search terms if initial results aren't helpful
+
+#### Content Quality
+* **Keep Relevant**: Remove memories that are no longer useful or accurate
+* **Update Information**: Edit memories when information becomes outdated
+* **Add Context**: When editing, ensure memories remain clear and useful
+* **Avoid Duplicates**: Remove redundant memories that store the same information
+
+#### Project Integration
+When using Projects (see [Projects](#projects)):
+* Each project maintains its own memory directory
+* Memories are isolated between projects to prevent context bleed
+* Use project-specific memory directories for focused work
+* Clear project memories when archiving completed projects
+
+> [!TIP]
+> Combine memory management with the backup system to preserve important memory states. Before clearing or making bulk changes, create a backup so you can restore if needed.
+
+> [!IMPORTANT]
+> Memory management directly affects agent behavior and recall. Regularly maintaining your memory database ensures optimal agent performance and relevant context retention.
+
+## Backup & Restore
+Agent Zero provides a comprehensive backup and restore system to protect your data and configurations. This feature helps you safeguard your work and migrate Agent Zero setups between different systems.
+
+### Creating Backups
+Access the backup functionality through the Settings interface:
+
+1. Click the **Settings** button in the sidebar
+2. Navigate to the **Backup & Restore** tab
+3. Click **Create Backup** to start the backup process
+
+#### What Gets Backed Up
+By default, Agent Zero backs up your most important data:
+
+* **Knowledge Base**: Your custom knowledge files and documents
+* **Memory System**: Agent memories and learned information
+* **Chat History**: All your conversations and interactions
+* **Configuration Files**: Settings, API keys, and system preferences
+* **Custom Skills**: Any skills you've added or modified (SKILL.md format)
+* **Uploaded Files**: Documents and files you've worked with
+
+> [!NOTE]
+> Chat history is stored at `/a0/usr/chats/` inside the container.
+
+#### Customizing Backup Content
+Before creating a backup, you can customize what to include:
+
+* **Edit Patterns**: Use the built-in editor to specify exactly which files and folders to backup
+* **Include Hidden Files**: Choose whether to include system and configuration files
+* **Preview Files**: See exactly what will be included before creating the backup
+* **Organized View**: Files are grouped by directory for easy review
+
+> [!TIP]
+> The backup system uses pattern matching, so you can include or exclude specific file types. For example, you can backup all `.py` files but exclude temporary `.tmp` files.
+
+#### Creating Your Backup
+1. Review the file preview to ensure you're backing up what you need
+2. Give your backup a descriptive name
+3. Click **Create Backup** to generate the archive
+4. The backup file will download automatically as a ZIP archive
+
+> [!NOTE]
+> Backup creation may take a few minutes depending on the amount of data. You'll see progress updates during the process.
+> Secrets stored in `/a0/usr/secrets.env` are not always included in backup archives. Keep a manual copy if you rely on secrets.
+
+### Restoring from Backup
+The restore process allows you to recover your Agent Zero setup from a previous backup:
+
+#### Starting a Restore
+1. Navigate to **Settings** → **Backup & Restore** tab
+2. Click **Restore from Backup**
+3. Upload your backup ZIP file
+
+#### Reviewing Before Restore
+After uploading, you can review and customize the restore:
+
+* **Inspect Metadata**: View information about when and where the backup was created
+* **Edit Restore Patterns**: Choose exactly which files to restore
+* **Preview Changes**: See which files will be restored, overwritten, or skipped
+* **Cross-System Compatibility**: Paths are automatically adjusted when restoring on different systems
+
+#### Restore Options
+Configure how the restore should handle existing files:
+
+* **Overwrite**: Replace existing files with backup versions
+* **Skip**: Keep existing files, only restore missing ones
+* **Backup Existing**: Create backup copies of existing files before overwriting
+
+#### Clean Before Restore
+Optionally clean up existing files before restoring:
+
+* **Smart Cleanup**: Remove files that match backup patterns before restoring
+* **Preview Cleanup**: See which files would be deleted before confirming
+* **Safe Operation**: Only affects files that match your specified patterns
+
+### Best Practices
+
+#### When to Create Backups
+* **Before Major Changes**: Always backup before significant modifications
+* **Regular Schedule**: Create weekly or monthly backups of your work
+* **Before System Updates**: Backup before updating Agent Zero or system components
+* **Project Milestones**: Save backups when completing important work
+
+#### Backup Management
+* **Descriptive Names**: Use clear names like "project-completion-2024-01"
+* **External Storage**: Keep backup files in a safe location outside Agent Zero
+* **Multiple Versions**: Maintain several backup versions for different time periods
+* **Test Restores**: Occasionally test restoring backups to ensure they work
+
+#### Security Considerations
+* **Secrets**: Backups do **not** reliably include `/a0/usr/secrets.env`. Copy it manually when migrating.
+* **Secure Storage**: Store backup files securely and don't share them
+* **Clean Systems**: When restoring on new systems, verify all configurations
+
+### Common Use Cases
+
+#### System Migration
+Moving Agent Zero to a new server or computer:
+1. Create a complete backup on the original system
+2. Install Agent Zero on the new system
+3. Restore the backup to migrate all your data and settings
+
+#### Project Archival
+Preserving completed projects:
+1. Create project-specific backup patterns
+2. Include only relevant files and conversations
+3. Store the backup as a project archive
+
+#### Development Snapshots
+Saving work-in-progress states:
+1. Create frequent backups during development
+2. Use descriptive names to track progress
+3. Restore previous versions if something goes wrong
+
+#### Team Collaboration
+Sharing Agent Zero configurations:
+1. Create backups with shared configurations and tools
+2. Team members can restore to get consistent setups
+3. Include documentation and project files
+
+> [!IMPORTANT]
+> Always test your backup and restore process in a safe environment before relying on it for critical data. Keep multiple backup versions and store them in secure, accessible locations.
+
+> [!TIP]
+> The backup system is designed to work across different operating systems and Agent Zero installations. Your backups from a Windows system will work on Linux, and vice versa.
diff --git a/docs/installation.md b/docs/installation.md
deleted file mode 100644
index b8688f0919..0000000000
--- a/docs/installation.md
+++ /dev/null
@@ -1,380 +0,0 @@
-# Users installation guide for Windows, macOS and Linux
-
-Click to open a video to learn how to install Agent Zero:
-
-[](https://www.youtube.com/watch?v=w5v5Kjx51hs)
-
-The following user guide provides instructions for installing and running Agent Zero using Docker, which is the primary runtime environment for the framework. For developers and contributors, we also provide instructions for setting up the [full development environment](#in-depth-guide-for-full-binaries-installation).
-
-
-## Windows, macOS and Linux Setup Guide
-
-
-1. **Install Docker Desktop:**
-- Docker Desktop provides the runtime environment for Agent Zero, ensuring consistent behavior and security across platforms
-- The entire framework runs within a Docker container, providing isolation and easy deployment
-- Available as a user-friendly GUI application for all major operating systems
-
-1.1. Go to the download page of Docker Desktop [here](https://www.docker.com/products/docker-desktop/). If the link does not work, just search the web for "docker desktop download".
-
-1.2. Download the version for your operating system. For Windows users, the Intel/AMD version is the main download button.
-
-
-
-
-> [!NOTE]
-> **Linux Users:** You can install either Docker Desktop or docker-ce (Community Edition).
-> For Docker Desktop, follow the instructions for your specific Linux distribution [here](https://docs.docker.com/desktop/install/linux-install/).
-> For docker-ce, follow the instructions [here](https://docs.docker.com/engine/install/).
->
-> If you're using docker-ce, you'll need to add your user to the `docker` group:
-> ```bash
-> sudo usermod -aG docker $USER
-> ```
-> Log out and back in, then run:
-> ```bash
-> docker login
-> ```
-
-1.3. Run the installer with default settings. On macOS, drag and drop the application to your Applications folder.
-
-
-
-
-
-
-
-> [!NOTE]
-> **MacOS Configuration:** In Docker Desktop's preferences (Docker menu) → Settings →
-> Advanced, enable "Allow the default Docker socket to be used (requires password)."
-
-
-
-2. **Run Agent Zero:**
-
-- Note: Agent Zero also offers a Hacking Edition based on Kali linux with modified prompts for cybersecurity tasks. The setup is the same as the regular version, just use the agent0ai/agent-zero:hacking image instead of agent0ai/agent-zero.
-
-2.1. Pull the Agent Zero Docker image:
-- Search for `agent0ai/agent-zero` in Docker Desktop
-- Click the `Pull` button
-- The image will be downloaded to your machine in a few minutes
-
-
-
-> [!TIP]
-> Alternatively, run the following command in your terminal:
->
-> ```bash
-> docker pull agent0ai/agent-zero
-> ```
-
-2.2. OPTIONAL - Create a data directory for persistence:
-
-> [!CAUTION]
-> Preferred way of persisting Agent Zero data is to use the backup and restore feature.
-> By mapping the whole `/a0` directory to a local directory, you will run into problems when upgrading Agent Zero to a newer version.
-
-- Choose or create a directory on your machine where you want to store Agent Zero's data
-- This can be any location you prefer (e.g., `C:/agent-zero-data` or `/home/user/agent-zero-data`)
-- You can map individual subfolders of `/a0` to a local directory or the full `/a0` directory (not recommended).
-- This directory will contain all your Agent Zero files, like the legacy root folder structure:
- - `/agents` - Specialized agents with their prompts and tools
- - `/memory` - Agent's memory and learned information
- - `/knowledge` - Knowledge base
- - `/instruments` - Instruments and functions
- - `/prompts` - Prompt files
- - `.env` - Your API keys
- - `/tmp/settings.json` - Your Agent Zero settings
-
-> [!TIP]
-> Choose a location that's easy to access and backup. All your Agent Zero data
-> will be directly accessible in this directory.
-
-2.3. Run the container:
-- In Docker Desktop, go back to the "Images" tab
-- Click the `Run` button next to the `agent0ai/agent-zero` image
-- Open the "Optional settings" menu
-- Set the web port (80) to desired host port number in the second "Host port" field or set to `0` for automatic port assignment
-
-Optionally you can map local folders for file persistence:
-> [!CAUTION]
-> Preferred way of persisting Agent Zero data is to use the backup and restore feature.
-> By mapping the whole `/a0` directory to a local directory, you will run into problems when upgrading Agent Zero to a newer version.
-- OPTIONAL: Under "Volumes", configure your mapped folders, if needed:
- - Example host path: Your chosen directory (e.g., `C:\agent-zero\memory`)
- - Example container path: `/a0/memory`
-
-
-- Click the `Run` button in the "Images" tab.
-
-
-
-
-- The container will start and show in the "Containers" tab
-
-
-
-> [!TIP]
-> Alternatively, run the following command in your terminal:
-> ```bash
-> docker run -p $PORT:80 -v /path/to/your/data:/a0 agent0ai/agent-zero
-> ```
-> - Replace `$PORT` with the port you want to use (e.g., `50080`)
-> - Replace `/path/to/your/data` with your chosen directory path
-
-2.4. Access the Web UI:
-- The framework will take a few seconds to initialize and the Docker logs will look like the image below.
-- Find the mapped port in Docker Desktop (shown as `:80`) or click the port right under the container ID as shown in the image below
-
-
-
-- Open `http://localhost:` in your browser
-- The Web UI will open. Agent Zero is ready for configuration!
-
-
-
-> [!TIP]
-> You can also access the Web UI by clicking the ports right under the container ID in Docker Desktop.
-
-> [!NOTE]
-> After starting the container, you'll find all Agent Zero files in your chosen
-> directory. You can access and edit these files directly on your machine, and
-> the changes will be immediately reflected in the running container.
-
-3. Configure Agent Zero
-- Refer to the following sections for a full guide on how to configure Agent Zero.
-
-## Settings Configuration
-Agent Zero provides a comprehensive settings interface to customize various aspects of its functionality. Access the settings by clicking the "Settings"button with a gear icon in the sidebar.
-
-### Agent Configuration
-- **Prompts Subdirectory:** Choose the subdirectory within `/prompts` for agent behavior customization. The 'default' directory contains the standard prompts.
-- **Memory Subdirectory:** Select the subdirectory for agent memory storage, allowing separation between different instances.
-- **Knowledge Subdirectory:** Specify the location of custom knowledge files to enhance the agent's understanding.
-
-
-
-### Chat Model Settings
-- **Provider:** Select the chat model provider (e.g., Ollama)
-- **Model Name:** Choose the specific model (e.g., llama3.2)
-- **API URL:** URL of the API endpoint for the chat model - only needed for custom providers like Ollama, Azure, etc.
-- **Context Length:** Set the maximum token limit for context window
-- **Context Window Space:** Configure how much of the context window is dedicated to chat history
-
-
-
-### Utility Model Configuration
-- **Provider & Model:** Select a smaller, faster model for utility tasks like memory organization and summarization
-- **Temperature:** Adjust the determinism of utility responses
-
-### Embedding Model Settings
-- **Provider:** Choose the embedding model provider (e.g., OpenAI)
-- **Model Name:** Select the specific embedding model (e.g., text-embedding-3-small)
-
-### Speech to Text Options
-- **Model Size:** Choose the speech recognition model size
-- **Language Code:** Set the primary language for voice recognition
-- **Silence Settings:** Configure silence threshold, duration, and timeout parameters for voice input
-
-### API Keys
-- Configure API keys for various service providers directly within the Web UI
-- Click `Save` to confirm your settings
-
-> [!CAUTION]
-> **GitHub Copilot Provider:** When using the GitHub Copilot provider, after selecting the model and entering your first prompt, the OAuth login procedure will begin. You'll find the authentication code and link in the output logs. Complete the authentication process by following the provided link and entering the code, then you may continue using Agent Zero.
-
-> [!NOTE]
-> **GitHub Copilot Limitations:** GitHub Copilot models typically have smaller rate limits and context windows compared to models hosted by other providers like OpenAI, Anthropic, or Azure. Consider this when working with large conversations or high-frequency requests.
-
-
-
-### Authentication
-- **UI Login:** Set username for web interface access
-- **UI Password:** Configure password for web interface security
-- **Root Password:** Manage Docker container root password for SSH access
-
-
-
-### Development Settings
-- **RFC Parameters (local instances only):** configure URLs and ports for remote function calls between instances
-- **RFC Password:** Configure password for remote function calls
-Learn more about Remote Function Calls and their purpose [here](#7-configure-agent-zero-rfc).
-
-> [!IMPORTANT]
-> Always keep your API keys and passwords secure.
-
-# Choosing Your LLMs
-The Settings page is the control center for selecting the Large Language Models (LLMs) that power Agent Zero. You can choose different LLMs for different roles:
-
-| LLM Role | Description |
-| --- | --- |
-| `chat_llm` | This is the primary LLM used for conversations and generating responses. |
-| `utility_llm` | This LLM handles internal tasks like summarizing messages, managing memory, and processing internal prompts. Using a smaller, less expensive model here can improve efficiency. |
-| `embedding_llm` | This LLM is responsible for generating embeddings used for memory retrieval and knowledge base lookups. Changing the `embedding_llm` will re-index all of A0's memory. |
-
-**How to Change:**
-1. Open Settings page in the Web UI.
-2. Choose the provider for the LLM for each role (Chat model, Utility model, Embedding model) and write the model name.
-3. Click "Save" to apply the changes.
-
-## Important Considerations
-
-## Installing and Using Ollama (Local Models)
-If you're interested in Ollama, which is a powerful tool that allows you to run various large language models locally, here's how to install and use it:
-
-#### First step: installation
-**On Windows:**
-
-Download Ollama from the official website and install it on your machine.
-
-
-
-**On macOS:**
-```
-brew install ollama
-```
-Otherwise choose macOS installer from the [official website](https://ollama.com/).
-
-**On Linux:**
-```bash
-curl -fsSL https://ollama.com/install.sh | sh
-```
-
-**Finding Model Names:**
-Visit the [Ollama model library](https://ollama.com/library) for a list of available models and their corresponding names. The format is usually `provider/model-name` (or just `model-name` in some cases).
-
-#### Second step: pulling the model
-**On Windows, macOS, and Linux:**
-```
-ollama pull
-```
-
-1. Replace `` with the name of the model you want to use. For example, to pull the Mistral Large model, you would use the command `ollama pull mistral-large`.
-
-2. A CLI message should confirm the model download on your system
-
-#### Selecting your model within Agent Zero
-1. Once you've downloaded your model(s), you must select it in the Settings page of the GUI.
-
-2. Within the Chat model, Utility model, or Embedding model section, choose Ollama as provider.
-
-3. Write your model code as expected by Ollama, in the format `llama3.2` or `qwen2.5:7b`
-
-4. Provide your API base URL to your ollama API endpoint, usually `http://host.docker.internal:11434`
-
-5. Click `Save` to confirm your settings.
-
-
-
-#### Managing your downloaded models
-Once you've downloaded some models, you might want to check which ones you have available or remove any you no longer need.
-
-- **Listing downloaded models:**
- To see a list of all the models you've downloaded, use the command:
- ```
- ollama list
- ```
-- **Removing a model:**
- If you need to remove a downloaded model, you can use the `ollama rm` command followed by the model name:
- ```
- ollama rm
- ```
-
-
-- Experiment with different model combinations to find the balance of performance and cost that best suits your needs. E.g., faster and lower latency LLMs will help, and you can also use `faiss_gpu` instead of `faiss_cpu` for the memory.
-
-## Using Agent Zero on your mobile device
-Agent Zero's Web UI is accessible from any device on your network through the Docker container:
-
-> [!NOTE]
-> In settings, External Services tab, you can enable Cloudflare Tunnel to expose your Agent Zero instance to the internet.
-> ⚠️ Do not forget to set username and password in the settings Authentication tab to secure your instance on the internet.
-
-1. The Docker container automatically exposes the Web UI on all network interfaces
-2. Find the mapped port in Docker Desktop:
- - Look under the container name (usually in the format `:80`)
- - For example, if you see `32771:80`, your port is `32771`
-3. Access the Web UI from any device using:
- - Local access: `http://localhost:`
- - Network access: `http://:`
-
-> [!TIP]
-> - Your computer's IP address is usually in the format `192.168.x.x` or `10.0.x.x`
-> - You can find your external IP address by running `ipconfig` (Windows) or `ifconfig` (Linux/Mac)
-> - The port is automatically assigned by Docker unless you specify one
-
-> [!NOTE]
-> If you're running Agent Zero directly on your system (legacy approach) instead of
-> using Docker, you'll need to configure the host manually in `run_ui.py` to run on all interfaces using `host="0.0.0.0"`.
-
-For developers or users who need to run Agent Zero directly on their system,see the [In-Depth Guide for Full Binaries Installation](#in-depth-guide-for-full-binaries-installation).
-
-# How to update Agent Zero
-
-> [!NOTE]
-> Since v0.9, Agent Zero has a Backup and Restore feature, so you don't need to backup the files manually.
-> In Settings, Backup and Restore tab will guide you through the process.
-
-1. **If you come from the previous version of Agent Zero:**
-- Your data is safely stored across various directories and files inside the Agent Zero folder.
-- To update to the new Docker runtime version, you might want to backup the following files and directories:
- - `/memory` - Agent's memory
- - `/knowledge` - Custom knowledge base (if you imported any custom knowledge files)
- - `/instruments` - Custom instruments and functions (if you created any custom)
- - `/tmp/settings.json` - Your Agent Zero settings
- - `/tmp/chats/` - Your chat history
-- Once you have saved these files and directories, you can proceed with the Docker runtime [installation instructions above](#windows-macos-and-linux-setup-guide) setup guide.
-- Reach for the folder where you saved your data and copy it to the new Agent Zero folder set during the installation process.
-- Agent Zero will automatically detect your saved data and use it across memory, knowledge, instruments, prompts and settings.
-
-> [!IMPORTANT]
-> If you have issues loading your settings, you can try to delete the `/tmp/settings.json` file and let Agent Zero generate a new one.
-> The same goes for chats in `/tmp/chats/`, they might be incompatible with the new version
-
-2. **Update Process (Docker Desktop)**
-- Go to Docker Desktop and stop the container from the "Containers" tab
-- Right-click and select "Remove" to remove the container
-- Go to "Images" tab and remove the `agent0ai/agent-zero` image or click the three dots to pull the difference and update the Docker image.
-
-
-
-- Search and pull the new image if you chose to remove it
-- Run the new container with the same volume settings as the old one
-
-> [!IMPORTANT]
-> Make sure to use the same volume mount path when running the new
-> container to preserve your data. The exact path depends on where you stored
-> your Agent Zero data directory (the chosen directory on your machine).
-
-> [!TIP]
-> Alternatively, run the following commands in your terminal:
->
-> ```bash
-> # Stop the current container
-> docker stop agent-zero
->
-> # Remove the container (data is safe in the folder)
-> docker rm agent-zero
->
-> # Remove the old image
-> docker rmi agent0ai/agent-zero
->
-> # Pull the latest image
-> docker pull agent0ai/agent-zero
->
-> # Run new container with the same volume mount
-> docker run -p $PORT:80 -v /path/to/your/data:/a0 agent0ai/agent-zero
-> ```
-
-
-### Conclusion
-After following the instructions for your specific operating system, you should have Agent Zero successfully installed and running. You can now start exploring the framework's capabilities and experimenting with creating your own intelligent agents.
-
-If you encounter any issues during the installation process, please consult the [Troubleshooting section](troubleshooting.md) of this documentation or refer to the Agent Zero [Skool](https://www.skool.com/agent-zero) or [Discord](https://discord.gg/B8KZKNsPpj) community for assistance.
-
diff --git a/docs/mcp_setup.md b/docs/mcp_setup.md
deleted file mode 100644
index a1d382e46e..0000000000
--- a/docs/mcp_setup.md
+++ /dev/null
@@ -1,146 +0,0 @@
-# Agent Zero: MCP Server Integration Guide
-
-This guide explains how to configure and utilize external tool providers through the Model Context Protocol (MCP) with Agent Zero. This allows Agent Zero to leverage tools hosted by separate local or remote MCP-compliant servers.
-
-## What are MCP Servers?
-
-MCP servers are external processes or services that expose a set of tools that Agent Zero can use. Agent Zero acts as an MCP *client*, consuming tools made available by these servers. The integration supports three main types of MCP servers:
-
-1. **Local Stdio Servers**: These are typically local executables that Agent Zero communicates with via standard input/output (stdio).
-2. **Remote SSE Servers**: These are servers, often accessible over a network, that Agent Zero communicates with using Server-Sent Events (SSE), usually over HTTP/S.
-3. **Remote Streaming HTTP Servers**: These are servers that use the streamable HTTP transport protocol for MCP communication, providing an alternative to SSE for network-based MCP servers.
-
-## How Agent Zero Consumes MCP Tools
-
-Agent Zero discovers and integrates MCP tools dynamically:
-
-1. **Configuration**: You define the MCP servers Agent Zero should connect to in its configuration. The primary way to do this is through the Agent Zero settings UI.
-2. **Saving Settings**: When you save your settings via the UI, Agent Zero updates the `tmp/settings.json` file, specifically the `"mcp_servers"` key.
-3. **Automatic Installation (on Restart)**: After saving your settings and restarting Agent Zero, the system will attempt to automatically install any MCP server packages defined with `command: "npx"` and the `--package` argument in their configuration (this process is managed by `initialize.py`). You can monitor the application logs (e.g., Docker logs) for details on this installation attempt.
-4. **Tool Discovery**: Upon initialization (or when settings are updated), Agent Zero connects to each configured and enabled MCP server and queries it for the list of available tools, their descriptions, and expected parameters.
-5. **Dynamic Prompting**: The information about these discovered tools is then dynamically injected into the agent's system prompt. A placeholder like `{{tools}}` in a system prompt template (e.g., `prompts/default/agent.system.mcp_tools.md`) is replaced with a formatted list of all available MCP tools. This allows the agent's underlying Language Model (LLM) to know which external tools it can request.
-6. **Tool Invocation**: When the LLM decides to use an MCP tool, Agent Zero's `process_tools` method (handled by `mcp_handler.py`) identifies it as an MCP tool and routes the request to the appropriate `MCPConfig` helper, which then communicates with the designated MCP server to execute the tool.
-
-## Configuration
-
-### Configuration File & Method
-
-The primary method for configuring MCP servers is through **Agent Zero's settings UI**.
-
-When you input and save your MCP server details in the UI, these settings are written to:
-
-* `tmp/settings.json`
-
-### The `mcp_servers` Setting in `tmp/settings.json`
-
-Within `tmp/settings.json`, the MCP servers are defined under the `"mcp_servers"` key.
-
-* **Value Type**: The value for `"mcp_servers"` must be a **JSON formatted string**. This string itself contains an **array** of server configuration objects.
-* **Default Value**: If `tmp/settings.json` does not exist, or if it exists but does not contain the `"mcp_servers"` key, Agent Zero will use a default value of `""` (an empty string), meaning no MCP servers are configured.
-* **Manual Editing (Advanced)**: While UI configuration is recommended, you can also manually edit `tmp/settings.json`. If you do, ensure the `"mcp_servers"` value is a valid JSON string, with internal quotes properly escaped.
-
-**Example `mcp_servers` string in `tmp/settings.json`:**
-
-```json
-{
- // ... other settings ...
- "mcp_servers": "[{'name': 'sequential-thinking','command': 'npx','args': ['--yes', '--package', '@modelcontextprotocol/server-sequential-thinking', 'mcp-server-sequential-thinking']}, {'name': 'brave-search', 'command': 'npx', 'args': ['--yes', '--package', '@modelcontextprotocol/server-brave-search', 'mcp-server-brave-search'], 'env': {'BRAVE_API_KEY': 'YOUR_BRAVE_KEY_HERE'}}, {'name': 'fetch', 'command': 'npx', 'args': ['--yes', '--package', '@tokenizin/mcp-npx-fetch', 'mcp-npx-fetch', '--ignore-robots-txt', '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36']}]",
- // ... other settings ...
-}
-```
-*Note: In the actual `settings.json` file, the entire value for `mcp_servers` is a single string, with backslashes escaping the quotes within the array structure.*
-
-* **Updating**: As mentioned, the recommended way to set or update this value is through Agent Zero's settings UI.
-* **For Existing `settings.json` Files (After an Upgrade)**: If you have an existing `tmp/settings.json` from a version of Agent Zero prior to MCP server support, the `"mcp_servers"` key will likely be missing. To add this key:
- 1. Ensure you are running a version of Agent Zero that includes MCP server support.
- 2. Run Agent Zero and open its settings UI.
- 3. Save the settings (even without making changes). This action will write the complete current settings structure, including a default `"mcp_servers": ""` if not otherwise populated, to `tmp/settings.json`. You can then configure your servers via the UI or by carefully editing this string.
-
-### MCP Server Configuration Structure
-
-Here are templates for configuring individual servers within the `mcp_servers` JSON array string:
-
-**1. Local Stdio Server**
-
-```json
-{
- "name": "My Local Tool Server",
- "description": "Optional: A brief description of this server.",
- "type": "stdio", // Optional: Explicitly specify server type. Can be "stdio", "sse", or streaming HTTP variants ("http-stream", "streaming-http", "streamable-http", "http-streaming"). Auto-detected if omitted.
- "command": "python", // The executable to run (e.g., python, /path/to/my_tool_server)
- "args": ["path/to/your/mcp_stdio_script.py", "--some-arg"], // List of arguments for the command
- "env": { // Optional: Environment variables for the command's process
- "PYTHONPATH": "/path/to/custom/libs:.",
- "ANOTHER_VAR": "value"
- },
- "encoding": "utf-8", // Optional: Encoding for stdio communication (default: "utf-8")
- "encoding_error_handler": "strict", // Optional: How to handle encoding errors. Can be "strict", "ignore", or "replace" (default: "strict").
- "disabled": false // Set to true to temporarily disable this server without removing its configuration.
-}
-```
-
-**2. Remote SSE Server**
-
-```json
-{
- "name": "My Remote API Tools",
- "description": "Optional: Description of the remote SSE server.",
- "type": "sse", // Optional: Explicitly specify server type. Can be "stdio", "sse", or streaming HTTP variants ("http-stream", "streaming-http", "streamable-http", "http-streaming"). Auto-detected if omitted.
- "url": "https://api.example.com/mcp-sse-endpoint", // The full URL for the SSE endpoint of the MCP server.
- "headers": { // Optional: Any HTTP headers required for the connection.
- "Authorization": "Bearer YOUR_API_KEY_OR_TOKEN",
- "X-Custom-Header": "some_value"
- },
- "timeout": 5.0, // Optional: Connection timeout in seconds (default: 5.0).
- "sse_read_timeout": 300.0, // Optional: Read timeout for the SSE stream in seconds (default: 300.0, i.e., 5 minutes).
- "disabled": false
-}
-```
-
-**3. Remote Streaming HTTP Server**
-
-```json
-{
- "name": "My Streaming HTTP Tools",
- "description": "Optional: Description of the remote streaming HTTP server.",
- "type": "streaming-http", // Optional: Explicitly specify server type. Can be "stdio", "sse", or streaming HTTP variants ("http-stream", "streaming-http", "streamable-http", "http-streaming"). Auto-detected if omitted.
- "url": "https://api.example.com/mcp-http-endpoint", // The full URL for the streaming HTTP endpoint of the MCP server.
- "headers": { // Optional: Any HTTP headers required for the connection.
- "Authorization": "Bearer YOUR_API_KEY_OR_TOKEN",
- "X-Custom-Header": "some_value"
- },
- "timeout": 5.0, // Optional: Connection timeout in seconds (default: 5.0).
- "sse_read_timeout": 300.0, // Optional: Read timeout for the SSE and streaming HTTP streams in seconds (default: 300.0, i.e., 5 minutes).
- "disabled": false
-}
-```
-
-**Example `mcp_servers` value in `tmp/settings.json`:**
-
-```json
-{
- // ... other settings ...
- "mcp_servers": "[{'name': 'MyPythonTools', 'command': 'python3', 'args': ['mcp_scripts/my_server.py'], 'disabled': false}, {'name': 'ExternalAPI', 'url': 'https://data.example.com/mcp', 'headers': {'X-Auth-Token': 'supersecret'}, 'disabled': false}]",
- // ... other settings ...
-}
-```
-
-**Key Configuration Fields:**
-
-* `"name"`: A unique name for the server. This name will be used to prefix the tools provided by this server (e.g., `my_server_name.tool_name`). The name is normalized internally (converted to lowercase, spaces and hyphens replaced with underscores).
-* `"type"`: Optional explicit server type specification. Can be `"stdio"`, `"sse"`, or streaming HTTP variants (`"http-stream"`, `"streaming-http"`, `"streamable-http"`, `"http-streaming"`). If omitted, the type is auto-detected based on the presence of `"command"` (stdio) or `"url"` (defaults to sse for backward compatibility).
-* `"disabled"`: A boolean (`true` or `false`). If `true`, Agent Zero will ignore this server configuration.
-* `"url"`: **Required for Remote SSE and Streaming HTTP Servers.** The endpoint URL.
-* `"command"`: **Required for Local Stdio Servers.** The executable command.
-* `"args"`: Optional list of arguments for local Stdio servers.
-* Other fields are specific to the server type and mostly optional with defaults.
-
-## Using MCP Tools
-
-Once configured, successfully installed (if applicable, e.g., for `npx` based servers), and discovered by Agent Zero:
-
-* **Tool Naming**: MCP tools will appear to the agent with a name prefixed by the server name you defined (and normalized, e.g., lowercase, underscores for spaces/hyphens). For instance, if your server is named `"sequential-thinking"` in the configuration and it offers a tool named `"run_chain"`, the agent will know it as `sequential_thinking.run_chain`.
-* **Agent Interaction**: You can instruct the agent to use these tools. For example: "Agent, use the `sequential_thinking.run_chain` tool with the following input..." The agent's LLM will then formulate the appropriate JSON request.
-* **Execution Flow**: Agent Zero's `process_tools` method (with logic in `python/helpers/mcp_handler.py`) prioritizes looking up the tool name in the `MCPConfig`. If found, the execution is delegated to the corresponding MCP server. If not found as an MCP tool, it then attempts to find a local/built-in tool with that name.
-
-This setup provides a flexible way to extend Agent Zero's capabilities by integrating with various external tool providers without modifying its core codebase.
diff --git a/docs/plans/2026-02-28-docker-auto-clone-design.md b/docs/plans/2026-02-28-docker-auto-clone-design.md
new file mode 100644
index 0000000000..a36b84b73a
--- /dev/null
+++ b/docs/plans/2026-02-28-docker-auto-clone-design.md
@@ -0,0 +1,51 @@
+# Context Engine Docker Auto-Clone & Build Design
+
+## Problem
+
+The plugin's `docker-compose.context-engine.yaml` references non-existent images
+(`ghcr.io/context-engine-ai/*`). The real Context Engine builds services from
+Dockerfiles in its GitHub repository. Users get "denied" errors trying to pull.
+
+## Solution
+
+The Docker handler auto-clones the Context Engine repo, generates a `.env` with
+Agent Zero defaults, and runs `docker compose` from the real repo. One toggle in
+the settings page handles everything.
+
+## Flow
+
+1. User toggles "Deploy" ON
+2. Handler checks if Context Engine repo exists at configured path
+3. If missing: `git clone https://github.com/Context-Engine-AI/Context-Engine.git`
+4. If `.env` missing: generate from `.env.example` with AZ-specific defaults
+5. Run `docker compose up -d` from the cloned repo directory
+6. UI shows phase-specific status (cloning → building → running)
+
+## .env Defaults for Agent Zero
+
+```
+QDRANT_URL=http://qdrant:6333
+COLLECTION_NAME=codebase
+EMBEDDING_PROVIDER=remote
+EMBEDDING_SERVICE_URL=http://embedding:8100
+EMBEDDING_MODEL=nomic-ai/nomic-embed-text-v1.5
+HOST_INDEX_PATH=
+CODEBASE_STATE_BACKEND=redis
+CODEBASE_STATE_REDIS_URL=redis://redis:6379/0
+FASTMCP_HOST=0.0.0.0
+FASTMCP_PORT=8000
+FASTMCP_INDEXER_PORT=8001
+FASTMCP_TRANSPORT=sse
+FASTMCP_HTTP_TRANSPORT=streamable-http
+FASTMCP_HTTP_PORT=8002
+FASTMCP_INDEXER_HTTP_PORT=8003
+```
+
+## Files Changed
+
+| File | Action |
+|------|--------|
+| `api/docker.py` | Rewrite: add clone, .env generation, real repo compose |
+| `webui/config.html` | Modify: add repo_path field, cloning/building states |
+| `default_config.yaml` | Modify: add context_engine_repo_path |
+| `docker-compose.context-engine.yaml` | Delete: no longer needed |
diff --git a/docs/plans/2026-02-28-docker-services-ui-design.md b/docs/plans/2026-02-28-docker-services-ui-design.md
new file mode 100644
index 0000000000..265588f031
--- /dev/null
+++ b/docs/plans/2026-02-28-docker-services-ui-design.md
@@ -0,0 +1,400 @@
+# Context Engine Docker Services UI — Implementation Plan
+
+> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
+
+**Goal:** Add a Docker deploy toggle and test connection button to the Context Engine plugin settings UI.
+
+**Architecture:** A new `api/docker.py` handler runs `docker compose` commands via `asyncio.create_subprocess_exec`. The existing `webui/config.html` gets a new "Docker Services" section at the top with an Alpine.js-driven toggle, status indicator, and test connection button. No new config fields — Docker state is derived at runtime.
+
+**Tech Stack:** Python 3 (asyncio subprocess), Alpine.js, Agent Zero plugin API framework (Flask-based `ApiHandler`).
+
+---
+
+### Task 1: Create the Docker API handler
+
+**Files:**
+- Create: `usr/plugins/context-engine/api/docker.py`
+
+**Step 1: Write the handler**
+
+Create `usr/plugins/context-engine/api/docker.py`:
+
+```python
+import asyncio
+import json
+
+from python.helpers.api import ApiHandler, Request, Response
+
+from pathlib import Path
+
+_plugin_root = Path(__file__).parent.parent
+_compose_file = _plugin_root / "docker-compose.context-engine.yaml"
+
+
+class DockerHandler(ApiHandler):
+ """Deploy, stop, and check status of Context Engine Docker services."""
+
+ async def process(self, input: dict, request: Request) -> dict | Response:
+ action = input.get("action", "").strip().lower()
+ if action not in ("up", "down", "ps"):
+ return {"ok": False, "error": "Invalid action. Use 'up', 'down', or 'ps'."}
+
+ if not _compose_file.is_file():
+ return {"ok": False, "error": f"Compose file not found: {_compose_file.name}"}
+
+ try:
+ if action == "up":
+ return await self._run_compose(["up", "-d"], timeout=120)
+ elif action == "down":
+ return await self._run_compose(["down"], timeout=30)
+ else: # ps
+ return await self._get_status()
+ except FileNotFoundError:
+ return {"ok": False, "error": "Docker is not installed or not in PATH."}
+ except asyncio.TimeoutError:
+ return {"ok": False, "error": "Operation timed out. Try running 'docker compose pull' manually first."}
+ except Exception as e:
+ return {"ok": False, "error": str(e)}
+
+ async def _run_compose(self, args: list[str], timeout: int) -> dict:
+ proc = await asyncio.create_subprocess_exec(
+ "docker", "compose", "-f", str(_compose_file), *args,
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE,
+ )
+ stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout)
+ output = (stdout.decode() + stderr.decode()).strip()
+ if proc.returncode == 0:
+ return {"ok": True, "output": output}
+ return {"ok": False, "error": output or f"docker compose {args[0]} failed", "output": output}
+
+ async def _get_status(self) -> dict:
+ proc = await asyncio.create_subprocess_exec(
+ "docker", "compose", "-f", str(_compose_file), "ps", "--format", "json",
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE,
+ )
+ stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=30)
+ if proc.returncode != 0:
+ return {"ok": False, "running": False, "error": stderr.decode().strip(), "services": []}
+
+ raw = stdout.decode().strip()
+ if not raw:
+ return {"ok": True, "running": False, "services": [], "service_count": 0}
+
+ # docker compose ps --format json outputs one JSON object per line
+ services = []
+ for line in raw.splitlines():
+ line = line.strip()
+ if not line:
+ continue
+ try:
+ svc = json.loads(line)
+ services.append({
+ "name": svc.get("Name", svc.get("Service", "")),
+ "state": svc.get("State", ""),
+ "status": svc.get("Status", ""),
+ })
+ except json.JSONDecodeError:
+ continue
+
+ running_count = sum(1 for s in services if s["state"] == "running")
+ return {
+ "ok": True,
+ "running": running_count > 0 and running_count == len(services),
+ "services": services,
+ "service_count": len(services),
+ "running_count": running_count,
+ }
+```
+
+**Step 2: Verify the handler loads**
+
+Run: `cd /Users/lazy/intent/workspaces/full-create/agent-zero && python -c "from pathlib import Path; print(Path('usr/plugins/context-engine/api/docker.py').is_file())"`
+Expected: `True`
+
+**Step 3: Commit**
+
+```bash
+git add usr/plugins/context-engine/api/docker.py
+git commit -m "feat(context-engine): add Docker compose API handler"
+```
+
+---
+
+### Task 2: Add Docker Services section to settings UI
+
+**Files:**
+- Modify: `usr/plugins/context-engine/webui/config.html`
+
+**Step 1: Add the Docker Services section**
+
+Insert a new section at the top of `config.html`, right after the opening `
` inside the ``, before the existing "Context Engine" section-title. The section uses inline Alpine.js `x-data` with `x-init` to check Docker status on load.
+
+Replace the beginning of config.html (lines 1-14) with:
+
+```html
+
+
+ Context Engine
+
+
+
+
+
+
+
+
+
+
Docker Services
+
+ Deploy and manage the Context Engine Docker stack (Qdrant, Redis, Embedding, MCP services).
+
+
+
+
+
Deploy Services
+
+ Start or stop all Context Engine Docker containers.
+
+ Integration with Context Engine for semantic code search, symbol graph queries, context-aware Q&A,
+ and persistent developer memory.
+
+```
+
+The rest of `config.html` (lines 16-160, from the first `
` for Indexer Endpoint onwards) stays unchanged.
+
+**Step 2: Verify the HTML is valid**
+
+Open Agent Zero settings UI in the browser. Navigate to the Context Engine plugin settings. Verify:
+- The Docker Services section appears at the top
+- The toggle reflects actual container state
+- The existing settings fields appear below
+
+**Step 3: Commit**
+
+```bash
+git add usr/plugins/context-engine/webui/config.html
+git commit -m "feat(context-engine): add Docker deploy toggle and test connection to settings"
+```
+
+---
+
+### Task 3: Manual integration test
+
+**Step 1: Test with containers stopped**
+
+1. Ensure all context-engine containers are stopped: `docker compose -f usr/plugins/context-engine/docker-compose.context-engine.yaml down`
+2. Open Agent Zero settings → Context Engine
+3. Verify: toggle is OFF, status shows "Stopped"
+
+**Step 2: Test deploy**
+
+1. Toggle ON
+2. Verify: status shows "Starting..."
+3. Wait for completion
+4. Verify: status shows "Running (7/7 services)" or appropriate count
+
+**Step 3: Test connection**
+
+1. Click "Test Connection"
+2. Verify: green check "MCP endpoints responding" (or red X if services aren't ready yet)
+
+**Step 4: Test stop**
+
+1. Toggle OFF
+2. Verify: status shows "Stopping..." then "Stopped"
+
+**Step 5: Commit final state**
+
+```bash
+git add -A usr/plugins/context-engine/
+git commit -m "feat(context-engine): Docker services UI integration complete"
+```
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 437cc9b65d..893cb18d3f 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -1,54 +1,101 @@
# Quick Start
-This guide provides a quick introduction to using Agent Zero. We'll cover launching the web UI, starting a new chat, and running a simple task.
+This guide provides a quick introduction to using Agent Zero. We'll cover the essential installation steps and running your first Skill.
-## Launching the Web UI
-1. Make sure you have Agent Zero installed and your environment set up correctly (refer to the [Installation guide](installation.md) if needed).
-2. Open a terminal in the Agent Zero directory and activate your conda environment (if you're using one).
-3. Run the following command:
+## Installation Steps
+
+### Step 1: Install Docker Desktop
+
+Download and install Docker Desktop for your operating system:
+
+- **Windows:** Download from [Docker Desktop](https://www.docker.com/products/docker-desktop/) and run the installer with default settings
+- **macOS:** Download for Apple Silicon or Intel, drag to Applications, and enable the Docker socket in Settings → Advanced
+- **Linux:** Install Docker Desktop or docker-ce following the [official instructions](https://docs.docker.com/desktop/install/linux-install/)
+
+> [!TIP]
+> For complete OS-specific installation instructions, see the [full Installation Guide](setup/installation.md#step-1-install-docker-desktop).
+
+### Step 2: Pull the Agent Zero Image
+
+Using Docker Desktop GUI, search for `agent0ai/agent-zero` and click Pull, or use the terminal:
```bash
-python run_ui.py
+docker pull agent0ai/agent-zero
```
-4. A message similar to this will appear in your terminal, indicating the Web UI is running:
+### Step 3: Run the Container
-
+**Using Docker Desktop:** Go to Images tab, click Run next to `agent0ai/agent-zero`, open Optional settings, map a host port to container port `80` (use `0` for automatic assignment), then click Run.
-5. Open your web browser and navigate to the URL shown in the terminal (usually `http://127.0.0.1:50001`). You should see the Agent Zero Web UI.
+**Using Terminal:**
-
+```bash
+docker run -p 0:80 agent0ai/agent-zero
+```
-> [!TIP]
-> As you can see, the Web UI has four distinct buttons for easy chat management:
-> `New Chat`, `Reset Chat`, `Save Chat`, and `Load Chat`.
-> Chats can be saved and loaded individually in `json` format and are stored in the
-> `/tmp/chats` directory.
+The container will start in a few seconds. Find the mapped port in Docker Desktop (shown as `:80`).
+
+### Step 4: Open the Web UI and Configure API Key
+
+Open your browser and navigate to `http://localhost:`. The Web UI will show a warning banner about missing API key.
+
+
- 
+Click **Add your API key** to open Settings and configure:
-## Running a Simple Task
-Let's ask Agent Zero to download a YouTube video. Here's how:
+- **Default Provider:** OpenRouter (supports most models with a single API key)
+- **Alternative Providers:** Anthropic, OpenAI, Ollama/LM Studio (local models), and many others
+- **Model Selection:** Choose your chat model (e.g., `anthropic/claude-sonnet-4-5` for OpenRouter)
-1. Type "Download a YouTube video for me" in the chat input field and press Enter or click the send button.
+> [!NOTE]
+> Agent Zero supports any LLM provider, including local models via Ollama. For detailed provider configuration and local model setup, see the [Installation Guide](setup/installation.md#choosing-your-llms).
-2. Agent Zero will process your request. You'll see its "thoughts" and the actions it takes displayed in the UI. It will find a default already existing solution, that implies using the `code_execution_tool` to run a simple Python script to perform the task.
+### Step 5: Start Your First Chat
-3. The agent will then ask you for the URL of the YouTube video you want to download.
+Once configured, you'll see the Agent Zero dashboard with access to:
+
+- **Projects** - organize your work into projects
+- **Memory** - open the memory dashboard
+- **Scheduler** - create and manage planned tasks
+- **Files** - open the File Browser
+- **Settings** - configure models and preferences
+- **System Stats** - monitor resource usage
+
+Click **New Chat** to start creating with Agent Zero!
+
+
+
+> [!TIP]
+> The Web UI provides a comprehensive chat actions dropdown with options for managing conversations, including creating new chats, resetting, saving/loading, and many more advanced features. Chats are saved in JSON format in the `/usr/chats` directory.
+>
+> 
+
+---
## Example Interaction
+Let's ask Agent Zero to use one of the built-in skills. Here's how:
+
+1. Type "Activate your brainstorming skill" in the chat input field and press Enter or click the send button.
+2. Agent Zero will process your request. You'll see its thoughts and tool calls in the UI.
+3. The agent will acknowledge the skill activation and ask you for a follow-up on the brainstorming request.
+
Here's an example of what you might see in the Web UI at step 3:
-
+
+
## Next Steps
Now that you've run a simple task, you can experiment with more complex requests. Try asking Agent Zero to:
-* Perform calculations
-* Search the web for information
+* Connect to your email
* Execute shell commands
+* Develop skills
* Explore web development tasks
-* Create or modify files
+* Develop A0 itself
-> [!TIP]
-> The [Usage Guide](usage.md) provides more in-depth information on using Agent
-> Zero's various features, including prompt engineering, tool usage, and multi-agent
-> cooperation.
\ No newline at end of file
+### [Open A0 Usage Guide](guides/usage.md)
+
+Provides more in-depth information on tools, projects, tasks, and backup/restore.
+
+## 🎓 Video Tutorials
+- [MCP Server Setup](https://youtu.be/pM5f4Vz3_IQ)
+- [Projects & Workspaces](https://youtu.be/RrTDp_v9V1c)
+- [Memory Management](https://youtu.be/sizjAq2-d9s)
diff --git a/docs/res/081_vid.png b/docs/res/081_vid.png
deleted file mode 100644
index c4e7349afb..0000000000
Binary files a/docs/res/081_vid.png and /dev/null differ
diff --git a/docs/res/arch-01.svg b/docs/res/arch-01.svg
deleted file mode 100644
index 899e26ae8e..0000000000
--- a/docs/res/arch-01.svg
+++ /dev/null
@@ -1,1406 +0,0 @@
-
-
-
diff --git a/docs/res/banner.png b/docs/res/banner.png
index a7a2ec1bf9..03ea6eb405 100644
Binary files a/docs/res/banner.png and b/docs/res/banner.png differ
diff --git a/docs/res/banner_high.png b/docs/res/banner_high.png
index 69e4155628..45ca87b70a 100644
Binary files a/docs/res/banner_high.png and b/docs/res/banner_high.png differ
diff --git a/docs/res/code_exec_jailbreak.png b/docs/res/code_exec_jailbreak.png
deleted file mode 100644
index 3c09ca626b..0000000000
Binary files a/docs/res/code_exec_jailbreak.png and /dev/null differ
diff --git a/docs/res/david_vid.jpg b/docs/res/david_vid.jpg
deleted file mode 100644
index 70ba53cfaf..0000000000
Binary files a/docs/res/david_vid.jpg and /dev/null differ
diff --git a/docs/res/dev/devinst-1.png b/docs/res/dev/devinst-1.png
index d8993740a8..09ed2cb6f4 100644
Binary files a/docs/res/dev/devinst-1.png and b/docs/res/dev/devinst-1.png differ
diff --git a/docs/res/dev/devinst-10.png b/docs/res/dev/devinst-10.png
index 1744f2ccb5..2fa3b38408 100644
Binary files a/docs/res/dev/devinst-10.png and b/docs/res/dev/devinst-10.png differ
diff --git a/docs/res/dev/devinst-11.png b/docs/res/dev/devinst-11.png
index 26a77ea1e4..3f48e12c2b 100644
Binary files a/docs/res/dev/devinst-11.png and b/docs/res/dev/devinst-11.png differ
diff --git a/docs/res/dev/devinst-12.png b/docs/res/dev/devinst-12.png
index 410afd10a0..47b4a36523 100644
Binary files a/docs/res/dev/devinst-12.png and b/docs/res/dev/devinst-12.png differ
diff --git a/docs/res/dev/devinst-13.png b/docs/res/dev/devinst-13.png
index 61f2ab5524..6eb8fffef0 100644
Binary files a/docs/res/dev/devinst-13.png and b/docs/res/dev/devinst-13.png differ
diff --git a/docs/res/dev/devinst-14.png b/docs/res/dev/devinst-14.png
index 646531e343..c49c79dcca 100644
Binary files a/docs/res/dev/devinst-14.png and b/docs/res/dev/devinst-14.png differ
diff --git a/docs/res/dev/devinst-2.png b/docs/res/dev/devinst-2.png
index b2d692eb93..b533c8191f 100644
Binary files a/docs/res/dev/devinst-2.png and b/docs/res/dev/devinst-2.png differ
diff --git a/docs/res/dev/devinst-3.png b/docs/res/dev/devinst-3.png
index aa3a8c3fab..71b8e36124 100644
Binary files a/docs/res/dev/devinst-3.png and b/docs/res/dev/devinst-3.png differ
diff --git a/docs/res/dev/devinst-4.png b/docs/res/dev/devinst-4.png
index 70b2adcf44..619b9e22cf 100644
Binary files a/docs/res/dev/devinst-4.png and b/docs/res/dev/devinst-4.png differ
diff --git a/docs/res/dev/devinst-5.png b/docs/res/dev/devinst-5.png
index aae44f0763..9c4e356b6a 100644
Binary files a/docs/res/dev/devinst-5.png and b/docs/res/dev/devinst-5.png differ
diff --git a/docs/res/dev/devinst-6.png b/docs/res/dev/devinst-6.png
index 6a006c44bf..f37d0eb9a1 100644
Binary files a/docs/res/dev/devinst-6.png and b/docs/res/dev/devinst-6.png differ
diff --git a/docs/res/dev/devinst-7.png b/docs/res/dev/devinst-7.png
index 3869b02234..37f3782567 100644
Binary files a/docs/res/dev/devinst-7.png and b/docs/res/dev/devinst-7.png differ
diff --git a/docs/res/dev/devinst-8.png b/docs/res/dev/devinst-8.png
index b125e6d965..a3b7f10c6a 100644
Binary files a/docs/res/dev/devinst-8.png and b/docs/res/dev/devinst-8.png differ
diff --git a/docs/res/dev/devinst-9.png b/docs/res/dev/devinst-9.png
index 323c9a6d4b..d1c6dad714 100644
Binary files a/docs/res/dev/devinst-9.png and b/docs/res/dev/devinst-9.png differ
diff --git a/docs/res/devguide_vid.png b/docs/res/devguide_vid.png
index eeb10cfb8d..0b6f3288f0 100644
Binary files a/docs/res/devguide_vid.png and b/docs/res/devguide_vid.png differ
diff --git a/docs/res/easy_ins_vid.png b/docs/res/easy_ins_vid.png
index 43fa0bac95..49e54b3cc6 100644
Binary files a/docs/res/easy_ins_vid.png and b/docs/res/easy_ins_vid.png differ
diff --git a/docs/res/favicon.png b/docs/res/favicon.png
index f34f924635..32a1c127ed 100644
Binary files a/docs/res/favicon.png and b/docs/res/favicon.png differ
diff --git a/docs/res/favicon_round.png b/docs/res/favicon_round.png
index 4fc7e88332..03d0be1955 100644
Binary files a/docs/res/favicon_round.png and b/docs/res/favicon_round.png differ
diff --git a/docs/res/flask_link.png b/docs/res/flask_link.png
deleted file mode 100644
index 1db2c85529..0000000000
Binary files a/docs/res/flask_link.png and /dev/null differ
diff --git a/docs/res/flow-01.svg b/docs/res/flow-01.svg
deleted file mode 100644
index f9398bb4b3..0000000000
--- a/docs/res/flow-01.svg
+++ /dev/null
@@ -1,144 +0,0 @@
-
-
\ No newline at end of file
diff --git a/docs/res/header.png b/docs/res/header.png
index c274e50569..a2acc5befb 100644
Binary files a/docs/res/header.png and b/docs/res/header.png differ
diff --git a/docs/res/image-24.png b/docs/res/image-24.png
deleted file mode 100644
index 34df46d6bf..0000000000
Binary files a/docs/res/image-24.png and /dev/null differ
diff --git a/docs/res/joke.png b/docs/res/joke.png
deleted file mode 100644
index d25232b024..0000000000
Binary files a/docs/res/joke.png and /dev/null differ
diff --git a/docs/res/memory-man.png b/docs/res/memory-man.png
deleted file mode 100644
index 374e3c9b58..0000000000
Binary files a/docs/res/memory-man.png and /dev/null differ
diff --git a/docs/res/new_vid.jpg b/docs/res/new_vid.jpg
deleted file mode 100644
index 08ad2d2914..0000000000
Binary files a/docs/res/new_vid.jpg and /dev/null differ
diff --git a/docs/res/physics-2.png b/docs/res/physics-2.png
deleted file mode 100644
index df2c38887f..0000000000
Binary files a/docs/res/physics-2.png and /dev/null differ
diff --git a/docs/res/physics.png b/docs/res/physics.png
deleted file mode 100644
index 762451862e..0000000000
Binary files a/docs/res/physics.png and /dev/null differ
diff --git a/docs/res/profiles.png b/docs/res/profiles.png
new file mode 100644
index 0000000000..55e2ef2f66
Binary files /dev/null and b/docs/res/profiles.png differ
diff --git a/docs/res/prompts.png b/docs/res/prompts.png
deleted file mode 100644
index 7c2764437c..0000000000
Binary files a/docs/res/prompts.png and /dev/null differ
diff --git a/docs/res/quickstart/image-24.png b/docs/res/quickstart/image-24.png
new file mode 100644
index 0000000000..b804d503a3
Binary files /dev/null and b/docs/res/quickstart/image-24.png differ
diff --git a/docs/res/quickstart/ui_chat_management.png b/docs/res/quickstart/ui_chat_management.png
new file mode 100644
index 0000000000..0190a7a6e2
Binary files /dev/null and b/docs/res/quickstart/ui_chat_management.png differ
diff --git a/docs/res/quickstart/ui_newchat1.png b/docs/res/quickstart/ui_newchat1.png
new file mode 100644
index 0000000000..34a6eb8d00
Binary files /dev/null and b/docs/res/quickstart/ui_newchat1.png differ
diff --git a/docs/res/settings-page-ui.png b/docs/res/settings-page-ui.png
deleted file mode 100644
index 4c6d0010a1..0000000000
Binary files a/docs/res/settings-page-ui.png and /dev/null differ
diff --git a/docs/res/settings-page-ui1.png b/docs/res/settings-page-ui1.png
new file mode 100644
index 0000000000..a8b4242f51
Binary files /dev/null and b/docs/res/settings-page-ui1.png differ
diff --git a/docs/res/setup/1-docker-image-search.png b/docs/res/setup/1-docker-image-search.png
index 09fc12bd43..78924a946c 100644
Binary files a/docs/res/setup/1-docker-image-search.png and b/docs/res/setup/1-docker-image-search.png differ
diff --git a/docs/res/setup/2-docker-image-run-3.png b/docs/res/setup/2-docker-image-run-3.png
new file mode 100644
index 0000000000..21323751f4
Binary files /dev/null and b/docs/res/setup/2-docker-image-run-3.png differ
diff --git a/docs/res/setup/2-docker-image-run.png b/docs/res/setup/2-docker-image-run.png
index 763d8ce233..7ff784458d 100644
Binary files a/docs/res/setup/2-docker-image-run.png and b/docs/res/setup/2-docker-image-run.png differ
diff --git a/docs/res/setup/2-docker-image-run2.png b/docs/res/setup/2-docker-image-run2.png
deleted file mode 100644
index d4ae93f774..0000000000
Binary files a/docs/res/setup/2-docker-image-run2.png and /dev/null differ
diff --git a/docs/res/setup/3-docker-port-mapping.png b/docs/res/setup/3-docker-port-mapping.png
index 3cf442f728..c67caab985 100644
Binary files a/docs/res/setup/3-docker-port-mapping.png and b/docs/res/setup/3-docker-port-mapping.png differ
diff --git a/docs/res/setup/4-docker-container-started.png b/docs/res/setup/4-docker-container-started.png
index 33a3bb7839..0252e9dac9 100644
Binary files a/docs/res/setup/4-docker-container-started.png and b/docs/res/setup/4-docker-container-started.png differ
diff --git a/docs/res/setup/5-docker-click-to-open.png b/docs/res/setup/5-docker-click-to-open.png
index 371d2c36f9..3e0ca37006 100644
Binary files a/docs/res/setup/5-docker-click-to-open.png and b/docs/res/setup/5-docker-click-to-open.png differ
diff --git a/docs/res/setup/6-docker-a0-running-new.png b/docs/res/setup/6-docker-a0-running-new.png
new file mode 100644
index 0000000000..03d78d07f6
Binary files /dev/null and b/docs/res/setup/6-docker-a0-running-new.png differ
diff --git a/docs/res/setup/6-docker-a0-running.png b/docs/res/setup/6-docker-a0-running.png
deleted file mode 100644
index a8612702f5..0000000000
Binary files a/docs/res/setup/6-docker-a0-running.png and /dev/null differ
diff --git a/docs/res/setup/9-rfc-devpage-on-docker-instance-1.png b/docs/res/setup/9-rfc-devpage-on-docker-instance-1.png
index 4c7a379664..7e14eb877b 100644
Binary files a/docs/res/setup/9-rfc-devpage-on-docker-instance-1.png and b/docs/res/setup/9-rfc-devpage-on-docker-instance-1.png differ
diff --git a/docs/res/setup/9-rfc-devpage-on-local-sbs-1.png b/docs/res/setup/9-rfc-devpage-on-local-sbs-1.png
index 74c7623fe4..dd2ee9ab4c 100644
Binary files a/docs/res/setup/9-rfc-devpage-on-local-sbs-1.png and b/docs/res/setup/9-rfc-devpage-on-local-sbs-1.png differ
diff --git a/docs/res/setup/a2a/a2a-conn.png b/docs/res/setup/a2a/a2a-conn.png
new file mode 100644
index 0000000000..d0ae234aef
Binary files /dev/null and b/docs/res/setup/a2a/a2a-conn.png differ
diff --git a/docs/res/setup/a2a/a2a2.png b/docs/res/setup/a2a/a2a2.png
new file mode 100644
index 0000000000..82856c38e2
Binary files /dev/null and b/docs/res/setup/a2a/a2a2.png differ
diff --git a/docs/res/setup/docker-delete-image-1.png b/docs/res/setup/docker-delete-image-1.png
index 042e57ea81..a8106c0697 100644
Binary files a/docs/res/setup/docker-delete-image-1.png and b/docs/res/setup/docker-delete-image-1.png differ
diff --git a/docs/res/setup/image-1.png b/docs/res/setup/image-1.png
index 9ea2b068fd..e6ef01cc1a 100644
Binary files a/docs/res/setup/image-1.png and b/docs/res/setup/image-1.png differ
diff --git a/docs/res/setup/image-10.png b/docs/res/setup/image-10.png
index cdcb115e28..5ba5b0c390 100644
Binary files a/docs/res/setup/image-10.png and b/docs/res/setup/image-10.png differ
diff --git a/docs/res/setup/image-11.png b/docs/res/setup/image-11.png
index c08ba1b382..fb59dee9de 100644
Binary files a/docs/res/setup/image-11.png and b/docs/res/setup/image-11.png differ
diff --git a/docs/res/setup/image-12.png b/docs/res/setup/image-12.png
index 2e4a8b5313..3d6d414413 100644
Binary files a/docs/res/setup/image-12.png and b/docs/res/setup/image-12.png differ
diff --git a/docs/res/setup/image-13.png b/docs/res/setup/image-13.png
index 2b2a91bf7e..da111bf8ad 100644
Binary files a/docs/res/setup/image-13.png and b/docs/res/setup/image-13.png differ
diff --git a/docs/res/setup/image-14-u.png b/docs/res/setup/image-14-u.png
index d20a84c2ee..3c279a9933 100644
Binary files a/docs/res/setup/image-14-u.png and b/docs/res/setup/image-14-u.png differ
diff --git a/docs/res/setup/image-14.png b/docs/res/setup/image-14.png
index f1823d6ccc..ed7d9c503d 100644
Binary files a/docs/res/setup/image-14.png and b/docs/res/setup/image-14.png differ
diff --git a/docs/res/setup/image-15.png b/docs/res/setup/image-15.png
index fe871994b0..75fdbf7f55 100644
Binary files a/docs/res/setup/image-15.png and b/docs/res/setup/image-15.png differ
diff --git a/docs/res/setup/image-16.png b/docs/res/setup/image-16.png
index 72c8a2972d..29ca4646a8 100644
Binary files a/docs/res/setup/image-16.png and b/docs/res/setup/image-16.png differ
diff --git a/docs/res/setup/image-17.png b/docs/res/setup/image-17.png
index 222438acc5..6a8379c20d 100644
Binary files a/docs/res/setup/image-17.png and b/docs/res/setup/image-17.png differ
diff --git a/docs/res/setup/image-18.png b/docs/res/setup/image-18.png
index 62c52021ce..460cb48386 100644
Binary files a/docs/res/setup/image-18.png and b/docs/res/setup/image-18.png differ
diff --git a/docs/res/setup/image-19.png b/docs/res/setup/image-19.png
index 54a1f745a7..87c6f73abe 100644
Binary files a/docs/res/setup/image-19.png and b/docs/res/setup/image-19.png differ
diff --git a/docs/res/setup/image-2.png b/docs/res/setup/image-2.png
index 798f391053..5e2609f571 100644
Binary files a/docs/res/setup/image-2.png and b/docs/res/setup/image-2.png differ
diff --git a/docs/res/setup/image-20.png b/docs/res/setup/image-20.png
index dd9d80c579..4053618050 100644
Binary files a/docs/res/setup/image-20.png and b/docs/res/setup/image-20.png differ
diff --git a/docs/res/setup/image-21.png b/docs/res/setup/image-21.png
index e3c93be942..bbb33b0a18 100644
Binary files a/docs/res/setup/image-21.png and b/docs/res/setup/image-21.png differ
diff --git a/docs/res/setup/image-22-1.png b/docs/res/setup/image-22-1.png
index 704f259219..a0b4e34a40 100644
Binary files a/docs/res/setup/image-22-1.png and b/docs/res/setup/image-22-1.png differ
diff --git a/docs/res/setup/image-23-1.png b/docs/res/setup/image-23-1.png
index 5d639fc812..aac45078bd 100644
Binary files a/docs/res/setup/image-23-1.png and b/docs/res/setup/image-23-1.png differ
diff --git a/docs/res/setup/image-3.png b/docs/res/setup/image-3.png
index 3c10531706..dc0af02f50 100644
Binary files a/docs/res/setup/image-3.png and b/docs/res/setup/image-3.png differ
diff --git a/docs/res/setup/image-4.png b/docs/res/setup/image-4.png
index 04f936a394..b2b44e5308 100644
Binary files a/docs/res/setup/image-4.png and b/docs/res/setup/image-4.png differ
diff --git a/docs/res/setup/image-5.png b/docs/res/setup/image-5.png
index 87437eecc1..232a33bbb3 100644
Binary files a/docs/res/setup/image-5.png and b/docs/res/setup/image-5.png differ
diff --git a/docs/res/setup/image-6.png b/docs/res/setup/image-6.png
index 4a9f59a716..7feda13848 100644
Binary files a/docs/res/setup/image-6.png and b/docs/res/setup/image-6.png differ
diff --git a/docs/res/setup/image-7.png b/docs/res/setup/image-7.png
index cb1c39dcfe..5a915d278f 100644
Binary files a/docs/res/setup/image-7.png and b/docs/res/setup/image-7.png differ
diff --git a/docs/res/setup/image-8.png b/docs/res/setup/image-8.png
index f148e8eb68..0296fc8146 100644
Binary files a/docs/res/setup/image-8.png and b/docs/res/setup/image-8.png differ
diff --git a/docs/res/setup/image-9.png b/docs/res/setup/image-9.png
index 3d806d9475..9d42f21c0e 100644
Binary files a/docs/res/setup/image-9.png and b/docs/res/setup/image-9.png differ
diff --git a/docs/res/setup/image.png b/docs/res/setup/image.png
index 6f99debdaf..ee61eb8970 100644
Binary files a/docs/res/setup/image.png and b/docs/res/setup/image.png differ
diff --git a/docs/res/setup/macsocket.png b/docs/res/setup/macsocket.png
index 531744eb2f..2574848b44 100644
Binary files a/docs/res/setup/macsocket.png and b/docs/res/setup/macsocket.png differ
diff --git a/docs/res/setup/mcp/mcp-example-config.png b/docs/res/setup/mcp/mcp-example-config.png
new file mode 100644
index 0000000000..5dbe327eb2
Binary files /dev/null and b/docs/res/setup/mcp/mcp-example-config.png differ
diff --git a/docs/res/setup/mcp/mcp-open-config.png b/docs/res/setup/mcp/mcp-open-config.png
new file mode 100644
index 0000000000..dc63ce0daa
Binary files /dev/null and b/docs/res/setup/mcp/mcp-open-config.png differ
diff --git a/docs/res/setup/oses/apple.png b/docs/res/setup/oses/apple.png
new file mode 100644
index 0000000000..b11a74a82b
Binary files /dev/null and b/docs/res/setup/oses/apple.png differ
diff --git a/docs/res/setup/oses/linux.png b/docs/res/setup/oses/linux.png
new file mode 100644
index 0000000000..cbeaf4547d
Binary files /dev/null and b/docs/res/setup/oses/linux.png differ
diff --git a/docs/res/setup/oses/windows.png b/docs/res/setup/oses/windows.png
new file mode 100644
index 0000000000..130b33c8f8
Binary files /dev/null and b/docs/res/setup/oses/windows.png differ
diff --git a/docs/res/setup/settings/1-agentConfig.png b/docs/res/setup/settings/1-agentConfig.png
index 9d73abbf14..5082c40c37 100644
Binary files a/docs/res/setup/settings/1-agentConfig.png and b/docs/res/setup/settings/1-agentConfig.png differ
diff --git a/docs/res/setup/settings/2-chat-model.png b/docs/res/setup/settings/2-chat-model.png
index 497f3173df..52fa0fb107 100644
Binary files a/docs/res/setup/settings/2-chat-model.png and b/docs/res/setup/settings/2-chat-model.png differ
diff --git a/docs/res/setup/settings/3-auth.png b/docs/res/setup/settings/3-auth.png
index 59cebb9c51..15d294c15d 100644
Binary files a/docs/res/setup/settings/3-auth.png and b/docs/res/setup/settings/3-auth.png differ
diff --git a/docs/res/setup/settings/4-local-models.png b/docs/res/setup/settings/4-local-models.png
index 78e17996ce..216ada1d88 100644
Binary files a/docs/res/setup/settings/4-local-models.png and b/docs/res/setup/settings/4-local-models.png differ
diff --git a/docs/res/setup/thumb_play.png b/docs/res/setup/thumb_play.png
index 13646aa239..8e5f30965e 100644
Binary files a/docs/res/setup/thumb_play.png and b/docs/res/setup/thumb_play.png differ
diff --git a/docs/res/setup/thumb_setup.png b/docs/res/setup/thumb_setup.png
index 27288fdbe9..e56d5c99a6 100644
Binary files a/docs/res/setup/thumb_setup.png and b/docs/res/setup/thumb_setup.png differ
diff --git a/docs/res/setup/update-initialize.png b/docs/res/setup/update-initialize.png
index 90759bd02a..454753dc61 100644
Binary files a/docs/res/setup/update-initialize.png and b/docs/res/setup/update-initialize.png differ
diff --git a/docs/res/showcase-thumb.png b/docs/res/showcase-thumb.png
index c5e6d9d15a..c2cb31020c 100644
Binary files a/docs/res/showcase-thumb.png and b/docs/res/showcase-thumb.png differ
diff --git a/docs/res/splash_wide.png b/docs/res/splash_wide.png
index bfa2ab210e..1f8654f988 100644
Binary files a/docs/res/splash_wide.png and b/docs/res/splash_wide.png differ
diff --git a/docs/res/ui-actions.png b/docs/res/ui-actions.png
deleted file mode 100644
index fe99b67ffa..0000000000
Binary files a/docs/res/ui-actions.png and /dev/null differ
diff --git a/docs/res/ui-attachments-2.png b/docs/res/ui-attachments-2.png
deleted file mode 100644
index 376e0bebdb..0000000000
Binary files a/docs/res/ui-attachments-2.png and /dev/null differ
diff --git a/docs/res/ui-attachments.png b/docs/res/ui-attachments.png
deleted file mode 100644
index 69f3360aef..0000000000
Binary files a/docs/res/ui-attachments.png and /dev/null differ
diff --git a/docs/res/ui-behavior-change-chat.png b/docs/res/ui-behavior-change-chat.png
deleted file mode 100644
index 40ae9601ad..0000000000
Binary files a/docs/res/ui-behavior-change-chat.png and /dev/null differ
diff --git a/docs/res/ui-context.png b/docs/res/ui-context.png
deleted file mode 100644
index e3ca586a58..0000000000
Binary files a/docs/res/ui-context.png and /dev/null differ
diff --git a/docs/res/ui-file-browser.png b/docs/res/ui-file-browser.png
deleted file mode 100644
index 03396fc114..0000000000
Binary files a/docs/res/ui-file-browser.png and /dev/null differ
diff --git a/docs/res/ui-history.png b/docs/res/ui-history.png
deleted file mode 100644
index 209d905bfc..0000000000
Binary files a/docs/res/ui-history.png and /dev/null differ
diff --git a/docs/res/ui-katex-1.png b/docs/res/ui-katex-1.png
deleted file mode 100644
index 561e5143b3..0000000000
Binary files a/docs/res/ui-katex-1.png and /dev/null differ
diff --git a/docs/res/ui-katex-2.png b/docs/res/ui-katex-2.png
deleted file mode 100644
index 5bd52c9156..0000000000
Binary files a/docs/res/ui-katex-2.png and /dev/null differ
diff --git a/docs/res/ui-nudge.png b/docs/res/ui-nudge.png
deleted file mode 100644
index ea9b656dbd..0000000000
Binary files a/docs/res/ui-nudge.png and /dev/null differ
diff --git a/docs/res/ui-restarting.png b/docs/res/ui-restarting.png
deleted file mode 100644
index 7ce626a03b..0000000000
Binary files a/docs/res/ui-restarting.png and /dev/null differ
diff --git a/docs/res/ui-screen-2.png b/docs/res/ui-screen-2.png
deleted file mode 100644
index b2215ffa4e..0000000000
Binary files a/docs/res/ui-screen-2.png and /dev/null differ
diff --git a/docs/res/ui-screen.png b/docs/res/ui-screen.png
deleted file mode 100644
index 977bdc170f..0000000000
Binary files a/docs/res/ui-screen.png and /dev/null differ
diff --git a/docs/res/ui-settings-5-speech-to-text.png b/docs/res/ui-settings-5-speech-to-text.png
deleted file mode 100644
index 7bc03a80a1..0000000000
Binary files a/docs/res/ui-settings-5-speech-to-text.png and /dev/null differ
diff --git a/docs/res/ui-tts-stop-speech.png b/docs/res/ui-tts-stop-speech.png
deleted file mode 100644
index bae9e222e8..0000000000
Binary files a/docs/res/ui-tts-stop-speech.png and /dev/null differ
diff --git a/docs/res/ui_chat_management.png b/docs/res/ui_chat_management.png
deleted file mode 100644
index 74545a5aba..0000000000
Binary files a/docs/res/ui_chat_management.png and /dev/null differ
diff --git a/docs/res/ui_newchat1.png b/docs/res/ui_newchat1.png
deleted file mode 100644
index d1ee0036d6..0000000000
Binary files a/docs/res/ui_newchat1.png and /dev/null differ
diff --git a/docs/res/ui_screen.png b/docs/res/ui_screen.png
deleted file mode 100644
index 90bb5ab31d..0000000000
Binary files a/docs/res/ui_screen.png and /dev/null differ
diff --git a/docs/res/ui_screen2.png b/docs/res/ui_screen2.png
new file mode 100644
index 0000000000..58c62582ab
Binary files /dev/null and b/docs/res/ui_screen2.png differ
diff --git a/docs/res/usage/action-btns.png b/docs/res/usage/action-btns.png
new file mode 100644
index 0000000000..42679e02ed
Binary files /dev/null and b/docs/res/usage/action-btns.png differ
diff --git a/docs/res/usage/api-int/api-int-1.png b/docs/res/usage/api-int/api-int-1.png
new file mode 100644
index 0000000000..35d868d25e
Binary files /dev/null and b/docs/res/usage/api-int/api-int-1.png differ
diff --git a/docs/res/usage/api-int/api-int-2image-gen-api2.png b/docs/res/usage/api-int/api-int-2image-gen-api2.png
new file mode 100644
index 0000000000..e80b8ddb89
Binary files /dev/null and b/docs/res/usage/api-int/api-int-2image-gen-api2.png differ
diff --git a/docs/res/usage/api-int/api-int-3-api-key-missing-secrets.png b/docs/res/usage/api-int/api-int-3-api-key-missing-secrets.png
new file mode 100644
index 0000000000..e56e8cfb69
Binary files /dev/null and b/docs/res/usage/api-int/api-int-3-api-key-missing-secrets.png differ
diff --git a/docs/res/usage/api-int/api-int-4-secrets-setting.png b/docs/res/usage/api-int/api-int-4-secrets-setting.png
new file mode 100644
index 0000000000..551576849f
Binary files /dev/null and b/docs/res/usage/api-int/api-int-4-secrets-setting.png differ
diff --git a/docs/res/usage/api-int/api-int-5-finish.png b/docs/res/usage/api-int/api-int-5-finish.png
new file mode 100644
index 0000000000..d673e7301c
Binary files /dev/null and b/docs/res/usage/api-int/api-int-5-finish.png differ
diff --git a/docs/res/usage/attachments-1.png b/docs/res/usage/attachments-1.png
new file mode 100644
index 0000000000..02c348dbe4
Binary files /dev/null and b/docs/res/usage/attachments-1.png differ
diff --git a/docs/res/usage/attachments-2.png b/docs/res/usage/attachments-2.png
new file mode 100644
index 0000000000..744e3406c2
Binary files /dev/null and b/docs/res/usage/attachments-2.png differ
diff --git a/docs/res/usage/file-browser.png b/docs/res/usage/file-browser.png
new file mode 100644
index 0000000000..82cc9cba6e
Binary files /dev/null and b/docs/res/usage/file-browser.png differ
diff --git a/docs/res/usage/file-edit.png b/docs/res/usage/file-edit.png
new file mode 100644
index 0000000000..f3706b4f40
Binary files /dev/null and b/docs/res/usage/file-edit.png differ
diff --git a/docs/res/usage/first-task.png b/docs/res/usage/first-task.png
new file mode 100644
index 0000000000..5720acff75
Binary files /dev/null and b/docs/res/usage/first-task.png differ
diff --git a/docs/res/usage/memory-dashboard.png b/docs/res/usage/memory-dashboard.png
new file mode 100644
index 0000000000..6c9506c357
Binary files /dev/null and b/docs/res/usage/memory-dashboard.png differ
diff --git a/docs/res/usage/memory-editing.png b/docs/res/usage/memory-editing.png
new file mode 100644
index 0000000000..469fb7dc05
Binary files /dev/null and b/docs/res/usage/memory-editing.png differ
diff --git a/docs/res/usage/multi-agent.png b/docs/res/usage/multi-agent.png
new file mode 100644
index 0000000000..9286f96f7a
Binary files /dev/null and b/docs/res/usage/multi-agent.png differ
diff --git a/docs/res/usage/nudge.png b/docs/res/usage/nudge.png
new file mode 100644
index 0000000000..8746667bd0
Binary files /dev/null and b/docs/res/usage/nudge.png differ
diff --git a/docs/res/usage/projects/projects-activate-project.png b/docs/res/usage/projects/projects-activate-project.png
new file mode 100644
index 0000000000..722145a4bb
Binary files /dev/null and b/docs/res/usage/projects/projects-activate-project.png differ
diff --git a/docs/res/usage/projects/projects-creation.png b/docs/res/usage/projects/projects-creation.png
new file mode 100644
index 0000000000..41630d87cc
Binary files /dev/null and b/docs/res/usage/projects/projects-creation.png differ
diff --git a/docs/res/usage/projects/projects-desc-and-instructions.png b/docs/res/usage/projects/projects-desc-and-instructions.png
new file mode 100644
index 0000000000..c74cecbe78
Binary files /dev/null and b/docs/res/usage/projects/projects-desc-and-instructions.png differ
diff --git a/docs/res/usage/projects/projects-first-ops.png b/docs/res/usage/projects/projects-first-ops.png
new file mode 100644
index 0000000000..228ec15dd8
Binary files /dev/null and b/docs/res/usage/projects/projects-first-ops.png differ
diff --git a/docs/res/usage/projects/projects-git-projects-tree.png b/docs/res/usage/projects/projects-git-projects-tree.png
new file mode 100644
index 0000000000..55fd6391bf
Binary files /dev/null and b/docs/res/usage/projects/projects-git-projects-tree.png differ
diff --git a/docs/res/usage/projects/projects-gitprojects-clone.png b/docs/res/usage/projects/projects-gitprojects-clone.png
new file mode 100644
index 0000000000..f0bad18fae
Binary files /dev/null and b/docs/res/usage/projects/projects-gitprojects-clone.png differ
diff --git a/docs/res/usage/restart.png b/docs/res/usage/restart.png
new file mode 100644
index 0000000000..383974d713
Binary files /dev/null and b/docs/res/usage/restart.png differ
diff --git a/docs/res/usage/tasks/edit-task.png b/docs/res/usage/tasks/edit-task.png
new file mode 100644
index 0000000000..3043935414
Binary files /dev/null and b/docs/res/usage/tasks/edit-task.png differ
diff --git a/docs/res/usage/tasks/scheduler-1.png b/docs/res/usage/tasks/scheduler-1.png
new file mode 100644
index 0000000000..2ca582d564
Binary files /dev/null and b/docs/res/usage/tasks/scheduler-1.png differ
diff --git a/docs/res/usage/ui-context1.png b/docs/res/usage/ui-context1.png
new file mode 100644
index 0000000000..3aa276f688
Binary files /dev/null and b/docs/res/usage/ui-context1.png differ
diff --git a/docs/res/usage/ui-history1.png b/docs/res/usage/ui-history1.png
new file mode 100644
index 0000000000..62e42af620
Binary files /dev/null and b/docs/res/usage/ui-history1.png differ
diff --git a/docs/res/usage/ui-katex-2.png b/docs/res/usage/ui-katex-2.png
new file mode 100644
index 0000000000..1adda894cb
Binary files /dev/null and b/docs/res/usage/ui-katex-2.png differ
diff --git a/docs/res/usage/ui-settings-5-speech-to-text.png b/docs/res/usage/ui-settings-5-speech-to-text.png
new file mode 100644
index 0000000000..91c5c6faf6
Binary files /dev/null and b/docs/res/usage/ui-settings-5-speech-to-text.png differ
diff --git a/docs/res/usage/ui-tts-stop-speech1.png b/docs/res/usage/ui-tts-stop-speech1.png
new file mode 100644
index 0000000000..1a8e973276
Binary files /dev/null and b/docs/res/usage/ui-tts-stop-speech1.png differ
diff --git a/docs/res/web-ui.mp4 b/docs/res/web-ui.mp4
deleted file mode 100644
index 86fc850aa6..0000000000
Binary files a/docs/res/web-ui.mp4 and /dev/null differ
diff --git a/docs/res/web_screenshot.jpg b/docs/res/web_screenshot.jpg
deleted file mode 100644
index 19bb94286a..0000000000
Binary files a/docs/res/web_screenshot.jpg and /dev/null differ
diff --git a/docs/res/win_webui2.gif b/docs/res/win_webui2.gif
deleted file mode 100644
index e1f52aed69..0000000000
Binary files a/docs/res/win_webui2.gif and /dev/null differ
diff --git a/docs/development.md b/docs/setup/dev-setup.md
similarity index 83%
rename from docs/development.md
rename to docs/setup/dev-setup.md
index 54fe39580e..d9894bf6e0 100644
--- a/docs/development.md
+++ b/docs/setup/dev-setup.md
@@ -68,7 +68,7 @@ Now when you select one of the python files in the project, you should see prope
```bash
pip install -r requirements.txt
playwright install chromium
-```
+```
These will install all the python packages and browser binaries for playwright (browser agent).
Errors in the code editor caused by missing packages should now be gone. If not, try reloading the window.
@@ -81,7 +81,9 @@ It will not be able to do code execution and few other features requiring the Do

-The framework will run at the default port 5000. If you open `http://localhost:5000` in your browser and see `ERR_EMPTY_RESPONSE`, don't panic, you may need to select another port like I did for some reason. If you need to change the defaut port, you can add `"--port=5555"` to the args in the `.vscode/launch.json` file or you can create a `.env` file in the root directory and set the `WEB_UI_PORT` variable to the desired port.
+The framework will run at the default port 5000. If you open `http://localhost:5000` in your browser and see `ERR_EMPTY_RESPONSE`, don't panic, you may need to select another port like I did for some reason. If you need to change the default port, you can add `"--port=5555"` to the args in the `.vscode/launch.json` file or you can create a `.env` file in the root directory and set the `WEB_UI_PORT` variable to the desired port.
+
+You can also set the bind host via `"--host=0.0.0.0"` (or `WEB_UI_HOST=0.0.0.0`).
It may take a while the first time. You should see output like the screenshot below. The RFC error is ok for now as we did not yet connect our local development to another instance in docker.

@@ -132,25 +134,43 @@ My Dockerized instance:
My VS Code instance:

+## RFC Notes (Host IDE + Docker Execution)
+Agent Zero runs code inside the container by default. If you are running the framework locally in your IDE but want tools (like code execution) to run in Docker, configure RFC in **Settings -> Development** and point it to a running Agent Zero container. This routes execution through SSH/RFC to the container while keeping the UI and agent loop on your host.
-# 🎉 Congratulations! 🚀
+
+# Congratulations!
You have successfully set up a complete Agent Zero development environment! You now have:
-- ✅ A local development instance running in your IDE with full debugging capabilities
-- ✅ A dockerized instance for code execution and system operations
-- ✅ RFC and SSH communication between both instances
-- ✅ The ability to develop, debug, and test Agent Zero features seamlessly
+- A local development instance running in your IDE with full debugging capabilities
+- A dockerized instance for code execution and system operations
+- RFC and SSH communication between both instances
+- The ability to develop, debug, and test Agent Zero features seamlessly
-You're now ready to contribute to Agent Zero, create custom extensions, or modify the framework to suit your needs. Happy coding! 💻✨
+You're now ready to contribute to Agent Zero, create custom extensions, or modify the framework to suit your needs. Happy coding!
## Next steps
-- See [extensibility](extensibility.md) for instructions on how to create custom extensions.
-- See [contribution](contribution.md) for instructions on how to contribute to the framework.
+- See [extensions](../developer/extensions.md) for instructions on how to create custom extensions.
+- See [websocket infrastructure](websocket-infrastructure.md) for real-time handler patterns, client APIs, and troubleshooting tips.
+- See [contribution](../guides/contribution.md) for instructions on how to contribute to the framework.
+
+## Configuration via Environment Variables
+
+For development and testing, you can override default settings using the `.env` file with `A0_SET_` prefixed variables:
+
+```env
+# Add to your .env file
+A0_SET_chat_model_provider=ollama
+A0_SET_chat_model_name=llama3.2
+A0_SET_chat_model_api_base=http://localhost:11434
+A0_SET_memory_recall_interval=5
+```
+
+These environment variables automatically override the hardcoded defaults in `get_default_settings()` without modifying code. Useful for testing different configurations or multi-environment setups.
## Want to build your docker image?
- You can use the `DockerfileLocal` to build your docker image.
- Navigate to your project root in the terminal and run `docker build -f DockerfileLocal -t agent-zero-local --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .`
- The `CACHE_DATE` argument is optional, it is used to cache most of the build process and only rebuild the last steps when the files or dependencies change.
-- See `docker/run/build.txt` for more build command examples.
\ No newline at end of file
+- See `docker/run/build.txt` for more build command examples.
diff --git a/docs/setup/installation.md b/docs/setup/installation.md
new file mode 100644
index 0000000000..f6e84809f2
--- /dev/null
+++ b/docs/setup/installation.md
@@ -0,0 +1,585 @@
+# Installation Guide
+
+Click to open a video to learn how to install Agent Zero:
+
+[](https://www.youtube.com/watch?v=w5v5Kjx51hs)
+
+## **Goal:** Go from zero to a first working chat with minimal setup.
+
+
+## Step 1: Install Docker Desktop
+
+Docker Desktop provides the runtime environment for Agent Zero, ensuring consistent behavior and security across platforms. The entire framework runs within a Docker container, providing isolation and easy deployment.
+
+**Choose your operating system:**
+
+
+
+---
+
+
+## Windows Installation
+
+**1.1. Download Docker Desktop**
+
+Go to the [Docker Desktop download page](https://www.docker.com/products/docker-desktop/) and download the Windows version (Intel/AMD is the main download button).
+
+
+
+
+**1.2. Run the Installer**
+
+Run the installer with default settings.
+
+
+
+
+
+**1.3. Launch Docker Desktop**
+
+Once installed, launch Docker Desktop from your Start menu or desktop shortcut.
+
+
+
+✅ **Docker is now installed!**
+
+### Continue to [Step 2: Run Agent Zero](#step-2-run-agent-zero)
+
+---
+
+
+## macOS Installation
+
+**1.1. Download Docker Desktop**
+
+Go to the [Docker Desktop download page](https://www.docker.com/products/docker-desktop/) and download the macOS version (choose Apple Silicon or Intel based on your Mac).
+
+
+
+
+**1.2. Install Docker Desktop**
+
+Drag and drop the Docker application to your Applications folder.
+
+
+
+
+**1.3. Launch Docker Desktop**
+
+Open Docker Desktop from your Applications folder.
+
+
+
+
+**1.4. Configure Docker Socket**
+
+> [!NOTE]
+> **Important macOS Configuration:** In Docker Desktop's preferences (Docker menu) → Settings → Advanced, enable "Allow the default Docker socket to be used (requires password)."
+
+
+
+✅ **Docker is now installed!**
+
+### Continue to [Step 2: Run Agent Zero](#step-2-run-agent-zero)
+
+---
+
+
+## Linux Installation
+
+**1.1. Choose Installation Method**
+
+You can install either Docker Desktop or docker-ce (Community Edition).
+
+**Option A: Docker Desktop (Recommended for beginners)**
+
+Follow the instructions for your specific Linux distribution [here](https://docs.docker.com/desktop/install/linux-install/).
+
+**Option B: docker-ce (Lightweight alternative)**
+
+Follow the installation instructions [here](https://docs.docker.com/engine/install/).
+
+**1.2. Post-Installation Steps (docker-ce only)**
+
+If you installed docker-ce, add your user to the `docker` group:
+
+```bash
+sudo usermod -aG docker $USER
+```
+
+Log out and back in, then authenticate:
+
+```bash
+docker login
+```
+
+**1.3. Launch Docker**
+
+If you installed Docker Desktop, launch it from your applications menu.
+
+✅ **Docker is now installed!**
+
+> [!TIP]
+> **Deploying on a VPS/Server?** For production deployments with reverse proxy, SSL, and domain configuration, see the [VPS Deployment Guide](vps-deployment.md).
+
+---
+
+## Step 2: Run Agent Zero
+
+### 2.1. Pull the Agent Zero Docker Image
+
+**Using Docker Desktop GUI:**
+
+- Search for `agent0ai/agent-zero` in Docker Desktop
+- Click the `Pull` button
+- The image will be downloaded to your machine in a few minutes
+
+
+
+**Using Terminal:**
+
+```bash
+docker pull agent0ai/agent-zero
+```
+
+### 2.2. (Optional) Map Folders for Persistence
+
+Choose or create a folder on your computer where Agent Zero will save its data.
+
+### Setting up persistence is needed only if you want your data and files to remain available even after you delete the container.
+
+You can pick any location you find convenient:
+
+- **Windows:** `C:\agent-zero-data`
+- **macOS/Linux:** `/home/user/agent-zero-data`
+
+You can map just the `/a0/usr` directory (recommended) or individual subfolders of `/a0` to a local directory.
+
+> [!CAUTION]
+> Do **not** map the entire `/a0` directory: it contains the application code and can break upgrades.
+
+> [!TIP]
+> Choose a location that's easy to access and backup. All your Agent Zero data will be directly accessible in this directory.
+
+### 2.3. Run the Container
+
+**Using Docker Desktop GUI:**
+
+- In Docker Desktop, go to the "Images" tab
+- Click the `Run` button next to the `agent0ai/agent-zero` image
+- Open the "Optional settings" menu
+- **Ensure at least one host port is mapped to container port `80`** (set host port to `0` for automatic assignment)
+- Click the `Run` button
+
+
+
+
+The container will start and show in the "Containers" tab:
+
+
+
+### 2.4. Access the Web UI
+
+The framework will take a few seconds to initialize. Find the mapped port in Docker Desktop (shown as `:80`) or click the port right under the container ID:
+
+
+
+Open `http://localhost:` in your browser. The Web UI will open - Agent Zero is ready for configuration!
+
+
+
+> [!TIP]
+> You can also access the Web UI by clicking the port link directly under the container ID in Docker Desktop.
+
+> [!NOTE]
+> After starting the container, you'll find all Agent Zero files in your chosen directory. You can access and edit these files directly on your machine, and the changes will be immediately reflected in the running container.
+
+**Running A0 using Terminal?**
+
+```bash
+docker run -p 0:80 -v /path/to/your/work_dir:/a0/usr agent0ai/agent-zero
+```
+
+- Replace `0` with a fixed port if you prefer (e.g., `50080:80`)
+
+---
+
+## Step 3: Configure Agent Zero
+
+The UI will show a warning banner "Missing LLM API Key for current settings". Click on `Add your API key` to enter Settings and start configuring A0.
+
+### Settings Configuration
+
+Agent Zero provides a comprehensive settings interface to customize various aspects of its functionality. Access the settings by clicking the "Settings" button with a gear icon in the sidebar.
+
+### Agent Configuration
+
+- **Agent Profile:** Select the agent profile (e.g., `agent0`, `hacker`, `researcher`). Profiles can override prompts, tools, and extensions.
+- **Memory Subdirectory:** Select the subdirectory for agent memory storage, allowing separation between different instances.
+- **Knowledge Subdirectory:** Specify the location of custom knowledge files to enhance the agent's understanding.
+
+> [!NOTE]
+> Since v0.9.7, custom prompts belong in `/a0/agents//prompts/` rather than a shared `/prompts` folder. See the [Extensions guide](../developer/extensions.md#prompts) for details.
+
+> [!NOTE]
+> The Hacker profile is included in the main image. After launch, choose the **hacker** agent profile in Settings if you want the security-focused prompts and tooling. The "hacker" branch is deprecated.
+
+
+
+### Chat Model Settings
+
+- **Provider:** Select the chat model provider (e.g., Anthropic)
+- **Model Name:** Choose the specific model (e.g., claude-sonnet-4-5)
+- **Context Length:** Set the maximum token limit for context window
+- **Context Window Space:** Configure how much of the context window is dedicated to chat history
+
+
+
+**Model naming is provider-specific.**
+
+Use `claude-sonnet-4-5` for Anthropic, but use `anthropic/claude-sonnet-4-5` for OpenRouter. If you see "Invalid model ID," verify the provider and naming format on the provider website, or search the web for " model naming".
+
+> [!TIP]
+> **Context window tuning:** Set the total context window size first (for example, 100k), then adjust the chat history portion as a fraction of that total. A large fraction on a very large context window can still be enormous.
+
+> [!TIP]
+> **API URL:** URL of the API endpoint for the chat model - only needed for some providers like Ollama, LM Studio, Azure, etc.
+
+### Utility Model Configuration
+
+- **Provider & Model:** Select a model for utility tasks like memory organization and summarization
+- **Temperature:** Adjust the determinism of utility responses
+
+> [!NOTE]
+> Utility models need to be strong enough to extract and consolidate memory reliably. Very small models (e.g., 4B) often fail at this; 70B-class models or high-quality cloud "flash/mini" models work best.
+
+### Embedding Model Settings [Optional]
+
+- **Provider:** Choose the embedding model provider (e.g., OpenAI)
+- **Model Name:** Select the specific embedding model (e.g., text-embedding-3-small)
+
+> [!NOTE]
+> Agent Zero uses a local embedding model by default (runs on CPU), but you can switch to OpenAI embeddings like `text-embedding-3-small` or `text-embedding-3-large` if preferred.
+
+### Speech to Text Options
+
+- **Model Size:** Choose the speech recognition model size
+- **Language Code:** Set the primary language for voice recognition
+- **Silence Settings:** Configure silence threshold, duration, and timeout parameters for voice input
+
+### API Keys
+
+Configure API keys for various service providers directly within the Web UI. Click `Save` to confirm your settings.
+
+> [!NOTE]
+> **OpenAI API vs Plus subscription:** A ChatGPT Plus subscription does not include API credits. You must provide a separate API key for OpenAI usage in Agent Zero.
+
+> [!TIP]
+> For OpenAI-compatible providers (e.g., custom gateways or Z.AI/GLM), add the API key under **External Services → Other OpenAI-compatible API keys**, then select **OpenAI Compatible** as the provider in model settings.
+
+> [!CAUTION]
+> **GitHub Copilot Provider:** When using the GitHub Copilot provider, after selecting the model and entering your first prompt, the OAuth login procedure will begin. You'll find the authentication code and link in the output logs. Complete the authentication process by following the provided link and entering the code, then you may continue using Agent Zero.
+
+### Authentication
+
+- **UI Login:** Set username for web interface access
+- **UI Password:** Configure password for web interface security
+- **Root Password:** Manage Docker container root password for SSH access
+
+
+
+### Development Settings
+
+- **RFC Parameters (local instances only):** Configure URLs and ports for remote function calls between instances
+- **RFC Password:** Configure password for remote function calls
+
+Learn more about Remote Function Calls in the [Development Setup guide](dev-setup.md#step-6-configure-ssh-and-rfc-connection).
+
+> [!IMPORTANT]
+> Always keep your API keys and passwords secure.
+
+> [!NOTE]
+> On Windows host installs (non-Docker), you must use RFC to run shell code on the host system. The Docker runtime handles this automatically.
+
+---
+
+## Choosing Your LLMs
+
+The Settings page is the control center for selecting the Large Language Models (LLMs) that power Agent Zero. You can choose different LLMs for different roles:
+
+| LLM Role | Description |
+| --- | --- |
+| `chat_llm` | This is the primary LLM used for conversations and generating responses. |
+| `utility_llm` | This LLM handles internal tasks like summarizing messages, managing memory, and processing internal prompts. Using a smaller, less expensive model here can improve efficiency. |
+| `browser_llm` | This LLM powers the browser agent for web navigation and interaction tasks. Vision support is recommended for better page understanding. |
+| `embedding_llm` | The embedding model shipped with A0 runs on CPU and is responsible for generating embeddings used for memory retrieval and knowledge base lookups. Changing the `embedding_llm` will re-index all of A0's memory. |
+
+**How to Change:**
+
+1. Open Settings page in the Web UI.
+2. Choose the provider for the LLM for each role (Chat model, Utility model, Browser model, Embedding model) and write the model name.
+3. Click "Save" to apply the changes.
+
+### Important Considerations
+
+#### Model Naming by Provider
+
+Use the naming format required by your selected provider:
+
+| Provider | Model Name Format | Example |
+| --- | --- | --- |
+| OpenAI | Model name only | `claude-sonnet-4-5` |
+| OpenRouter | Provider prefix mostly required | `anthropic/claude-sonnet-4-5` |
+| Ollama | Model name only | `gpt-oss:20b` |
+
+> [!TIP]
+> If you see "Invalid model ID," verify the provider and naming format on the provider website, or search the web for " model naming".
+
+#### Context Window & Memory Split
+
+- Set the **total context window** (e.g., 100k) first.
+- Then tune the **chat history portion** as a fraction of that total.
+- Extremely large totals can make even small fractions very large; adjust thoughtfully.
+
+#### Utility Model Guidance
+
+- Utility models handle summarization and memory extraction.
+- Very small models (≈4B) usually fail at reliable context extraction.
+- Aim for ~70B class models or strong cloud "flash/mini" models for better results.
+
+#### Reasoning/Thinking Models
+
+- Reasoning can increase cost and latency. Some models perform better **without** reasoning.
+- If a model supports it, disable reasoning via provider-specific parameters (e.g., Venice `disable_thinking=true`).
+
+---
+
+## Installing and Using Ollama (Local Models)
+
+Ollama is a powerful tool that allows you to run various large language models locally.
+
+---
+
+
+### Windows Ollama Installation
+
+Download and install Ollama from the official website:
+
+
+
+Once installed, continue to [Pulling Models](#pulling-models).
+
+---
+
+
+### macOS Ollama Installation
+
+**Using Homebrew:**
+
+```bash
+brew install ollama
+```
+
+**Using Installer:**
+
+Download from the [official website](https://ollama.com/).
+
+Once installed, continue to [Pulling Models](#pulling-models).
+
+---
+
+
+### Linux Ollama Installation
+
+Run the installation script:
+
+```bash
+curl -fsSL https://ollama.com/install.sh | sh
+```
+
+Once installed, continue to [Pulling Models](#pulling-models).
+
+---
+
+### Pulling Models
+
+**Finding Model Names:**
+
+Visit the [Ollama model library](https://ollama.com/library) for a list of available models and their corresponding names. Ollama models are referenced by **model name only** (for example, `llama3.2`).
+
+**Pull a model:**
+
+```bash
+ollama pull
+```
+
+Replace `` with the name of the model you want to use. For example: `ollama pull mistral-large`
+
+### Configuring Ollama in Agent Zero
+
+1. Once you've downloaded your model(s), select it in the Settings page of the GUI.
+2. Within the Chat model, Utility model, or Embedding model section, choose **Ollama** as provider.
+3. Write your model code as expected by Ollama, in the format `llama3.2` or `qwen2.5:7b`
+4. Provide your API base URL to your Ollama API endpoint, usually `http://host.docker.internal:11434`
+5. Click `Save` to confirm your settings.
+
+
+
+> [!NOTE]
+> If Agent Zero runs in Docker and Ollama runs on the host, ensure port **11434** is reachable from the container. If both services are in the same Docker network, you can use `http://:11434` instead of `host.docker.internal`.
+
+### Managing Downloaded Models
+
+**Listing downloaded models:**
+
+```bash
+ollama list
+```
+
+**Removing a model:**
+
+```bash
+ollama rm
+```
+
+> [!TIP]
+> Experiment with different model combinations to find the balance of performance and cost that best suits your needs. E.g., faster and lower latency LLMs will help, and you can also use `faiss_gpu` instead of `faiss_cpu` for the memory.
+
+---
+
+## How to Update Agent Zero
+
+> [!NOTE]
+> Since v0.9, Agent Zero includes a Backup & Restore workflow in the Settings UI. This is the **safest** way to upgrade Docker instances.
+
+### Recommended Update Process (Docker)
+
+1. **Keep the old container running** and note its port.
+2. **Pull the new image** (`agent0ai/agent-zero:latest`).
+3. **Start a new container** on a different host port.
+4. In the **old** instance, open **Settings → Backup & Restore** and create a backup.
+5. In the **new** instance, restore that backup from the same panel.
+
+> [!TIP]
+> If the new instance fails to load settings, remove `/a0/usr/settings.json` and restart to regenerate default settings.
+
+---
+
+## Using Agent Zero on Your Mobile Device
+
+Agent Zero can be accessed from mobile devices and other computers using the built-in **Tunnel feature**.
+
+### Recommended: Using Tunnel (Remote Access)
+
+The Tunnel feature allows secure access to your Agent Zero instance from anywhere:
+
+1. Open Settings in the Web UI
+2. Navigate to the **External Services** tab
+3. Click on **Flare Tunnel** in the navigation menu
+4. Click **Create Tunnel** to generate a secure HTTPS URL
+5. Share this URL to access Agent Zero from any device
+
+> [!IMPORTANT]
+> **Security:** Always set a username and password in Settings → Authentication before creating a tunnel to secure your instance on the internet.
+
+For complete details on tunnel configuration and security considerations, see the [Remote Access via Tunneling](../guides/usage.md#remote-access-via-tunneling) section in the Usage Guide.
+
+### Alternative: Local Network Access
+
+If you prefer to keep access limited to your local network:
+
+1. Find the mapped port in Docker Desktop (format: `:80`, e.g., `32771:80`)
+2. Access from the same computer: `http://localhost:`
+3. Access from other devices on the network: `http://:`
+
+> [!TIP]
+> Find your computer's IP address with `ipconfig` (Windows) or `ifconfig`/`ip addr` (macOS/Linux). It's usually in the format `192.168.x.x` or `10.0.x.x`.
+
+For developers or users who need to run Agent Zero directly on their system, see the [In-Depth Guide for Full Binaries Installation](dev-setup.md).
+
+---
+
+## Advanced: Automated Configuration via Environment Variables
+
+Agent Zero settings can be automatically configured using environment variables with the `A0_SET_` prefix in your `.env` file. This enables automated deployments without manual configuration.
+
+**Usage:**
+
+Add variables to your `.env` file in the format:
+
+```env
+A0_SET_{setting_name}={value}
+```
+
+**Examples:**
+
+```env
+# Model configuration
+A0_SET_chat_model_provider=anthropic
+A0_SET_chat_model_name=claude-3-5-sonnet-20241022
+A0_SET_chat_model_ctx_length=200000
+
+# Memory settings
+A0_SET_memory_recall_enabled=true
+A0_SET_memory_recall_interval=5
+
+# Agent configuration
+A0_SET_agent_profile=custom
+A0_SET_agent_memory_subdir=production
+```
+
+**Docker usage:**
+
+When running Docker, you can pass these as environment variables:
+
+```bash
+docker run -p 50080:80 \
+ -e A0_SET_chat_model_provider=anthropic \
+ -e A0_SET_chat_model_name=claude-3-5-sonnet-20241022 \
+ agent0ai/agent-zero
+```
+
+**Notes:**
+
+- These provide initial default values when settings.json doesn't exist or when new settings are added to the application. Once a value is saved in settings.json, it takes precedence over these environment variables.
+- Sensitive settings (API keys, passwords) use their existing environment variables
+- Container/process restart required for changes to take effect
+
+---
+
+### Manual Migration (Legacy or Non-Docker)
+
+If you are migrating from older, non-Docker setups, A0 handles the migration of legacy folders and files automatically at runtime. The right place to save your files and directories is `a0/usr`.
+
+## Conclusion
+
+After following the instructions for your specific operating system, you should have Agent Zero successfully installed and running. You can now start exploring the framework's capabilities and experimenting with creating your own intelligent agents.
+
+**Next Steps:**
+
+- For production server deployments, see the [VPS Deployment Guide](vps-deployment.md)
+- For development setup and extensions, see the [Development Setup Guide](dev-setup.md)
+- For remote access via tunnel, see [Remote Access via Tunneling](../guides/usage.md#remote-access-via-tunneling)
+
+If you encounter any issues during the installation process, please consult the [Troubleshooting section](../guides/troubleshooting.md) of this documentation or refer to the Agent Zero [Skool](https://www.skool.com/agent-zero) or [Discord](https://discord.gg/B8KZKNsPpj) community for assistance.
diff --git a/docs/setup/vps-deployment.md b/docs/setup/vps-deployment.md
new file mode 100644
index 0000000000..24066f6c4a
--- /dev/null
+++ b/docs/setup/vps-deployment.md
@@ -0,0 +1,771 @@
+# Agent Zero Installation Guide
+
+> **Purpose:** Step-by-step guide for deploying Agent Zero instances on VPS/dedicated servers
+> **Author:** Auto-generated from deployment experience
+> **Last Updated:** December 21 2025
+> **Compatibility:** Docker-capable Linux servers (AlmaLinux, CentOS, Rocky, Ubuntu, Debian)
+
+---
+
+## Table of Contents
+
+1. [Prerequisites](#prerequisites)
+2. [Docker Installation](#docker-installation)
+3. [Agent Zero Container Deployment](#agent-zero-container-deployment)
+4. [Apache Reverse Proxy Configuration](#apache-reverse-proxy-configuration)
+5. [SSL/TLS Configuration](#ssltls-configuration)
+6. [Authentication Setup](#authentication-setup)
+7. [Domain & DNS Setup](#domain--dns-setup)
+8. [Verification & Testing](#verification--testing)
+9. [Troubleshooting](#troubleshooting)
+10. [Maintenance & Updates](#maintenance--updates)
+11. [Quick Reference](#quick-reference)
+
+---
+
+## Prerequisites
+
+### Server Requirements
+
+| Requirement | Minimum | Recommended |
+|-------------|---------|-------------|
+| **RAM** | 2 GB | 4+ GB |
+| **Storage** | 20 GB | 50+ GB |
+| **CPU** | 1 vCPU | 2+ vCPU |
+| **OS** | Linux (64-bit) | AlmaLinux 9, Ubuntu 22.04+ |
+| **Network** | Static IP | Dedicated IP with reverse DNS |
+
+### Required Access
+
+- Root or sudo access to the server
+- SSH access (preferably on non-standard port)
+- Domain/subdomain with DNS control
+- SSL certificate (Let's Encrypt or commercial)
+
+### Software Dependencies
+
+- Docker Engine 24.0+
+- Apache 2.4+ with mod_proxy, mod_proxy_http, mod_proxy_wstunnel, mod_ssl, mod_rewrite
+- curl, git (optional)
+
+---
+
+## Docker Installation
+
+> [!NOTE]
+> For detailed Docker installation instructions and alternative methods, see the [Linux Installation section](installation.md#linux-installation) in the main installation guide.
+
+### Method A: Debian/Ubuntu Systems
+
+```bash
+# Update package index
+apt-get update
+
+# Install prerequisites
+apt-get install -y ca-certificates curl gnupg
+
+# Add Docker's official GPG key
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+
+# Set up repository
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+
+# Install Docker
+apt-get update
+apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+
+# Start and enable Docker
+systemctl enable docker
+systemctl start docker
+```
+
+### Method B: AlmaLinux/Rocky/CentOS/RHEL Systems
+
+```bash
+# Install required packages
+dnf -y install dnf-plugins-core
+
+# Add Docker repository (use CentOS repo for AlmaLinux/Rocky)
+dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
+
+# Install Docker
+dnf -y install docker-ce docker-ce-cli containerd.io docker-compose-plugin
+
+# Start and enable Docker
+systemctl enable docker
+systemctl start docker
+```
+
+### Method C: Generic (Convenience Script)
+
+> ⚠️ **Note:** May not work on all distributions (e.g., AlmaLinux)
+
+```bash
+curl -fsSL https://get.docker.com -o get-docker.sh
+sh get-docker.sh
+systemctl enable docker
+systemctl start docker
+```
+
+### Verify Docker Installation
+
+```bash
+docker --version
+docker run hello-world
+```
+
+---
+
+## Agent Zero Container Deployment
+
+### Step 1: Create Directory Structure
+
+```bash
+# Choose your installation path
+A0_NAME="a0-instance" # Change this to your instance name
+A0_PATH="/opt/${A0_NAME}"
+
+# Create directories
+mkdir -p ${A0_PATH}
+mkdir -p ${A0_PATH}/work_dir
+mkdir -p ${A0_PATH}/memory
+mkdir -p ${A0_PATH}/logs
+```
+
+### Step 2: Create Environment Configuration
+
+```bash
+# Create .env file with authentication
+cat > ${A0_PATH}/.env << 'EOF'
+# Agent Zero Configuration
+# Authentication (REQUIRED for web access)
+AUTH_LOGIN=your_username_here
+AUTH_PASSWORD=your_secure_password_here
+
+# Optional: Additional configuration
+# See Agent Zero documentation for all options
+EOF
+```
+
+> ⚠️ **CRITICAL:** `AUTH_LOGIN` is the **username**, not a boolean!
+> - ✅ Correct: `AUTH_LOGIN=admin`
+> - ❌ Wrong: `AUTH_LOGIN=true`
+
+### Step 3: Choose Host Port
+
+| Port | Use Case |
+|------|----------|
+| `50080` | Standard/recommended for reverse proxy setups |
+| `50081`, `50082`... | Additional instances on same server |
+| `80` | Direct access (not recommended for production) |
+
+### Step 4: Pull and Run Container
+
+```bash
+# Set variables
+A0_NAME="a0-instance"
+A0_PATH="/opt/${A0_NAME}"
+A0_PORT="50080"
+
+# Pull latest image
+docker pull agent0ai/agent-zero:latest
+
+# Run container
+docker run -d --name ${A0_NAME} --restart unless-stopped -p ${A0_PORT}:80 -v ${A0_PATH}/.env:/a0/.env -v ${A0_PATH}/usr:/a0/usr agent0ai/agent-zero:latest
+```
+
+### Step 5: Verify Container
+
+```bash
+# Check container is running
+docker ps | grep ${A0_NAME}
+
+# Check logs
+docker logs ${A0_NAME}
+
+# Test local access
+curl -I http://127.0.0.1:${A0_PORT}/
+```
+
+Expected response: `HTTP/1.1 302 FOUND` with `Location: /login` (if auth enabled)
+
+---
+
+## Apache Reverse Proxy Configuration
+
+### Required Apache Modules
+
+```bash
+# Debian/Ubuntu
+a2enmod proxy proxy_http proxy_wstunnel ssl rewrite headers
+systemctl restart apache2
+
+# AlmaLinux/CentOS (usually pre-loaded)
+httpd -M | grep -E "proxy|rewrite|ssl"
+```
+
+### Configuration for Standard Apache (Debian/Ubuntu)
+
+Create `/etc/apache2/sites-available/a0-instance.conf`:
+
+```apache
+# Agent Zero Reverse Proxy Configuration
+# Instance: a0-instance
+# Domain: a0.example.com
+
+# HTTP - Redirect to HTTPS
+
+ ServerName a0.example.com
+ ServerAlias www.a0.example.com
+
+ RewriteEngine On
+ RewriteCond %{HTTPS} off
+ RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+
+
+# HTTPS - Proxy to Container
+
+ ServerName a0.example.com
+ ServerAlias www.a0.example.com
+ ServerAdmin webmaster@example.com
+
+ # SSL Configuration
+ SSLEngine on
+ SSLCertificateFile /path/to/certificate.crt
+ SSLCertificateKeyFile /path/to/private.key
+ SSLCertificateChainFile /path/to/chain.crt
+
+ # Proxy Configuration
+ ProxyPreserveHost On
+ ProxyPass / http://127.0.0.1:50080/
+ ProxyPassReverse / http://127.0.0.1:50080/
+
+ # WebSocket Support (Required for real-time features)
+ RewriteEngine On
+ RewriteCond %{HTTP:Upgrade} websocket [NC]
+ RewriteCond %{HTTP:Connection} upgrade [NC]
+ RewriteRule ^/?(.*) ws://127.0.0.1:50080/$1 [P,L]
+
+ # Logging
+ ErrorLog ${APACHE_LOG_DIR}/a0-instance.error.log
+ CustomLog ${APACHE_LOG_DIR}/a0-instance.access.log combined
+
+```
+
+Enable and restart:
+
+```bash
+a2ensite a0-instance.conf
+apache2ctl configtest
+systemctl reload apache2
+```
+
+### Configuration for DirectAdmin Apache (AlmaLinux/CentOS)
+
+#### Option A: Use httpd-includes.conf (Recommended)
+
+Edit `/etc/httpd/conf/extra/httpd-includes.conf`:
+
+```apache
+# Agent Zero Proxy Configuration
+# Instance: a0-instance
+# Domain: a0.example.com
+# Note: Use specific IP, not wildcards, for DirectAdmin compatibility
+
+
+ ServerName a0.example.com
+ ServerAlias www.a0.example.com
+
+ RewriteEngine On
+ RewriteCond %{HTTPS} off
+ RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+
+
+
+ ServerName a0.example.com
+ ServerAlias www.a0.example.com
+ ServerAdmin webmaster@example.com
+
+ SSLEngine on
+ # DirectAdmin SSL cert paths (adjust user and domain)
+ SSLCertificateFile /usr/local/directadmin/data/users/USERNAME/domains/example.com.cert.combined
+ SSLCertificateKeyFile /usr/local/directadmin/data/users/USERNAME/domains/example.com.key
+
+ ProxyPreserveHost On
+ ProxyPass / http://127.0.0.1:50080/
+ ProxyPassReverse / http://127.0.0.1:50080/
+
+ # WebSocket Support
+ RewriteEngine On
+ RewriteCond %{HTTP:Upgrade} websocket [NC]
+ RewriteCond %{HTTP:Connection} upgrade [NC]
+ RewriteRule ^/?(.*) ws://127.0.0.1:50080/$1 [P,L]
+
+ ErrorLog /var/log/httpd/domains/a0.example.com.error.log
+ CustomLog /var/log/httpd/domains/a0.example.com.access.log combined
+
+```
+
+> ⚠️ **Important for DirectAdmin:**
+> - Use **specific IP address** (e.g., `192.168.1.100:443`), not `*:443`
+> - IP-bound vhosts take precedence over DirectAdmin's vhosts
+> - SSL certs are in `/usr/local/directadmin/data/users/USERNAME/domains/`
+
+#### Option B: Standalone conf.d file
+
+If `/etc/httpd/conf.d/` is included in your Apache config:
+
+```bash
+# Check if conf.d is included
+grep 'conf.d' /etc/httpd/conf/httpd.conf
+
+# If not, add before directadmin-vhosts.conf include:
+sed -i '/Include conf\/extra\/directadmin-vhosts.conf/i Include conf.d/*.conf' /etc/httpd/conf/httpd.conf
+
+# Create config
+mkdir -p /etc/httpd/conf.d
+cat > /etc/httpd/conf.d/httpd-vhosts-a0.conf << 'EOF'
+# Your vhost config here (same as Option A)
+EOF
+```
+
+### Verify and Restart Apache
+
+```bash
+# Test configuration
+httpd -t # AlmaLinux/CentOS
+apachectl -t # Alternative
+apache2ctl -t # Debian/Ubuntu
+
+# Restart
+systemctl restart httpd # AlmaLinux/CentOS
+systemctl restart apache2 # Debian/Ubuntu
+```
+
+---
+
+## SSL/TLS Configuration
+
+### Option A: Let's Encrypt with Certbot
+
+```bash
+# Install Certbot
+# Debian/Ubuntu:
+apt-get install certbot python3-certbot-apache
+
+# AlmaLinux/CentOS:
+dnf install certbot python3-certbot-apache
+
+# Obtain certificate
+certbot --apache -d a0.example.com -d www.a0.example.com
+
+# Auto-renewal (usually automatic, but verify)
+certbot renew --dry-run
+```
+
+### Option B: DirectAdmin Auto-SSL
+
+If using DirectAdmin, SSL is typically managed automatically:
+
+1. Create domain/subdomain in DirectAdmin
+2. Enable "SSL" for the domain
+3. DirectAdmin will obtain Let's Encrypt certificate
+4. Certs stored in `/usr/local/directadmin/data/users/USERNAME/domains/`
+
+### Option C: Manual/Commercial Certificates
+
+Place certificates in secure location:
+
+```bash
+mkdir -p /etc/ssl/a0
+chmod 700 /etc/ssl/a0
+
+# Copy your certificates
+cp certificate.crt /etc/ssl/a0/
+cp private.key /etc/ssl/a0/
+cp chain.crt /etc/ssl/a0/ # if applicable
+
+chmod 600 /etc/ssl/a0/*
+```
+
+---
+
+## Authentication Setup
+
+### Understanding A0 Authentication Variables
+
+| Variable | Purpose | Example |
+|----------|---------|--------|
+| `AUTH_LOGIN` | The **username** for login | `AUTH_LOGIN=admin` |
+| `AUTH_PASSWORD` | The **password** for login | `AUTH_PASSWORD=SecurePass123!` |
+
+> ⚠️ **Common Mistake:** `AUTH_LOGIN` is the username, **not** a boolean to enable auth!
+
+### Setting Up Authentication
+
+```bash
+# Edit .env file
+vi /opt/a0-instance/.env
+
+# Add/update these lines:
+AUTH_LOGIN=your_username
+AUTH_PASSWORD=your_secure_password
+
+# Restart container to apply
+docker restart a0-instance
+```
+
+### Password Requirements
+
+- Minimum 8 characters recommended
+- Special characters are supported (properly escaped)
+- Avoid these characters in passwords: `' " \` $ \` (or escape carefully)
+
+### Disabling Authentication (Not Recommended)
+
+To disable authentication (local/dev use only):
+
+```bash
+# Remove or comment out both lines in .env:
+# AUTH_LOGIN=
+# AUTH_PASSWORD=
+
+docker restart a0-instance
+```
+
+---
+
+## Domain & DNS Setup
+
+### DNS Configuration
+
+Create an A record pointing to your server:
+
+| Type | Name | Value | TTL |
+|------|------|-------|-----|
+| A | a0 | YOUR_SERVER_IP | 300 |
+| A | www.a0 | YOUR_SERVER_IP | 300 |
+
+### DirectAdmin Subdomain Setup
+
+1. Log into DirectAdmin
+2. Navigate to: **Domain Setup** → Select domain → **Subdomain Management**
+3. Create subdomain (e.g., `a0`)
+4. Note: You'll override the DocumentRoot with Apache proxy config
+
+### Verify DNS Propagation
+
+```bash
+# Check DNS resolution
+dig a0.example.com +short
+nslookup a0.example.com
+
+# Should return your server IP
+```
+
+---
+
+## Verification & Testing
+
+### Step-by-Step Verification Checklist
+
+```bash
+# 1. Verify Docker container is running
+docker ps | grep a0-instance
+
+# 2. Check container logs for errors
+docker logs a0-instance --tail 50
+
+# 3. Test local container access
+curl -I http://127.0.0.1:50080/
+# Expected: HTTP/1.1 302 FOUND, Location: /login
+
+# 4. Test Apache config
+httpd -t # or apache2ctl -t
+
+# 5. Check Apache is proxying correctly
+curl -I http://127.0.0.1:80 -H "Host: a0.example.com"
+curl -Ik https://127.0.0.1:443 -H "Host: a0.example.com"
+
+# 6. Test external HTTPS access
+curl -I https://a0.example.com/
+# Expected: HTTP/2 302 with Location: /login
+
+# 7. Test login page loads
+curl -s https://a0.example.com/login | grep -i ""
+# Expected: Login - Agent Zero
+```
+
+### WebSocket Verification
+
+```bash
+# Install wscat if needed
+npm install -g wscat
+
+# Test WebSocket connection
+wscat -c wss://a0.example.com/ws
+```
+
+---
+
+## Troubleshooting
+
+### Issue: "Invalid Credentials" on Login
+
+**Cause:** Incorrect `.env` configuration
+
+**Fix:**
+```bash
+# Verify .env inside container
+docker exec a0-instance cat /a0/.env
+
+# Ensure format is:
+# AUTH_LOGIN=username (NOT AUTH_LOGIN=true)
+# AUTH_PASSWORD=password
+
+# Restart after fixing
+docker restart a0-instance
+```
+
+### Issue: 403 Forbidden
+
+**Cause:** DirectAdmin vhost overriding custom proxy config
+
+**Fix:**
+```bash
+# Check vhost order
+httpd -S 2>&1 | grep your-domain
+
+# Ensure custom config loads BEFORE directadmin-vhosts.conf
+# Use specific IP binding (e.g., 192.168.1.1:443) not wildcards (*:443)
+
+# Restart Apache
+systemctl restart httpd
+```
+
+### Issue: 502 Bad Gateway
+
+**Cause:** Container not running or wrong port
+
+**Fix:**
+```bash
+# Check container status
+docker ps -a | grep a0-instance
+
+# If stopped, check logs
+docker logs a0-instance
+
+# Restart container
+docker start a0-instance
+
+# Verify port binding
+netstat -tlnp | grep 50080
+```
+
+### Issue: 504 Gateway Timeout
+
+**Cause:** Container overloaded or unresponsive
+
+**Fix:**
+```bash
+# Check container resource usage
+docker stats a0-instance --no-stream
+
+# Restart container
+docker restart a0-instance
+
+# Check for memory issues
+free -h
+```
+
+### Issue: WebSocket Connection Failed
+
+**Cause:** Missing WebSocket proxy rules
+
+**Fix:**
+Ensure these lines are in your vhost config:
+
+```apache
+RewriteEngine On
+RewriteCond %{HTTP:Upgrade} websocket [NC]
+RewriteCond %{HTTP:Connection} upgrade [NC]
+RewriteRule ^/?(.*) ws://127.0.0.1:50080/$1 [P,L]
+```
+
+### Issue: Container Won't Start
+
+**Cause:** Port conflict or Docker issue
+
+**Fix:**
+```bash
+# Check what's using the port
+netstat -tlnp | grep 50080
+
+# Remove conflicting container
+docker rm -f conflicting-container
+
+# Check Docker daemon
+systemctl status docker
+journalctl -u docker --since "1 hour ago"
+```
+
+### Issue: Changes to .env Not Taking Effect
+
+**Cause:** Container needs restart to reload env
+
+**Fix:**
+```bash
+docker restart a0-instance
+
+# Verify env is loaded
+docker exec a0-instance cat /a0/.env
+```
+
+---
+
+## Maintenance & Updates
+
+### Updating Agent Zero
+
+```bash
+# Pull latest image
+docker pull agent0ai/agent-zero:latest
+
+# Stop and remove old container (data persists in volumes)
+docker stop a0-instance
+docker rm a0-instance
+
+# Recreate with same settings
+docker run -d --name a0-instance --restart unless-stopped -p 50080:80 -v /opt/a0-instance/.env:/a0/.env -v /opt/a0-instance/usr:/a0/usr -v /opt/agent-zero:latest
+```
+
+### Backup Strategy
+
+```bash
+# Backup all instance data
+tar -czvf a0-backup-$(date +%Y%m%d).tar.gz /opt/a0-instance/
+
+# Key items to backup:
+# - /opt/a0-instance/.env (configuration)
+# - /opt/a0-instance/memory/ (agent memories)
+# - /opt/a0-instance/work_dir/ (working files)
+```
+
+### Monitoring
+
+```bash
+# Check container health
+docker ps --format "table {{.Names}} {{.Status}} {{.Ports}}"
+
+# View recent logs
+docker logs --tail 100 -f a0-instance
+
+# Resource usage
+docker stats a0-instance
+```
+
+### Docker Cleanup
+
+```bash
+# Remove unused images
+docker image prune -f
+
+# Remove all unused Docker resources
+docker system prune -f
+```
+
+---
+
+## Quick Reference
+
+### Essential Commands
+
+```bash
+# Container Management
+docker start a0-instance
+docker stop a0-instance
+docker restart a0-instance
+docker logs a0-instance
+docker exec -it a0-instance bash
+
+# Apache Management
+systemctl restart httpd # RHEL/AlmaLinux
+systemctl restart apache2 # Debian/Ubuntu
+httpd -t # Test config
+
+# Quick Diagnostics
+docker ps | grep a0
+curl -I https://your-domain.com/login
+```
+
+### Standard Paths
+
+| Component | Path |
+|-----------|----- |
+| Instance Data | `/opt/a0-instance/` |
+| Environment File | `/opt/a0-instance/.env` |
+| Memory Storage | `/opt/a0-instance/memory/` |
+| Work Directory | `/opt/a0-instance/work_dir/` |
+| Logs | `/opt/a0-instance/logs/` |
+| Apache Config (Standard) | `/etc/apache2/sites-available/` |
+| Apache Config (DirectAdmin) | `/etc/httpd/conf/extra/httpd-includes.conf` |
+| DirectAdmin SSL Certs | `/usr/local/directadmin/data/users/USER/domains/` |
+
+### Standard Ports
+
+| Port | Purpose |
+|------|---------|
+| 50080 | First A0 instance |
+| 50081 | Second A0 instance |
+| 50082 | Third A0 instance |
+| 80 | HTTP (redirect to HTTPS) |
+| 443 | HTTPS (main access) |
+
+### .env Template
+
+```bash
+# Agent Zero Configuration Template
+# Copy and customize for each instance
+
+# Authentication (REQUIRED for production)
+AUTH_LOGIN=your_username
+AUTH_PASSWORD=your_secure_password
+
+# Optional: Additional settings
+# Refer to Agent Zero documentation for all options
+```
+
+---
+
+## Appendix: Multi-Instance Setup
+
+For running multiple A0 instances on the same server:
+
+```bash
+# Instance 1: a0-primary on port 50080
+mkdir -p /opt/a0-primary
+# ... create .env, run container on port 50080
+
+# Instance 2: a0-dev on port 50081
+mkdir -p /opt/a0-dev
+# ... create .env, run container on port 50081
+
+# Instance 3: a0-backup on port 50082
+mkdir -p /opt/a0-backup
+# ... create .env, run container on port 50082
+```
+
+Each instance needs:
+- Unique container name
+- Unique host port
+- Separate data directory
+- Separate domain/subdomain
+- Separate Apache vhost config
+
+---
+
+*This guide comes from successful Agent Zero deployments across DirectAdmin and standard Linux environments.*
+
+Contributed by @hurtdidit in the A0 Community.
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
deleted file mode 100644
index 487ec524d2..0000000000
--- a/docs/troubleshooting.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# Troubleshooting and FAQ
-This page addresses frequently asked questions (FAQ) and provides troubleshooting steps for common issues encountered while using Agent Zero.
-
-## Frequently Asked Questions
-**1. How do I ask Agent Zero to work directly on my files or dirs?**
-- Place the files/dirs in the `work_dir` directory. Agent Zero will be able to perform tasks on them. The `work_dir` directory is located in the root directory of the Docker Container.
-
-**2. When I input something in the chat, nothing happens. What's wrong?**
-- Check if you have set up API keys in the Settings page. If not, the application will not be able to communicate with the endpoints it needs to run LLMs and to perform tasks.
-
-**3. How do I integrate open-source models with Agent Zero?**
-Refer to the [Choosing your LLMs](installation.md#installing-and-using-ollama-local-models) section of the documentation for detailed instructions and examples for configuring different LLMs. Local models can be run using Ollama or LM Studio.
-
-> [!TIP]
-> Some LLM providers offer free usage of their APIs, for example Groq, Mistral, SambaNova or CometAPI.
-
-**6. How can I make Agent Zero retain memory between sessions?**
-Refer to the [How to update Agent Zero](installation.md#how-to-update-agent-zero) section of the documentation for instructions on how to update Agent Zero while retaining memory and data.
-
-**7. Where can I find more documentation or tutorials?**
-- Join the Agent Zero [Skool](https://www.skool.com/agent-zero) or [Discord](https://discord.gg/B8KZKNsPpj) community for support and discussions.
-
-**8. How do I adjust API rate limits?**
-Modify the `rate_limit_seconds` and `rate_limit_requests` parameters in the `AgentConfig` class within `initialize.py`.
-
-**9. My code_execution_tool doesn't work, what's wrong?**
-- Ensure you have Docker installed and running. If using Docker Desktop on macOS, grant it access to your project files in Docker Desktop's settings. Check the [Installation guide](installation.md#4-install-docker-docker-desktop-application) for more details.
-- Verify that the Docker image is updated.
-
-**10. Can Agent Zero interact with external APIs or services (e.g., WhatsApp)?**
-Extending Agent Zero to interact with external APIs is possible by creating custom tools or solutions. Refer to the documentation on creating them.
-
-## Troubleshooting
-
-**Installation**
-- **Docker Issues:** If Docker containers fail to start, consult the Docker documentation and verify your Docker installation and configuration. On macOS, ensure you've granted Docker access to your project files in Docker Desktop's settings as described in the [Installation guide](installation.md#4-install-docker-docker-desktop-application). Verify that the Docker image is updated.
-
-**Usage**
-
-- **Terminal commands not executing:** Ensure the Docker container is running and properly configured. Check SSH settings if applicable. Check if the Docker image is updated by removing it from Docker Desktop app, and subsequently pulling it again.
-
-* **Error Messages:** Pay close attention to the error messages displayed in the Web UI or terminal. They often provide valuable clues for diagnosing the issue. Refer to the specific error message in online searches or community forums for potential solutions.
-
-* **Performance Issues:** If Agent Zero is slow or unresponsive, it might be due to resource limitations, network latency, or the complexity of your prompts and tasks, especially when using local models.
\ No newline at end of file
diff --git a/docs/tunnel.md b/docs/tunnel.md
deleted file mode 100644
index aa7de020ad..0000000000
--- a/docs/tunnel.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Agent Zero Tunnel Feature
-
-The tunnel feature in Agent Zero allows you to expose your local Agent Zero instance to the internet using Flaredantic tunnels. This makes it possible to share your Agent Zero instance with others without requiring them to install and run Agent Zero themselves.
-
-## How It Works
-
-Agent Zero uses the [Flaredantic](https://pypi.org/project/flaredantic/) library to create secure tunnels to expose your local instance to the internet. These tunnels:
-
-- Are secure (HTTPS)
-- Don't require any configuration
-- Generate unique URLs for each session
-- Can be regenerated on demand
-
-## Using the Tunnel Feature
-
-1. Open the settings and navigate to the "External Services" tab
-2. Click on "Flare Tunnel" in the navigation menu
-3. Click the "Create Tunnel" button to generate a new tunnel
-4. Once created, the tunnel URL will be displayed and can be copied to share with others
-5. The tunnel URL will remain active until you stop the tunnel or close the Agent Zero application
-
-## Security Considerations
-
-When sharing your Agent Zero instance via a tunnel:
-
-- Anyone with the URL can access your Agent Zero instance
-- No additional authentication is added beyond what your Agent Zero instance already has
-- Consider setting up authentication if you're sharing sensitive information
-- The tunnel exposes your local Agent Zero instance, not your entire system
-
-## Troubleshooting
-
-If you encounter issues with the tunnel feature:
-
-1. Check your internet connection
-2. Try refreshing the tunnel URL
-3. Restart Agent Zero
-4. Check the console logs for any error messages
-
-## Adding Authentication
-
-To add basic authentication to your Agent Zero instance when using tunnels, you can set the following environment variables:
-
-```
-AUTH_LOGIN=your_username
-AUTH_PASSWORD=your_password
-```
-
-Alternatively, you can configure the username and password directly in the settings:
-
-1. Open the settings modal in the Agent Zero UI
-2. Navigate to the "External Services" tab
-3. Find the "Authentication" section
-4. Enter your desired username and password in the "UI Login" and "UI Password" fields
-5. Click the "Save" button to apply the changes
-
-This will require users to enter these credentials when accessing your tunneled Agent Zero instance. When attempting to create a tunnel without authentication configured, Agent Zero will display a security warning.
\ No newline at end of file
diff --git a/docs/usage.md b/docs/usage.md
deleted file mode 100644
index 045d9095a8..0000000000
--- a/docs/usage.md
+++ /dev/null
@@ -1,364 +0,0 @@
-# Usage Guide
-This guide explores usage and configuration scenarios for Agent Zero. You can consider this as a reference post-installation guide.
-
-
-
-## Basic Operations
-Agent Zero provides several basic operations through its interface:
-
-### Restart Framework
-The Restart button allows you to quickly restart the Agent Zero framework without using the terminal:
-
-
-
-* Click the "Restart" button in the sidebar
-* A blue notification will appear indicating "Restarting..."
-* Once complete, a green success message "Restarted" will be shown
-* The framework will reinitialize while maintaining your current chat history and context
-
-> [!TIP]
-> Use the Restart function when you want to:
-> - Reset the framework if you encounter unexpected behavior
-> - Reinitialize the system when agents become unresponsive
-
-### Action Buttons
-Located beneath the chat input box, Agent Zero provides a set of action buttons for enhanced control and visibility:
-
-
-#### Chat Flow Control
-* **Pause/Resume Agent:** Toggle button to pause and resume chat flow
- - Click to pause ongoing agent operations
- - Changes to "Resume Agent" when paused
- - Click again to resume chat flow and command execution
-
-#### Knowledge and File Management
-* **Import Knowledge:** Import external files into the agent's knowledge base
- - Supports `.txt`, `.pdf`, `.csv`, `.html`, `.json`, and `.md` formats
- - Files are stored in `\knowledge\custom\main`
- - Success message confirms successful import
- - See [knowledge](architecture.md#knowledge) for more details
-
-### File Browser: Manage files in the Agent Zero environment
- - Upload new files and folders
- - Download files (click filename) or folders (as zip archives)
- - Delete files and folders
- - Navigate directories using the "Up" button
- - Support for file renaming and search coming soon
- - See [File Browser](#file-browser) section for detailed features
-
-#### Debugging and Monitoring
-* **Context:** View the complete context window sent to the LLM
- - Includes system prompts
- - Shows current conversation context
- - Displays active instructions and parameters
-
-
-
-### History:
-Access the chat history in JSON format
- - View the conversation as processed by the LLM
- - Useful for debugging and understanding agent behavior
-
-
-
-* **Nudge:** Restart the agent's last process
- - Useful when agents become unresponsive
- - Retries the last operation
- - Helps recover from stuck states
-
-
-
-> [!TIP]
-> Use the Context and History buttons to understand how the agent interprets your instructions and debug any unexpected behavior.
-
-### File Attachments
-Agent Zero supports direct file attachments in the chat interface for seamless file operations:
-
-#### Attaching Files
-* Click the attachment icon (📎) on the left side of the chat input box
-* Select one or multiple files to attach
-* Preview attached files before sending:
- - File names are displayed with their types (HTML, PDF, JPG, etc.)
- - Images show thumbnails when available
- - Files are listed in the chat input area waiting to be sent
-
-
-
-#### Working with Attached Files
-* Files can be referenced directly in your messages
-* Agent Zero can:
- - Process attached files
- - Move files to specific directories
- - Perform operations on multiple files simultaneously
- - Confirm successful file operations with detailed responses
-
-
-
-> [!TIP]
-> When working with multiple files, you can attach them all at once and then give instructions about what to do with them. The agent will handle them as a batch while keeping you informed of the progress.
-
-## Tool Usage
-Agent Zero's power comes from its ability to use [tools](architecture.md#tools). Here's how to leverage them effectively:
-
-- **Understand Tools:** Agent Zero includes default tools like knowledge (powered by SearXNG), code execution, and communication. Understand the capabilities of these tools and how to invoke them.
-
-## Example of Tools Usage: Web Search and Code Execution
-Let's say you want Agent Zero to perform some financial analysis tasks. Here's a possible prompt:
-
-> Please be a professional financial analyst. Find last month Bitcoin/ USD price trend and make a chart in your environment. The chart must have highlighted key points corresponding with dates of major news about cryptocurrency. Use the 'search_engine' and 'document_query_tool' to find the price and the news, and the 'code_execution_tool' to perform the rest of the job.
-
-Agent Zero might then:
-
-1. Use the `search_engine` and `document_query_tool` to query a reliable source for the Bitcoin price and for the news about cryptocurrency as prompted.
-2. Extract the price from the search results and save the news, extracting their dates and possible impact on the price.
-3. Use the `code_execution_tool` to execute a Python script that performs the graph creation and key points highlighting, using the extracted data and the news dates as inputs.
-4. Save the final chart on disk inside the container and provide a link to it with the `response_tool`.
-
-> [!NOTE]
-> The first run of `code_execution_tool` may take a while as it downloads and builds the Agent Zero Docker image. Subsequent runs will be faster.
-
-This example demonstrates how to combine multiple tools to achieve an analysis task. By mastering prompt engineering and tool usage, you can unlock the full potential of Agent Zero to solve complex problems.
-
-## Multi-Agent Cooperation
-One of Agent Zero's unique features is multi-agent cooperation.
-
-* **Creating Sub-Agents:** Agents can create sub-agents to delegate sub-tasks. This helps manage complexity and distribute workload.
-* **Communication:** Agents can communicate with each other, sharing information and coordinating actions. The system prompt and message history play a key role in guiding this communication.
-* **Hierarchy:** Agent Zero uses a [hierarchical structure](architecture.md#agent-hierarchy-and-communication), with superior agents delegating tasks to subordinates. This allows for structured problem-solving and efficient resource allocation.
-
-
-
-
-## Prompt Engineering
-Effective prompt engineering is crucial for getting the most out of Agent Zero. Here are some tips and techniques:
-
-* **Be Clear and Specific:** Clearly state your desired outcome. The more specific you are, the better Agent Zero can understand and fulfill your request. Avoid vague or ambiguous language.
-* **Provide Context:** If necessary, provide background information or context to help the agent understand the task better. This might include relevant details, constraints, or desired format for the response.
-* **Break Down Complex Tasks:** For complex tasks, break them down into smaller, more manageable sub-tasks. This makes it easier for the agent to reason through the problem and generate a solution.
-* **Iterative Refinement:** Don't expect perfect results on the first try. Experiment with different prompts, refine your instructions based on the agent's responses, and iterate until you achieve the desired outcome. To achieve a full-stack, web-app development task, for example, you might need to iterate for a few hours for 100% success.
-
-## Voice Interface
-Agent Zero provides both Text-to-Speech (TTS) and Speech-to-Text (STT) capabilities for natural voice interaction:
-
-### Text-to-Speech
-Enable voice responses from agents:
-* Toggle the "Speech" switch in the Preferences section of the sidebar
-* Agents will use your system's built-in voice synthesizer to speak their messages
-* Click the "Stop Speech" button above the input area to immediately stop any ongoing speech
-* You can also click the speech button when hovering over messages to speak individual messages or their parts
-
-
-
-- The interface allows users to stop speech at any time if a response is too lengthy or if they wish to intervene during the conversation.
-
-The TTS uses a standard voice interface provided by modern browsers, which may sound robotic but is effective and does not require complex AI models. This ensures low latency and quick responses across various platforms, including mobile devices.
-
-
-> [!TIP]
-> The Text-to-Speech feature is great for:
-> - Multitasking while receiving agent responses
-> - Accessibility purposes
-> - Creating a more interactive experience
-
-### Speech-to-Text
-Send voice messages to agents using OpenAI's Whisper model (does not require OpenAI API key!):
-
-1. Click the microphone button in the input area to start recording
-2. The button color indicates the current status:
- - Grey: Inactive
- - Red: Listening
- - Green: Recording
- - Teal: Waiting
- - Cyan (pulsing): Processing
-
-Users can adjust settings such as silence threshold and message duration before sending to optimize their interaction experience.
-
-Configure STT settings in the Settings page:
-* **Model Size:** Choose between Base (74M, English) or other models
- - Note: Only Large and Turbo models support multiple languages
-* **Language Code:** Set your preferred language (e.g., 'en', 'fr', 'it', 'cz')
-* **Silence Detection:**
- - Threshold: Adjust sensitivity (lower values are more sensitive)
- - Duration: Set how long silence should last before ending recording
- - Timeout: Set maximum waiting time before closing the microphone
-
-
-
-> [!IMPORTANT]
-> All STT and TTS functionalities operate locally within the Docker container,
-> ensuring that no data is transmitted to external servers or OpenAI APIs. This
-> enhances user privacy while maintaining functionality.
-
-
-* **Complex Mathematics:** Supports full KaTeX syntax for:
- - Fractions, exponents, and roots
- - Matrices and arrays
- - Greek letters and mathematical symbols
- - Integrals, summations, and limits
- - Mathematical alignments and equations
-
-
-
-> [!TIP]
-> When asking the agent to solve mathematical problems, it will automatically respond using KaTeX formatting for clear and professional-looking mathematical expressions.
-
-### File Browser
-Agent Zero provides a powerful file browser interface for managing your workspace:
-
-#### Interface Overview
-- **Navigation Bar**: Shows current directory path with "Up" button for parent directory
-- **File List**: Displays files and directories with key information:
- - Name (sortable)
- - Size in bytes
- - Last modified timestamp
-- **Action Icons**: Each file/directory has:
- - Download button
- - Delete button (with confirmation)
-
-
-
-#### Features
-- **Directory Navigation**:
- - Click directories to enter them
- - Use "Up" button to move to parent directory
- - Current path always visible for context
-
-> [!NOTE]
-> The files browser allows the user to go in the Agent Zero root folder if you click the `Up` button, but the working directory of Agents will always be `/work_dir`
->
-- **File Operations**:
- - Create new files and directories
- - Delete existing files and directories
- - Download files to your local system
- - Upload files from your local system
-- **File Information**:
- - Visual indicators for file types (folders, code files, documents)
- - Size information in human-readable format
- - Last modification timestamps
-- **Bulk Operations**:
- - Upload multiple files simultaneously
- - Select and manage multiple files at once
-
-> [!TIP]
-> The File Browser integrates seamlessly with Agent Zero's capabilities. You can reference files directly in your conversations, and the agent can help you manage, modify, and organize your files.
-
-## Backup & Restore
-Agent Zero provides a comprehensive backup and restore system to protect your data and configurations. This feature helps you safeguard your work and migrate Agent Zero setups between different systems.
-
-### Creating Backups
-Access the backup functionality through the Settings interface:
-
-1. Click the **Settings** button in the sidebar
-2. Navigate to the **Backup** tab
-3. Click **Create Backup** to start the backup process
-
-#### What Gets Backed Up
-By default, Agent Zero backs up your most important data:
-
-* **Knowledge Base**: Your custom knowledge files and documents
-* **Memory System**: Agent memories and learned information
-* **Chat History**: All your conversations and interactions
-* **Configuration Files**: Settings, API keys, and system preferences
-* **Custom Instruments**: Any tools you've added or modified
-* **Uploaded Files**: Documents and files you've worked with
-
-#### Customizing Backup Content
-Before creating a backup, you can customize what to include:
-
-* **Edit Patterns**: Use the built-in editor to specify exactly which files and folders to backup
-* **Include Hidden Files**: Choose whether to include system and configuration files
-* **Preview Files**: See exactly what will be included before creating the backup
-* **Organized View**: Files are grouped by directory for easy review
-
-> [!TIP]
-> The backup system uses pattern matching, so you can include or exclude specific file types. For example, you can backup all `.py` files but exclude temporary `.tmp` files.
-
-#### Creating Your Backup
-1. Review the file preview to ensure you're backing up what you need
-2. Give your backup a descriptive name
-3. Click **Create Backup** to generate the archive
-4. The backup file will download automatically as a ZIP archive
-
-> [!NOTE]
-> Backup creation may take a few minutes depending on the amount of data. You'll see progress updates during the process.
-
-### Restoring from Backup
-The restore process allows you to recover your Agent Zero setup from a previous backup:
-
-#### Starting a Restore
-1. Navigate to **Settings** → **Backup** tab
-2. Click **Restore from Backup**
-3. Upload your backup ZIP file
-
-#### Reviewing Before Restore
-After uploading, you can review and customize the restore:
-
-* **Inspect Metadata**: View information about when and where the backup was created
-* **Edit Restore Patterns**: Choose exactly which files to restore
-* **Preview Changes**: See which files will be restored, overwritten, or skipped
-* **Cross-System Compatibility**: Paths are automatically adjusted when restoring on different systems
-
-#### Restore Options
-Configure how the restore should handle existing files:
-
-* **Overwrite**: Replace existing files with backup versions
-* **Skip**: Keep existing files, only restore missing ones
-* **Backup Existing**: Create backup copies of existing files before overwriting
-
-#### Clean Before Restore
-Optionally clean up existing files before restoring:
-
-* **Smart Cleanup**: Remove files that match backup patterns before restoring
-* **Preview Cleanup**: See which files would be deleted before confirming
-* **Safe Operation**: Only affects files that match your specified patterns
-
-### Best Practices
-
-#### When to Create Backups
-* **Before Major Changes**: Always backup before significant modifications
-* **Regular Schedule**: Create weekly or monthly backups of your work
-* **Before System Updates**: Backup before updating Agent Zero or system components
-* **Project Milestones**: Save backups when completing important work
-
-#### Backup Management
-* **Descriptive Names**: Use clear names like "project-completion-2024-01"
-* **External Storage**: Keep backup files in a safe location outside Agent Zero
-* **Multiple Versions**: Maintain several backup versions for different time periods
-* **Test Restores**: Occasionally test restoring backups to ensure they work
-
-#### Security Considerations
-* **API Keys**: Backups include your API keys and sensitive configuration
-* **Secure Storage**: Store backup files securely and don't share them
-* **Clean Systems**: When restoring on new systems, verify all configurations
-
-### Common Use Cases
-
-#### System Migration
-Moving Agent Zero to a new server or computer:
-1. Create a complete backup on the original system
-2. Install Agent Zero on the new system
-3. Restore the backup to migrate all your data and settings
-
-#### Project Archival
-Preserving completed projects:
-1. Create project-specific backup patterns
-2. Include only relevant files and conversations
-3. Store the backup as a project archive
-
-#### Development Snapshots
-Saving work-in-progress states:
-1. Create frequent backups during development
-2. Use descriptive names to track progress
-3. Restore previous versions if something goes wrong
-
-#### Team Collaboration
-Sharing Agent Zero configurations:
-1. Create backups with shared configurations and tools
-2. Team members can restore to get consistent setups
-3. Include documentation and project files
-
-> [!IMPORTANT]
-> Always test your backup and restore process in a safe environment before relying on it for critical data. Keep multiple backup versions and store them in secure, accessible locations.
-
-> [!TIP]
-> The backup system is designed to work across different operating systems and Agent Zero installations. Your backups from a Windows system will work on Linux, and vice versa.
diff --git a/initialize.py b/initialize.py
index ec26227fa9..296d2d4f55 100644
--- a/initialize.py
+++ b/initialize.py
@@ -1,9 +1,10 @@
from agent import AgentConfig
import models
-from python.helpers import runtime, settings, defer
+from python.helpers import runtime, settings, defer, extension
from python.helpers.print_style import PrintStyle
+@extension.extensible
def initialize_agent(override_settings: dict | None = None):
current_settings = settings.get_settings()
if override_settings:
@@ -78,7 +79,6 @@ def _normalize_model_kwargs(kwargs: dict) -> dict:
embeddings_model=embedding_llm,
browser_model=browser_llm,
profile=current_settings["agent_profile"],
- memory_subdir=current_settings["agent_memory_subdir"],
knowledge_subdirs=[current_settings["agent_knowledge_subdir"], "default"],
mcp_servers=current_settings["mcp_servers"],
browser_http_headers=current_settings["browser_http_headers"],
@@ -109,7 +109,7 @@ def _normalize_model_kwargs(kwargs: dict) -> dict:
# if first_context:
# (
# first_context.log
- # .log(type="warning", content=f"Failed to update MCP settings: {e}", temp=False)
+ # .log(type="warning", content=f"Failed to update MCP settings: {e}")
# )
# (
# print_style_helper.PrintStyle(background_color="black", font_color="red", padding=True)
@@ -119,12 +119,14 @@ def _normalize_model_kwargs(kwargs: dict) -> dict:
# return config object
return config
+@extension.extensible
def initialize_chats():
from python.helpers import persist_chat
async def initialize_chats_async():
persist_chat.load_tmp_chats()
return defer.DeferredTask().start_task(initialize_chats_async)
+@extension.extensible
def initialize_mcp():
set = settings.get_settings()
async def initialize_mcp_async():
@@ -132,14 +134,25 @@ async def initialize_mcp_async():
return _initialize_mcp(set["mcp_servers"])
return defer.DeferredTask().start_task(initialize_mcp_async)
+@extension.extensible
def initialize_job_loop():
from python.helpers.job_loop import run_loop
return defer.DeferredTask("JobLoop").start_task(run_loop)
+@extension.extensible
def initialize_preload():
import preload
return defer.DeferredTask().start_task(preload.preload)
+@extension.extensible
+def initialize_migration():
+ from python.helpers import migration, dotenv
+ # run migration
+ migration.startup_migration()
+ # reload .env as it might have been moved
+ dotenv.load_dotenv()
+ # reload settings to ensure new paths are picked up
+ settings.reload_settings()
def _args_override(config):
# update config with runtime args
diff --git a/instruments/default/.DS_Store b/instruments/default/.DS_Store
deleted file mode 100644
index 5008ddfcf5..0000000000
Binary files a/instruments/default/.DS_Store and /dev/null differ
diff --git a/instruments/default/yt_download/download_video.py b/instruments/default/yt_download/download_video.py
deleted file mode 100644
index db75f32693..0000000000
--- a/instruments/default/yt_download/download_video.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import sys
-import yt_dlp # type: ignore
-
-if len(sys.argv) != 2:
- print("Usage: python3 download_video.py ")
- sys.exit(1)
-
-url = sys.argv[1]
-
-ydl_opts = {}
-with yt_dlp.YoutubeDL(ydl_opts) as ydl:
- ydl.download([url])
diff --git a/instruments/default/yt_download/yt_download.md b/instruments/default/yt_download/yt_download.md
deleted file mode 100644
index b6fbe355ec..0000000000
--- a/instruments/default/yt_download/yt_download.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Problem
-Download a YouTube video
-# Solution
-1. If folder is specified, cd to it
-2. Run the shell script with your video URL:
-
-```bash
-bash /a0/instruments/default/yt_download/yt_download.sh
-```
-3. Replace `` with your video URL.
-4. The script will handle the installation of yt-dlp and the download process.
diff --git a/instruments/default/yt_download/yt_download.sh b/instruments/default/yt_download/yt_download.sh
deleted file mode 100644
index e71f1d0e34..0000000000
--- a/instruments/default/yt_download/yt_download.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-# Install yt-dlp and ffmpeg
-sudo apt-get update && sudo apt-get install -y yt-dlp ffmpeg
-
-# Install yt-dlp using pip
-pip install --upgrade yt-dlp
-
-# Call the Python script to download the video
-python3 /a0/instruments/default/yt_download/download_video.py "$1"
diff --git a/jsconfig.json b/jsconfig.json
index 7efa80e954..17f9b25371 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -1,9 +1,17 @@
{
"compilerOptions": {
+ "checkJs": true,
+ "allowJs": true,
+ "strict": true,
+ "noImplicitAny": false,
+ "module": "esnext",
+ "target": "es2022",
"baseUrl": ".",
"paths": {
- "*": ["webui/*"]
+ "*": ["webui/*"],
+ "/plugins/*": ["plugins/*"],
+ "/usr/plugins/*": ["usr/plugins/*"]
}
},
- "include": ["webui/**/*.js"]
+ "include": ["webui/**/*.js", "plugins/**/*.js", "usr/plugins/**/*.js"]
}
\ No newline at end of file
diff --git a/knowledge/default/main/about/github_readme.md b/knowledge/default/main/about/github_readme.md
deleted file mode 100644
index 4307241f4d..0000000000
--- a/knowledge/default/main/about/github_readme.md
+++ /dev/null
@@ -1,65 +0,0 @@
-
-# Agent Zero Documentation
-To begin with Agent Zero, follow the links below for detailed guides on various topics:
-
-- **[Installation](installation.md):** Set up (or [update](installation.md#how-to-update-agent-zero)) Agent Zero on your system.
-- **[Usage Guide](usage.md):** Explore GUI features and usage scenarios.
-- **[Architecture Overview](architecture.md):** Understand the internal workings of the framework.
-- **[Contributing](contribution.md):** Learn how to contribute to the Agent Zero project.
-- **[Troubleshooting and FAQ](troubleshooting.md):** Find answers to common issues and questions.
-
-### Your experience with Agent Zero starts now!
-
-- **Download Agent Zero:** Follow the [installation guide](installation.md) to download and run Agent Zero.
-- **Join the Community:** Join the Agent Zero [Skool](https://www.skool.com/agent-zero) or [Discord](https://discord.gg/B8KZKNsPpj) community to discuss ideas, ask questions, and collaborate with other contributors.
-- **Share your Work:** Share your Agent Zero creations, workflows and discoverings on our [Show and Tell](https://github.com/agent0ai/agent-zero/discussions/categories/show-and-tell) area on GitHub.
-- **Report Issues:** Use the [GitHub issue tracker](https://github.com/agent0ai/agent-zero/issues) to report framework-relative bugs or suggest new features.
-
-## Table of Contents
-
-- [Welcome to the Agent Zero Documentation](#agent-zero-documentation)
- - [Your Experience with Agent Zero](#your-experience-with-agent-zero-starts-now)
- - [Table of Contents](#table-of-contents)
-- [Installation Guide](installation.md)
- - [Windows, macOS and Linux Setup](installation.md#windows-macos-and-linux-setup-guide)
- - [Settings Configuration](installation.md#settings-configuration)
- - [Choosing Your LLMs](installation.md#choosing-your-llms)
- - [Installing and Using Ollama](installation.md#installing-and-using-ollama-local-models)
- - [Using Agent Zero on Mobile](installation.md#using-agent-zero-on-your-mobile-device)
- - [How to Update Agent Zero](installation.md#how-to-update-agent-zero)
- - [Full Binaries Installation](installation.md#in-depth-guide-for-full-binaries-installation)
-- [Usage Guide](usage.md)
- - [Basic Operations](usage.md#basic-operations)
- - [Restart Framework](usage.md#restart-framework)
- - [Action Buttons](usage.md#action-buttons)
- - [File Attachments](usage.md#file-attachments)
- - [Tool Usage](usage.md#tool-usage)
- - [Example of Tools Usage](usage.md#example-of-tools-usage-web-search-and-code-execution)
- - [Multi-Agent Cooperation](usage.md#multi-agent-cooperation)
- - [Prompt Engineering](usage.md#prompt-engineering)
- - [Voice Interface](usage.md#voice-interface)
- - [Mathematical Expressions](usage.md#mathematical-expressions)
- - [File Browser](usage.md#file-browser)
- - [Backup & Restore](usage.md#backup--restore)
-- [Architecture Overview](architecture.md)
- - [System Architecture](architecture.md#system-architecture)
- - [Runtime Architecture](architecture.md#runtime-architecture)
- - [Implementation Details](architecture.md#implementation-details)
- - [Core Components](architecture.md#core-components)
- - [Agents](architecture.md#1-agents)
- - [Tools](architecture.md#2-tools)
- - [SearXNG Integration](architecture.md#searxng-integration)
- - [Memory System](architecture.md#3-memory-system)
- - [Messages History and Summarization](archicture.md#messages-history-and-summarization)
- - [Prompts](architecture.md#4-prompts)
- - [Knowledge](architecture.md#5-knowledge)
- - [Instruments](architecture.md#6-instruments)
- - [Extensions](architecture.md#7-extensions)
- - [Contributing](contribution.md)
- - [Getting Started](contribution.md#getting-started)
- - [Making Changes](contribution.md#making-changes)
- - [Submitting a Pull Request](contribution.md#submitting-a-pull-request)
- - [Documentation Stack](contribution.md#documentation-stack)
-- [Troubleshooting and FAQ](troubleshooting.md)
- - [Frequently Asked Questions](troubleshooting.md#frequently-asked-questions)
- - [Troubleshooting](troubleshooting.md#troubleshooting)
diff --git a/knowledge/default/main/about/installation.md b/knowledge/default/main/about/installation.md
deleted file mode 100644
index 5cbaea5e1a..0000000000
--- a/knowledge/default/main/about/installation.md
+++ /dev/null
@@ -1,554 +0,0 @@
-# Users installation guide for Windows, macOS and Linux
-
-Click to open a video to learn how to install Agent Zero:
-
-[](https://www.youtube.com/watch?v=w5v5Kjx51hs)
-
-The following user guide provides instructions for installing and running Agent Zero using Docker, which is the primary runtime environment for the framework. For developers and contributors, we also provide instructions for setting up the [full development environment](#in-depth-guide-for-full-binaries-installation).
-
-
-## Windows, macOS and Linux Setup Guide
-
-
-1. **Install Docker Desktop:**
-- Docker Desktop provides the runtime environment for Agent Zero, ensuring consistent behavior and security across platforms
-- The entire framework runs within a Docker container, providing isolation and easy deployment
-- Available as a user-friendly GUI application for all major operating systems
-
-1.1. Go to the download page of Docker Desktop [here](https://www.docker.com/products/docker-desktop/). If the link does not work, just search the web for "docker desktop download".
-
-1.2. Download the version for your operating system. For Windows users, the Intel/AMD version is the main download button.
-
-
-
-
-> [!NOTE]
-> **Linux Users:** You can install either Docker Desktop or docker-ce (Community Edition).
-> For Docker Desktop, follow the instructions for your specific Linux distribution [here](https://docs.docker.com/desktop/install/linux-install/).
-> For docker-ce, follow the instructions [here](https://docs.docker.com/engine/install/).
->
-> If you're using docker-ce, you'll need to add your user to the `docker` group:
-> ```bash
-> sudo usermod -aG docker $USER
-> ```
-> Log out and back in, then run:
-> ```bash
-> docker login
-> ```
-
-1.3. Run the installer with default settings. On macOS, drag and drop the application to your Applications folder.
-
-
-
-
-
-
-
-> [!IMPORTANT]
-> **macOS Configuration:** In Docker Desktop's preferences (Docker menu) → Settings →
-> Advanced, enable "Allow the default Docker socket to be used (requires password)."
-
-
-
-2. **Run Agent Zero:**
-
-- Note: Agent Zero also offers a Hacking Edition based on Kali linux with modified prompts for cybersecurity tasks. The setup is the same as the regular version, just use the agent0ai/agent-zero:hacking image instead of agent0ai/agent-zero.
-
-2.1. Pull the Agent Zero Docker image:
-- Search for `agent0ai/agent-zero` in Docker Desktop
-- Click the `Pull` button
-- The image will be downloaded to your machine in a few minutes
-
-
-
-> [!TIP]
-> Alternatively, run the following command in your terminal:
->
-> ```bash
-> docker pull agent0ai/agent-zero
-> ```
-
-2.2. Create a data directory for persistence:
-- Choose or create a directory on your machine where you want to store Agent Zero's data
-- This can be any location you prefer (e.g., `C:/agent-zero-data` or `/home/user/agent-zero-data`)
-- This directory will contain all your Agent Zero files, like the legacy root folder structure:
- - `/memory` - Agent's memory and learned information
- - `/knowledge` - Knowledge base
- - `/instruments` - Instruments and functions
- - `/prompts` - Prompt files
- - `/work_dir` - Working directory
- - `.env` - Your API keys
- - `settings.json` - Your Agent Zero settings
-
-> [!TIP]
-> Choose a location that's easy to access and backup. All your Agent Zero data
-> will be directly accessible in this directory.
-
-2.3. Run the container:
-- In Docker Desktop, go back to the "Images" tab
-- Click the `Run` button next to the `agent0ai/agent-zero` image
-- Open the "Optional settings" menu
-- Set the port to `0` in the second "Host port" field (for automatic port assignment)
-
-Optionally you can map local folders for file persistence:
-- Under "Volumes", configure:
- - Host path: Your chosen directory (e.g., `C:\agent-zero-data`)
- - Container path: `/a0`
-
-
-
-- Click the `Run` button in the "Images" tab.
-- The container will start and show in the "Containers" tab
-
-
-
-> [!TIP]
-> Alternatively, run the following command in your terminal:
-> ```bash
-> docker run -p $PORT:80 -v /path/to/your/data:/a0 agent0ai/agent-zero
-> ```
-> - Replace `$PORT` with the port you want to use (e.g., `50080`)
-> - Replace `/path/to/your/data` with your chosen directory path
-
-2.4. Access the Web UI:
-- The framework will take a few seconds to initialize and the Docker logs will look like the image below.
-- Find the mapped port in Docker Desktop (shown as `:80`) or click the port right under the container ID as shown in the image below
-
-
-
-- Open `http://localhost:` in your browser
-- The Web UI will open. Agent Zero is ready for configuration!
-
-
-
-> [!TIP]
-> You can also access the Web UI by clicking the ports right under the container ID in Docker Desktop.
-
-> [!NOTE]
-> After starting the container, you'll find all Agent Zero files in your chosen
-> directory. You can access and edit these files directly on your machine, and
-> the changes will be immediately reflected in the running container.
-
-3. Configure Agent Zero
-- Refer to the following sections for a full guide on how to configure Agent Zero.
-
-## Settings Configuration
-Agent Zero provides a comprehensive settings interface to customize various aspects of its functionality. Access the settings by clicking the "Settings"button with a gear icon in the sidebar.
-
-### Agent Configuration
-- **Prompts Subdirectory:** Choose the subdirectory within `/prompts` for agent behavior customization. The 'default' directory contains the standard prompts.
-- **Memory Subdirectory:** Select the subdirectory for agent memory storage, allowing separation between different instances.
-- **Knowledge Subdirectory:** Specify the location of custom knowledge files to enhance the agent's understanding.
-
-
-
-### Chat Model Settings
-- **Provider:** Select the chat model provider (e.g., Ollama)
-- **Model Name:** Choose the specific model (e.g., llama3.2)
-- **Temperature:** Adjust response randomness (0 for deterministic, higher values for more creative responses)
-- **Context Length:** Set the maximum token limit for context window
-- **Context Window Space:** Configure how much of the context window is dedicated to chat history
-
-
-
-### Utility Model Configuration
-- **Provider & Model:** Select a smaller, faster model for utility tasks like memory organization and summarization
-- **Temperature:** Adjust the determinism of utility responses
-
-### Embedding Model Settings
-- **Provider:** Choose the embedding model provider (e.g., OpenAI)
-- **Model Name:** Select the specific embedding model (e.g., text-embedding-3-small)
-
-### Speech to Text Options
-- **Model Size:** Choose the speech recognition model size
-- **Language Code:** Set the primary language for voice recognition
-- **Silence Settings:** Configure silence threshold, duration, and timeout parameters for voice input
-
-### API Keys
-- Configure API keys for various service providers directly within the Web UI
-- Click `Save` to confirm your settings
-
-### Authentication
-- **UI Login:** Set username for web interface access
-- **UI Password:** Configure password for web interface security
-- **Root Password:** Manage Docker container root password for SSH access
-
-
-
-### Development Settings
-- **RFC Parameters (local instances only):** configure URLs and ports for remote function calls between instances
-- **RFC Password:** Configure password for remote function calls
-Learn more about Remote Function Calls and their purpose [here](#7-configure-agent-zero-rfc).
-
-> [!IMPORTANT]
-> Always keep your API keys and passwords secure.
-
-# Choosing Your LLMs
-The Settings page is the control center for selecting the Large Language Models (LLMs) that power Agent Zero. You can choose different LLMs for different roles:
-
-| LLM Role | Description |
-| --- | --- |
-| `chat_llm` | This is the primary LLM used for conversations and generating responses. |
-| `utility_llm` | This LLM handles internal tasks like summarizing messages, managing memory, and processing internal prompts. Using a smaller, less expensive model here can improve efficiency. |
-| `embedding_llm` | This LLM is responsible for generating embeddings used for memory retrieval and knowledge base lookups. Changing the `embedding_llm` will re-index all of A0's memory. |
-
-**How to Change:**
-1. Open Settings page in the Web UI.
-2. Choose the provider for the LLM for each role (Chat model, Utility model, Embedding model) and write the model name.
-3. Click "Save" to apply the changes.
-
-## Important Considerations
-
-> [!CAUTION]
-> Changing the `embedding_llm` will re-index all the memory and knowledge, and
-> requires clearing the `memory` folder to avoid errors, as the embeddings can't be
-> mixed in the vector database. Note that this will DELETE ALL of Agent Zero's memory.
-
-## Installing and Using Ollama (Local Models)
-If you're interested in Ollama, which is a powerful tool that allows you to run various large language models locally, here's how to install and use it:
-
-#### First step: installation
-**On Windows:**
-
-Download Ollama from the official website and install it on your machine.
-
-
-
-**On macOS:**
-```
-brew install ollama
-```
-Otherwise choose macOS installer from the [official website](https://ollama.com/).
-
-**On Linux:**
-```bash
-curl -fsSL https://ollama.com/install.sh | sh
-```
-
-**Finding Model Names:**
-Visit the [Ollama model library](https://ollama.com/library) for a list of available models and their corresponding names. The format is usually `provider/model-name` (or just `model-name` in some cases).
-
-#### Second step: pulling the model
-**On Windows, macOS, and Linux:**
-```
-ollama pull
-```
-
-1. Replace `` with the name of the model you want to use. For example, to pull the Mistral Large model, you would use the command `ollama pull mistral-large`.
-
-2. A CLI message should confirm the model download on your system
-
-#### Selecting your model within Agent Zero
-1. Once you've downloaded your model(s), you must select it in the Settings page of the GUI.
-
-2. Within the Chat model, Utility model, or Embedding model section, choose Ollama as provider.
-
-3. Write your model code as expected by Ollama, in the format `llama3.2` or `qwen2.5:7b`
-
-4. Click `Save` to confirm your settings.
-
-
-
-#### Managing your downloaded models
-Once you've downloaded some models, you might want to check which ones you have available or remove any you no longer need.
-
-- **Listing downloaded models:**
- To see a list of all the models you've downloaded, use the command:
- ```
- ollama list
- ```
-- **Removing a model:**
- If you need to remove a downloaded model, you can use the `ollama rm` command followed by the model name:
- ```
- ollama rm
- ```
-
-
-- Experiment with different model combinations to find the balance of performance and cost that best suits your needs. E.g., faster and lower latency LLMs will help, and you can also use `faiss_gpu` instead of `faiss_cpu` for the memory.
-
-## Using Agent Zero on your mobile device
-Agent Zero's Web UI is accessible from any device on your network through the Docker container:
-
-1. The Docker container automatically exposes the Web UI on all network interfaces
-2. Find the mapped port in Docker Desktop:
- - Look under the container name (usually in the format `:80`)
- - For example, if you see `32771:80`, your port is `32771`
-3. Access the Web UI from any device using:
- - Local access: `http://localhost:`
- - Network access: `http://:`
-
-> [!TIP]
-> - Your computer's IP address is usually in the format `192.168.x.x` or `10.0.x.x`
-> - You can find your external IP address by running `ipconfig` (Windows) or `ifconfig` (Linux/Mac)
-> - The port is automatically assigned by Docker unless you specify one
-
-> [!NOTE]
-> If you're running Agent Zero directly on your system (legacy approach) instead of
-> using Docker, you'll need to configure the host manually in `run_ui.py` to run on all interfaces using `host="0.0.0.0"`.
-
-For developers or users who need to run Agent Zero directly on their system,see the [In-Depth Guide for Full Binaries Installation](#in-depth-guide-for-full-binaries-installation).
-
-# How to update Agent Zero
-
-1. **If you come from the previous version of Agent Zero:**
-- Your data is safely stored across various directories and files inside the Agent Zero folder.
-- To update to the new Docker runtime version, you might want to backup the following files and directories:
- - `/memory` - Agent's memory
- - `/knowledge` - Custom knowledge base (if you imported any custom knowledge files)
- - `/instruments` - Custom instruments and functions (if you created any custom)
- - `/tmp/settings.json` - Your Agent Zero settings
- - `/tmp/chats/` - Your chat history
-- Once you have saved these files and directories, you can proceed with the Docker runtime [installation instructions above](#windows-macos-and-linux-setup-guide) setup guide.
-- Reach for the folder where you saved your data and copy it to the new Agent Zero folder set during the installation process.
-- Agent Zero will automatically detect your saved data and use it across memory, knowledge, instruments, prompts and settings.
-
-> [!IMPORTANT]
-> If you have issues loading your settings, you can try to delete the `/tmp/settings.json` file and let Agent Zero generate a new one.
-> The same goes for chats in `/tmp/chats/`, they might be incompatible with the new version
-
-2. **Update Process (Docker Desktop)**
-- Go to Docker Desktop and stop the container from the "Containers" tab
-- Right-click and select "Remove" to remove the container
-- Go to "Images" tab and remove the `agent0ai/agent-zero` image or click the three dots to pull the difference and update the Docker image.
-
-
-
-- Search and pull the new image if you chose to remove it
-- Run the new container with the same volume settings as the old one
-
-> [!IMPORTANT]
-> Make sure to use the same volume mount path when running the new
-> container to preserve your data. The exact path depends on where you stored
-> your Agent Zero data directory (the chosen directory on your machine).
-
-> [!TIP]
-> Alternatively, run the following commands in your terminal:
->
-> ```bash
-> # Stop the current container
-> docker stop agent-zero
->
-> # Remove the container (data is safe in the folder)
-> docker rm agent-zero
->
-> # Remove the old image
-> docker rmi agent0ai/agent-zero
->
-> # Pull the latest image
-> docker pull agent0ai/agent-zero
->
-> # Run new container with the same volume mount
-> docker run -p $PORT:80 -v /path/to/your/data:/a0 agent0ai/agent-zero
-> ```
-
-3. **Full Binaries**
-- Using Git/GitHub: Pull the latest version of the Agent Zero repository.
-- The custom knowledge, solutions, memory, and other data will get ignored, so you don't need to worry about losing any of your custom data. The same goes for your .env file with all of your API keys and settings.json.
-
-> [!WARNING]
-> - If you update manually, beware: save your .env file with the API keys, and look for new dependencies in requirements.txt.
-> - If any changes are made to the requirements of the updated version, you have to execute this command inside the a0 conda env after activating it:
-> ```bash
-> pip install -r requirements.txt
-
-# In-Depth Guide for Full Binaries Installation
-- Agent Zero is a framework. It's made to be customized, edited, enhanced. Therefore you need to install the necessary components to run it when downloading its full binaries. This guide will help you to do so.
-- The following step by step instructions can be followed along with a video for this tutorial on how to make Agent Zero work with its full development environment.
-
-[](https://youtu.be/8H7mFsvxKYQ)
-
-## Reminders:
-1. There's no need to install Python, Conda will manage that for you.
-2. You don't necessarily need API keys: Agent Zero can run with local models. For this tutorial though, we will leave it to the default OpenAI API. A guide for downloading Ollama along with local models is available [here](#installing-and-using-ollama-local-models).
-3. Visual Studio Code or any other code editor is not mandatory, but it makes it easier to navigate and edit files.
-4. Git/GitHub is not mandatory, you can download the framework files through your browser. We will not be showing how to use Git in this tutorial.
-5. Docker is not mandatory for the full binaries installation, since the framework will run on your machine connecting to the Docker container through the Web UI RFC functionality.
-6. Running Agent Zero without Docker makes the process more complicated and it's thought for developers and contributors.
-
-> [!IMPORTANT]
-> Linux instructions are provided as general instructions for any Linux distribution. If you're using a distribution other than Debian/Ubuntu, you may need to adjust the instructions accordingly.
->
-> For Debian/Ubuntu, just follow the macOS instructions, as they are the same.
-
-## 1. Install Conda (miniconda)
-- Conda is a Python environment manager, it will help you keep your projects and installations separated.
-- It's a lightweight version of Anaconda that includes only conda, Python, the packages they depend on, and a small number of other useful packages, including pip, zlib and a few others.
-
-1. Go to the download page of miniconda [here](https://docs.anaconda.com/miniconda/#miniconda-latest-installer-links). If the link does not work, just search the web for "miniconda download".
-2. Based on your operating system, download the right installer of miniconda. For macOS select the version with "pkg" at the end.
-
-
-
-
-
-3. Run the installer and go through the installation process, here you can leave everything to default and just click Next, Next... The same goes for macOS with the "pkg" graphical installer.
-
-
-
-
-
-
-
-4. After the installation is complete, you should have "Anaconda Powershell Prompt" installed on your Windows machine. On macOS, when you open the Terminal application in your Applications folder and type "conda --version", you should see the version installed.
-
-
-
-
-
-
-## 2. Download Agent Zero
-- You can clone the Agent Zero repository (https://github.com/agent0ai/agent-zero) from GitHub if you know how to use Git. In this tutorial I will just show how to download the files.
-
-1. Go to the Agent Zero releases [here](https://github.com/agent0ai/agent-zero/releases).
-2. The latest release is on the top of the list, click the "Source Code (zip)" button under "Assets" to download it.
-
-
-
-
-3. Extract the downloaded archive where you want to have it. I will extract them to "agent-zero" folder on my Desktop - "C:\Users\frdel\Desktop\agent-zero" on Windows and "/Users/frdel/Desktop/agent-zero" on macOS.
-
-## 3. Set up Conda environment
-- Now that we have the project files and Conda, we can create **virtual Python environment** for this project, activate it and install requirements.
-
-1. Open your **"Anaconda Powershell Prompt"** application on windows or **"Terminal"** application on macOS.
-2. In the terminal, navigate to your Agent Zero folder using **"cd"** command. Replace the path with your actual Agent Zero folder path.
-~~~
-cd C:\Users\frdel\Desktop\agent-zero
-~~~
-You should see your folder has changed on the next terminal line.
-
-
-
-
-
-3. Create Conda environment using command **"conda create"**. After **"-n"** is your environment name, you can choose your own, i will use **"a0"** - short for Agent Zero. After **"python"** is the Python version that Conda will install for you into this environment, right now, 3.12 works fine. **-y** skips confirmations.
-~~~
-conda create -n a0 python=3.12 -y
-~~~
-
-4. Once done, activate the new environment for this terminal window by another command:
-~~~
-conda activate a0
-~~~
-And you should see that the **(base)** on the left has changed to **(a0)**. This means that this terminal now uses the new **a0** virtual environment and all packages will be installed into this environment.
-
-
-
-
-
-> [!IMPORTANT]
-> If you open a new terminal window, you will need to activate the environment with
-> "conda activate a0" again for that window.
-
-5. Install requirements using **"pip"**. Pip is a Python package manager. We can install all required packages from requirements.txt file using command:
-~~~
-pip install -r requirements.txt
-~~~
-This might take some time. If you get any errors regarding version conflicts and compatibility, double check that your environment is activated and that you created that environment with the correct Python version.
-
-
-
-
-## 4. Install Docker (Docker Desktop application)
-Simply put, Docker is a way of running virtual computers on your machine. These are lightweight, disposable and isolated from your operating system, so it is a way to sandbox Agent Zero.
-- Agent Zero only connects to the Docker container when it needs to execute code and commands. The frameworks itself runs on your machine.
-- Docker has a desktop application with GUI for all major operating system, which is the recommended way to install it.
-
-1. Go to the download page of Docker Desktop [here](https://www.docker.com/products/docker-desktop/). If the link does not work, just search the web for "docker desktop download".
-2. Download the version for your operating system. Don't be tricked by the seemingly missing windows intel/amd version, it's the button itself, not in the dropdown menu.
-
-
-
-
-3. Run the installer and go through the installation process. It should be even shorter than Conda installation, you can leave everything to default. On macOS, the installer is a "dmg" image, so just drag and drop the application to your Applications folder like always.
-
-
-
-
-
-
-
-
-4. Once installed, you should see Docker Desktop application on your Windows/Mac machine.
-
-
-
-
-
-5. Create account in the application.
-- It's required to be signed in to the Docker Hub, so create a free account in the Docker Desktop application, you will be prompted when the application first runs.
-
-> [!IMPORTANT]
-> **Important macOS-only Docker Configuration:** In Docker Desktop's preferences
-> (Docker menu) go to Settings, navigate to "Advanced" and check "Allow the default
-> Docker socket to be used (requires password)." This allows Agent Zero to
-> communicate with the Docker daemon.
-
-
-
-> [!NOTE]
-> **Linux Users:** You can install both Docker Desktop or docker-ce (Community Edition).
-> For Docker Desktop, follow the instructions for your specific Linux distribution [here](https://docs.docker.com/desktop/install/linux-install/).
-> For docker-ce, follow the instructions [here](https://docs.docker.com/engine/install/).
->
-> If you're using docker-ce, you will need to add your user to the `docker` group to be able to run docker commands without sudo. You can do this by running the following command in your terminal: `sudo usermod -aG docker $USER`. Then log out and log back in for the changes to take effect.
->
-> Login in the Docker CLI with `docker login` and provide your Docker Hub credentials.
-
-6. Pull the Docker image
-- Agent Zero needs a Docker image to be pulled from the Docker Hub to be run, even when using the full binaries.
-You can refer to the [installation instructions above](#windows-macos-and-linux-setup-guide) to run the Docker container and then resume from the next step. There are two differences:
- - You need to map two ports instead of one:
- - 55022 in the first field to run the Remote Function Call SSH
- - 0 in the second field to run the Web UI in automatic port assignment
- - You need to map the `/a0` volume to the location of your local Agent Zero folder.
-- Run the Docker container following the instructions.
-
-## 5. Run the local Agent Zero instance
-Run the Agent Zero with Web UI:
-~~~
-python run_ui.py
-~~~
-
-
-
-
-- Open the URL shown in terminal in your web browser. You should see the Agent Zero interface.
-
-## 6. Configure Agent Zero
-Now we can configure Agent Zero - select models, settings, API Keys etc. Refer to the [Usage](usage.md#agent-configuration) guide for a full guide on how to configure Agent Zero.
-
-## 7. Configure Agent Zero RFC
-Agent Zero needs to be configured further to redirect some functions to the Docker container. This is crucial for development as A0 needs to run in a standardized environment to support all features.
-1. Go in "Settings" page in the Web UI of your local instance and go in the "Development" section.
-2. Set "RFC Destination URL" to `http://localhost`
-3. Set the two ports (HTTP and SSH) to the ones used when creating the Docker container
-4. Click "Save"
-
-
-
-5. Go in "Settings" page in the Web UI of your Docker instance and go in the "Development" section.
-
-
-
-6. This time the page has only the password field, set it to the same password you used when creating the Docker container.
-7. Click "Save"
-8. Use the Development environment
-9. Now you have the full development environment to work on Agent Zero.
-
-
-
-
-
-
-### Conclusion
-After following the instructions for your specific operating system, you should have Agent Zero successfully installed and running. You can now start exploring the framework's capabilities and experimenting with creating your own intelligent agents.
-
-If you encounter any issues during the installation process, please consult the [Troubleshooting section](troubleshooting.md) of this documentation or refer to the Agent Zero [Skool](https://www.skool.com/agent-zero) or [Discord](https://discord.gg/B8KZKNsPpj) community for assistance.
-
diff --git a/instruments/custom/.gitkeep b/knowledge/main/.gitkeep
similarity index 100%
rename from instruments/custom/.gitkeep
rename to knowledge/main/.gitkeep
diff --git a/knowledge/main/about/github_readme.md b/knowledge/main/about/github_readme.md
new file mode 100644
index 0000000000..aca76272ae
--- /dev/null
+++ b/knowledge/main/about/github_readme.md
@@ -0,0 +1,392 @@
+
+
+# `Agent Zero`
+
+
+
+
+
+[](https://agent-zero.ai) [](https://github.com/sponsors/agent0ai) [](https://x.com/Agent0ai) [](https://discord.gg/B8KZKNsPpj) [](https://www.youtube.com/@AgentZeroFW) [](https://www.linkedin.com/in/jan-tomasek/) [](https://warpcast.com/agent-zero)
+
+
+## Documentation:
+
+[Introduction](#a-personal-organic-agentic-framework-that-grows-and-learns-with-you) •
+[Installation](./docs/setup/installation.md) •
+[How to update](./docs/setup/installation.md#how-to-update-agent-zero)
+[Development Setup](./docs/setup/dev-setup.md) •
+[Usage](./docs/guides/usage.md)
+
+Or see DeepWiki generated documentation:
+
+[](https://deepwiki.com/agent0ai/agent-zero)
+
+
+
+
+
+
+> ### 🚨 **AGENT ZERO SKILLS** 🚨
+> **Skills System** - portable, structured agent capabilities using the open `SKILL.md` standard (compatible with Claude Code, Codex and more).
+>
+> **Plus:** Git-based Projects with authentication for public/private repositories - clone codebases directly into isolated workspaces.
+>
+> See [Usage Guide](./docs/guides/usage.md) and [Projects Tutorial](./docs/guides/projects.md) to get started.
+
+
+
+
+[](https://youtu.be/lazLNcEYsiQ)
+
+
+## A personal, organic agentic framework that grows and learns with you
+
+
+
+- Agent Zero is not a predefined agentic framework. It is designed to be dynamic, organically growing, and learning as you use it.
+- Agent Zero is fully transparent, readable, comprehensible, customizable, and interactive.
+- Agent Zero uses the computer as a tool to accomplish its (your) tasks.
+
+# ⚙️ Installation
+
+Click to open a video to learn how to install Agent Zero:
+
+[](https://www.youtube.com/watch?v=w5v5Kjx51hs)
+
+A detailed setup guide for Windows, macOS, and Linux with a video can be found in the Agent Zero Documentation at [this page](./docs/setup/installation.md).
+
+### ⚡ Quick Start
+
+```bash
+# Pull and run with Docker
+
+docker pull agent0ai/agent-zero
+docker run -p 50001:80 agent0ai/agent-zero
+
+# Visit http://localhost:50001 to start
+```
+
+
+# 💡 Key Features
+
+1. **General-purpose Assistant**
+
+- Agent Zero is not pre-programmed for specific tasks (but can be). It is meant to be a general-purpose personal assistant. Give it a task, and it will gather information, execute commands and code, cooperate with other agent instances, and do its best to accomplish it.
+- It has a persistent memory, allowing it to memorize previous solutions, code, facts, instructions, etc., to solve tasks faster and more reliably in the future.
+
+
+
+2. **Computer as a Tool**
+
+- Agent Zero uses the operating system as a tool to accomplish its tasks. It has no single-purpose tools pre-programmed. Instead, it can write its own code and use the terminal to create and use its own tools as needed.
+- The only default tools in its arsenal are online search, memory features, communication (with the user and other agents), and code/terminal execution. Everything else is created by the agent itself or can be extended by the user.
+- Tool usage functionality has been developed from scratch to be the most compatible and reliable, even with very small models.
+- **Default Tools:** Agent Zero includes tools like knowledge, code execution, and communication.
+- **Creating Custom Tools:** Extend Agent Zero's functionality by creating your own custom tools.
+- **Skills (SKILL.md Standard):** Skills are contextual expertise loaded dynamically when relevant. They use the open SKILL.md standard (developed by Anthropic), making them compatible with Claude Code, Cursor, Goose, OpenAI Codex CLI, and GitHub Copilot.
+
+3. **Multi-agent Cooperation**
+
+- Every agent has a superior agent giving it tasks and instructions. Every agent then reports back to its superior.
+- In the case of the first agent in the chain (Agent 0), the superior is the human user; the agent sees no difference.
+- Every agent can create its subordinate agent to help break down and solve subtasks. This helps all agents keep their context clean and focused.
+
+
+
+4. **Completely Customizable and Extensible**
+
+- Almost nothing in this framework is hard-coded. Nothing is hidden. Everything can be extended or changed by the user.
+- The whole behavior is defined by a system prompt in the **prompts/default/agent.system.md** file. Change this prompt and change the framework dramatically.
+- The framework does not guide or limit the agent in any way. There are no hard-coded rails that agents have to follow.
+- Every prompt, every small message template sent to the agent in its communication loop can be found in the **prompts/** folder and changed.
+- Every default tool can be found in the **python/tools/** folder and changed or copied to create new predefined tools.
+- **Automated configuration** via `A0_SET_` environment variables for deployment automation and easy setup.
+
+
+
+5. **Communication is Key**
+
+- Give your agent a proper system prompt and instructions, and it can do miracles.
+- Agents can communicate with their superiors and subordinates, asking questions, giving instructions, and providing guidance. Instruct your agents in the system prompt on how to communicate effectively.
+- The terminal interface is real-time streamed and interactive. You can stop and intervene at any point. If you see your agent heading in the wrong direction, just stop and tell it right away.
+- There is a lot of freedom in this framework. You can instruct your agents to regularly report back to superiors asking for permission to continue. You can instruct them to use point-scoring systems when deciding when to delegate subtasks. Superiors can double-check subordinates' results and dispute. The possibilities are endless.
+
+## 🚀 Real-world use cases
+
+- **Financial Analysis & Charting** - `"Find last month's Bitcoin/USD price trend, correlate with major cryptocurrency news events, generate annotated chart with highlighted key dates"`
+
+- **Excel Automation Pipeline** - `"Scan incoming directory for financial spreadsheets, validate and clean data, consolidate from multiple sources, generate executive reports with flagged anomalies"`
+
+- **API Integration Without Code** - `"Use this Google Gemini API snippet to generate product images, remember the integration for future use"` - agent learns and stores the solution in memory
+
+- **Automated Server Monitoring** - `"Check server status every 30 minutes: CPU usage, disk space, memory. Alert if metrics exceed thresholds"` (scheduled task with project-scoped credentials)
+
+- **Multi-Client Project Isolation** - Separate projects for each client with isolated memory, custom instructions, and dedicated secrets - prevents context bleed across sensitive work
+
+## 🐳 Fully Dockerized, with Speech-to-Text and TTS
+
+
+
+- Customizable settings allow users to tailor the agent's behavior and responses to their needs.
+- The Web UI output is very clean, fluid, colorful, readable, and interactive; nothing is hidden.
+- You can load or save chats directly within the Web UI.
+- The same output you see in the terminal is automatically saved to an HTML file in **logs/** folder for every session.
+
+
+
+- Agent output is streamed in real-time, allowing users to read along and intervene at any time.
+- No coding is required; only prompting and communication skills are necessary.
+- With a solid system prompt, the framework is reliable even with small models, including precise tool usage.
+
+## 👀 Keep in Mind
+
+1. **Agent Zero Can Be Dangerous!**
+
+- With proper instruction, Agent Zero is capable of many things, even potentially dangerous actions concerning your computer, data, or accounts. Always run Agent Zero in an isolated environment (like Docker) and be careful what you wish for.
+
+2. **Agent Zero Is Prompt-based.**
+
+- The whole framework is guided by the **prompts/** folder. Agent guidelines, tool instructions, messages, utility AI functions, it's all there.
+
+
+## 📚 Read the Documentation
+
+| Page | Description |
+|-------|-------------|
+| [Installation](./docs/setup/installation.md) | Installation, setup and configuration |
+| [Usage](./docs/guides/usage.md) | Basic and advanced usage |
+| [Guides](./docs/guides/) | Step-by-step guides: Usage, Projects, API Integration, MCP Setup, A2A Setup |
+| [Development Setup](./docs/setup/dev-setup.md) | Development and customization |
+| [WebSocket Infrastructure](./docs/developer/websockets.md) | Real-time WebSocket handlers, client APIs, filtering semantics, envelopes |
+| [Extensions](./docs/developer/extensions.md) | Extending Agent Zero |
+| [Connectivity](./docs/developer/connectivity.md) | External API endpoints, MCP server connections, A2A protocol |
+| [Architecture](./docs/developer/architecture.md) | System design and components |
+| [Contributing](./docs/guides/contribution.md) | How to contribute |
+| [Troubleshooting](./docs/guides/troubleshooting.md) | Common issues and their solutions |
+
+
+## 🎯 Changelog
+
+### v0.9.8 - Skills, UI Redesign & Git projects
+[Release video](https://youtu.be/NV7s78yn6DY)
+
+- Skills
+ - Skills System replacing the legacy Instruments with a new `SKILL.md` standard for structured, portable agent capabilities.
+ - Built-in skills, and UI support for importing and listing skills
+- Real-time WebSocket infrastructure replacing the polling-based approach for UI state synchronization
+- UI Redesign
+ - Process groups to visually group agent actions with expand/collapse support
+ - Timestamps, steps count and execution time with tool-specific badges
+ - Step detail modals with key-value and raw JSON display
+ - Collapsible responses with show more/less and copy buttons on code blocks and tables
+ - Message queue system allowing users to queue messages while the agent is still processing
+ - In-browser file editor for viewing and editing files without leaving the UI
+ - Welcome screen redesign with info and warning banners for connection security, missing API keys, and system resources
+ - Scheduler redesign with standalone modal, separate task list, detail and editor components, and project support
+ - Smooth response rendering and scroll stabilization across chat, terminals, and image viewer
+ - Chat width setting and reworked preferences panel
+ - Image viewer improvements with scroll support and expanded viewer
+ - Redesigned sidebar with reusable dropdown component and streamlined buttons
+ - Inline button confirmations for critical actions
+ - Improved login design and new logout button
+ - File browser enhanced with rename and file actions dropdown
+- Git projects
+ - Git-based projects with clone authentication for public and private repositories
+- Four new LLM providers: CometAPI, Z.AI, Moonshot AI, and AWS Bedrock
+- Microsoft Dev Tunnels integration for secure remote access
+- User data migration to `/usr` directory for cleaner separation of user and system files
+- Subagents system with configurable agent profiles for different roles
+- Memory operations offloaded to deferred tasks for better performance
+- Environment variables can now configure settings via `A0_SET_*` prefix in `.env`
+- Automatic migration with overwrite support for `.env`, scheduler, knowledge, and legacy directories
+- Projects support extended to MCP, A2A, and external API
+- Workdir outside project support for more flexible file organization
+- Agent number tracking in backend and responses for multi-agent identification
+- Many bug fixes and stability improvements across the UI, MCP tools, scheduler, uploads, and WebSocket handling
+
+
+### v0.9.7 - Projects
+[Release video](https://youtu.be/RrTDp_v9V1c)
+- Projects management
+ - Support for custom instructions
+ - Integration with memory, knowledge, files
+ - Project specific secrets
+- New Welcome screen/Dashboard
+- New Wait tool
+- Subordinate agent configuration override support
+- Support for multiple documents at once in document_query_tool
+- Improved context on interventions
+- Openrouter embedding support
+- Frontend components refactor and polishing
+- SSH metadata output fix
+- Support for windows powershell in local TTY utility
+- More efficient selective streaming for LLMs
+- UI output length limit improvements
+
+### v0.9.6 - Memory Dashboard
+[Release video](https://youtu.be/sizjAq2-d9s)
+- Memory Management Dashboard
+- Kali update
+- Python update + dual installation
+- Browser Use update
+- New login screen
+- LiteLLM retry on temporary errors
+- Github Copilot provider support
+
+### v0.9.5 - Secrets
+[Release video](https://www.youtube.com/watch?v=VqxUdt7pjd8)
+- Secrets management - agent can use credentials without seeing them
+- Agent can copy paste messages and files without rewriting them
+- LiteLLM global configuration field
+- Custom HTTP headers field for browser agent
+- Progressive web app support
+- Extra model params support for JSON
+- Short IDs for files and memories to prevent LLM errors
+- Tunnel component frontend rework
+- Fix for timezone change bug
+- Notifications z-index fix
+
+### v0.9.4 - Connectivity, UI
+[Release video](https://www.youtube.com/watch?v=C2BAdDOduIc)
+- External API endpoints
+- Streamable HTTP MCP A0 server
+- A2A (Agent to Agent) protocol - server+client
+- New notifications system
+- New local terminal interface for stability
+- Rate limiter integration to models
+- Delayed memory recall
+- Smarter autoscrolling in UI
+- Action buttons in messages
+- Multiple API keys support
+- Download streaming
+- Tunnel URL QR code
+- Internal fixes and optimizations
+
+### v0.9.3 - Subordinates, memory, providers Latest
+[Release video](https://www.youtube.com/watch?v=-LfejFWL34k)
+- Faster startup/restart
+- Subordinate agents can have dedicated prompts, tools and system extensions
+- Streamable HTTP MCP server support
+- Memory loading enhanced by AI filter
+- Memory AI consolidation when saving memories
+- Auto memory system configuration in settings
+- LLM providers available are set by providers.yaml configuration file
+- Venice.ai LLM provider supported
+- Initial agent message for user + as example for LLM
+- Docker build support for local images
+- File browser fix
+
+### v0.9.2 - Kokoro TTS, Attachments
+[Release video](https://www.youtube.com/watch?v=sPot_CAX62I)
+
+- Kokoro text-to-speech integration
+- New message attachments system
+- Minor updates: log truncation, hyperlink targets, component examples, api cleanup
+
+### v0.9.1 - LiteLLM, UI improvements
+[Release video](https://youtu.be/crwr0M4Spcg)
+- Langchain replaced with LiteLLM
+ - Support for reasoning models streaming
+ - Support for more providers
+ - Openrouter set as default instead of OpenAI
+- UI improvements
+ - New message grouping system
+ - Communication smoother and more efficient
+ - Collapsible messages by type
+ - Code execution tool output improved
+ - Tables and code blocks scrollable
+ - More space efficient on mobile
+- Streamable HTTP MCP servers support
+- LLM API URL added to models config for Azure, local and custom providers
+
+### v0.9.0 - Agent roles, backup/restore
+[Release video](https://www.youtube.com/watch?v=rMIe-TC6H-k)
+- subordinate agents can use prompt profiles for different roles
+- backup/restore functionality for easier upgrades
+- security and bug fixes
+
+### v0.8.7 - Formatting, Document RAG Latest
+[Release video](https://youtu.be/OQJkfofYbus)
+- markdown rendering in responses
+- live response rendering
+- document Q&A tool
+
+### v0.8.6 - Merge and update
+[Release video](https://youtu.be/l0qpK3Wt65A)
+- Merge with Hacking Edition
+- browser-use upgrade and integration re-work
+- tunnel provider switch
+
+### v0.8.5 - **MCP Server + Client**
+[Release video](https://youtu.be/pM5f4Vz3_IQ)
+
+- Agent Zero can now act as MCP Server
+- Agent Zero can use external MCP servers as tools
+
+### v0.8.4.1 - 2
+Default models set to gpt-4.1
+- Code execution tool improvements
+- Browser agent improvements
+- Memory improvements
+- Various bugfixes related to context management
+- Message formatting improvements
+- Scheduler improvements
+- New model provider
+- Input tool fix
+- Compatibility and stability improvements
+
+### v0.8.4
+[Release video](https://youtu.be/QBh_h_D_E24)
+
+- **Remote access (mobile)**
+
+### v0.8.3.1
+[Release video](https://youtu.be/AGNpQ3_GxFQ)
+
+- **Automatic embedding**
+
+### v0.8.3
+[Release video](https://youtu.be/bPIZo0poalY)
+
+- ***Planning and scheduling***
+
+### v0.8.2
+[Release video](https://youtu.be/xMUNynQ9x6Y)
+
+- **Multitasking in terminal**
+- **Chat names**
+
+### v0.8.1
+[Release video](https://youtu.be/quv145buW74)
+
+- **Browser Agent**
+- **UX Improvements**
+
+### v0.8
+[Release video](https://youtu.be/cHDCCSr1YRI)
+
+- **Docker Runtime**
+- **New Messages History and Summarization System**
+- **Agent Behavior Change and Management**
+- **Text-to-Speech (TTS) and Speech-to-Text (STT)**
+- **Settings Page in Web UI**
+- **SearXNG Integration Replacing Perplexity + DuckDuckGo**
+- **File Browser Functionality**
+- **KaTeX Math Visualization Support**
+- **In-chat File Attachments**
+
+### v0.7
+[Release video](https://youtu.be/U_Gl0NPalKA)
+
+- **Automatic Memory**
+- **UI Improvements**
+- **Instruments**
+- **Extensions Framework**
+- **Reflection Prompts**
+- **Bug Fixes**
+
+## 🤝 Community and Support
+
+- [Join our Discord](https://discord.gg/B8KZKNsPpj) for live discussions or [visit our Skool Community](https://www.skool.com/agent-zero).
+- [Follow our YouTube channel](https://www.youtube.com/@AgentZeroFW) for hands-on explanations and tutorials
+- [Report Issues](https://github.com/agent0ai/agent-zero/issues) for bug fixes and features
diff --git a/knowledge/main/about/installation.md b/knowledge/main/about/installation.md
new file mode 100644
index 0000000000..f6e84809f2
--- /dev/null
+++ b/knowledge/main/about/installation.md
@@ -0,0 +1,585 @@
+# Installation Guide
+
+Click to open a video to learn how to install Agent Zero:
+
+[](https://www.youtube.com/watch?v=w5v5Kjx51hs)
+
+## **Goal:** Go from zero to a first working chat with minimal setup.
+
+
+## Step 1: Install Docker Desktop
+
+Docker Desktop provides the runtime environment for Agent Zero, ensuring consistent behavior and security across platforms. The entire framework runs within a Docker container, providing isolation and easy deployment.
+
+**Choose your operating system:**
+
+
+
+---
+
+
+## Windows Installation
+
+**1.1. Download Docker Desktop**
+
+Go to the [Docker Desktop download page](https://www.docker.com/products/docker-desktop/) and download the Windows version (Intel/AMD is the main download button).
+
+
+
+
+**1.2. Run the Installer**
+
+Run the installer with default settings.
+
+
+
+
+
+**1.3. Launch Docker Desktop**
+
+Once installed, launch Docker Desktop from your Start menu or desktop shortcut.
+
+
+
+✅ **Docker is now installed!**
+
+### Continue to [Step 2: Run Agent Zero](#step-2-run-agent-zero)
+
+---
+
+
+## macOS Installation
+
+**1.1. Download Docker Desktop**
+
+Go to the [Docker Desktop download page](https://www.docker.com/products/docker-desktop/) and download the macOS version (choose Apple Silicon or Intel based on your Mac).
+
+
+
+
+**1.2. Install Docker Desktop**
+
+Drag and drop the Docker application to your Applications folder.
+
+
+
+
+**1.3. Launch Docker Desktop**
+
+Open Docker Desktop from your Applications folder.
+
+
+
+
+**1.4. Configure Docker Socket**
+
+> [!NOTE]
+> **Important macOS Configuration:** In Docker Desktop's preferences (Docker menu) → Settings → Advanced, enable "Allow the default Docker socket to be used (requires password)."
+
+
+
+✅ **Docker is now installed!**
+
+### Continue to [Step 2: Run Agent Zero](#step-2-run-agent-zero)
+
+---
+
+
+## Linux Installation
+
+**1.1. Choose Installation Method**
+
+You can install either Docker Desktop or docker-ce (Community Edition).
+
+**Option A: Docker Desktop (Recommended for beginners)**
+
+Follow the instructions for your specific Linux distribution [here](https://docs.docker.com/desktop/install/linux-install/).
+
+**Option B: docker-ce (Lightweight alternative)**
+
+Follow the installation instructions [here](https://docs.docker.com/engine/install/).
+
+**1.2. Post-Installation Steps (docker-ce only)**
+
+If you installed docker-ce, add your user to the `docker` group:
+
+```bash
+sudo usermod -aG docker $USER
+```
+
+Log out and back in, then authenticate:
+
+```bash
+docker login
+```
+
+**1.3. Launch Docker**
+
+If you installed Docker Desktop, launch it from your applications menu.
+
+✅ **Docker is now installed!**
+
+> [!TIP]
+> **Deploying on a VPS/Server?** For production deployments with reverse proxy, SSL, and domain configuration, see the [VPS Deployment Guide](vps-deployment.md).
+
+---
+
+## Step 2: Run Agent Zero
+
+### 2.1. Pull the Agent Zero Docker Image
+
+**Using Docker Desktop GUI:**
+
+- Search for `agent0ai/agent-zero` in Docker Desktop
+- Click the `Pull` button
+- The image will be downloaded to your machine in a few minutes
+
+
+
+**Using Terminal:**
+
+```bash
+docker pull agent0ai/agent-zero
+```
+
+### 2.2. (Optional) Map Folders for Persistence
+
+Choose or create a folder on your computer where Agent Zero will save its data.
+
+### Setting up persistence is needed only if you want your data and files to remain available even after you delete the container.
+
+You can pick any location you find convenient:
+
+- **Windows:** `C:\agent-zero-data`
+- **macOS/Linux:** `/home/user/agent-zero-data`
+
+You can map just the `/a0/usr` directory (recommended) or individual subfolders of `/a0` to a local directory.
+
+> [!CAUTION]
+> Do **not** map the entire `/a0` directory: it contains the application code and can break upgrades.
+
+> [!TIP]
+> Choose a location that's easy to access and backup. All your Agent Zero data will be directly accessible in this directory.
+
+### 2.3. Run the Container
+
+**Using Docker Desktop GUI:**
+
+- In Docker Desktop, go to the "Images" tab
+- Click the `Run` button next to the `agent0ai/agent-zero` image
+- Open the "Optional settings" menu
+- **Ensure at least one host port is mapped to container port `80`** (set host port to `0` for automatic assignment)
+- Click the `Run` button
+
+
+
+
+The container will start and show in the "Containers" tab:
+
+
+
+### 2.4. Access the Web UI
+
+The framework will take a few seconds to initialize. Find the mapped port in Docker Desktop (shown as `:80`) or click the port right under the container ID:
+
+
+
+Open `http://localhost:` in your browser. The Web UI will open - Agent Zero is ready for configuration!
+
+
+
+> [!TIP]
+> You can also access the Web UI by clicking the port link directly under the container ID in Docker Desktop.
+
+> [!NOTE]
+> After starting the container, you'll find all Agent Zero files in your chosen directory. You can access and edit these files directly on your machine, and the changes will be immediately reflected in the running container.
+
+**Running A0 using Terminal?**
+
+```bash
+docker run -p 0:80 -v /path/to/your/work_dir:/a0/usr agent0ai/agent-zero
+```
+
+- Replace `0` with a fixed port if you prefer (e.g., `50080:80`)
+
+---
+
+## Step 3: Configure Agent Zero
+
+The UI will show a warning banner "Missing LLM API Key for current settings". Click on `Add your API key` to enter Settings and start configuring A0.
+
+### Settings Configuration
+
+Agent Zero provides a comprehensive settings interface to customize various aspects of its functionality. Access the settings by clicking the "Settings" button with a gear icon in the sidebar.
+
+### Agent Configuration
+
+- **Agent Profile:** Select the agent profile (e.g., `agent0`, `hacker`, `researcher`). Profiles can override prompts, tools, and extensions.
+- **Memory Subdirectory:** Select the subdirectory for agent memory storage, allowing separation between different instances.
+- **Knowledge Subdirectory:** Specify the location of custom knowledge files to enhance the agent's understanding.
+
+> [!NOTE]
+> Since v0.9.7, custom prompts belong in `/a0/agents//prompts/` rather than a shared `/prompts` folder. See the [Extensions guide](../developer/extensions.md#prompts) for details.
+
+> [!NOTE]
+> The Hacker profile is included in the main image. After launch, choose the **hacker** agent profile in Settings if you want the security-focused prompts and tooling. The "hacker" branch is deprecated.
+
+
+
+### Chat Model Settings
+
+- **Provider:** Select the chat model provider (e.g., Anthropic)
+- **Model Name:** Choose the specific model (e.g., claude-sonnet-4-5)
+- **Context Length:** Set the maximum token limit for context window
+- **Context Window Space:** Configure how much of the context window is dedicated to chat history
+
+
+
+**Model naming is provider-specific.**
+
+Use `claude-sonnet-4-5` for Anthropic, but use `anthropic/claude-sonnet-4-5` for OpenRouter. If you see "Invalid model ID," verify the provider and naming format on the provider website, or search the web for " model naming".
+
+> [!TIP]
+> **Context window tuning:** Set the total context window size first (for example, 100k), then adjust the chat history portion as a fraction of that total. A large fraction on a very large context window can still be enormous.
+
+> [!TIP]
+> **API URL:** URL of the API endpoint for the chat model - only needed for some providers like Ollama, LM Studio, Azure, etc.
+
+### Utility Model Configuration
+
+- **Provider & Model:** Select a model for utility tasks like memory organization and summarization
+- **Temperature:** Adjust the determinism of utility responses
+
+> [!NOTE]
+> Utility models need to be strong enough to extract and consolidate memory reliably. Very small models (e.g., 4B) often fail at this; 70B-class models or high-quality cloud "flash/mini" models work best.
+
+### Embedding Model Settings [Optional]
+
+- **Provider:** Choose the embedding model provider (e.g., OpenAI)
+- **Model Name:** Select the specific embedding model (e.g., text-embedding-3-small)
+
+> [!NOTE]
+> Agent Zero uses a local embedding model by default (runs on CPU), but you can switch to OpenAI embeddings like `text-embedding-3-small` or `text-embedding-3-large` if preferred.
+
+### Speech to Text Options
+
+- **Model Size:** Choose the speech recognition model size
+- **Language Code:** Set the primary language for voice recognition
+- **Silence Settings:** Configure silence threshold, duration, and timeout parameters for voice input
+
+### API Keys
+
+Configure API keys for various service providers directly within the Web UI. Click `Save` to confirm your settings.
+
+> [!NOTE]
+> **OpenAI API vs Plus subscription:** A ChatGPT Plus subscription does not include API credits. You must provide a separate API key for OpenAI usage in Agent Zero.
+
+> [!TIP]
+> For OpenAI-compatible providers (e.g., custom gateways or Z.AI/GLM), add the API key under **External Services → Other OpenAI-compatible API keys**, then select **OpenAI Compatible** as the provider in model settings.
+
+> [!CAUTION]
+> **GitHub Copilot Provider:** When using the GitHub Copilot provider, after selecting the model and entering your first prompt, the OAuth login procedure will begin. You'll find the authentication code and link in the output logs. Complete the authentication process by following the provided link and entering the code, then you may continue using Agent Zero.
+
+### Authentication
+
+- **UI Login:** Set username for web interface access
+- **UI Password:** Configure password for web interface security
+- **Root Password:** Manage Docker container root password for SSH access
+
+
+
+### Development Settings
+
+- **RFC Parameters (local instances only):** Configure URLs and ports for remote function calls between instances
+- **RFC Password:** Configure password for remote function calls
+
+Learn more about Remote Function Calls in the [Development Setup guide](dev-setup.md#step-6-configure-ssh-and-rfc-connection).
+
+> [!IMPORTANT]
+> Always keep your API keys and passwords secure.
+
+> [!NOTE]
+> On Windows host installs (non-Docker), you must use RFC to run shell code on the host system. The Docker runtime handles this automatically.
+
+---
+
+## Choosing Your LLMs
+
+The Settings page is the control center for selecting the Large Language Models (LLMs) that power Agent Zero. You can choose different LLMs for different roles:
+
+| LLM Role | Description |
+| --- | --- |
+| `chat_llm` | This is the primary LLM used for conversations and generating responses. |
+| `utility_llm` | This LLM handles internal tasks like summarizing messages, managing memory, and processing internal prompts. Using a smaller, less expensive model here can improve efficiency. |
+| `browser_llm` | This LLM powers the browser agent for web navigation and interaction tasks. Vision support is recommended for better page understanding. |
+| `embedding_llm` | The embedding model shipped with A0 runs on CPU and is responsible for generating embeddings used for memory retrieval and knowledge base lookups. Changing the `embedding_llm` will re-index all of A0's memory. |
+
+**How to Change:**
+
+1. Open Settings page in the Web UI.
+2. Choose the provider for the LLM for each role (Chat model, Utility model, Browser model, Embedding model) and write the model name.
+3. Click "Save" to apply the changes.
+
+### Important Considerations
+
+#### Model Naming by Provider
+
+Use the naming format required by your selected provider:
+
+| Provider | Model Name Format | Example |
+| --- | --- | --- |
+| OpenAI | Model name only | `claude-sonnet-4-5` |
+| OpenRouter | Provider prefix mostly required | `anthropic/claude-sonnet-4-5` |
+| Ollama | Model name only | `gpt-oss:20b` |
+
+> [!TIP]
+> If you see "Invalid model ID," verify the provider and naming format on the provider website, or search the web for " model naming".
+
+#### Context Window & Memory Split
+
+- Set the **total context window** (e.g., 100k) first.
+- Then tune the **chat history portion** as a fraction of that total.
+- Extremely large totals can make even small fractions very large; adjust thoughtfully.
+
+#### Utility Model Guidance
+
+- Utility models handle summarization and memory extraction.
+- Very small models (≈4B) usually fail at reliable context extraction.
+- Aim for ~70B class models or strong cloud "flash/mini" models for better results.
+
+#### Reasoning/Thinking Models
+
+- Reasoning can increase cost and latency. Some models perform better **without** reasoning.
+- If a model supports it, disable reasoning via provider-specific parameters (e.g., Venice `disable_thinking=true`).
+
+---
+
+## Installing and Using Ollama (Local Models)
+
+Ollama is a powerful tool that allows you to run various large language models locally.
+
+---
+
+
+### Windows Ollama Installation
+
+Download and install Ollama from the official website:
+
+
+
+Once installed, continue to [Pulling Models](#pulling-models).
+
+---
+
+
+### macOS Ollama Installation
+
+**Using Homebrew:**
+
+```bash
+brew install ollama
+```
+
+**Using Installer:**
+
+Download from the [official website](https://ollama.com/).
+
+Once installed, continue to [Pulling Models](#pulling-models).
+
+---
+
+
+### Linux Ollama Installation
+
+Run the installation script:
+
+```bash
+curl -fsSL https://ollama.com/install.sh | sh
+```
+
+Once installed, continue to [Pulling Models](#pulling-models).
+
+---
+
+### Pulling Models
+
+**Finding Model Names:**
+
+Visit the [Ollama model library](https://ollama.com/library) for a list of available models and their corresponding names. Ollama models are referenced by **model name only** (for example, `llama3.2`).
+
+**Pull a model:**
+
+```bash
+ollama pull
+```
+
+Replace `` with the name of the model you want to use. For example: `ollama pull mistral-large`
+
+### Configuring Ollama in Agent Zero
+
+1. Once you've downloaded your model(s), select it in the Settings page of the GUI.
+2. Within the Chat model, Utility model, or Embedding model section, choose **Ollama** as provider.
+3. Write your model code as expected by Ollama, in the format `llama3.2` or `qwen2.5:7b`
+4. Provide your API base URL to your Ollama API endpoint, usually `http://host.docker.internal:11434`
+5. Click `Save` to confirm your settings.
+
+
+
+> [!NOTE]
+> If Agent Zero runs in Docker and Ollama runs on the host, ensure port **11434** is reachable from the container. If both services are in the same Docker network, you can use `http://:11434` instead of `host.docker.internal`.
+
+### Managing Downloaded Models
+
+**Listing downloaded models:**
+
+```bash
+ollama list
+```
+
+**Removing a model:**
+
+```bash
+ollama rm
+```
+
+> [!TIP]
+> Experiment with different model combinations to find the balance of performance and cost that best suits your needs. E.g., faster and lower latency LLMs will help, and you can also use `faiss_gpu` instead of `faiss_cpu` for the memory.
+
+---
+
+## How to Update Agent Zero
+
+> [!NOTE]
+> Since v0.9, Agent Zero includes a Backup & Restore workflow in the Settings UI. This is the **safest** way to upgrade Docker instances.
+
+### Recommended Update Process (Docker)
+
+1. **Keep the old container running** and note its port.
+2. **Pull the new image** (`agent0ai/agent-zero:latest`).
+3. **Start a new container** on a different host port.
+4. In the **old** instance, open **Settings → Backup & Restore** and create a backup.
+5. In the **new** instance, restore that backup from the same panel.
+
+> [!TIP]
+> If the new instance fails to load settings, remove `/a0/usr/settings.json` and restart to regenerate default settings.
+
+---
+
+## Using Agent Zero on Your Mobile Device
+
+Agent Zero can be accessed from mobile devices and other computers using the built-in **Tunnel feature**.
+
+### Recommended: Using Tunnel (Remote Access)
+
+The Tunnel feature allows secure access to your Agent Zero instance from anywhere:
+
+1. Open Settings in the Web UI
+2. Navigate to the **External Services** tab
+3. Click on **Flare Tunnel** in the navigation menu
+4. Click **Create Tunnel** to generate a secure HTTPS URL
+5. Share this URL to access Agent Zero from any device
+
+> [!IMPORTANT]
+> **Security:** Always set a username and password in Settings → Authentication before creating a tunnel to secure your instance on the internet.
+
+For complete details on tunnel configuration and security considerations, see the [Remote Access via Tunneling](../guides/usage.md#remote-access-via-tunneling) section in the Usage Guide.
+
+### Alternative: Local Network Access
+
+If you prefer to keep access limited to your local network:
+
+1. Find the mapped port in Docker Desktop (format: `:80`, e.g., `32771:80`)
+2. Access from the same computer: `http://localhost:`
+3. Access from other devices on the network: `http://:`
+
+> [!TIP]
+> Find your computer's IP address with `ipconfig` (Windows) or `ifconfig`/`ip addr` (macOS/Linux). It's usually in the format `192.168.x.x` or `10.0.x.x`.
+
+For developers or users who need to run Agent Zero directly on their system, see the [In-Depth Guide for Full Binaries Installation](dev-setup.md).
+
+---
+
+## Advanced: Automated Configuration via Environment Variables
+
+Agent Zero settings can be automatically configured using environment variables with the `A0_SET_` prefix in your `.env` file. This enables automated deployments without manual configuration.
+
+**Usage:**
+
+Add variables to your `.env` file in the format:
+
+```env
+A0_SET_{setting_name}={value}
+```
+
+**Examples:**
+
+```env
+# Model configuration
+A0_SET_chat_model_provider=anthropic
+A0_SET_chat_model_name=claude-3-5-sonnet-20241022
+A0_SET_chat_model_ctx_length=200000
+
+# Memory settings
+A0_SET_memory_recall_enabled=true
+A0_SET_memory_recall_interval=5
+
+# Agent configuration
+A0_SET_agent_profile=custom
+A0_SET_agent_memory_subdir=production
+```
+
+**Docker usage:**
+
+When running Docker, you can pass these as environment variables:
+
+```bash
+docker run -p 50080:80 \
+ -e A0_SET_chat_model_provider=anthropic \
+ -e A0_SET_chat_model_name=claude-3-5-sonnet-20241022 \
+ agent0ai/agent-zero
+```
+
+**Notes:**
+
+- These provide initial default values when settings.json doesn't exist or when new settings are added to the application. Once a value is saved in settings.json, it takes precedence over these environment variables.
+- Sensitive settings (API keys, passwords) use their existing environment variables
+- Container/process restart required for changes to take effect
+
+---
+
+### Manual Migration (Legacy or Non-Docker)
+
+If you are migrating from older, non-Docker setups, A0 handles the migration of legacy folders and files automatically at runtime. The right place to save your files and directories is `a0/usr`.
+
+## Conclusion
+
+After following the instructions for your specific operating system, you should have Agent Zero successfully installed and running. You can now start exploring the framework's capabilities and experimenting with creating your own intelligent agents.
+
+**Next Steps:**
+
+- For production server deployments, see the [VPS Deployment Guide](vps-deployment.md)
+- For development setup and extensions, see the [Development Setup Guide](dev-setup.md)
+- For remote access via tunnel, see [Remote Access via Tunneling](../guides/usage.md#remote-access-via-tunneling)
+
+If you encounter any issues during the installation process, please consult the [Troubleshooting section](../guides/troubleshooting.md) of this documentation or refer to the Agent Zero [Skool](https://www.skool.com/agent-zero) or [Discord](https://discord.gg/B8KZKNsPpj) community for assistance.
diff --git a/instruments/default/.gitkeep b/knowledge/solutions/.gitkeep
similarity index 100%
rename from instruments/default/.gitkeep
rename to knowledge/solutions/.gitkeep
diff --git a/models.py b/models.py
index fbc2694dfd..dcc19a26c2 100644
--- a/models.py
+++ b/models.py
@@ -22,7 +22,7 @@
from python.helpers import dotenv
from python.helpers import settings, dirty_json
from python.helpers.dotenv import load_dotenv
-from python.helpers.providers import get_provider_config
+from python.helpers.providers import ModelType as ProviderModelType, get_provider_config
from python.helpers.rate_limiter import RateLimiter
from python.helpers.tokens import approximate_tokens
from python.helpers import dirty_json, browser_use_monkeypatch
@@ -115,8 +115,8 @@ def add_chunk(self, chunk: ChatChunk) -> ChatChunk:
# if the model outputs thinking tags, we ned to parse them manually as reasoning
processed_chunk = self._process_thinking_chunk(chunk)
- self.reasoning += processed_chunk["reasoning_delta"]
- self.response += processed_chunk["response_delta"]
+ self.reasoning += processed_chunk.get("reasoning_delta", "")
+ self.response += processed_chunk.get("response_delta", "")
return processed_chunk
@@ -316,7 +316,7 @@ def __init__(
def _llm_type(self) -> str:
return "litellm-chat"
- def _convert_messages(self, messages: List[BaseMessage]) -> List[dict]:
+ def _convert_messages(self, messages: List[BaseMessage], explicit_caching: bool = False) -> List[dict]:
result = []
# Map LangChain message types to LiteLLM roles
role_mapping = {
@@ -361,7 +361,21 @@ def _convert_messages(self, messages: List[BaseMessage]) -> List[dict]:
if tool_call_id:
message_dict["tool_call_id"] = tool_call_id
+ # Skip messages with empty content
+ content = message_dict.get("content")
+ has_content = bool(content) if not isinstance(content, list) else len(content) > 0
+ if not has_content:
+ continue
result.append(message_dict)
+
+ if explicit_caching and result:
+ if result[0]["role"] == "system":
+ result[0]["cache_control"] = {"type": "ephemeral"}
+ for i in range(len(result) - 1, -1, -1):
+ if result[i]["role"] == "assistant":
+ result[i]["cache_control"] = {"type": "ephemeral"}
+ break
+
return result
def _call(
@@ -464,6 +478,7 @@ async def unified_call(
rate_limiter_callback: (
Callable[[str, str, int, int], Awaitable[bool]] | None
) = None,
+ explicit_caching: bool = False,
**kwargs: Any,
) -> Tuple[str, str]:
@@ -478,7 +493,7 @@ async def unified_call(
messages.append(HumanMessage(content=user_message))
# convert to litellm format
- msgs_conv = self._convert_messages(messages)
+ msgs_conv = self._convert_messages(messages, explicit_caching=explicit_caching)
# Apply rate limiting if configured
limiter = await apply_rate_limiter(
@@ -813,7 +828,7 @@ def _parse_chunk(chunk: Any) -> ChatChunk:
message.get("content", "")
if isinstance(message, dict)
else getattr(message, "content", "")
- )
+ ) or ""
reasoning_delta = (
delta.get("reasoning_content", "")
if isinstance(delta, dict)
@@ -822,7 +837,7 @@ def _parse_chunk(chunk: Any) -> ChatChunk:
message.get("reasoning_content", "")
if isinstance(message, dict)
else getattr(message, "reasoning_content", "")
- )
+ ) or ""
return ChatChunk(reasoning_delta=reasoning_delta, response_delta=response_delta)
@@ -844,7 +859,7 @@ def _adjust_call_args(provider_name: str, model_name: str, kwargs: dict):
def _merge_provider_defaults(
- provider_type: str, original_provider: str, kwargs: dict
+ provider_type: ProviderModelType, original_provider: str, kwargs: dict
) -> tuple[str, dict]:
# Normalize .env-style numeric strings (e.g., "timeout=30") into ints/floats for LiteLLM
def _normalize_values(values: dict) -> dict:
diff --git a/plugins/README.md b/plugins/README.md
new file mode 100644
index 0000000000..f2f1c21bea
--- /dev/null
+++ b/plugins/README.md
@@ -0,0 +1,67 @@
+# Agent Zero - Core Plugins
+
+This directory contains the system-level plugins bundled with Agent Zero.
+
+## Directory Structure
+
+- `plugins/`: Core system plugins. Reserved for framework updates — do not place custom plugins here.
+- `usr/plugins/`: The correct location for all user-developed and custom plugins. This directory is gitignored.
+
+## Documentation
+
+For detailed guides on how to create, extend, or configure plugins, refer to:
+
+- [`AGENTS.plugins.md`](../AGENTS.plugins.md): Full-stack plugin architecture, manifest format, extension points, and Plugin Index submission.
+- [`docs/developer/plugins.md`](../docs/developer/plugins.md): Human-facing developer guide covering the full plugin lifecycle.
+- [`AGENTS.md`](../AGENTS.md): Main framework guide and backend context.
+- [`skills/a0-create-plugin/SKILL.md`](../skills/a0-create-plugin/SKILL.md): Agent-facing authoring workflow (local and community plugins).
+
+## What a Plugin Can Provide
+
+Plugins are automatically discovered based on the presence of a `plugin.yaml` file. Each plugin can contribute:
+
+- **Backend**: API handlers, tools, helpers, and lifecycle extensions
+- **Frontend**: HTML/JS UI contributions via core extension breakpoints
+- **Settings**: Isolated configuration scoped per-project and per-agent profile
+- **Activation**: Global and scoped ON/OFF rules via `.toggle-1` and `.toggle-0` files, including advanced per-scope switching in the WebUI
+- **Agent profiles**: Plugin-distributed subagent definitions under `agents//agent.yaml`
+
+## Plugin Manifest
+
+Every plugin requires a `plugin.yaml` at its root:
+
+```yaml
+title: My Plugin
+description: What this plugin does.
+version: 1.0.0
+settings_sections:
+ - agent
+per_project_config: false
+per_agent_config: false
+always_enabled: false
+```
+
+## Plugin Index & Community Sharing
+
+The **Plugin Index** at https://github.com/agent0ai/a0-plugins is the community-maintained registry of plugins available to all Agent Zero users.
+
+To share a plugin with the community:
+
+1. Create a standalone GitHub repository with the plugin contents at the repo root and the runtime `plugin.yaml` there.
+2. Fork `https://github.com/agent0ai/a0-plugins` and add a folder `plugins//` containing a separate index `plugin.yaml`:
+
+```yaml
+title: My Plugin
+description: What this plugin does.
+github: https://github.com/yourname/your-plugin-repo
+tags:
+ - tools
+```
+
+3. Open a Pull Request. CI validates the submission; a maintainer reviews and merges.
+
+Note: The index `plugin.yaml` is a **different schema** from the runtime manifest — it contains only `title`, `description`, `github`, and optional `tags`. Do not mix them up.
+
+## Plugin Marketplace (Coming Soon)
+
+A built-in **Plugin Marketplace** (always-active plugin) is planned and will allow users to browse the Plugin Index and install community plugins directly from the Agent Zero UI.
diff --git a/plugins/chat_branching/api/branch_chat.py b/plugins/chat_branching/api/branch_chat.py
new file mode 100644
index 0000000000..16655856a3
--- /dev/null
+++ b/plugins/chat_branching/api/branch_chat.py
@@ -0,0 +1,75 @@
+from datetime import datetime
+
+from python.helpers.api import ApiHandler, Input, Output, Request, Response
+from python.helpers.persist_chat import (
+ _serialize_context,
+ _deserialize_context,
+ save_tmp_chat,
+)
+from agent import AgentContext
+
+
+class BranchChat(ApiHandler):
+ """Create a new chat branched from an existing chat at a specific log message."""
+
+ async def process(self, input: Input, request: Request) -> Output:
+ ctxid = input.get("context", "")
+ log_no = input.get("log_no") # LogItem.no from frontend
+
+ if not ctxid:
+ return Response("Missing context id", 400)
+ if log_no is None:
+ return Response("Missing log_no", 400)
+
+ context = AgentContext.get(ctxid)
+ if not context:
+ return Response("Context not found", 404)
+
+ # Serialize the source context
+ data = _serialize_context(context)
+
+ # Remove id so _deserialize_context generates a new one
+ del data["id"]
+
+ # Trim log entries: keep only items up to and including log_no.
+ # _serialize_log uses log.logs[-LOG_SIZE:], so the serialized "no"
+ # values may start above 0 for long chats. We match against the
+ # original "no" field that each LogItem.output() emits.
+ src_logs = data["log"]["logs"]
+ cut_idx = None
+ for i, item in enumerate(src_logs):
+ if item["no"] == log_no:
+ cut_idx = i
+ break
+
+ if cut_idx is None:
+ # Fallback: log_no might already be a 0-based index within the
+ # serialized array (e.g. after a reload where _deserialize_log
+ # resets "no" to sequential). Accept if within bounds.
+ if 0 <= log_no < len(src_logs):
+ cut_idx = log_no
+ else:
+ return Response("log_no not found in chat log", 400)
+
+ data["log"]["logs"] = src_logs[: cut_idx + 1]
+
+ # Give the branch a distinguishable name
+ src_name = data.get("name") or "Chat"
+ data["name"] = f"{src_name} (branch)"
+ data["created_at"] = datetime.now().isoformat()
+
+ # Deserialize into a brand-new context (new id, fresh agent config)
+ new_context = _deserialize_context(data)
+
+ # Persist immediately
+ save_tmp_chat(new_context)
+
+ # Notify all tabs
+ from python.helpers.state_monitor_integration import mark_dirty_all
+ mark_dirty_all(reason="plugins.chat_branching.BranchChat")
+
+ return {
+ "ok": True,
+ "ctxid": new_context.id,
+ "message": "Chat branched successfully.",
+ }
\ No newline at end of file
diff --git a/plugins/chat_branching/extensions/webui/set_messages_after_loop/inject-branch-buttons.js b/plugins/chat_branching/extensions/webui/set_messages_after_loop/inject-branch-buttons.js
new file mode 100644
index 0000000000..a0c2a31235
--- /dev/null
+++ b/plugins/chat_branching/extensions/webui/set_messages_after_loop/inject-branch-buttons.js
@@ -0,0 +1,32 @@
+// Chat Branching Plugin — injects a "branch" button into every message's action bar.
+// Uses the unified handler output: context.results[] = { args: { no, … }, result: { element, … } }
+
+import { createActionButton } from "/components/messages/action-buttons/simple-action-buttons.js";
+import { callJsonApi } from "/js/api.js";
+import { store as chatsStore } from "/components/sidebar/chats/chats-store.js";
+
+export default async function injectBranchButtons(context) {
+ if (!context?.results?.length) return;
+
+ for (const { args, result } of context.results) {
+ if (!result?.element || args.no == null) continue;
+
+ const logNo = args.no;
+ for (const bar of result.element.querySelectorAll(".step-action-buttons")) {
+ if (bar.querySelector(".action-fork_right")) continue;
+ bar.appendChild(
+ createActionButton("fork_right", "Branch chat", async () => {
+ const ctxid = globalThis.getContext?.();
+ if (!ctxid) throw new Error("No active chat");
+
+ const res = await callJsonApi("/plugins/chat_branching/branch_chat", {
+ context: ctxid,
+ log_no: logNo,
+ });
+ if (!res?.ok) throw new Error(res?.message || "Branch failed");
+ chatsStore.selectChat(res.ctxid);
+ }),
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/chat_branching/plugin.yaml b/plugins/chat_branching/plugin.yaml
new file mode 100644
index 0000000000..7ca67b2781
--- /dev/null
+++ b/plugins/chat_branching/plugin.yaml
@@ -0,0 +1,3 @@
+name: Chat Branching
+description: Branch a chat from any message, creating a new chat with history up to that point.
+version: 1.0.0
\ No newline at end of file
diff --git a/plugins/example_agent/agents/plugin_example/agent.yaml b/plugins/example_agent/agents/plugin_example/agent.yaml
new file mode 100644
index 0000000000..c624990ce2
--- /dev/null
+++ b/plugins/example_agent/agents/plugin_example/agent.yaml
@@ -0,0 +1,4 @@
+title: Plugin Example Agent
+description: This is an example agent profile loaded from the 'example_agent' plugin.
+context: You are an example agent provided by the 'example_agent' plugin. Your purpose
+ is to demonstrate how plugins can distribute agent profiles.
diff --git a/plugins/example_agent/agents/plugin_example/prompts/agent.system.plugin_example.md b/plugins/example_agent/agents/plugin_example/prompts/agent.system.plugin_example.md
new file mode 100644
index 0000000000..97fefe1a64
--- /dev/null
+++ b/plugins/example_agent/agents/plugin_example/prompts/agent.system.plugin_example.md
@@ -0,0 +1,3 @@
+You are the Example Plugin Agent.
+You were loaded from the `plugins/example_agent` directory.
+Your main goal is to demonstrate that agent profiles can be distributed via plugins.
diff --git a/plugins/example_agent/plugin.yaml b/plugins/example_agent/plugin.yaml
new file mode 100644
index 0000000000..bc5dad0e40
--- /dev/null
+++ b/plugins/example_agent/plugin.yaml
@@ -0,0 +1,7 @@
+title: Example Agent
+description: Example agent plugin demonstrating the Agent Zero plugin system.
+version: 1.0.0
+settings_sections: []
+per_project_config: true
+per_agent_config: false
+always_enabled: true
diff --git a/python/api/import_knowledge.py b/plugins/memory/api/import_knowledge.py
similarity index 76%
rename from python/api/import_knowledge.py
rename to plugins/memory/api/import_knowledge.py
index bfc25b6490..aa17114429 100644
--- a/python/api/import_knowledge.py
+++ b/plugins/memory/api/import_knowledge.py
@@ -1,7 +1,8 @@
from python.helpers.api import ApiHandler, Request, Response
-from python.helpers import files, memory
+from python.helpers import files
+from python.helpers.security import safe_filename
+from plugins.memory.helpers.memory import Memory, get_custom_knowledge_subdir_abs
import os
-from werkzeug.utils import secure_filename
class ImportKnowledge(ApiHandler):
@@ -16,7 +17,7 @@ async def process(self, input: dict, request: Request) -> dict | Response:
context = self.use_context(ctxid)
file_list = request.files.getlist("files[]")
- KNOWLEDGE_FOLDER = files.get_abs_path(memory.get_custom_knowledge_subdir_abs(context.agent0), "main")
+ KNOWLEDGE_FOLDER = files.get_abs_path(get_custom_knowledge_subdir_abs(context.agent0), "main")
# Ensure knowledge folder exists (create if missing)
try:
@@ -32,12 +33,14 @@ async def process(self, input: dict, request: Request) -> dict | Response:
for file in file_list:
if file and file.filename:
- filename = secure_filename(file.filename) # type: ignore
+ filename = safe_filename(file.filename)
+ if not filename:
+ continue
file.save(os.path.join(KNOWLEDGE_FOLDER, filename))
saved_filenames.append(filename)
#reload memory to re-import knowledge
- await memory.Memory.reload(context.agent0)
+ await Memory.reload(context.agent0)
context.log.set_initial_progress()
return {
diff --git a/python/api/knowledge_path_get.py b/plugins/memory/api/knowledge_path_get.py
similarity index 65%
rename from python/api/knowledge_path_get.py
rename to plugins/memory/api/knowledge_path_get.py
index dadf0a692b..64121449fd 100644
--- a/python/api/knowledge_path_get.py
+++ b/plugins/memory/api/knowledge_path_get.py
@@ -1,7 +1,6 @@
from python.helpers.api import ApiHandler, Request, Response
-from python.helpers import files, memory, notification, projects, notification
-import os
-from werkzeug.utils import secure_filename
+from python.helpers import files, projects
+from plugins.memory.helpers.memory import get_custom_knowledge_subdir_abs
class GetKnowledgePath(ApiHandler):
@@ -13,13 +12,13 @@ async def process(self, input: dict, request: Request) -> dict | Response:
project_name = projects.get_context_project_name(context)
if project_name:
- knowledge_folder = projects.get_project_meta_folder(project_name, "knowledge")
+ knowledge_folder = projects.get_project_meta(project_name, "knowledge")
else:
- knowledge_folder = memory.get_custom_knowledge_subdir_abs(context.agent0)
+ knowledge_folder = get_custom_knowledge_subdir_abs(context.agent0)
knowledge_folder = files.normalize_a0_path(knowledge_folder)
return {
"ok": True,
"path": knowledge_folder,
- }
\ No newline at end of file
+ }
diff --git a/python/api/knowledge_reindex.py b/plugins/memory/api/knowledge_reindex.py
similarity index 74%
rename from python/api/knowledge_reindex.py
rename to plugins/memory/api/knowledge_reindex.py
index b86eafeaf1..b8c0a8f453 100644
--- a/python/api/knowledge_reindex.py
+++ b/plugins/memory/api/knowledge_reindex.py
@@ -1,7 +1,5 @@
from python.helpers.api import ApiHandler, Request, Response
-from python.helpers import files, memory, notification, projects, notification
-import os
-from werkzeug.utils import secure_filename
+from plugins.memory.helpers.memory import Memory
class ReindexKnowledge(ApiHandler):
@@ -12,7 +10,7 @@ async def process(self, input: dict, request: Request) -> dict | Response:
context = self.use_context(ctxid)
# reload memory to re-import knowledge
- await memory.Memory.reload(context.agent0)
+ await Memory.reload(context.agent0)
context.log.set_initial_progress()
return {
diff --git a/python/api/memory_dashboard.py b/plugins/memory/api/memory_dashboard.py
similarity index 97%
rename from python/api/memory_dashboard.py
rename to plugins/memory/api/memory_dashboard.py
index d1275fe417..774319a493 100644
--- a/python/api/memory_dashboard.py
+++ b/plugins/memory/api/memory_dashboard.py
@@ -1,10 +1,17 @@
from python.helpers.api import ApiHandler, Request, Response
-from python.helpers.memory import Memory, get_existing_memory_subdirs, get_context_memory_subdir
from python.helpers import files
from models import ModelConfig, ModelType
from langchain_core.documents import Document
from agent import AgentContext
+# Import Memory functions from plugin
+import sys
+from pathlib import Path
+_plugin_root = Path(__file__).parent.parent
+if str(_plugin_root) not in sys.path:
+ sys.path.insert(0, str(_plugin_root))
+from helpers.memory import Memory, get_existing_memory_subdirs, get_context_memory_subdir
+
class MemoryDashboard(ApiHandler):
diff --git a/plugins/memory/default_config.yaml b/plugins/memory/default_config.yaml
new file mode 100644
index 0000000000..ff0562467e
--- /dev/null
+++ b/plugins/memory/default_config.yaml
@@ -0,0 +1,16 @@
+project_memory_isolation: true
+memory_recall_enabled: true
+memory_recall_delayed: false
+memory_recall_interval: 3
+memory_recall_history_len: 10000
+memory_recall_memories_max_search: 12
+memory_recall_solutions_max_search: 8
+memory_recall_memories_max_result: 5
+memory_recall_solutions_max_result: 3
+memory_recall_similarity_threshold: 0.7
+memory_recall_query_prep: false
+memory_recall_post_filter: false
+memory_memorize_enabled: true
+memory_memorize_consolidation: true
+memory_memorize_replace_threshold: 0.9
+agent_memory_subdir: default
\ No newline at end of file
diff --git a/plugins/memory/extensions/python/embedding_model_changed/_10_memory_reload.py b/plugins/memory/extensions/python/embedding_model_changed/_10_memory_reload.py
new file mode 100644
index 0000000000..db561d9b46
--- /dev/null
+++ b/plugins/memory/extensions/python/embedding_model_changed/_10_memory_reload.py
@@ -0,0 +1,10 @@
+from python.helpers.extension import Extension
+
+# Direct import - this extension lives inside the memory plugin
+from plugins.memory.helpers.memory import reload as memory_reload
+
+
+class MemoryReload(Extension):
+
+ async def execute(self, **kwargs):
+ memory_reload()
diff --git a/python/extensions/message_loop_prompts_after/_50_recall_memories.py b/plugins/memory/extensions/python/message_loop_prompts_after/_50_recall_memories.py
similarity index 86%
rename from python/extensions/message_loop_prompts_after/_50_recall_memories.py
rename to plugins/memory/extensions/python/message_loop_prompts_after/_50_recall_memories.py
index 6f95960b3f..ab8ec6ac26 100644
--- a/python/extensions/message_loop_prompts_after/_50_recall_memories.py
+++ b/plugins/memory/extensions/python/message_loop_prompts_after/_50_recall_memories.py
@@ -1,13 +1,16 @@
import asyncio
from python.helpers.extension import Extension
-from python.helpers.memory import Memory
from agent import LoopData
-from python.tools.memory_load import DEFAULT_THRESHOLD as DEFAULT_MEMORY_THRESHOLD
-from python.helpers import dirty_json, errors, settings, log
+from python.helpers import dirty_json, errors, log, plugins
+
+# Direct import - this extension lives inside the memory plugin
+from plugins.memory.helpers.memory import Memory
+from plugins.memory.tools.memory_load import DEFAULT_THRESHOLD as DEFAULT_MEMORY_THRESHOLD
DATA_NAME_TASK = "_recall_memories_task"
DATA_NAME_ITER = "_recall_memories_iter"
+SEARCH_TIMEOUT = 30
class RecallMemories(Extension):
@@ -22,11 +25,13 @@ class RecallMemories(Extension):
async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
- set = settings.get_settings()
+ set = plugins.get_plugin_config("memory", self.agent)
+ if not set:
+ return None
# turned off in settings?
if not set["memory_recall_enabled"]:
- return
+ return None
# every X iterations (or the first one) recall memories
if loop_data.iteration % set["memory_recall_interval"] == 0:
@@ -38,7 +43,10 @@ async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
)
task = asyncio.create_task(
- self.search_memories(loop_data=loop_data, log_item=log_item, **kwargs)
+ asyncio.wait_for(
+ self.search_memories(loop_data=loop_data, log_item=log_item, **kwargs),
+ timeout=SEARCH_TIMEOUT,
+ )
)
else:
task = None
@@ -57,15 +65,17 @@ async def search_memories(self, log_item: log.LogItem, loop_data: LoopData, **kw
del extras["solutions"]
- set = settings.get_settings()
+ set = plugins.get_plugin_config("memory", self.agent)
+ if not set:
+ return None
# try:
# get system message and chat history for util llm
system = self.agent.read_prompt("memory.memories_query.sys.md")
- # log query streamed by LLM
- async def log_callback(content):
- log_item.stream(query=content)
+ # # log query streamed by LLM
+ # async def log_callback(content):
+ # log_item.stream(query=content)
# call util llm to summarize conversation
user_instruction = (
@@ -83,13 +93,14 @@ async def log_callback(content):
query = await self.agent.call_utility_model(
system=system,
message=message,
- callback=log_callback,
+ # callback=log_callback,
)
query = query.strip()
+ log_item.update(query=query) # no need for streaming here
except Exception as e:
err = errors.format_error(e)
self.agent.context.log.log(
- type="error", heading="Recall memories extension error:", content=err
+ type="warning", heading="Recall memories extension error:", content=err
)
query = ""
@@ -180,7 +191,7 @@ async def log_callback(content):
except Exception as e:
err = errors.format_error(e)
self.agent.context.log.log(
- type="error", heading="Failed to filter relevant memories", content=err
+ type="warning", heading="Failed to filter relevant memories", content=err
)
filter_inds = []
diff --git a/python/extensions/message_loop_prompts_after/_91_recall_wait.py b/plugins/memory/extensions/python/message_loop_prompts_after/_91_recall_wait.py
similarity index 59%
rename from python/extensions/message_loop_prompts_after/_91_recall_wait.py
rename to plugins/memory/extensions/python/message_loop_prompts_after/_91_recall_wait.py
index 6be6321c3e..45965a2221 100644
--- a/python/extensions/message_loop_prompts_after/_91_recall_wait.py
+++ b/plugins/memory/extensions/python/message_loop_prompts_after/_91_recall_wait.py
@@ -1,13 +1,14 @@
from python.helpers.extension import Extension
from agent import LoopData
-from python.extensions.message_loop_prompts_after._50_recall_memories import DATA_NAME_TASK as DATA_NAME_TASK_MEMORIES, DATA_NAME_ITER as DATA_NAME_ITER_MEMORIES
-# from python.extensions.message_loop_prompts_after._51_recall_solutions import DATA_NAME_TASK as DATA_NAME_TASK_SOLUTIONS
-from python.helpers import settings
+from plugins.memory.extensions.python.message_loop_prompts_after._50_recall_memories import DATA_NAME_TASK as DATA_NAME_TASK_MEMORIES, DATA_NAME_ITER as DATA_NAME_ITER_MEMORIES
+from python.helpers import plugins
class RecallWait(Extension):
async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
- set = settings.get_settings()
+ set = plugins.get_plugin_config("memory", self.agent)
+ if not set:
+ return None
task = self.agent.get_data(DATA_NAME_TASK_MEMORIES)
iter = self.agent.get_data(DATA_NAME_ITER_MEMORIES) or 0
@@ -21,12 +22,6 @@ async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
delay_text = self.agent.read_prompt("memory.recall_delay_msg.md")
loop_data.extras_temporary["memory_recall_delayed"] = delay_text
return
-
+
# otherwise await the task
await task
-
- # task = self.agent.get_data(DATA_NAME_TASK_SOLUTIONS)
- # if task and not task.done():
- # # self.agent.context.log.set_progress("Recalling solutions...")
- # await task
-
diff --git a/plugins/memory/extensions/python/monologue_end/_50_memorize_fragments.py b/plugins/memory/extensions/python/monologue_end/_50_memorize_fragments.py
new file mode 100644
index 0000000000..391cf4104d
--- /dev/null
+++ b/plugins/memory/extensions/python/monologue_end/_50_memorize_fragments.py
@@ -0,0 +1,203 @@
+import asyncio
+from python.helpers import errors, plugins
+from python.helpers.extension import Extension
+from python.helpers.dirty_json import DirtyJson
+from agent import LoopData
+from python.helpers.log import LogItem
+from python.helpers.defer import DeferredTask, THREAD_BACKGROUND
+
+# Direct import - this extension lives inside the memory plugin
+from plugins.memory.helpers.memory import Memory
+from plugins.memory.tools.memory_load import DEFAULT_THRESHOLD as DEFAULT_MEMORY_THRESHOLD
+
+
+class MemorizeMemories(Extension):
+
+ async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
+ # try:
+
+ set = plugins.get_plugin_config("memory", self.agent)
+ if not set:
+ return None
+
+ if not set["memory_memorize_enabled"]:
+ return
+
+ # show full util message
+ log_item = self.agent.context.log.log(
+ type="util",
+ heading="Memorizing new information...",
+ )
+
+ # memorize in background
+ task = DeferredTask(thread_name=THREAD_BACKGROUND)
+ task.start_task(self.memorize, loop_data, log_item)
+ # task = asyncio.create_task(self.memorize(loop_data, log_item))
+ return task
+
+ async def memorize(self, loop_data: LoopData, log_item: LogItem, **kwargs):
+
+ try:
+ set = plugins.get_plugin_config("memory", self.agent)
+ if not set:
+ return None
+
+ db = await Memory.get(self.agent)
+
+ # get system message and chat history for util llm
+ system = self.agent.read_prompt("memory.memories_sum.sys.md")
+ msgs_text = self.agent.concat_messages(self.agent.history)
+
+ # # log query streamed by LLM
+ # async def log_callback(content):
+ # log_item.stream(content=content)
+
+ # call util llm to find info in history
+ memories_json = await self.agent.call_utility_model(
+ system=system,
+ message=msgs_text,
+ # callback=log_callback,
+ background=True,
+ )
+
+ # log data < no need for streaming utility messages
+ log_item.update(content=memories_json)
+
+ # Add validation and error handling for memories_json
+ if not memories_json or not isinstance(memories_json, str):
+ log_item.update(heading="No response from utility model.")
+ return
+
+ # Strip any whitespace that might cause issues
+ memories_json = memories_json.strip()
+
+ if not memories_json:
+ log_item.update(heading="Empty response from utility model.")
+ return
+
+ try:
+ memories = DirtyJson.parse_string(memories_json)
+ except Exception as e:
+ log_item.update(heading=f"Failed to parse memories response: {str(e)}")
+ return
+
+ # Validate that memories is a list or convertible to one
+ if memories is None:
+ log_item.update(heading="No valid memories found in response.")
+ return
+
+ # If memories is not a list, try to make it one
+ if not isinstance(memories, list):
+ if isinstance(memories, (str, dict)):
+ memories = [memories]
+ else:
+ log_item.update(heading="Invalid memories format received.")
+ return
+
+ if not isinstance(memories, list) or len(memories) == 0:
+ log_item.update(heading="No useful information to memorize.")
+ return
+ else:
+ memories_txt = "\n\n".join([str(memory) for memory in memories]).strip()
+ log_item.update(heading=f"{len(memories)} entries to memorize.", memories=memories_txt)
+
+ # Process memories with intelligent consolidation
+ total_processed = 0
+ total_consolidated = 0
+ rem = []
+
+ for memory in memories:
+ # Convert memory to plain text
+ txt = f"{memory}"
+
+ if set["memory_memorize_consolidation"]:
+
+ try:
+ # Use intelligent consolidation system
+ from plugins.memory.helpers.memory_consolidation import create_memory_consolidator
+ consolidator = create_memory_consolidator(
+ self.agent,
+ similarity_threshold=DEFAULT_MEMORY_THRESHOLD, # More permissive for discovery
+ max_similar_memories=8,
+ max_llm_context_memories=4
+ )
+
+ # Create memory item-specific log for detailed tracking
+ memory_log = None # too many utility messages, skip log for now
+ # memory_log = self.agent.context.log.log(
+ # type="util",
+ # heading=f"Processing memory fragment: {txt[:50]}...",
+ # update_progress="none" # Don't affect status bar
+ # )
+
+ # Process with intelligent consolidation
+ result_obj = await consolidator.process_new_memory(
+ new_memory=txt,
+ area=Memory.Area.FRAGMENTS.value,
+ metadata={"area": Memory.Area.FRAGMENTS.value},
+ log_item=memory_log
+ )
+
+ # Update the individual log item with completion status but keep it temporary
+ if result_obj.get("success"):
+ total_consolidated += 1
+ if memory_log:
+ memory_log.update(
+ result="Fragment processed successfully",
+ heading=f"Memory fragment completed: {txt[:50]}...",
+ update_progress="none" # Show briefly then disappear
+ )
+ else:
+ if memory_log:
+ memory_log.update(
+ result="Fragment processing failed",
+ heading=f"Memory fragment failed: {txt[:50]}...",
+ update_progress="none" # Show briefly then disappear
+ )
+ total_processed += 1
+
+ except Exception as e:
+ # Log error but continue processing
+ log_item.update(consolidation_error=str(e))
+ total_processed += 1
+
+ # Update final results with structured logging
+ log_item.update(
+ heading=f"Memorization completed: {total_processed} memories processed, {total_consolidated} intelligently consolidated",
+ memories=memories_txt,
+ result=f"{total_processed} memories processed, {total_consolidated} intelligently consolidated",
+ memories_processed=total_processed,
+ memories_consolidated=total_consolidated,
+ update_progress="none"
+ )
+
+ else:
+
+ # remove previous fragments too similiar to this one
+ if set["memory_memorize_replace_threshold"] > 0:
+ rem += await db.delete_documents_by_query(
+ query=txt,
+ threshold=set["memory_memorize_replace_threshold"],
+ filter=f"area=='{Memory.Area.FRAGMENTS.value}'",
+ )
+ if rem:
+ rem_txt = "\n\n".join(Memory.format_docs_plain(rem))
+ log_item.update(replaced=rem_txt)
+
+ # insert new memory
+ await db.insert_text(text=txt, metadata={"area": Memory.Area.FRAGMENTS.value})
+
+ log_item.update(
+ result=f"{len(memories)} entries memorized.",
+ heading=f"{len(memories)} entries memorized.",
+ )
+ if rem:
+ log_item.stream(result=f"\nReplaced {len(rem)} previous memories.")
+
+
+
+ except Exception as e:
+ err = errors.format_error(e)
+ self.agent.context.log.log(
+ type="warning", heading="Memorize memories extension error", content=err
+ )
diff --git a/plugins/memory/extensions/python/monologue_end/_51_memorize_solutions.py b/plugins/memory/extensions/python/monologue_end/_51_memorize_solutions.py
new file mode 100644
index 0000000000..aeef9ea1c4
--- /dev/null
+++ b/plugins/memory/extensions/python/monologue_end/_51_memorize_solutions.py
@@ -0,0 +1,208 @@
+import asyncio
+from python.helpers import errors, plugins
+from python.helpers.extension import Extension
+from python.helpers.dirty_json import DirtyJson
+from agent import LoopData
+from python.helpers.log import LogItem
+from python.helpers.defer import DeferredTask, THREAD_BACKGROUND
+
+# Direct import - this extension lives inside the memory plugin
+from plugins.memory.helpers.memory import Memory
+from plugins.memory.tools.memory_load import DEFAULT_THRESHOLD as DEFAULT_MEMORY_THRESHOLD
+
+class MemorizeSolutions(Extension):
+
+ async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
+ # try:
+
+ set = plugins.get_plugin_config("memory", self.agent)
+ if not set:
+ return None
+
+ if not set["memory_memorize_enabled"]:
+ return
+
+ # show full util message
+ log_item = self.agent.context.log.log(
+ type="util",
+ heading="Memorizing succesful solutions...",
+ )
+
+ # memorize in background
+ task = DeferredTask(thread_name=THREAD_BACKGROUND)
+ task.start_task(self.memorize, loop_data, log_item)
+ # task = asyncio.create_task(self.memorize(loop_data, log_item))
+ return task
+
+ async def memorize(self, loop_data: LoopData, log_item: LogItem, **kwargs):
+ try:
+ set = plugins.get_plugin_config("memory", self.agent)
+ if not set:
+ return None
+
+
+ db = await Memory.get(self.agent)
+
+ # get system message and chat history for util llm
+ system = self.agent.read_prompt("memory.solutions_sum.sys.md")
+ msgs_text = self.agent.concat_messages(self.agent.history)
+
+ # log query streamed by LLM
+ # async def log_callback(content):
+ # log_item.stream(content=content)
+
+ # call util llm to find solutions in history
+ solutions_json = await self.agent.call_utility_model(
+ system=system,
+ message=msgs_text,
+ # callback=log_callback,
+ background=True,
+ )
+
+ # log query < no need for streaming utility messages
+ log_item.update(content=solutions_json)
+
+
+
+ # Add validation and error handling for solutions_json
+ if not solutions_json or not isinstance(solutions_json, str):
+ log_item.update(heading="No response from utility model.")
+ return
+
+ # Strip any whitespace that might cause issues
+ solutions_json = solutions_json.strip()
+
+ if not solutions_json:
+ log_item.update(heading="Empty response from utility model.")
+ return
+
+ try:
+ solutions = DirtyJson.parse_string(solutions_json)
+ except Exception as e:
+ log_item.update(heading=f"Failed to parse solutions response: {str(e)}")
+ return
+
+ # Validate that solutions is a list or convertible to one
+ if solutions is None:
+ log_item.update(heading="No valid solutions found in response.")
+ return
+
+ # If solutions is not a list, try to make it one
+ if not isinstance(solutions, list):
+ if isinstance(solutions, (str, dict)):
+ solutions = [solutions]
+ else:
+ log_item.update(heading="Invalid solutions format received.")
+ return
+
+ if not isinstance(solutions, list) or len(solutions) == 0:
+ log_item.update(heading="No successful solutions to memorize.")
+ return
+ else:
+ solutions_txt = "\n\n".join([str(solution) for solution in solutions]).strip()
+ log_item.update(
+ heading=f"{len(solutions)} successful solutions to memorize.", solutions=solutions_txt
+ )
+
+ # Process solutions with intelligent consolidation
+ total_processed = 0
+ total_consolidated = 0
+ rem = []
+
+ for solution in solutions:
+ # Convert solution to structured text
+ if isinstance(solution, dict):
+ problem = solution.get('problem', 'Unknown problem')
+ solution_text = solution.get('solution', 'Unknown solution')
+ txt = f"# Problem\n {problem}\n# Solution\n {solution_text}"
+ else:
+ # If solution is not a dict, convert it to string
+ txt = f"# Solution\n {str(solution)}"
+
+ if set["memory_memorize_consolidation"]:
+ try:
+ # Use intelligent consolidation system
+ from plugins.memory.helpers.memory_consolidation import create_memory_consolidator
+ consolidator = create_memory_consolidator(
+ self.agent,
+ similarity_threshold=DEFAULT_MEMORY_THRESHOLD, # More permissive for discovery
+ max_similar_memories=6, # Fewer for solutions (more complex)
+ max_llm_context_memories=3
+ )
+
+ # Create solution-specific log for detailed tracking
+ solution_log = None # too many utility messages, skip log for now
+ # solution_log = self.agent.context.log.log(
+ # type="util",
+ # heading=f"Processing solution: {txt[:50]}...",
+ # update_progress="none" # Don't affect status bar
+ # )
+
+ # Process with intelligent consolidation
+ result_obj = await consolidator.process_new_memory(
+ new_memory=txt,
+ area=Memory.Area.SOLUTIONS.value,
+ metadata={"area": Memory.Area.SOLUTIONS.value},
+ log_item=solution_log
+ )
+
+ # Update the individual log item with completion status but keep it temporary
+ if result_obj.get("success"):
+ total_consolidated += 1
+ if solution_log:
+ solution_log.update(
+ result="Solution processed successfully",
+ heading=f"Solution completed: {txt[:50]}...",
+ update_progress="none" # Show briefly then disappear
+ )
+ else:
+ if solution_log:
+ solution_log.update(
+ result="Solution processing failed",
+ heading=f"Solution failed: {txt[:50]}...",
+ update_progress="none" # Show briefly then disappear
+ )
+ total_processed += 1
+
+ except Exception as e:
+ # Log error but continue processing
+ log_item.update(consolidation_error=str(e))
+ total_processed += 1
+
+ # Update final results with structured logging
+ log_item.update(
+ heading=f"Solution memorization completed: {total_processed} solutions processed, {total_consolidated} intelligently consolidated",
+ solutions=solutions_txt,
+ result=f"{total_processed} solutions processed, {total_consolidated} intelligently consolidated",
+ solutions_processed=total_processed,
+ solutions_consolidated=total_consolidated,
+ update_progress="none"
+ )
+ else:
+ # remove previous solutions too similiar to this one
+ if set["memory_memorize_replace_threshold"] > 0:
+ rem += await db.delete_documents_by_query(
+ query=txt,
+ threshold=set["memory_memorize_replace_threshold"],
+ filter=f"area=='{Memory.Area.SOLUTIONS.value}'",
+ )
+ if rem:
+ rem_txt = "\n\n".join(Memory.format_docs_plain(rem))
+ log_item.update(replaced=rem_txt)
+
+ # insert new solution
+ await db.insert_text(text=txt, metadata={"area": Memory.Area.SOLUTIONS.value})
+
+ log_item.update(
+ result=f"{len(solutions)} solutions memorized.",
+ heading=f"{len(solutions)} solutions memorized.",
+ )
+ if rem:
+ log_item.stream(result=f"\nReplaced {len(rem)} previous solutions.")
+
+
+ except Exception as e:
+ err = errors.format_error(e)
+ self.agent.context.log.log(
+ type="warning", heading="Memorize solutions extension error", content=err
+ )
diff --git a/python/extensions/monologue_start/_10_memory_init.py b/plugins/memory/extensions/python/monologue_start/_10_memory_init.py
similarity index 68%
rename from python/extensions/monologue_start/_10_memory_init.py
rename to plugins/memory/extensions/python/monologue_start/_10_memory_init.py
index 26c94de30a..1bacc881c2 100644
--- a/python/extensions/monologue_start/_10_memory_init.py
+++ b/plugins/memory/extensions/python/monologue_start/_10_memory_init.py
@@ -1,13 +1,11 @@
from python.helpers.extension import Extension
from agent import LoopData
-from python.helpers import memory
-import asyncio
+
+# Direct import - this extension lives inside the memory plugin
+from plugins.memory.helpers import memory
class MemoryInit(Extension):
async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
db = await memory.Memory.get(self.agent)
-
-
-
\ No newline at end of file
diff --git a/python/extensions/system_prompt/_20_behaviour_prompt.py b/plugins/memory/extensions/python/system_prompt/_20_behaviour_prompt.py
similarity index 76%
rename from python/extensions/system_prompt/_20_behaviour_prompt.py
rename to plugins/memory/extensions/python/system_prompt/_20_behaviour_prompt.py
index 1650e9ee8c..bec18f0fdd 100644
--- a/python/extensions/system_prompt/_20_behaviour_prompt.py
+++ b/plugins/memory/extensions/python/system_prompt/_20_behaviour_prompt.py
@@ -1,24 +1,27 @@
-from datetime import datetime
from python.helpers.extension import Extension
from agent import Agent, LoopData
-from python.helpers import files, memory
+from python.helpers import files
+
+# Direct import - this extension lives inside the memory plugin
+from plugins.memory.helpers import memory
class BehaviourPrompt(Extension):
async def execute(self, system_prompt: list[str]=[], loop_data: LoopData = LoopData(), **kwargs):
prompt = read_rules(self.agent)
- system_prompt.insert(0, prompt) #.append(prompt)
+ system_prompt.insert(0, prompt)
+
def get_custom_rules_file(agent: Agent):
return files.get_abs_path(memory.get_memory_subdir_abs(agent), "behaviour.md")
+
def read_rules(agent: Agent):
rules_file = get_custom_rules_file(agent)
if files.exists(rules_file):
- rules = files.read_file(rules_file) # no includes and vars here, that could crash
+ rules = files.read_file(rules_file)
return agent.read_prompt("agent.system.behaviour.md", rules=rules)
else:
rules = agent.read_prompt("agent.system.behaviour_default.md")
return agent.read_prompt("agent.system.behaviour.md", rules=rules)
-
\ No newline at end of file
diff --git a/plugins/memory/extensions/webui/sidebar-quick-actions-dropdown-start/memory-entry.html b/plugins/memory/extensions/webui/sidebar-quick-actions-dropdown-start/memory-entry.html
new file mode 100644
index 0000000000..4b854b6cc8
--- /dev/null
+++ b/plugins/memory/extensions/webui/sidebar-quick-actions-dropdown-start/memory-entry.html
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/plugins/memory/extensions/webui/sidebar-quick-actions-main-start/memory-entry.html b/plugins/memory/extensions/webui/sidebar-quick-actions-main-start/memory-entry.html
new file mode 100644
index 0000000000..a964d471ad
--- /dev/null
+++ b/plugins/memory/extensions/webui/sidebar-quick-actions-main-start/memory-entry.html
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/python/helpers/knowledge_import.py b/plugins/memory/helpers/knowledge_import.py
similarity index 100%
rename from python/helpers/knowledge_import.py
rename to plugins/memory/helpers/knowledge_import.py
diff --git a/python/helpers/memory.py b/plugins/memory/helpers/memory.py
similarity index 90%
rename from python/helpers/memory.py
rename to plugins/memory/helpers/memory.py
index 8c8785c5af..c3edba92de 100644
--- a/python/helpers/memory.py
+++ b/plugins/memory/helpers/memory.py
@@ -23,9 +23,9 @@
import numpy as np
from python.helpers.print_style import PrintStyle
-from . import files
+from python.helpers import files, plugins, projects
from langchain_core.documents import Document
-from python.helpers import knowledge_import
+from . import knowledge_import
from python.helpers.log import Log, LogItem
from enum import Enum
from agent import Agent, AgentContext
@@ -57,7 +57,6 @@ class Area(Enum):
MAIN = "main"
FRAGMENTS = "fragments"
SOLUTIONS = "solutions"
- INSTRUMENTS = "instruments"
index: dict[str, "MyFaiss"] = {}
@@ -139,7 +138,7 @@ def initialize(
log_item.stream(progress="\nInitializing VectorDB")
em_dir = files.get_abs_path(
- "memory/embeddings"
+ "tmp/memory/embeddings"
) # just caching, no need to parameterize
db_dir = abs_db_dir(memory_subdir)
@@ -308,7 +307,7 @@ def _preload_knowledge_folders(
log_item,
abs_knowledge_dir(kn_dir),
index,
- {"area": Memory.Area.MAIN},
+ {"area": Memory.Area.MAIN.value},
filename_pattern="*",
recursive=False,
)
@@ -323,16 +322,6 @@ def _preload_knowledge_folders(
recursive=True,
)
- # load instruments descriptions
- index = knowledge_import.load_knowledge(
- log_item,
- files.get_abs_path("instruments"),
- index,
- {"area": Memory.Area.INSTRUMENTS.value},
- filename_pattern="**/*.md",
- recursive=True,
- )
-
return index
def get_document_by_id(self, id: str) -> Document | None:
@@ -483,7 +472,9 @@ def get_timestamp():
def get_custom_knowledge_subdir_abs(agent: Agent) -> str:
for dir in agent.config.knowledge_subdirs:
if dir != "default":
- return files.get_abs_path("knowledge", dir)
+ if dir == "custom":
+ return files.get_abs_path("usr/knowledge")
+ return files.get_abs_path("usr/knowledge", dir)
raise Exception("No custom knowledge subdir set")
@@ -495,23 +486,27 @@ def reload():
def abs_db_dir(memory_subdir: str) -> str:
# patch for projects, this way we don't need to re-work the structure of memory subdirs
if memory_subdir.startswith("projects/"):
- from python.helpers.projects import get_project_meta_folder
+ from python.helpers.projects import get_project_meta
- return files.get_abs_path(get_project_meta_folder(memory_subdir[9:]), "memory")
+ return files.get_abs_path(get_project_meta(memory_subdir[9:]), "memory")
# standard subdirs
- return files.get_abs_path("memory", memory_subdir)
+ return files.get_abs_path("usr/memory", memory_subdir)
def abs_knowledge_dir(knowledge_subdir: str, *sub_dirs: str) -> str:
# patch for projects, this way we don't need to re-work the structure of knowledge subdirs
if knowledge_subdir.startswith("projects/"):
- from python.helpers.projects import get_project_meta_folder
+ from python.helpers.projects import get_project_meta
return files.get_abs_path(
- get_project_meta_folder(knowledge_subdir[9:]), "knowledge", *sub_dirs
+ get_project_meta(knowledge_subdir[9:]), "knowledge", *sub_dirs
)
# standard subdirs
- return files.get_abs_path("knowledge", knowledge_subdir, *sub_dirs)
+ if knowledge_subdir == "default":
+ return files.get_abs_path("knowledge", *sub_dirs)
+ if knowledge_subdir == "custom":
+ return files.get_abs_path("usr/knowledge", *sub_dirs)
+ return files.get_abs_path("usr/knowledge", knowledge_subdir, *sub_dirs)
def get_memory_subdir_abs(agent: Agent) -> str:
@@ -520,38 +515,40 @@ def get_memory_subdir_abs(agent: Agent) -> str:
def get_agent_memory_subdir(agent: Agent) -> str:
- # if project is active, use project memory subdir
- return get_context_memory_subdir(agent.context)
+ config = plugins.get_plugin_config("memory", agent)
+ if not config:
+ return "default"
+
+ # Check if project isolation is enabled and we are in a project
+ if config.get("project_memory_isolation", True):
+ project_name = projects.get_context_project_name(agent.context)
+ if project_name:
+ return "projects/" + project_name
-def get_context_memory_subdir(context: AgentContext) -> str:
- # if project is active, use project memory subdir
- from python.helpers.projects import (
- get_context_memory_subdir as get_project_memory_subdir,
- )
+ # Fallback to configured subdir or default
+ return config.get("agent_memory_subdir", "") or "default"
- memory_subdir = get_project_memory_subdir(context)
- if memory_subdir:
- return memory_subdir
- # no project, regular memory subdir
- return context.config.memory_subdir or "default"
+def get_context_memory_subdir(context: AgentContext) -> str:
+ agent = context.get_agent()
+ return get_agent_memory_subdir(agent)
def get_existing_memory_subdirs() -> list[str]:
try:
from python.helpers.projects import (
- get_project_meta_folder,
+ get_project_meta,
get_projects_parent_folder,
)
# Get subdirectories from memory folder
- subdirs = files.get_subdirectories("memory", exclude="embeddings")
+ subdirs = files.get_subdirectories("usr/memory")
project_subdirs = files.get_subdirectories(get_projects_parent_folder())
for project_subdir in project_subdirs:
if files.exists(
- get_project_meta_folder(project_subdir), "memory", "index.faiss"
+ get_project_meta(project_subdir), "memory", "index.faiss"
):
subdirs.append(f"projects/{project_subdir}")
@@ -569,7 +566,7 @@ def get_knowledge_subdirs_by_memory_subdir(
memory_subdir: str, default: list[str]
) -> list[str]:
if memory_subdir.startswith("projects/"):
- from python.helpers.projects import get_project_meta_folder
+ from python.helpers.projects import get_project_meta
- default.append(get_project_meta_folder(memory_subdir[9:], "knowledge"))
+ default.append(get_project_meta(memory_subdir[9:], "knowledge"))
return default
diff --git a/python/helpers/memory_consolidation.py b/plugins/memory/helpers/memory_consolidation.py
similarity index 98%
rename from python/helpers/memory_consolidation.py
rename to plugins/memory/helpers/memory_consolidation.py
index 6a100d8f48..9c1fe04b3d 100644
--- a/python/helpers/memory_consolidation.py
+++ b/plugins/memory/helpers/memory_consolidation.py
@@ -7,13 +7,20 @@
from langchain_core.documents import Document
-from python.helpers.memory import Memory
+from .memory import Memory
from python.helpers.dirty_json import DirtyJson
from python.helpers.log import LogItem
from python.helpers.print_style import PrintStyle
-from python.tools.memory_load import DEFAULT_THRESHOLD as DEFAULT_MEMORY_THRESHOLD
from agent import Agent
+# Import from tools within plugin
+import sys
+from pathlib import Path
+_plugin_root = Path(__file__).parent.parent
+if str(_plugin_root) not in sys.path:
+ sys.path.insert(0, str(_plugin_root))
+from tools.memory_load import DEFAULT_THRESHOLD as DEFAULT_MEMORY_THRESHOLD
+
class ConsolidationAction(Enum):
"""Actions that can be taken during memory consolidation."""
@@ -82,7 +89,7 @@ async def process_new_memory(
Args:
new_memory: The new memory content to process
- area: Memory area (MAIN, FRAGMENTS, SOLUTIONS, INSTRUMENTS)
+ area: Memory area (MAIN, FRAGMENTS, SOLUTIONS)
metadata: Initial metadata for the memory
log_item: Optional log item for progress tracking
@@ -130,7 +137,6 @@ async def _process_memory_with_consolidation(
if log_item:
log_item.update(
progress="No similar memories found, inserting new memory",
- temp=True
)
try:
db = await Memory.get(self.agent)
@@ -153,7 +159,6 @@ async def _process_memory_with_consolidation(
if log_item:
log_item.update(
progress=f"Found {len(similar_memories)} similar memories, analyzing...",
- temp=True,
similar_memories_count=len(similar_memories)
)
@@ -174,7 +179,6 @@ async def _process_memory_with_consolidation(
if log_item:
log_item.update(
progress=f"Filtered out {deleted_count} deleted memories, {len(valid_similar_memories)} remain for analysis",
- temp=True,
race_condition_detected=True,
deleted_similar_memories_count=deleted_count
)
@@ -185,7 +189,6 @@ async def _process_memory_with_consolidation(
if log_item:
log_item.update(
progress="No valid similar memories remain, inserting new memory",
- temp=True
)
try:
db = await Memory.get(self.agent)
@@ -220,7 +223,6 @@ async def _process_memory_with_consolidation(
if log_item:
log_item.update(
progress="LLM analysis suggests skipping consolidation",
- temp=True
)
try:
db = await Memory.get(self.agent)
diff --git a/plugins/memory/plugin.yaml b/plugins/memory/plugin.yaml
new file mode 100644
index 0000000000..fce9f5c505
--- /dev/null
+++ b/plugins/memory/plugin.yaml
@@ -0,0 +1,7 @@
+title: Memory
+description: Provides persistent memory capabilities to Agent Zero agents.
+version: 1.0.0
+settings_sections:
+ - agent
+per_project_config: true
+per_agent_config: true
diff --git a/prompts/agent.system.memories.md b/plugins/memory/prompts/agent.system.memories.md
similarity index 100%
rename from prompts/agent.system.memories.md
rename to plugins/memory/prompts/agent.system.memories.md
diff --git a/prompts/agent.system.solutions.md b/plugins/memory/prompts/agent.system.solutions.md
similarity index 100%
rename from prompts/agent.system.solutions.md
rename to plugins/memory/prompts/agent.system.solutions.md
diff --git a/prompts/agent.system.tool.memory.md b/plugins/memory/prompts/agent.system.tool.memory.md
similarity index 100%
rename from prompts/agent.system.tool.memory.md
rename to plugins/memory/prompts/agent.system.tool.memory.md
diff --git a/prompts/fw.memory.hist_suc.sys.md b/plugins/memory/prompts/fw.memory.hist_suc.sys.md
similarity index 100%
rename from prompts/fw.memory.hist_suc.sys.md
rename to plugins/memory/prompts/fw.memory.hist_suc.sys.md
diff --git a/prompts/fw.memory.hist_sum.sys.md b/plugins/memory/prompts/fw.memory.hist_sum.sys.md
similarity index 100%
rename from prompts/fw.memory.hist_sum.sys.md
rename to plugins/memory/prompts/fw.memory.hist_sum.sys.md
diff --git a/prompts/fw.memory_saved.md b/plugins/memory/prompts/fw.memory_saved.md
similarity index 100%
rename from prompts/fw.memory_saved.md
rename to plugins/memory/prompts/fw.memory_saved.md
diff --git a/prompts/memory.consolidation.msg.md b/plugins/memory/prompts/memory.consolidation.msg.md
similarity index 100%
rename from prompts/memory.consolidation.msg.md
rename to plugins/memory/prompts/memory.consolidation.msg.md
diff --git a/prompts/memory.consolidation.sys.md b/plugins/memory/prompts/memory.consolidation.sys.md
similarity index 100%
rename from prompts/memory.consolidation.sys.md
rename to plugins/memory/prompts/memory.consolidation.sys.md
diff --git a/prompts/memory.keyword_extraction.msg.md b/plugins/memory/prompts/memory.keyword_extraction.msg.md
similarity index 100%
rename from prompts/memory.keyword_extraction.msg.md
rename to plugins/memory/prompts/memory.keyword_extraction.msg.md
diff --git a/prompts/memory.keyword_extraction.sys.md b/plugins/memory/prompts/memory.keyword_extraction.sys.md
similarity index 100%
rename from prompts/memory.keyword_extraction.sys.md
rename to plugins/memory/prompts/memory.keyword_extraction.sys.md
diff --git a/prompts/memory.memories_filter.msg.md b/plugins/memory/prompts/memory.memories_filter.msg.md
similarity index 100%
rename from prompts/memory.memories_filter.msg.md
rename to plugins/memory/prompts/memory.memories_filter.msg.md
diff --git a/prompts/memory.memories_filter.sys.md b/plugins/memory/prompts/memory.memories_filter.sys.md
similarity index 100%
rename from prompts/memory.memories_filter.sys.md
rename to plugins/memory/prompts/memory.memories_filter.sys.md
diff --git a/prompts/memory.memories_query.msg.md b/plugins/memory/prompts/memory.memories_query.msg.md
similarity index 100%
rename from prompts/memory.memories_query.msg.md
rename to plugins/memory/prompts/memory.memories_query.msg.md
diff --git a/prompts/memory.memories_query.sys.md b/plugins/memory/prompts/memory.memories_query.sys.md
similarity index 100%
rename from prompts/memory.memories_query.sys.md
rename to plugins/memory/prompts/memory.memories_query.sys.md
diff --git a/prompts/memory.memories_sum.sys.md b/plugins/memory/prompts/memory.memories_sum.sys.md
similarity index 100%
rename from prompts/memory.memories_sum.sys.md
rename to plugins/memory/prompts/memory.memories_sum.sys.md
diff --git a/prompts/memory.recall_delay_msg.md b/plugins/memory/prompts/memory.recall_delay_msg.md
similarity index 100%
rename from prompts/memory.recall_delay_msg.md
rename to plugins/memory/prompts/memory.recall_delay_msg.md
diff --git a/prompts/memory.solutions_query.sys.md b/plugins/memory/prompts/memory.solutions_query.sys.md
similarity index 100%
rename from prompts/memory.solutions_query.sys.md
rename to plugins/memory/prompts/memory.solutions_query.sys.md
diff --git a/prompts/memory.solutions_sum.sys.md b/plugins/memory/prompts/memory.solutions_sum.sys.md
similarity index 100%
rename from prompts/memory.solutions_sum.sys.md
rename to plugins/memory/prompts/memory.solutions_sum.sys.md
diff --git a/python/tools/behaviour_adjustment.py b/plugins/memory/tools/behaviour_adjustment.py
similarity index 88%
rename from python/tools/behaviour_adjustment.py
rename to plugins/memory/tools/behaviour_adjustment.py
index e9c60bb05c..3aabf3198c 100644
--- a/python/tools/behaviour_adjustment.py
+++ b/plugins/memory/tools/behaviour_adjustment.py
@@ -1,7 +1,8 @@
-from python.helpers import files, memory
+from python.helpers import files
from python.helpers.tool import Tool, Response
from agent import Agent
from python.helpers.log import LogItem
+from plugins.memory.helpers import memory
class UpdateBehaviour(Tool):
@@ -17,12 +18,6 @@ async def execute(self, adjustments="", **kwargs):
message=self.agent.read_prompt("behaviour.updated.md"), break_loop=False
)
- # async def before_execution(self, **kwargs):
- # pass
-
- # async def after_execution(self, response, **kwargs):
- # pass
-
async def update_behaviour(agent: Agent, log_item: LogItem, adjustments: str):
@@ -58,7 +53,7 @@ def get_custom_rules_file(agent: Agent):
def read_rules(agent: Agent):
rules_file = get_custom_rules_file(agent)
if files.exists(rules_file):
- rules = files.read_prompt_file(rules_file)
+ rules = agent.read_prompt(rules_file)
return agent.read_prompt("agent.system.behaviour.md", rules=rules)
else:
rules = agent.read_prompt("agent.system.behaviour_default.md")
diff --git a/python/tools/memory_delete.py b/plugins/memory/tools/memory_delete.py
similarity index 89%
rename from python/tools/memory_delete.py
rename to plugins/memory/tools/memory_delete.py
index 7b13935a78..9accb62734 100644
--- a/python/tools/memory_delete.py
+++ b/plugins/memory/tools/memory_delete.py
@@ -1,5 +1,6 @@
-from python.helpers.memory import Memory
from python.helpers.tool import Tool, Response
+from plugins.memory.helpers.memory import Memory
+
class MemoryDelete(Tool):
diff --git a/python/tools/memory_forget.py b/plugins/memory/tools/memory_forget.py
similarity index 82%
rename from python/tools/memory_forget.py
rename to plugins/memory/tools/memory_forget.py
index 48c012d9d3..113f156298 100644
--- a/python/tools/memory_forget.py
+++ b/plugins/memory/tools/memory_forget.py
@@ -1,6 +1,7 @@
-from python.helpers.memory import Memory
from python.helpers.tool import Tool, Response
-from python.tools.memory_load import DEFAULT_THRESHOLD
+from plugins.memory.helpers.memory import Memory
+
+from tools.memory_load import DEFAULT_THRESHOLD
class MemoryForget(Tool):
diff --git a/python/tools/memory_load.py b/plugins/memory/tools/memory_load.py
similarity index 93%
rename from python/tools/memory_load.py
rename to plugins/memory/tools/memory_load.py
index 5fc7d6126b..bbe226dcc4 100644
--- a/python/tools/memory_load.py
+++ b/plugins/memory/tools/memory_load.py
@@ -1,5 +1,5 @@
-from python.helpers.memory import Memory
from python.helpers.tool import Tool, Response
+from plugins.memory.helpers.memory import Memory
DEFAULT_THRESHOLD = 0.7
DEFAULT_LIMIT = 10
diff --git a/python/tools/memory_save.py b/plugins/memory/tools/memory_save.py
similarity index 90%
rename from python/tools/memory_save.py
rename to plugins/memory/tools/memory_save.py
index 31f00ca29b..b33e92ca3f 100644
--- a/python/tools/memory_save.py
+++ b/plugins/memory/tools/memory_save.py
@@ -1,5 +1,6 @@
-from python.helpers.memory import Memory
from python.helpers.tool import Tool, Response
+from plugins.memory.helpers.memory import Memory
+
class MemorySave(Tool):
diff --git a/plugins/memory/webui/config.html b/plugins/memory/webui/config.html
new file mode 100644
index 0000000000..2d6b92cf94
--- /dev/null
+++ b/plugins/memory/webui/config.html
@@ -0,0 +1,272 @@
+
+
+ Memory
+
+
+
+
+
+
+
Memory
+
+ Configuration of A0's memory system. A0 memorizes and recalls memories automatically to help its
+ context awareness.
+
+
+
+
+
Project Isolation
+
+ If enabled, this project uses its own memory folder (projects/NAME). If disabled, it shares the global memory (default or custom subdir).
+
+
+
+
+
+
+
+
+
+
Memory Subdirectory
+
+ Subdirectory of /memory folder.
+
+
+
+
+
+
+
+
+
+
Memory Dashboard
+
+ View and explore all stored memories in a table format with filtering and search
+ capabilities.
+
+
+
+
+
+
+
+
+
+
Memory auto-recall enabled
+
Agent Zero will automatically recall memories based on
+ convesation context.
+
+
+
+
+
+
+
+
+
Memory auto-recall delayed
+
+ The agent will not wait for auto memory recall. Memories will be delivered one message
+ later. This speeds up agent's response time but may result in less relevant first step.
+
+
+
+
+
+
+
+
+
+
Auto-recall AI query preparation
+
+ Enables vector DB query preparation from conversation context by utility LLM for
+ auto-recall. Improves search quality, adds 1 utility LLM call per auto-recall.
+
+
+
+
+
+
+
+
+
+
Auto-recall AI post-filtering
+
+ Enables memory relevance filtering by utility LLM for auto-recall. Improves search quality,
+ adds 1 utility LLM call per auto-recall.
+
+
+
+
+
+
+
+
+
+
Memory auto-recall interval
+
+ Memories are recalled after every user or superior agent message. During agent's monologue,
+ memories are recalled every X turns based on this parameter.
+
+
+
+
+
+
+
+
+
+
+
Memory auto-recall history length
+
+ The length of conversation history passed to memory recall LLM for context (in characters).
+
+
+
+
+
+
+
+
+
+
Memory auto-recall similarity threshold
+
+ The threshold for similarity search in memory recall (0 = no similarity, 1 = exact match).
+
+
+
+
+
+
+
+
+
+
+
Memory auto-recall max memories to search
+
+ The maximum number of memories returned by vector DB for further processing.
+
+
+
+
+
+
+
+
+
+
Memory auto-recall max memories to use
+
+ The maximum number of memories to inject into A0's context window.
+
+
+
+
+
+
+
+
+
+
Memory auto-recall max solutions to search
+
+ The maximum number of solutions returned by vector DB for further processing.
+
+
+
+
+
+
+
+
+
+
Memory auto-recall max solutions to use
+
+ The maximum number of solutions to inject into A0's context window.
+
+
+
+
+
+
+
+
+
+
Auto-memorize enabled
+
+ A0 will automatically memorize facts and solutions from conversation history.
+
+
+
+
+
+
+
+
+
+
Auto-memorize AI consolidation
+
+ A0 will automatically consolidate similar memories using utility LLM. Improves memory quality
+ over time, adds 2 utility LLM calls per memory.
+
+
+
+
+
+
+
+
+
+
Auto-memorize replacement threshold
+
+ Only applies when AI consolidation is disabled. Replaces previous similar memories with new
+ ones based on this threshold. 0 = replace even if not similar at all, 1 = replace only if
+ exact match.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/memory/webui/main.html b/plugins/memory/webui/main.html
new file mode 100644
index 0000000000..58ec2cc1e2
--- /dev/null
+++ b/plugins/memory/webui/main.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+ Memory Dashboard
+
+
+
+
+
diff --git a/webui/components/settings/memory/memory-dashboard-store.js b/plugins/memory/webui/memory-dashboard-store.js
similarity index 95%
rename from webui/components/settings/memory/memory-dashboard-store.js
rename to plugins/memory/webui/memory-dashboard-store.js
index bf246f5e8a..d2b61cafaa 100644
--- a/webui/components/settings/memory/memory-dashboard-store.js
+++ b/plugins/memory/webui/memory-dashboard-store.js
@@ -3,6 +3,7 @@ import { getContext } from "/index.js";
import * as API from "/js/api.js";
import { openModal, closeModal } from "/js/modals.js";
import { store as notificationStore } from "/components/notifications/notification-store.js";
+const MEMORY_DASHBOARD_API = "/plugins/memory/memory_dashboard";
// Helper function for toasts
function justToast(text, type = "info", timeout = 5000) {
@@ -53,7 +54,7 @@ const memoryDashboardStore = {
pollingEnabled: false,
async openModal() {
- await openModal("settings/memory/memory-dashboard.html");
+ await openModal("../plugins/memory/webui/memory-dashboard.html");
},
init() {
@@ -91,7 +92,7 @@ const memoryDashboardStore = {
async getCurrentMemorySubdir() {
try {
// Try to get current memory subdirectory from the backend
- const response = await API.callJsonApi("memory_dashboard", {
+ const response = await API.callJsonApi(MEMORY_DASHBOARD_API, {
action: "get_current_memory_subdir",
context_id: getContext(),
});
@@ -113,7 +114,7 @@ const memoryDashboardStore = {
this.error = null;
try {
- const response = await API.callJsonApi("memory_dashboard", {
+ const response = await API.callJsonApi(MEMORY_DASHBOARD_API, {
action: "get_memory_subdirs",
});
@@ -172,7 +173,7 @@ const memoryDashboardStore = {
}
try {
- const response = await API.callJsonApi("memory_dashboard", {
+ const response = await API.callJsonApi(MEMORY_DASHBOARD_API, {
action: "search",
memory_subdir: this.selectedMemorySubdir,
area: this.areaFilter,
@@ -324,12 +325,9 @@ const memoryDashboardStore = {
const selectedMemories = this.selectedMemories;
if (selectedMemories.length === 0) return;
- const confirmMessage = `Are you sure you want to delete ${selectedMemories.length} selected memories? This cannot be undone.`;
- if (!confirm(confirmMessage)) return;
-
try {
this.loading = true;
- const response = await API.callJsonApi("memory_dashboard", {
+ const response = await API.callJsonApi(MEMORY_DASHBOARD_API, {
action: "bulk_delete",
memory_subdir: this.selectedMemorySubdir,
memory_ids: selectedMemories.map((memory) => memory.id),
@@ -451,7 +449,7 @@ ${memory.content_full}
this.editMode = false;
this.editMemoryBackup = null;
// Use global modal system
- openModal("settings/memory/memory-detail-modal.html");
+ openModal("../plugins/memory/webui/memory-detail-modal.html");
},
closeMemoryDetails() {
@@ -511,7 +509,7 @@ ${memory.content_full}
main: "#3b82f6",
fragments: "#10b981",
solutions: "#8b5cf6",
- instruments: "#f59e0b",
+ skills: "#f59e0b",
};
return colors[area] || "#6c757d";
},
@@ -554,20 +552,12 @@ ${memory.content_full}
},
async deleteMemory(memory) {
- if (
- !confirm(
- `Are you sure you want to delete this memory from ${memory.area}?`
- )
- ) {
- return;
- }
-
try {
// Check if this is the memory currently being viewed in detail modal
const isViewingThisMemory =
this.detailMemory && this.detailMemory.id === memory.id;
- const response = await API.callJsonApi("memory_dashboard", {
+ const response = await API.callJsonApi(MEMORY_DASHBOARD_API, {
action: "delete",
memory_subdir: this.selectedMemorySubdir,
memory_id: memory.id,
@@ -685,7 +675,7 @@ ${memory.content_full}
async confirmEditMode() {
try {
- const response = await API.callJsonApi("memory_dashboard", {
+ const response = await API.callJsonApi(MEMORY_DASHBOARD_API, {
action: "update",
memory_subdir: this.selectedMemorySubdir,
original: JSON.parse(this.editMemoryBackup),
diff --git a/webui/components/settings/memory/memory-dashboard.html b/plugins/memory/webui/memory-dashboard.html
similarity index 73%
rename from webui/components/settings/memory/memory-dashboard.html
rename to plugins/memory/webui/memory-dashboard.html
index aaaeac15d2..8cc6a7095e 100644
--- a/webui/components/settings/memory/memory-dashboard.html
+++ b/plugins/memory/webui/memory-dashboard.html
@@ -3,7 +3,7 @@
Memory Dashboard
@@ -14,7 +14,7 @@
class="memory-dashboard">
-