Skip to main content
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

Creates a configured FastAPI application with:
  • CORS middleware (allows all origins for local use)
  • Database initialization and shared AgentRegistry
  • Router registration (include_router for each module above)
  • Static file serving (for web frontend, when dist/ build exists)
  • Dispatch-queue + document-monitor startup tasks
Default port: 4200

Endpoint Registration

Each router under src/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:
  1. A background thread calls AgentSDK.send_stream() synchronously
  2. Chunks are placed into a queue.Queue
  3. The async generator polls the queue and yields SSE events
  4. 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.Row for 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 updated last_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 to localhost by default. Note: gaia chat --ui binds to 0.0.0.0 for Electron/browser access
  • No authentication: Designed for single-user local use. Do not expose to untrusted networks
  • File path validation: The upload-path endpoint 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() in server.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