Architecture

Llaboratory is a two-service application: a Python backend (FastAPI + SQLite) and a TypeScript/React frontend (Vite + Tailwind CSS). The two communicate over a REST API with Server-Sent Events for live streaming.

System overview

┌──────────────┐ ┌──────────────────────┐ ┌─────────────────┐
React UI ────> FastAPI Backend ────> LLM Provider
(Vite + TS) │ (Python + SQLite) │ (OpenAI API)
:5173 │ :8000
└──────────────┘ └──────────────────────┘ └─────────────────┘


┌──▼──────────┐
SQLite DB
(WAL mode)
└─────────────┘

Backend

The backend is a Python FastAPI application with the following layers:

Provider adapter layer

All providers are normalized to one internal representation so the agent loop, logging, and analysis are provider-agnostic. The harness ships two adapters — a Chat Completions adapter (OpenAI / OpenRouter / LM Studio / Ollama) and a Responses API adapter (OpenAI / OpenRouter /v1/responses) — selected by the model config's provider_kind. Each adapter:

Data model

Key entities (all persisted to SQLite):

Data lifecycle endpoints

Frontend

The frontend is a single-page React application:

Security

Dynamic tool code runs in-process without sandboxing. This is intentional for locally-authored tools in a single-user research harness.

API keys are supplied via environment variables and are never stored in the database or export bundles.

Concurrency

The batch runner executes at most 5 sessions concurrently. SQLite uses WAL mode so concurrent session writers don't serialize badly. Sessions beyond the cap wait in pending status.