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 @@ frdel%2Fagent-zero | Trendshift

-[![Agent Zero Website](https://img.shields.io/badge/Website-agent--zero.ai-0A192F?style=for-the-badge&logo=vercel&logoColor=white)](https://agent-zero.ai) [![Thanks to Sponsors](https://img.shields.io/badge/GitHub%20Sponsors-Thanks%20to%20Sponsors-FF69B4?style=for-the-badge&logo=githubsponsors&logoColor=white)](https://github.com/sponsors/agent0ai) [![Follow on X](https://img.shields.io/badge/X-Follow-000000?style=for-the-badge&logo=x&logoColor=white)](https://x.com/Agent0ai) [![Join our Discord](https://img.shields.io/badge/Discord-Join%20our%20server-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/B8KZKNsPpj) [![Subscribe on YouTube](https://img.shields.io/badge/YouTube-Subscribe-red?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/@AgentZeroFW) [![Connect on LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-blue?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/jan-tomasek/) [![Follow on Warpcast](https://img.shields.io/badge/Warpcast-Follow-5A32F3?style=for-the-badge)](https://warpcast.com/agent-zero) +[![Agent Zero Website](https://img.shields.io/badge/Website-agent--zero.ai-0A192F?style=for-the-badge&logo=vercel&logoColor=white)](https://agent-zero.ai) [![Thanks to Sponsors](https://img.shields.io/badge/GitHub%20Sponsors-Thanks%20to%20Sponsors-FF69B4?style=for-the-badge&logo=githubsponsors&logoColor=white)](https://github.com/sponsors/agent0ai) [![Follow on X](https://img.shields.io/badge/X-Follow-000000?style=for-the-badge&logo=x&logoColor=white)](https://x.com/Agent0ai) [![Join our Discord](https://img.shields.io/badge/Discord-Join%20our%20server-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/B8KZKNsPpj) [![Subscribe on YouTube](https://img.shields.io/badge/YouTube-Subscribe-red?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/@AgentZeroFW) [![Connect on LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-blue?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/jan-tomasek/) [![Follow on Warpcast](https://img.shields.io/badge/Warpcast-Follow-5A32F3?style=for-the-badge)](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.
-[![Showcase](/docs/res/showcase-thumb.png)](https://youtu.be/MdzLhWWoxEs) - +[![Showcase](/docs/res/showcase-thumb.png)](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: + +[![Easy Installation guide](/docs/res/easy_ins_vid.png)](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. -![Agent 0 Working](/docs/res/ui-screen-2.png) +![Agent 0 Working](/docs/res/ui_screen2.png) 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. -![Multi-agent](docs/res/physics.png) -![Multi-agent 2](docs/res/physics-2.png) +![Multi-agent](docs/res/usage/multi-agent.png) 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. -![Prompts](/docs/res/prompts.png) +![Prompts](/docs/res/profiles.png) 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: - -[![Easy Installation guide](/docs/res/easy_ins_vid.png)](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 -![Settings](docs/res/settings-page-ui.png) +![Settings](docs/res/settings-page-ui1.png) - 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 ![alt](img:///path/to/image.png) +images shown with ![alt](img:///path/to/image.png) 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 Logo](res/header.png) # 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 | +| `