You are viewing: API Specification - Complete technical referenceSee also: User Guide | SDK Reference
- Component: Agent UI Server - FastAPI backend for the desktop chat application
- Module:
gaia.ui - Import:
from gaia.ui.server import create_app - Source:
src/gaia/ui/
Overview
The Agent UI Server is a FastAPI-based backend that powers the GAIA Chat desktop application. It provides REST API endpoints for session management, real-time chat with SSE streaming, document library management, and system health monitoring. Key Design Decisions:- SQLite for zero-configuration persistence (WAL mode for concurrent reads)
- FastAPI for automatic OpenAPI docs and Pydantic validation
- SSE (Server-Sent Events) for streaming chat responses
- Hybrid document model — global library with per-session attachment
- Shared database between CLI and desktop app
Module Structure
Routers (src/gaia/ui/routers/)
As of v0.17.x the HTTP surface is split into focused router modules. Every route
is registered under the /api prefix (e.g. the chat router serves
POST /api/chat/send); the Mount column below names the surface, not the
literal path prefix. Additional routers exist beyond the core set below
(connectors, goals, hub, memory, schedules).
Server (server.py)
App Factory
- CORS middleware (allows all origins for local use)
- Database initialization and shared
AgentRegistry - Router registration (
include_routerfor each module above) - Static file serving (for web frontend, when
dist/build exists) - Dispatch-queue + document-monitor startup tasks
4200
Endpoint Registration
Each router undersrc/gaia/ui/routers/ is mounted via app.include_router(...).
Routers receive the shared ChatDatabase and AgentRegistry through the
dependency helpers in dependencies.py. Database objects remain accessible via
app.state.db for tests.
Streaming Implementation
Chat streaming uses a thread-based producer/consumer pattern:- A background thread calls
AgentSDK.send_stream()synchronously - Chunks are placed into a
queue.Queue - The async generator polls the queue and yields SSE events
- On completion, the full response is saved to the database
Helper Functions
Database (database.py)
Schema
Four tables with foreign key relationships:Configuration
- Foreign keys: Enabled (
PRAGMA foreign_keys = ON) - Journal mode: WAL (
PRAGMA journal_mode = WAL) - Thread safety:
check_same_thread=False(FastAPI runs across threads) - Row factory:
sqlite3.Rowfor dict-like access
Transaction Management
Document Deduplication
Documents are deduplicated by SHA-256 file hash. If a document with the same hash already exists, the existing record is returned with an updatedlast_accessed_at timestamp.
Document Upload Paths
The server exposes two document upload endpoints, each for a different source of truth:
The blob endpoint exists because browser
File objects never expose a filesystem path, and since Electron 32 File.path has been removed as well (see issue #728). It streams the upload with a running size check (capped at 20 MB), computes a SHA-256 hash, short-circuits on dedup by hash, and only then promotes the file into the managed directory via an atomic os.replace. On failure, partial and orphan files are cleaned up.
When a server-owned document is deleted (DELETE /api/documents/{id}), the on-disk file under ~/.gaia/documents/ is also unlinked as a best-effort cleanup. User-owned files from upload-path are left untouched.
Cascade Deletes
- Deleting a session cascades to its messages and session_documents entries
- Deleting a document cascades to session_documents entries
Models (models.py)
All 14 Pydantic models:
Dependencies
Required
Optional
Error Handling
Security Considerations
- CORS: Uses an allowlist of localhost origins plus ngrok regex. The standalone server (
python -m gaia.ui.server) binds tolocalhostby default. Note:gaia chat --uibinds to0.0.0.0for Electron/browser access - No authentication: Designed for single-user local use. Do not expose to untrusted networks
- File path validation: The
upload-pathendpoint sanitizes all user-provided paths:- Null byte rejection (prevents path injection)
- Path resolution to absolute canonical paths (eliminates
..traversal) - File extension allowlist (only document/code file types accepted)
- See
_sanitize_document_path()inserver.py
- Static file serving: URL paths are validated to stay within the
dist/directory via_sanitize_static_path(), preventing directory traversal - SQL injection: Prevented by parameterized queries throughout
- No telemetry: No data is sent externally