| name | gaia-build-agent |
| description | Build a new GAIA agent with the SDK end-to-end: scaffold the package, write the Agent subclass, register @tool functions, compose reusable tool mixins, set the model + system prompt, and test it locally — then hand off to publishing. Use when creating a NEW agent (a Python class inheriting from the base Agent) for the GAIA repo or a user-authored package, not for tuning an existing agent's prompt (prompt-engineer), adding one tool to an existing class (python-developer), or shipping/releasing an already-built agent (use the agent-hub-release skill + docs/guides/hub-publishing.mdx). Pairs with the agent-hub-release skill: this one BUILDS, that one PUBLISHES. |
Building a GAIA Agent
How to take an idea to a working, testable GAIA agent — a Python class that runs
locally on AI PCs. This skill covers build; publishing is its sibling
agent-hub-release skill and the author guide
docs/guides/hub-publishing.mdx. The
full prose walkthrough is docs/guides/custom-agent.mdx.
Read CLAUDE.md first — the "No Silent Fallbacks", code-reuse,
testing, and eval rules all apply to a new agent.
The mental model
A GAIA agent is one Python class that inherits from the base Agent
(src/gaia/agents/base/agent.py) and exposes capabilities as @tool-decorated
methods. The base class owns the agent loop, tool registry, state, error recovery,
and (via mixins) MCP / OpenAI-API exposure — you write the prompt + the tools, not
the plumbing. There are no YAML agent manifests for in-core agents (removed in
v0.17.5); a publishable hub package adds a gaia-agent.yaml manifest on top (see
the publish skill).
Steps
-
Scaffold. gaia agent init my-agent generates a starter package at
./my-agent/. For a publishable hub package in this repo, add --layout hub
so it lands at hub/agents/<id>/python/:
gaia agent init my-agent -o hub/agents/ --layout hub
Then mirror an existing package (e.g. analyst, browser) for structure.
-
Write the Agent subclass. Inherit from Agent (or a closer base like the
chat/docqa agents). Leave model_id unset — that inherits the base default,
Gemma-4-E4B-it-GGUF (DEFAULT_MODEL_NAME), which is right for nearly every agent.
Every agent sharing one model is what keeps a single model resident, so switching
agents never triggers an eviction + cold reload. Only set model_id when the agent
genuinely needs a different model (e.g. the summarizer's Qwen3-4B-Instruct-2507-GGUF),
and say why. Keep the constructor thin.
-
Register tools with @tool. Each @tool method is a capability the LLM can
call; its docstring is the schema the model sees, so write it for the model
(one line of intent + each arg). Return structured data or an actionable error —
never swallow exceptions into a placeholder (No Silent Fallbacks).
-
Reuse, don't reinvent — compose mixins. Before writing file/web/RAG/shell/SQL
logic, check KNOWN_TOOLS in src/gaia/agents/registry.py:
rag, file_io, file_search, shell, browser, scratchpad, code_index,
vlm, sd, … Compose them by name instead of duplicating. New shared logic →
add a mixin and register it in KNOWN_TOOLS.
-
System prompt. Implement _get_system_prompt() — state the agent's job, when
to use which tool, and the output contract. This is an LLM-affecting surface, so
it's covered by the eval rule below.
-
Then publish
Once it runs and is documented (README/SPEC/SKILL per the doc-sync rule), ship it:
- Standard wheel → Hub + PyPI (PR route, no token): the
hub-publishing.mdx guide.
- Frozen-binary + npm sidecar (like the email agent): the
agent-hub-release skill.
- Taking an agent that already exists to a publishable, Agent-UI-usable state
(the parity kit, the generalize-before-documenting rule, the day-one gate): the
porting-agent-to-hub skill.
Reference
Output style
Follow CLAUDE.md → "How You Communicate".