Skip to main content
Source Code: src/gaia/api/
Import: from gaia.api.openai_server import app

Detailed Spec: spec/api-server

7.1 OpenAI-Compatible API

Purpose: Expose GAIA agents as OpenAI-compatible REST API.
from gaia.api.openai_server import app
import uvicorn

# Run server (app is a module-level FastAPI instance)
uvicorn.run(app, host="0.0.0.0", port=8080)

# Now accessible via the OpenAI SDK:
# from openai import OpenAI
# client = OpenAI(base_url="http://localhost:8080/v1", api_key="dummy")
# response = client.chat.completions.create(
#     model="gaia-code",
#     messages=[{"role": "user", "content": "Write Python code"}]
# )
Port 8080 is shared by default with gaia mcp docker. Run one of them on a different port (e.g. gaia api start --port 8081) if you need both alive at the same time.

7.2 Custom API Agent

Import: from gaia.agents.base.api_agent import ApiAgent ApiAgent is a mixin that already subclasses the core Agent; you only need to inherit from ApiAgent:
from gaia.agents.base.api_agent import ApiAgent
from gaia.agents.base.tools import tool

class MyAPIAgent(ApiAgent):
    """Agent exposed via OpenAI-compatible API."""

    def get_model_id(self) -> str:
        # Model ID shown in /v1/models
        return "my-custom-agent"

    def get_model_info(self) -> dict:
        return {
            "max_input_tokens": 4096,
            "max_output_tokens": 2048,
            "description": "Custom agent for data analysis",
            "capabilities": ["data_analysis", "visualization"],
        }

    def _get_system_prompt(self) -> str:
        return "You are a data analysis assistant."

    def _register_tools(self):
        @tool
        def analyze(data: str) -> dict:
            """Analyze data."""
            return {"analysis": "Data is valid"}

Registering new agents with the server

The API server exposes a static registry of agent models at src/gaia/api/agent_registry.py, not a runtime register() API. To add a new model, append an entry to AGENT_MODELS:
# src/gaia/api/agent_registry.py
AGENT_MODELS = {
    "gaia-code": {
        "class_name": "gaia.agents.routing.agent.RoutingAgent",
        "init_params": {
            "api_mode": True,
            "silent_mode": True,
            "streaming": False,
            "max_steps": 100,
        },
        "description": "Intelligent routing agent ...",
    },
    # 👇 New entry
    "my-agent": {
        "class_name": "my_package.my_agent.MyAPIAgent",
        "init_params": {"api_mode": True, "silent_mode": True},
        "description": "Custom agent for data analysis",
    },
}
The server imports class_name lazily on the first request. init_params are passed to the agent’s constructor; gaia api start --debug, --show-prompts, --streaming, and --step-through inject GAIA_API_* env-vars that the registry merges into init_params at startup.
Runtime plug-in discovery is on the roadmap (see src/gaia/agents/registry.py), but the OpenAI-compatible server still requires editing AGENT_MODELS and restarting the process.

7.3 SSE Streaming

Import: from gaia.api.sse_handler import SSEOutputHandler
from gaia.api.sse_handler import SSEOutputHandler

# Create SSE handler
sse = SSEOutputHandler()

# Use with agent (parameter name is output_handler, not console)
agent = MyAgent(output_handler=sse)

# Process query — events are pushed as they happen
result = agent.process_query("Generate code")

Events emitted

The API-layer SSEOutputHandler emits a strict subset used for OpenAI-style chat completions: chunk (streamed token deltas) and answer (final message). The Agent UI uses a richer handler in src/gaia/ui/sse_handler.py that emits additional events — tool_start, tool_end, tool_result, thinking, processing, error. When wiring SSE through the Agent UI routers you will see both surfaces.
// Example payloads emitted by src/gaia/ui/sse_handler.py
{"event": "tool_start", "data": {"name": "generate_code", "args": {...}}}
{"event": "tool_result", "data": {"name": "generate_code", "result": {...}}}
{"event": "answer", "data": {"text": "Here's the code..."}}