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/ as a Python module. Once placed there, the agent registers automatically and is listed by the Agent UI backend’s GET /api/agents.
Custom agents can have their own:
- Personality and instructions (system prompt)
- Tools (RAG, file search, shell, image generation, vision, plus your own
@toolfunctions) - Preferred models (override the server default)
- Conversation starters (suggestion chips in the UI)
- MCP servers (any Model Context Protocol server)
- Connectors (Google, GitHub, and more) — give your agent permission to read your real email, calendar, repos, etc.
This guide builds a local custom agent in
~/.gaia/agents/ for your own Agent UI.Python Agent
A custom agent is a Python module — add custom tools, built-in tool mixins, MCP servers, or any logic you need.Directory structure
Minimal Python agent
_register_tools() (it’s abstract
on the base Agent); the other two have sensible defaults you can override:
Adding built-in tools
GAIA ships with ready-to-use tool mixins. To enable most of them, inherit the mixin and call itsregister_*_tools() method from _register_tools(). The sd and vlm mixins are the exception — call init_sd() / init_vlm() (which set up the client and register the tools in one step):
Overriding the default model (optional)
If your agent needs a specific model, setmodel_id in __init__():
agent.yaml next to agent.py with a models: list — the registry reads that list as an ordered preference. The sidecar only honours the models: key; any other top-level key is ignored.
Using GAIA connectors
If your agent needs to act on your behalf — read your inbox, list your calendar events, query GitHub, post to Slack, etc. — wire it up to a GAIA connector rather than asking users to paste API tokens into your code. A connector lets users:- Authenticate once in Settings → Connections (OAuth flow for Google-style providers, paste-an-API-key for MCP servers).
- Grant scopes per agent so each agent only sees the data it actually needs. The Agent UI surfaces this when a user first picks your agent.
- Trust that secrets stay in the OS keyring, never in plaintext files or env vars baked into your code.
REQUIRED_CONNECTORS on the
class, and call get_credential_sync(connector_id, agent_id, required_scopes=[...])
from inside a tool to get a usable token. The
connectors-demo agent
is a working reference for both oauth_pkce (Google) and mcp_server
(GitHub) connectors.
Read the connectors guide
Walks through what connectors are, how the OAuth + MCP flows differ,
per-agent grants, and a step-by-step setup for Google and GitHub.
Export and import agents
Custom agents can be packaged into a single.zip bundle and shared between machines, teammates, or environments with the gaia agent export and gaia agent import CLI commands. Exports include every ~/.gaia/agents/* directory with an agent.py — the installer-seeded bundled example included; imported copies land as user-owned agents the seeder never touches.
What’s in the bundle
Each.zip contains a bundle.json manifest at the root and one directory per agent:
Security
Importing runs third-party code. A bundle’s
agent.py files execute inside your GAIA process. gaia agent import (without --yes) lists the agent IDs and requires explicit confirmation before installing. Only import bundles from sources you trust.Examples
Example Agent — simple personality
Example Agent — simple personality
Research Agent — RAG + file search
Research Agent — RAG + file search
RAGToolsMixin and FileSearchToolsMixin read state off the host agent —
self.rag, self.indexed_files, self.max_chunks, self.current_session,
self.session_manager — that nothing sets by default, so the agent must wire
it up itself (see the RAG tools mixin contract
for what each attribute is for). Pass documents pointing at wherever your
documents actually live; the example never widens access beyond that.Code Review Agent — shell + file I/O
Code Review Agent — shell + file I/O
FileIOToolsMixin reads self.path_validator off the host agent, which
nothing sets by default, so the agent wires it up itself. Pass documents
pointing at wherever the code to review actually lives — an unset
PathValidator only allows the current directory, never widen it to a
filesystem root or the home directory.Why a custom RAG agent can’t see the Document Library
A custom agent’sdocuments list only ever contains what the caller passes
in — not the Agent UI’s Document Library. If you index a folder of PDFs
through the Library panel, then run a custom agent like ResearchAgent
above with no documents argument, query_documents will honestly report
"No documents are currently indexed" even though the Library shows them.
That’s expected, not a bug — here’s why.
The Agent UI passes each conversation only the documents explicitly attached
to it (internally, the rag_documents list), never the whole Library. This
is deliberate: earlier versions exposed every library document to every
agent, which meant one session’s documents could leak into an unrelated
session’s answers. If a session has no documents attached, rag_documents
comes through empty — not the library — so you have to index what you want
your custom agent to see.
There’s also no persistent, shared vector index an agent can just attach to.
The Document Library is file metadata plus files on disk; it caches
extracted text per file so re-indexing skips redundant parsing, but the
FAISS index itself is built in memory, per agent instance, from whatever
paths that instance was constructed with — nothing is written to or read
from disk as a vector index, and nothing carries over between agents.
The flow that works: call index_document or index_directory (both from
RAGToolsMixin) once your agent is constructed, then query. That’s the same
index-then-query sequence the built-in agents use — there’s no shortcut that
skips indexing.
Troubleshooting
My agent isn't registered
My agent isn't registered
- Ensure the directory is under
~/.gaia/agents/<id>/and containsagent.py. - The directory name does not need to match the
AGENT_IDclass attribute, but it helps. - Check the server logs for warnings like
Failed to load agent from .... - After adding or editing the agent, restart the GAIA server — discovery runs at boot.
Agent fails to load
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 required _register_tools() method is implemented (_get_system_prompt() and _create_console() are optional overrides).Imported agent doesn't appear or shows errors
Imported agent doesn't appear or shows errors
gaia agent importprints per-agent errors afterErrors:— check those first.- Confirm each agent directory in the bundle contains an
agent.pyat its root. Bundles missingagent.pyare rejected. - Restart the GAIA server so discovery picks up the imported agents.
- Bundles produced on a different GAIA version may reference imports that don’t exist locally — check the server logs for
ImportError.
MCP server not connecting
MCP server not connecting
- Ensure
npxor the MCP server command is installed and accessible in$PATH. - Check the server logs for
MCPconnection errors. - Test the MCP server standalone before adding it to your agent.
Agent uses wrong model
Agent uses wrong model
If your preferred model isn’t loaded on the Lemonade server, GAIA falls back to the server default. Run
gaia init to download additional models.Next Steps
Agent System SDK
Deep dive into the base Agent class, tool registry, and state machine
MCP Integration
Connect any MCP server to extend your agent with external tools
GAIA Connectors
Give your agent permission to read Gmail, GitHub, Slack, and more — without baking API keys into code
RAG SDK
Add document Q&A to your agent with the RAG SDK
Agent UI Guide
Learn about the GAIA Agent UI and how agents are surfaced there
Custom Installer
Ship your agent pre-loaded in a branded, signed GAIA installer