Source Code:
src/gaia/api/Import:
from gaia.api.openai_server import appDetailed Spec: spec/api-server
7.1 OpenAI-Compatible API
Purpose: Expose GAIA agents as OpenAI-compatible REST API.What a request delivers to the agent
Each request gets a fresh agent, loaded with the conversation the client sent:- History — every message before the final one becomes the agent’s conversation history. The final message must be from the user, or the request fails with 400.
- System instructions —
systemanddevelopermessages are added after the agent’s own system prompt; they don’t replace it. - Content parts —
contentmay be a string or an array of parts. Text parts are joined with newlines. Other part types (image_url,input_audio,file) fail with a 400 that names the type. - Sampling —
temperature,top_p, andmax_tokensapply to every model call the agent makes while answering, somax_tokenscaps each call, not the whole answer. Omit them to keep the agent’s defaults.
CORS
Browser (cross-origin) access is limited tolocalhost / 127.0.0.1 origins
by default. Non-browser clients (the OpenAI SDK, curl, VSCode) are unaffected —
CORS only gates requests made from web pages.
To let a web app on another origin call the API, list its origin in
GAIA_API_CORS_ORIGINS (comma-separated):
* opens the API to all origins but disables
credentialed requests — wildcard origins combined with credentials are
forbidden by the Fetch spec and would let any website the user visits call
the local API.
Authentication
POST /v1/chat/completions runs the agent loop, so a caller that reaches it can
make the agent read files and call tools. Set GAIA_API_KEY to require a key:
Browser requests from an origin outside the CORS allowlist are refused with
403 before the agent runs, whether or not a key is set.
The
/v1/<agent>/* relay is stricter: it is disabled (503) until
GAIA_API_KEY is set.
Agents served with --api through the framework’s generic server
(gaia.agents.base.server.AgentServer) apply the same policy to every route
except /health.
The VSCode extension sends a fixed key (
Bearer gaia). It keeps working while
GAIA_API_KEY is unset; once you set a key, the extension’s requests get 401.High-risk tools are refused
Tools that mutate the machine —run_shell_command, write_file, edit_file
and the rest of
TOOLS_REQUIRING_CONFIRMATION,
plus anything an agent adds via CONFIRMATION_REQUIRED_TOOLS — require explicit
user approval. That approval is GAIA’s backstop against prompt injection: a
document, email, or web page the agent reads can talk the model into a
destructive tool call the user never asked for.
The OpenAI-compatible API is a one-shot request/response surface with no channel
to ask the caller “allow this?”, so it refuses those tools rather than
auto-approving them — the tool returns
{"status": "denied", "error": "…requires explicit user approval…"} instead of
executing. The refusal is not silent to the caller either: streaming clients get
a tool_confirm_denied event and non-streaming responses are prefixed with the
same message, naming the tool and what to do instead:
gaia chat --ui),
which is the surface with a real confirmation handshake
(permission_request + POST /api/chat/confirm-tool).
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:
Registering new agents with the server
The API server exposes a static registry of agent models atsrc/gaia/api/agent_registry.py, not a runtime register() API. AGENT_MODELS
ships one entry, gaia, the flagship agent. To expose another model, append an
entry to AGENT_MODELS:
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
Events emitted
The API-layerSSEOutputHandler 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.
Disconnects and failures
If the client disconnects mid-stream, the agent is told to stop and quits at its next step instead of finishing the turn. If the agent fails after streaming has started, the stream ends with an{"error": {"message": ..., "type": "server_error"}} chunk and then
data: [DONE], since the HTTP status has already been sent.
The stop takes effect at the agent’s next step or tool, so a model call that
is already in flight runs to completion and keeps its worker thread until
it returns. Agent runs execute on the default thread pool, so a client that
repeatedly starts and cancels long requests can keep those workers busy and
delay unrelated requests.
Confirmation-gated tools are denied on this surface
This stream is one-way — the client has no channel to answer a permission request — so tools in the agent’sconfirmation_required_tools() set (shell,
file mutation, email send/delete) are denied rather than executed, and the
reason is streamed as a tool_confirm_denied event. See
High-risk tools are refused above for the full
contract and the unattended-approval opt-out.
Related Topics
- Core Agent System - Learn about the base Agent class
- MCP Integration - Model Context Protocol support
- Specialized Agents - Pre-built agent implementations
- Application Packaging - Package agents for distribution