Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ yarn-error.log*

# Node.js build outputs
build/
# Allow committed demo agents in the installer staging dir
!src/gaia/apps/webui/build/
!src/gaia/apps/webui/build/bundled-agents/
!src/gaia/apps/webui/build/bundled-agents/**
src/gaia/apps/webui/build/bundled-agents/**/__pycache__/
src/gaia/apps/webui/build/bundled-agents/**/*.pyc
dist/
out/
.next/
Expand Down
3 changes: 3 additions & 0 deletions docs/deployment/ui.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ The GAIA Agent UI is distributed as an [npm package](https://www.npmjs.com/packa
<Card title="Agent UI SDK" icon="code" href="/sdk/sdks/agent-ui">
Python backend API: FastAPI server, SQLite database, Pydantic models, and SSE streaming.
</Card>
<Card title="Custom Installer" icon="box-archive" href="/playbooks/custom-installer/index">
Ship a branded GAIA build with your agent pre-loaded.
</Card>
</CardGroup>

---
Expand Down
6 changes: 6 additions & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@
"playbooks/emr-agent/part-2-dashboard",
"playbooks/emr-agent/part-3-architecture"
]
},
{
"group": "Custom Installer",
"pages": [
"playbooks/custom-installer/index"
]
}
]
},
Expand Down
271 changes: 125 additions & 146 deletions docs/guides/custom-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ icon: "wand-magic-sparkles"

## Overview

GAIA's agent registry lets you extend the Agent UI with your own custom agents. Each agent lives in its own directory under `~/.gaia/agents/` and is described by either a YAML manifest or a Python module. Once placed there, the agent appears automatically in the **agent selector** dropdown of the GAIA UI.
GAIA's agent registry lets you extend the Agent UI with your own custom agents. Each agent lives in its own directory under `~/.gaia/agents/` as a Python module. Once placed there, the agent appears automatically in the **agent selector** dropdown of the GAIA UI.

Custom agents can have their own:
- **Personality and instructions** (system prompt)
- **Tools** (RAG, file search, shell, image generation, vision)
- **Tools** (RAG, file search, shell, image generation, vision, plus your own `@tool` functions)
- **Preferred models** (override the server default)
- **Conversation starters** (suggestion chips in the UI)
- **MCP servers** (any Model Context Protocol server)
Expand Down Expand Up @@ -46,106 +46,16 @@ Open that file to customize the instructions and add tools.

---

## Manual Creation: YAML Manifest
## Python Agent

For full control, write the manifest yourself.
For full control — custom tools, built-in tool mixins, MCP servers, or complex logic — write a Python module.

### Directory structure

```
~/.gaia/agents/
└── my-agent/
└── agent.yaml # required
```

### Minimal manifest

The smallest valid manifest needs only `id`, `name`, and `instructions`:

```yaml
manifest_version: 1
id: my-agent
name: My Agent
instructions: You are a helpful assistant.
```

### Full manifest reference

```yaml
manifest_version: 1

# Unique ID used internally (lowercase letters, numbers, hyphens only)
id: weather-agent

# Display name shown in the UI agent selector
name: Weather Agent

# One-line description shown as a tooltip
description: An agent that provides weather updates

# System prompt — defines your agent's personality and behavior
instructions: |
You are a cheerful weather forecaster who always relates topics back
to the current weather. When you don't know the actual weather, make
a playful estimate based on the season.

Be concise, friendly, and always sign off with a weather pun.

# Tools that give your agent extra capabilities.
# Available: rag, file_search, file_io, shell, screenshot, sd, vlm
# Omit this field to get the defaults: [rag, file_search]
tools: []

# Preferred models — first available model is used at runtime.
# Omit to use the server's current default model.
models:
- Qwen3.5-35B-A3B-GGUF
- Qwen3-0.6B-GGUF

# Suggestion chips shown on the welcome screen for this agent.
conversation_starters:
- "What's the weather like today?"
- "Tell me a weather fun fact"
- "What should I wear tomorrow?"

# MCP (Model Context Protocol) servers — each entry is a subprocess
# that provides additional tools to your agent.
# mcp_servers:
# time:
# command: npx
# args: ["-y", "@anthropic/mcp-time-server"]
#
# weather:
# command: npx
# args: ["-y", "@anthropic/mcp-weather-server"]
# env:
# WEATHER_API_KEY: "your-api-key-here"
```

### Available tools

| Tool | What it does |
|------|-------------|
| `rag` | Document Q&A with RAG — index and query files |
| `file_search` | Find files on disk by name or content |
| `file_io` | Read and write files |
| `shell` | Execute shell commands |
| `screenshot` | Capture screenshots |
| `sd` | Generate images with Stable Diffusion |
| `vlm` | Analyze images with a Vision Language Model |

---

## Advanced: Python Agent

For agents that need custom tools or complex logic, write a Python module instead of (or alongside) a YAML manifest.

### Directory structure

```
~/.gaia/agents/
└── my-python-agent/
├── agent.py # required — Python takes precedence over YAML
├── agent.py # required
└── agent.yaml # optional — used only for the `models` field
```

Expand Down Expand Up @@ -187,61 +97,132 @@ The three required methods are:
| `_create_console()` | Returns an `AgentConsole` instance |
| `_register_tools()` | Registers tools into `_TOOL_REGISTRY` |

### Adding built-in tools

GAIA ships with ready-to-use tool mixins. To enable them, inherit the mixin and call its `register_*_tools()` method from `_register_tools()`:

| Tool | Mixin | Register call |
|------|-------|---------------|
| `rag` | `gaia.agents.chat.tools.rag_tools.RAGToolsMixin` | `self.register_rag_tools()` |
| `file_search` | `gaia.agents.tools.file_tools.FileSearchToolsMixin` | `self.register_file_search_tools()` |
| `file_io` | `gaia.agents.code.tools.file_io.FileIOToolsMixin` | `self.register_file_io_tools()` |
| `shell` | `gaia.agents.chat.tools.shell_tools.ShellToolsMixin` | `self.register_shell_tools()` |
| `screenshot` | `gaia.agents.tools.screenshot_tools.ScreenshotToolsMixin` | `self.register_screenshot_tools()` |
| `sd` | `gaia.sd.mixin.SDToolsMixin` | `self.register_sd_tools()` |
| `vlm` | `gaia.vlm.mixin.VLMToolsMixin` | `self.register_vlm_tools()` |

### Overriding the default model (optional)

If your agent needs a specific model, set `model_id` in `__init__()`:

```python
def __init__(self, **kwargs):
kwargs.setdefault("model_id", "Qwen3-0.6B-GGUF")
super().__init__(**kwargs)
```

Alternatively, create a companion `agent.yaml` next to `agent.py` with a `models:` list — the registry reads that list as an ordered preference.

---

## Examples

<AccordionGroup>
<Accordion title="Zoo Agent — simple YAML personality">
```yaml
manifest_version: 1
id: zoo-agent
name: Zoo Agent
description: A zookeeper who loves animals
instructions: |
You are a funny and enthusiastic zookeeper! You work at the world's
best zoo and every response you give includes a fun fact or a playful
reference to one of your beloved zoo animals.
tools: []
conversation_starters:
- "Hello! What's happening at the zoo today?"
- "Tell me a fun fact about one of your animals."
<Accordion title="Zoo Agent — simple personality">
```python
from gaia.agents.base.agent import Agent
from gaia.agents.base.console import AgentConsole
from gaia.agents.base.tools import _TOOL_REGISTRY


class ZooAgent(Agent):
AGENT_ID = "zoo-agent"
AGENT_NAME = "Zoo Agent"
AGENT_DESCRIPTION = "A zookeeper who loves animals"
CONVERSATION_STARTERS = [
"Hello! What's happening at the zoo today?",
"Tell me a fun fact about one of your animals.",
]

def _get_system_prompt(self) -> str:
return (
"You are a funny and enthusiastic zookeeper! You work at the world's "
"best zoo and every response you give includes a fun fact or a playful "
"reference to one of your beloved zoo animals."
)

def _create_console(self) -> AgentConsole:
return AgentConsole()

def _register_tools(self) -> None:
_TOOL_REGISTRY.clear()
```
</Accordion>

<Accordion title="Research Agent — RAG + file search">
```yaml
manifest_version: 1
id: research-agent
name: Research Agent
description: Searches documents and files to answer questions
instructions: |
You are a thorough research assistant. When asked a question,
first search available documents and files before answering.
Always cite your sources.
tools:
- rag
- file_search
conversation_starters:
- "Summarize my project notes"
- "Find files related to..."
- "What does the documentation say about...?"
```python
from gaia.agents.base.agent import Agent
from gaia.agents.base.console import AgentConsole
from gaia.agents.base.tools import _TOOL_REGISTRY
from gaia.agents.chat.tools.rag_tools import RAGToolsMixin
from gaia.agents.tools.file_tools import FileSearchToolsMixin


class ResearchAgent(Agent, RAGToolsMixin, FileSearchToolsMixin):
AGENT_ID = "research-agent"
AGENT_NAME = "Research Agent"
AGENT_DESCRIPTION = "Searches documents and files to answer questions"
CONVERSATION_STARTERS = [
"Summarize my project notes",
"Find files related to...",
"What does the documentation say about...?",
]

def _get_system_prompt(self) -> str:
return (
"You are a thorough research assistant. When asked a question, "
"first search available documents and files before answering. "
"Always cite your sources."
)

def _create_console(self) -> AgentConsole:
return AgentConsole()

def _register_tools(self) -> None:
_TOOL_REGISTRY.clear()
self.register_rag_tools()
self.register_file_search_tools()
```
</Accordion>

<Accordion title="Code Review Agent — shell + file I/O">
```yaml
manifest_version: 1
id: code-review-agent
name: Code Review Agent
description: Reviews code and runs linters
instructions: |
You are an expert code reviewer. You read files, run linters,
and provide actionable feedback. Be specific about file names
and line numbers. Prioritize correctness and security.
tools:
- file_io
- shell
```python
from gaia.agents.base.agent import Agent
from gaia.agents.base.console import AgentConsole
from gaia.agents.base.tools import _TOOL_REGISTRY
from gaia.agents.chat.tools.shell_tools import ShellToolsMixin
from gaia.agents.code.tools.file_io import FileIOToolsMixin


class CodeReviewAgent(Agent, FileIOToolsMixin, ShellToolsMixin):
AGENT_ID = "code-review-agent"
AGENT_NAME = "Code Review Agent"
AGENT_DESCRIPTION = "Reviews code and runs linters"

def _get_system_prompt(self) -> str:
return (
"You are an expert code reviewer. You read files, run linters, "
"and provide actionable feedback. Be specific about file names "
"and line numbers. Prioritize correctness and security."
)

def _create_console(self) -> AgentConsole:
return AgentConsole()

def _register_tools(self) -> None:
_TOOL_REGISTRY.clear()
self.register_file_io_tools()
self.register_shell_tools()
```
</Accordion>
</AccordionGroup>
Expand All @@ -252,19 +233,14 @@ The three required methods are:

<AccordionGroup>
<Accordion title="My agent doesn't appear in the selector">
- Ensure the directory is under `~/.gaia/agents/<id>/` and contains `agent.yaml` or `agent.py`.
- The directory name does not need to match the `id` in the manifest, but it helps.
- Ensure the directory is under `~/.gaia/agents/<id>/` and contains `agent.py`.
- The directory name does not need to match the `AGENT_ID` class attribute, but it helps.
- Check the server logs for warnings like `Failed to load agent from ...`.
- If you created the agent manually (not via the Builder), **restart the GAIA server** — discovery runs at boot. Agents created via the Builder Agent are loaded immediately without a restart.
</Accordion>

<Accordion title="Manifest validation errors">
Run `python -c "import yaml; from gaia.agents.registry import AgentManifest; AgentManifest(**yaml.safe_load(open('~/.gaia/agents/<id>/agent.yaml').read()))"` to validate your manifest.

Common issues:
- `id` must be non-empty and contain only lowercase letters, numbers, and hyphens.
- `tools` must only reference known tool names (see table above).
- `manifest_version` must be `1`.
<Accordion title="Agent fails to load">
Check the server logs for load errors. Ensure `AGENT_ID`, `AGENT_NAME`, and `AGENT_DESCRIPTION` are set as class attributes, and that the three required methods (`_get_system_prompt`, `_create_console`, `_register_tools`) are implemented.
</Accordion>

<Accordion title="MCP server not connecting">
Expand Down Expand Up @@ -295,6 +271,9 @@ The three required methods are:
<Card title="Agent UI Guide" icon="browser" href="/guides/agent-ui">
Learn about the GAIA Agent UI and how agents are surfaced there
</Card>
<Card title="Custom Installer" icon="box-archive" href="/playbooks/custom-installer/index">
Ship your agent pre-loaded in a branded, signed GAIA installer
</Card>
</CardGroup>

---
Expand Down
Loading
Loading