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.
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.

CORS

Browser (cross-origin) access is limited to localhost / 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):
Setting the variable to * 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.

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:
Run requests that need these tools through the Agent UI (gaia chat --ui), which is the surface with a real confirmation handshake (permission_request + POST /api/chat/confirm-tool).
For a trusted, single-user, localhost-only server you can opt out:
This disables the approval requirement for every high-risk tool, so any prompt injection that reaches the agent can run shell commands and write files. gaia api start prints a warning when it is set, and every approval taken this way is logged with the tool name. Never set it on a shared or network-exposed host. See Output Handlers.

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 at src/gaia/api/agent_registry.py, not a runtime register() API. To add a new model, append an entry to AGENT_MODELS:
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

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.

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’s confirmation_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.