A self-hosted, multi-agent conversational assistant — LangGraph orchestration, Human-in-the-Loop before every mutation, transparency registers, enterprise observability, six languages.
If you find this project valuable, a star on GitHub is the best way to say so. Thank you!
Features • Admin & Monitoring • Quick Start • Architecture • Documentation • Contributing • Changelog
Version 1.47.1 — Connect a Google or Microsoft account once for the services you choose; see LIA's companion respond to what actually happens. Grouped consent and reconnection share one verified provider account while each service remains independently disconnectable. The expressive companion follows real work and the tone of the delivered answer, with quiet local-time and cached-weather context, and stays still when reduced motion is requested. Existing connections remain valid until you choose the new flow — 22 September 2026.
- What is LIA?
- Try LIA Online
- Built by an AI, Directed by a Human
- Screenshots
- Features
- Administration & Monitoring
- Quick Start
- Architecture
- Technologies
- Quality: Tests, CI/CD, Security
- Documentation
- Contributing
- Support
- License
- Acknowledgments
LIA is a personal assistant you host yourself. It reads your mail, calendar, contacts, tasks and documents through your own Google, Apple or Microsoft account, listens and speaks in six languages, acts on your behalf — never changes anything without asking first — and keeps a record of everything it did, read and decided.
Under the hood: a FastAPI backend orchestrating 20+ specialised agents with LangGraph, a Next.js front end, PostgreSQL + pgvector and Redis, and a multi-provider LLM layer that runs as well on a cloud model as on a local one through Ollama.
📅 "Find my meetings for tomorrow and send a reminder to all participants"
📧 "Summarize my unread emails from this week that have attachments"
👥 "Update the companies of my contacts who work at startups"
🔔 "Remind me tomorrow at 9am to call Marie for her birthday"
| The usual problem | What LIA does about it |
|---|---|
| Opaque LLM spend | Tokens are accounted per node and per provider; an account quota and an instance-wide daily ceiling both apply; prices live in an admin catalogue; everything exports to CSV |
| Actions nobody can audit | Human-in-the-Loop before any mutation, and three registers — what was done, what was read, what was decided — sealed per account on request |
| Fragmented integrations | One orchestration over 20+ agents, Google / Apple / Microsoft connectors, your own MCP servers, skills, plugins and sub-agents |
| Operations in the dark | Prometheus, Grafana, Loki, Tempo and Langfuse, a vital alert core with runbooks, and a self-diagnosis written in the administrator's language |
| Vendor lock-in | Seven LLM providers with local models as first-class citizens, self-hosted on anything from a Raspberry Pi to a server, AGPL-3.0 |
LIA is hosted at https://lia.jeyswork.com/ — no installation required.
The interactive showroom runs six guided synthetic missions, one per differentiating mechanism: orchestration under approval, proactivity, persistent memory, outbound calls, rich replies and in-app configuration. Approve, edit or refuse each prepared change through the real approval UI, and read LIA's closing reply rendered by the production pipeline. Everything is labelled synthetic — no account, model or external service is contacted — and a proof drawer links every visible capability to its exact source. When a live demonstrator is published, the same page lists what is switched on there and what is not — read from the demonstrator's own configuration, never kept by hand — before offering the link.
Closed beta — access is granted at the administrator's discretion. To request an invitation, write to liamyassistant@gmail.com.
Self-hosting starts at the Quick Start below.
"Speed comes from the AI. Quality comes from the framework."
Nearly 100% of this codebase was written by an AI, under human direction: a written engineering rulebook, blocking automated checks, systematic review, adversarial audits. The result is measured, not proclaimed:
| 51 functional domains | 720,000+ source lines (excl. tests) | 39,000+ automated tests | 301 ADRs |
| 266 versions shipped | 6 languages, parity enforced in CI | 583 Prometheus metrics | 8.3/10 technical audit, 24 normalized areas |
Source-line figure: 722,557 physical lines in Python, TypeScript, JavaScript and CSS under apps/api/src and apps/web/src, excluding test directories and *.test.*/*.spec.* files (measured 2026-09-22, rounded down). The published technical audit does not score security.
- The full story — method, trade-offs, results and what remains to be done, weaknesses included: lia.jeyswork.com/story
- The audit itself — 24 normalized areas mapped to ISO/IEC 25010:2023, every score backed by executed evidence, open worksites included, with the protocol and the full standalone report: docs/audit/
Dashboard — Homepage with quick access, usage statistics, and personalized greeting
Chat — Multi-agent conversation with real-time debug panel (right sidebar)
More screenshots
Chat — Debug panel: per-message routing, tool calls, token cost and reasoning timeline
Chat — Interactive skill widgets: maps, dashboards, calendars and mini-apps rendered inline
Settings — Preferences: connectors, MCP servers, language, timezone, and themes
Settings — Features: LIA Style, long-term memory, interests, proactive notifications, scheduled actions, sub-agents, channels
Settings — Long-term memory: pinned facts, automatic extraction, edit / delete / pin per memory
Settings — Psyche Engine: Big Five personality traits modulating the assistant's emotional responsiveness
Settings — Administration: LLM config, RAG Spaces, users, connectors, pricing, skills, voice, broadcast, debug
Administration — One-click simplicity: every admin action is accessible in a single click, no technical skills required
Administration — LLM Configuration: 7 providers (OpenAI, Anthropic, Google Gemini, DeepSeek, Qwen, Perplexity, Ollama), per-node model selection
Every capability below is documented in an architecture decision record (ADR) or a technical document — the links lead there.
- A chat that streams — answers arrive over SSE with rich HTML cards, interactive widgets and a per-message cost badge; in the rich HTML mode every data-bearing answer is a composed page — a lead sentence, one section per facet in the component that fits it, a closing callout — laid out on conversational turns too unless a voice is reading them (ADR-177); images and PDFs can be attached (vision analysis, text extraction, strict per-user isolation); long conversations are compacted by an LLM summary that preserves identifiers, and the history scrolls back page by page without limit.
- Voice, both ways — push-to-talk or the wake word "OK Guy", detected in the browser by sherpa-onnx so no audio leaves the device for detection; offline Whisper transcription in the user's own language; spoken answers from a catalogue-driven TTS (Edge, free; OpenAI; ElevenLabs) streamed sentence by sentence, first audio in about a second (VOICE, ADR-081, ADR-082).
- Live, voice to voice — a real-time session on a live model the person connects with their own key (Gemini Live over a WebSocket, GPT-Live over WebRTC, or an ElevenLabs agent whose voice stays on its portal); the audio never transits the server; the voice model owns the conversation and delegates every request for data or action to the chat engine through one declared function, so the delegated turn runs in the graph with its approvals, registers and quotas and is drawn in the thread while the person speaks; a provider declares its wire and the seam never branches on its name; a direct session holds the read-only tools itself and acts on nothing; the provider's own usage is folded into an indicative meter and shown, never recorded — the vendor's bill read once at the end where it has one (ADR-299, ADR-300, LIVE_MODE).
- An expressive companion — Psyche temperament, actual tool execution and the delivered answer's tone share one animation rig, including the shaded Smiley. Eyes lead a head with depth and weight; continuous mouth/brow contours, quiet thought and varied resting scenes keep transitions natural. Speech follows actual audio, and a prepared draft never earns an accomplished-action gesture. Fresh cached weather and the account clock add discreet ambience without a provider or LLM call; reduced motion keeps static contextual poses (ADR-240, ADR-252, ADR-253, ADR-264, ADR-294).
- A psyche of its own — Big Five traits, a mood space, discrete emotions, a relationship stage and curiosity drives shape word choice and rhythm without ever being announced; a four-chart dashboard, temperament sliders and two reset scopes in Settings (PSYCHE_ENGINE).
- Wherever you are — six languages end to end (UI, approvals, notifications, Telegram, skills); a bidirectional Telegram channel with OTP linking and localized approval keyboards (GUIDE_TELEGRAM); native Android and iOS shells that load your server, with native push and the sign-in flow Google permits (ADR-246, GUIDE_MOBILE_ANDROID, GUIDE_MOBILE_IOS); an offline-capable PWA (ADR-146).
- Mail, calendar, contacts, tasks — Google (OAuth 2.1 + PKCE), Apple iCloud (IMAP/SMTP, CalDAV, CardDAV) and Microsoft 365 (Graph API, personal and business tenants); one active provider per category, and activating one deactivates its competitor. Google and Microsoft each offer one consent to connect or reconnect several services on the same verified account, while each service can still be disconnected separately (ADR-302, OAUTH).
- E-mail, read whole and clean — the three providers speak one vocabulary at the client boundary (a text body, never HTML, quoted history and signature removed, measured on real payloads), and the assistant chooses how much to read from the question: headers to list, a body paginated by paragraph to read, a digest per message — computed once by a small model, cached thirty days, counted in your usage, never invented — to reason over many (ADR-287, EMAIL_FORMATTER); an attachment is read too — its text when it has one, the vision slot for a picture or a scan — bounded, paginated and treated as what a stranger sent (ADR-296).
- Connected from the first day — the connectors that ask nothing of the person (Wikipedia, page browsing, Google Places, Weather and Environment) are activated when the account is created, unless the administrator switched one off or the instance has no platform key; existing accounts keep their choices (CONNECTORS_PATTERNS).
- Documents, places and weather — Google Drive folders, sub-folders included, and a Gmail label as knowledge sources, synced incrementally, with the exact number of files stated before a large sync starts (ADR-262, ADR-297); Google Maps places, routes and geocoding; weather with change detection; a last-known-position cascade so every feature knows where you are, with the age of the fix stated (ADR-219).
- Home and body — Philips Hue lighting by voice (rooms, scenes, local bridge or cloud); daily steps and heart-rate batches pushed from an iPhone Shortcut, idempotently, with baselines, variation detection and charts (ADR-076, ADR-148, GUIDE_IPHONE_SHORTCUTS_HEALTH).
- Your own tools (MCP) — per-user servers with API key, bearer or OAuth 2.1 authentication (dynamic registration, PKCE), HTTPS-only, SSRF-checked, credentials encrypted; conformant to the protocol's current revision on both halves and reading tool declarations to the letter of JSON Schema 2020-12 (ADR-224, ADR-255); MCP Apps rendered as sandboxed widgets behind a CSP airlock (ADR-098); an iterative mode where a dedicated agent reads a complex server's docs before calling it (MCP_INTEGRATION).
- Skills and plugins — agentskills.io skills with progressive disclosure, sandboxed scripts and rich outputs (maps, dashboards, calendars, QR codes…), generated from a conversation and installed straight into My Skills (SKILLS_INTEGRATION); Agent Plugins v1 packages — skills plus streamable-http MCP servers — installed in one step with an exhaustive per-component report (ADR-225).
- Two execution modes, one toggle — the pipeline (planner → semantic validator → approval gate → parallel orchestrator) is deterministic and 4–8× cheaper in tokens; ReAct lets the model reason step by step for exploratory or ambiguous requests; both stream through the same response node (ADR-070, PLANNER); a ReAct tool result is projected item by item under a token budget derived from the slot's own window, never cut mid-item, the cut stated to the model and counted (ADR-286); the loop binds its tools by relevance — the detected domains' tools, the best-ranked doors of every other family, the top of the turn's global ranking — so no family falls off a blind cap and the schemas stop being most of the prompt, and it reads the same knowledge spaces the pipeline reads (ADR-293).
- Human-in-the-Loop — five interrupting approval levels (clarification, draft critique, destructive confirmation, bulk
FOR_EACHconfirmation, modifier review) plus plan approval, currently auto-approved because tool-level approval supersedes it (HITL, ADR-106); several independent drafts in one turn are reviewed one per question, with their position stated and nothing executed before the last answer, while a lot you pre-approved as a list keeps its grouped confirmation (ADR-288); a draft and its report are described once and drawn per surface — alia-cardin the chat, Markdown on a ticket or an external channel — the report naming to whom and what (ADR-289). - Phone calls on your behalf — and to you — through your own ElevenLabs + Twilio connector, every call to a third party confirmed before dialing, a strict mandate that forbids any expense beyond the objective, free/busy visibility only, no recording, and a post-call summary that states every cost (ADR-127, TELEPHONY); and the phone as a channel — LIA calls you on a number you declared and verified by a spoken code, with no confirmation card, the chat's own context and your configured personality on the line; the voice agent reads everything the chat reads through the same read-only tools (mails, calendar, tasks, contacts, files, places, weather, memory — one switch per domain, yours) and acts on nothing; what you say comes back as your own message, with drafts to confirm in the chat, ten relay verdicts and one bill per call for what LIA spent (ADR-290); since ADR-301 a voice session has a mode and the policy follows it whatever the line — Live (the default), where each request is a chat turn of yours handled while you speak, a question LIA asks being the answer and the next request resuming the run that asked, or Live direct, where the voice reads and the words are relayed at the end — one closing for the phone and the browser, the effective mode derived and published, and the browser's direct session relayed like a call (ADR-301).
- Documents and images — CSV, Excel, Word, PowerPoint, PDF, Markdown or text produced by local renderers with each format's native mechanisms (styles, fields, layouts, typed tables, bookmarks); nothing overflows by construction, and a truncated model answer is refused rather than rescued into a shorter file (ADR-226, ADR-274, ADR-275); image generation and natural-language editing with per-user quality and size preferences (IMAGE_GENERATION).
- A browser, a sandbox, delegates — browser control with progressive screenshot streaming (ADR-059); a short Python script run in the skills sandbox when a step needs real computation, ReAct only (ADR-249) — and, when the person allows it, reaching the web through one egress proxy that swaps per-run tokens for the person's own connector keys, an unknown host asked with three answers and settled inside the loop (ADR-298); persistent read-only sub-agents with their own instructions, skills and budgets (SUB_AGENTS).
- The workboard — a ticket has a lifecycle, a holder and a result (ADR-276, WORKBOARD):
- one row per ticket, shared by its owner and its holder, across seven columns with sub-tickets, comments and a history; the holder can be you, a connected peer, or LIA;
- when LIA holds it, a sweep claims one ticket at a time, runs it in the execution mode the ticket declares, and settles from an explicit result — a quota ceiling or a busy conversation postpones the run, never fails it;
- a run that needs a decision asks instead of refusing: the ticket lands in « To confirm » carrying the exact card the chat would show, and your comment is the answer.
- The heartbeat — LIA takes the initiative when it is worth it: calendar, mail, tasks, weather changes, interests, memories, habits and the workboard are aggregated, a cheap structured decision says whether to speak, at your local time, and a second pass writes it in your voice and language; each source has a switch that says whether it is connected, you set the windows, the daily maximum and the channels, rate every notification, and every pass files what it read in your registers (HEARTBEAT_AUTONOME, GUIDE_HEARTBEAT).
- Moments served to the minute — a periodic sweep cannot serve an instant, so a finished meeting or an awaited reply is kept as an anticipated moment, claimed under a lock, revalidated, and served under the full eligibility checker while bypassing only the deferrals; mail watches are answered from the push-driven wake that already holds the Gmail delta (ADR-281, ADR-261).
- Routines and reminders — one recurrence engine answers "when?" for both, as a product of calendar days and moments ("every three days", "the 2nd Tuesday of the month", "every two hours between 9 and 5"), timezone-aware, with a week view and a run history per tick (ADR-268, ADR-265, SCHEDULED_ACTIONS).
- Interests and habits, learned with restraint — an interest is created only on a named ground quoted from your own words, with six exclusion classes and a cap on deletions per run (ADR-166, INTERESTS); habits are learned deterministically from a recurrence ledger, promoted, refreshed or demoted by a nightly job and never on doubt; a status you set on a learned window holds for the heartbeat, its scheduling and the assistant's context alike, a missed routine is offered by name, and one learning switch closes every door (ADR-214).
- A daily briefing — the home page aggregates your sources in parallel with a per-section cache and an LLM synthesis, served by a read-only domain outside the agent graph (BRIEFING_DOMAIN).
- Long-term memory — facts extracted after each conversation, pinned or edited by hand, injected by relevance with their scores visible in the debug panel (LONG_TERM_MEMORY, MEMORY_RESOLUTION).
- Personal journals — introspective notebooks the assistant keeps in the first person, stratified from raw observations to a user portrait, with an epistemic status per entry and a deferred self-evaluation at zero added LLM cost; the portrait is compiled from four sources — memories, interests, learned habits, relationship debriefs — each read under its own gates, and it shows which ones it used (ADR-079, ADR-292, JOURNALS).
- Knowledge spaces — personal document bases in 15+ formats with hybrid search (pgvector cosine + BM25), Google Drive folder sync, a Gmail label as a source, and a system space that indexes the product's own FAQ so LIA can explain itself; a document that cannot be indexed says why in your language — a scanned PDF without a text layer names its remedy; any indexed document, paused space or not, attaches to a chat message as a copy from the composer's « + » (ADR-295, GUIDE_RAG_SPACES, ADR-055, ADR-058).
- Meetings and minutes — record from the phone or the computer while the chat stays usable, with a capture that survives reloads and lost microphones; a chain of transcription engines walked at processing time; minutes filled from one of thirty built-in templates or your own, reformatted in place or derived into a second set from the same transcript (ADR-258, ADR-259, MEETINGS).
- People — a 360° relationship lens over open loops, calls, messages and memories, with a written debrief per person built lazily when the card opens (ADR-176, ADR-193, ADR-269); connections between users of the same instance, assistant to assistant — relayed messages delivered by the recipient's own assistant, field-level read-only shares, silent blocking (ADR-180, ADR-182).
- What LIA produced is yours — generated images, documents and browser screenshots have their own galleries with search, exact totals and a visible retention deadline; clearing a conversation never clears them (ADR-279).
- What you keep is yours too — a bookmark on every answer copies it with the request that produced it and the answer's date, so it outlives the conversation; a Bookmarks tab beside the galleries lists them newest first, with search, an exact total against the account's cap, sharing, a Markdown export and deletion; every kept answer is also indexed in a knowledge space of your own, so LIA cites it weeks later when a question concerns it, and the card shows the indexing state and its cost (ADR-282, ADR-291, BOOKMARKS).
- Three registers, sealed on request — one row per action (claimed before it happens, closed from an explicit result), one per consultation (which capability read what, when, with what outcome), one per turn; proactive acts and direct reads are recorded too; extractions are complete, never capped; an opt-in per-account hash chain makes the registers tamper-evident while preserving the right to erasure (ADR-263, ADR-270, ADR-273, AI_ACT_TRACEABILITY).
- Spend that answers to two ceilings — every platform-paid token counts against the account's quota and the instance's daily budget; a refusal carries a dedicated code and a
Retry-After; where each module's spend is recorded is declared and guarded, never inferred; and the rule is not the model's alone — every euro the platform pays for a person, a Maps lookup during a call, the briefing's weather, a photo shown, a voice synthesis, reaches their ledger whatever the path, one persistence predicate covering every family the tracker holds and a counter that fails closed into an alert (ADR-216, ADR-272, USAGE_LIMITS). - Strong authentication — WebAuthn passkeys, a TOTP second factor with backup codes, step-up re-authentication on sensitive actions, device sessions with per-device revocation, server-side Redis sessions behind HTTP-only cookies (ADR-143, ADR-144, AUTHENTICATION).
- Your data, by construction — Fernet-encrypted credentials, PII kept out of logs, a full-account GDPR export (ADR-145), external content wrapped with a provenance that survives compaction, skill scripts confined to a throwaway container, automated backups with a tested one-command restore (ADR-109, SECURITY).
- Switches, not redeploys — every capability switches off from the admin panel, each declaring where it is enforced; a switch removes the capability, never the record (ADR-217, ADR-280).
Operators get complete control and real-time visibility without touching configuration files or the database.
| Area | What you control |
|---|---|
| LLM configuration | The model behind every node and slot, provider parameters, prompt versions, the context window per slot |
| Model catalogue & pricing | Providers, capability flags, accepted reasoning depths, a provenance badge and prices per model — the source of truth for the LLM factory, with its status against the public registries; image-generation and Google API pricing alongside; live cross-worker invalidation |
| Platform capabilities | One switch per capability, grouped in families, each row showing the deployment bound, the operator choice and the state actually enforced |
| Budgets & limits | Per-user token, message and cost quotas with live gauges; the instance daily ceiling in euros, today's spend and what remains |
| Knowledge & skills | Knowledge spaces and reindexation, the system FAQ space, skills (enable, translate, delete), admin MCP servers and plugins |
| People & voice | Users, roles, connector health, assistant personalities, the TTS catalogue and voice picker |
| Platform health | Incidents and their diagnoses, each shown with the evidence it was written from |
| Registers | Readable, technical and Article-12 extractions over one, several or all accounts — masked unless audited |
| Broadcast, debug, demo | System-wide notifications, per-user debug verbosity, the public showroom link, CSV consumption exports |
A 24-section panel embedded in the chat, organised into six groups; an empty section shows "N/A" rather than disappearing.
| Group | Sections |
|---|---|
| Request Analysis | Intent classification, Domain detection, Routing decision, Query transformations |
| Planning & Execution | Planner output, Tool selection, Context resolution, Token budget, Execution timeline, ForEach analysis, Execution waves |
| Intelligent Mechanisms | Cache hits, pattern learning, semantic expansion, Skills activation |
| Context Injection | Memory injection (scores), RAG injection (scores), Knowledge enrichment (Brave), Journal injection (per-entry scores, budget) |
| Background Extraction | Memory detection (create/update/delete), Journal extraction, Interest profile |
| LLM & API Pipeline | Request lifecycle (timing breakdown per node), LLM Pipeline (chronological reconciliation), LLM call details (model, tokens, latency, cost), Google API calls |
Built for developers and operators: diagnose, optimise prompts and understand the agent's decisions in real time — no external tool, no log access needed (DEBUG_PANEL).
- Prometheus: 583 custom metrics (agents, LLM, infrastructure). A metric nobody can see is a metric nobody acts on: every one must be wired to a Grafana panel, a recording rule or an alert, and a shrink-only ratchet fails the build on a newly blind metric.
- Grafana: 30 dashboards, including a product-value cockpit · Loki: structured JSON logs with PII filtering · Tempo: distributed tracing · Langfuse: LLM tracing with prompt versions.
- Probes: liveness (
GET /health) split from readiness (GET /ready, 503 unless PostgreSQL and Redis answer) — ADR-115. - Alerting: a vital core (service, database and Redis down, disk, OOM, 5xx rate, SSE latency, backup failure, public-endpoint and TLS probes, chain self-monitoring) evaluated by Prometheus, emailed by a dedicated Alertmanager, unit-tested with
promtool, every alert linking its runbook — ADR-119. - Per-process memory: every API worker publishes what it holds (
lia_worker_memory_bytes, one series per live worker), drawn on the infrastructure dashboard and watched by an alert that names the process; what a process loads is declared, measured on the target host and bounded where it multiplies — the supervisor never imports the application, heavy libraries load where they are used, and the speech engine keeps one resident model per worker (ADR-283). - Self-diagnostics: a leader-elected self-check of the golden signals, one incident per outage whichever observer saw it first, and a budget-capped diagnosis written in each administrator's language from evidence collected at diagnosis time — metrics, a sanitised log excerpt, the running build, the alert's runbook — shown under its verdict in Settings › Platform health (ADR-247, ADR-266).
| Software | Version | Required |
|---|---|---|
| Python | 3.14 | Yes |
| Node.js | 24 LTS | Yes |
| Docker | 24+ | Yes |
| pnpm | 10+ | Yes |
| Task | 3+ | Yes (build tool) |
Every command lives in Taskfile.yml.
# 1. Clone the repository
git clone https://github.com/jgouviergmail/LIA-Assistant.git
cd LIA-Assistant
# 2. Configure environment
cp .env.example .env # Edit with your API keys
# 3. Full setup (backend + frontend + git hooks)
task setup
# 4. Start all services (API + Web + PostgreSQL + Redis + observability)
task devManual setup (without Task)
# 1. Start the infrastructure
docker compose up -d postgres redis prometheus grafana
# 2. Backend setup
cd apps/api
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install --require-hashes -r requirements.lock.txt # compiled lockfile (reproducible)
cp ../../.env.example .env # Configure your API keys
# 3. Database migrations
alembic upgrade head
# 4. Frontend setup
cd ../web
pnpm install
# 5. Start the services
# Terminal 1 - Backend:
cd apps/api && uvicorn src.main:app --reload --port 8000
# Terminal 2 - Frontend:
cd apps/web && pnpm devA guided installer lives at the repository root (ADR-215). It asks a short questionnaire (LAN exposure, your own reverse proxy, or managed HTTPS with Caddy), generates a private .env and Compose overlay, applies the reference seeds atomically, creates the admin and provider keys over stdin, verifies the installation beyond /ready and prints a non-secret report. A complete source checkout builds the images locally; an official release directory uses prebuilt digests only when its adjacent manifest is qualified. Resume an interrupted run with ./install.sh --resume, change the routing later with ./install.sh --reconfigure. The shipped .env profiles size the connection pools against the database's memory floor as well as its ceiling, and a guard reads both profiles with the Compose file so the sizing cannot drift (ADR-283).
Full guide: docs/guides/GUIDE_SELF_HOSTING.md — what it installs, every setting, and what to do when a step fails. Production targets include the Raspberry Pi (ARM64) through multi-arch Docker images (linux/amd64,linux/arm64).
| Service | URL | Credentials |
|---|---|---|
| Frontend | http://localhost:3000 | — |
| API Docs | http://localhost:8000/docs | — |
| Grafana | http://localhost:3001 | admin/admin |
| Prometheus | http://localhost:9090 | — |
# Database
DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/lia
REDIS_URL=redis://localhost:6379/0
# Security (REQUIRED - change in production)
SECRET_KEY=change-me-in-production-use-openssl-rand-base64-32
FERNET_KEY=your-fernet-key-here
# LLM provider API keys are configured in the Admin UI after first login
# (Settings > Administration > LLM Configuration). At least one provider is required.
# Google OAuth (optional)
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
# Feature flags (optional, disabled by default unless stated)
MCP_ENABLED=false # Admin MCP servers
MCP_USER_ENABLED=false # Per-user MCP (requires MCP_ENABLED)
CHANNELS_ENABLED=false # Multi-channel messaging (Telegram)
HEARTBEAT_ENABLED=false # Autonomous proactive notifications
SUB_AGENTS_ENABLED=false # Persistent specialized sub-agents
SKILLS_ENABLED=false # Skills system (agentskills.io standard)
RAG_SPACES_ENABLED=true # Knowledge spaces (document upload & retrieval)
FCM_NOTIFICATIONS_ENABLED=false # Firebase push notificationsEvery optional subsystem is governed by a {FEATURE}_ENABLED flag, checked at startup, at route wiring and at node entry; the full list with defaults is in .env.example.
Three layers: a Next.js front end (chat, settings, six languages, SSE streaming, voice) talking over HTTP-only cookies to a FastAPI backend, whose LangGraph graph orchestrates the agents and tools; PostgreSQL (data, checkpoints, pgvector) and Redis (cache, sessions, rate limiting, locks) underneath, with Prometheus, Langfuse, Loki and Tempo watching. The backend follows Domain-Driven Design: one bounded context per domain, each with its router, service, repository and schemas.
Switchable per user from the chat header:
- Pipeline (default) — a Planner decomposes the request into an execution plan (a small DSL with dependencies, conditions and
FOR_EACHiteration), a Semantic Validator checks its coherence, the Approval Gate handles Human-in-the-Loop, and a Task Orchestrator runs the tools in parallel waves; Bayesian pattern learning shortens the next similar request. Deterministic, and 4–8× fewer tokens than ReAct. - ReAct (⚡) — the model reasons iteratively, calling tools one by one and adapting to each result. More autonomous, more expensive; ideal for exploratory, research or ambiguous queries. Its iteration budget is extended while the loop keeps producing results, a turn that stops mid-flight closes its own books, and the tools it binds are chosen by relevance to the question rather than cut by a cap.
graph TD
A[User Message] --> B[Router Node]
B -->|conversation| C[Response Node]
B -->|pipeline mode| D[Planner Node]
B -->|react mode| R1[ReAct Setup]
D --> E[Semantic Validator]
E --> F{Approval Gate}
F -->|approved| G[Task Orchestrator]
F -->|rejected| C
G --> H[Domain Agents + Tools]
H --> G
G --> C
R1 --> R2[ReAct Call Model]
R2 -->|tool_calls| R3[ReAct Execute Tools]
R2 -->|done| R4[ReAct Finalize]
R3 --> R2
R4 --> C
C --> J[SSE Stream]
apps/api/src/
├── core/ # Settings composed per domain, constants, i18n tables, recurrence engine
├── domains/ # 49 bounded contexts (DDD)
│ ├── agents/ # The LangGraph graph: nodes (router, planner, react ×4, response…), tools, prompts, orchestration
│ ├── connectors/ # Google, Apple and Microsoft clients behind one provider resolver
│ ├── heartbeat/ moments/ scheduled_actions/ reminders/ habits/ interests/ briefing/ # initiative
│ ├── memories/ journals/ rag_spaces/ meetings/ relations/ peers/ workboard/ attachments/ # what LIA keeps
│ ├── auth/ users/ usage_limits/ capabilities/ feature_switches/ diagnostics/ # control
│ └── voice/ skills/ plugins/ user_mcp/ telephony/ document_generation/ image_generation/ …
└── infrastructure/ # Cross-cutting: cache and Redis key families, LLM factory and providers,
# MCP client pool, browser pool, rate limiting, scheduler, startup steps, observability
apps/web/src/ # Next.js App Router under app/[lng]/, components, hooks, stores, six locales
apps/mobile/ # Capacitor shells for Android and iOS, loading a self-hosted server
infrastructure/ # Compose stacks, database seeds, observability config, backups, Caddy
scripts/ # Release, audit, deployment and measurement tooling
docs/ # Architecture, technical documents, guides, runbooks, ADRs, the public audit
| Pattern | What it buys |
|---|---|
| Five-layer tool system | A generic connector base with OAuth auto-refresh, a meta-decorator composing metrics + rate limiting + context save, domain formatters, a declarative ToolManifest, and a catalogue loader — a tool is a few lines, not a file |
| Domain taxonomy | One declarative DOMAIN_REGISTRY (agents, result key, related domains, priority, routability) feeds catalogue filtering, semantic expansion and the initiative phase — never a second hand-maintained table |
| Data registry | Tool results live in an in-memory store decoupled from the message history, so aggressive message windowing never loses a $steps.X.field reference |
| Semantic validator | A dedicated LLM, distinct from the planner, inspects every plan for hallucinated capabilities, ghost dependencies, cardinality and scope errors before anything runs |
| Adaptive re-planner | A rule-based analyser classifies an execution failure and picks a recovery; in panic mode the catalogue expands to every tool for one retry |
| Connector abstraction | Python protocols and normalisers make Google, Apple and Microsoft interchangeable behind unified domain models; a resolver guarantees one provider per category |
| Published bounds | Whatever a validator can reject, its producer can read: every enforced limit is published to the planner, and what is mechanically repairable is repaired before validation (ADR-184) |
| Exact counts | A number shown to a person is exact or it does not exist — aggregates over the whole set, pages of rows, never a count derived from a capped page (ADR-185) |
| Boot-time completeness | Every registry keyed by an enum or a domain is asserted complete at startup; the app refuses to boot on a missing entry rather than failing silently later |
| Error architecture | Tools return ToolResponse / ToolErrorModel with a closed ToolErrorCode taxonomy and a recoverability flag; the API raises through centralised exception helpers, never a raw HTTPException |
The long version: How does LIA work? (public architecture guide), ARCHITECTURE.md, ARCHITECTURE_LANGRAPH.md.
| Layer | Technology | Role |
|---|---|---|
| Backend | Python 3.14 · FastAPI 0.136.3 · Pydantic 2.13.4 · SQLAlchemy 2.0.50 · Alembic | REST API, SSE streaming, validation, async ORM, migrations |
| Orchestration | LangGraph 1.2.11 · LangChain 1.3.15 · mcp SDK (Streamable HTTP) |
Multi-agent graph, LLM abstraction, Model Context Protocol |
| Data | PostgreSQL 16 + pgvector · Redis 7.4 | Data, checkpoints, vector search · cache, sessions, locks |
| Frontend | Node.js 24 LTS · Next.js 16.3.4 · React 19.2.7 · TypeScript · TailwindCSS · Radix UI · TanStack Query · react-i18next | App Router UI, accessible primitives, server state, six languages |
| Voice | sherpa-onnx (wake word, offline Whisper) · Edge TTS · OpenAI · ElevenLabs | In-browser detection and transcription, speech synthesis |
| Observability | Prometheus · Grafana · Loki · Tempo · Langfuse · structlog | Metrics, dashboards, logs, traces, LLM tracing |
| Delivery | Docker (multi-arch amd64/arm64) · GitHub Actions · Task | Images, CI/CD, one build tool for every command |
The UI is responsive by design — desktop, tablet and phone — with touch-friendly, mobile-first components.
The model catalogue lives in the database, curated from vendored public registries and editable from the admin panel; every row states where its capabilities came from (ADR-244). Reasoning depth has one stored shape for every provider (ADR-245); a model family is declared once, and a caller that needs two sentences asks for no reasoning rather than a small budget — a reasoning model bills its thinking inside max_tokens (ADR-285). What a prompt says is what the code enforces, and nothing else: every placeholder has a producer, every published bound is the applied bound, prose never lives in a .py (ADR-284).
| Provider | Notes |
|---|---|
| OpenAI | Prompt caching, reasoning models, structured output |
| Anthropic | Extended thinking |
Gemini, multimodal; gemini-embedding-001 for retrieval |
|
| DeepSeek | Cost-effective reasoning with a thinking-mode toggle (deepseek-flash, deepseek-v4-pro); tariff by UTC window |
| Qwen | Thinking, tools and vision through Alibaba Cloud DashScope; regional endpoint via QWEN_BASE_URL |
| Perplexity | Web-augmented answers; endpoint via PERPLEXITY_BASE_URL |
| Ollama | Any local model, capabilities discovered from the server, native client; OLLAMA_BASE_URL |
Any LLM slot can run on a model hosted on your own machine, with no cloud account involved. LIA drives Ollama through its native API rather than an OpenAI compatibility layer (ADR-267):
- Thinking is controlled, not endured — the configured depth reaches the server as
think, including switching it off, and the thinking trace comes back separated from the answer. - The server declares the capabilities — tools, vision, thinking and context length are read from the tag listing, so a depth never reaches a model that cannot think and a control a local model would ignore is not offered.
- The context window belongs to the configured slot (ADR-278) — a frugal router and a generous responder can share one model with different windows; it is the number LIA asks for and the number it counts with.
task test:backend:unit:fast # fast unit suite, parallel (what the pre-commit hook runs)
task test:backend:unit:coverage # the CI command verbatim, including the coverage floor
task test:backend:integration # requires PostgreSQL + Redis
task test:backend:agents # LangGraph agent suite
task test:frontend # vitest
task test:e2e # Playwright + axe journeys (hermetic, mocked API)| Metric | Value |
|---|---|
| Backend tests | 30,855 collected over tests/ (pytest --collect-only -q, 1,852 files, 2026-09-22) |
| Frontend tests (vitest) | 8,911 passed across 712 files (task test:frontend:coverage, 2026-09-22), plus hermetic Playwright journeys with axe, dark-mode and zoom checks |
| Coverage floor | 73% enforced in CI on the backend — a shrink-only ratchet, never lowered; frontend thresholds per glob |
| Technical audit | 8.3/10 across 24 normalized areas — full public report & protocol |
Tests are risk-driven and behavioural: a module never disables itself on a missing provider key, a test double that receives a coroutine owns it, and an unawaited coroutine or a post-summary warning is a failure (GUIDE_TESTING).
Two layers: a local pre-commit hook (fast, on staged files) and a GitHub Actions pipeline on every push and PR to main. The workflow orchestrates and the Taskfile implements: every CI step is a task <name> call, so the pipeline runs literally the command a developer runs, and a guard fails on any inline step.
Pre-commit (local) GitHub Actions CI
=================== ==================
.bak files check Lint Backend (Ruff + Black + MyPy strict)
Secrets grep Lint Frontend (ESLint + TypeScript)
Ruff + Black + MyPy Fast unit tests + coverage floor
Fast unit tests Integration tests (PostgreSQL + Redis)
Critical pattern detection Agents suite
i18n keys sync Code hygiene (i18n, Alembic, lockfiles, patterns, docs)
Alembic migration conflicts Docker build smoke test
.env.example completeness Secret scan (Gitleaks)
ESLint + TypeScript check ──────────────────────
Security workflow (weekly)
CodeQL (Python + JS)
Dependency audit (pip-audit + pnpm audit)
Trivy filesystem scan
SBOM generation
| Practice | Implementation |
|---|---|
| Reproducible builds | Universal Python lockfiles (linux/amd64, arm64, Windows), hash-verified installs everywhere, a guard failing manifest edits without lock regeneration (ADR-112) |
| Supply chain | Every GitHub Action pinned by commit SHA, permissions: contents: read, Dependabot weekly with grouped minor/patch updates, SBOM per release |
| Shrink-only ratchets | Coverage, file size, cyclomatic complexity, MyPy debt, React hooks, accessibility and metric visibility can only improve — a baseline is lowered after the work, never raised to absorb a regression |
| Documentation gate | Every version, count and threshold a document states is recomputed from the code that owns it and a mismatch fails the build; broken links, stale code paths and unreachable documents too |
| Release pipeline | A tag builds candidates; a release is promoted only from a qualified, disposable-machine installer run (ADR-215); multi-arch images on ghcr.io |
Full details: CI/CD documentation.
| Reference | Concrete measure |
|---|---|
| GDPR / RGPD | PII filtering, data minimisation, full-account export and account deletion that also removes linked OAuth grants and transparency records (privacy guide) |
| EU AI Act | The interface identifies LIA as AI; approval before mutation and separate records of actions, reads and decisions support transparency and traceability. Applicable duties still depend on the deployment and use case (traceability boundaries) |
| OWASP Top 10 | XSS, SQL injection and CSRF safeguards; a global Redis-backed rate limit before routes; request bodies bounded before they are read, webhooks included |
| Prompt injection | External content wrapped in safety markers, trust classified by data type rather than by producing tool, and a provenance that survives history compaction — a summary built from third-party text inherits its banner instead of promoting the claim to system authority |
| OAuth / PKCE | PKCE S256, single-use state and issuer/identity checks; grouped Google/Microsoft consent shares grants only within the verified provider account (ADR-302) |
| MCP / plugins | Model Context Protocol servers and apps, agentskills.io skills and Agent Plugins v1 packages use documented open interfaces, with separately reviewed trust and sandbox boundaries (MCP, plugins) |
| Supply chain | Hash-verified universal lockfiles, pip-audit on the full transitive tree, SBOM per release |
| Untrusted code | Skill scripts execute in a throwaway container — no Docker socket, no network, read-only filesystem, unprivileged uid, all capabilities dropped — and no sandbox means no execution, never a weaker fallback; a script the assistant writes reaches the web only through one egress proxy holding the keys and the allowlist (ADR-298) |
These references describe implemented controls, not a GDPR/AI Act legal opinion, OWASP or ISO certification, or a security-audit score. The public 8.3/10 audit measures 24 technical-quality areas against an ISO/IEC 25010:2023-inspired grid and explicitly excludes security.
Reporting a vulnerability — do not open a GitHub issue. Write to liamyassistant@gmail.com with a description, the steps to reproduce and the potential impact; we answer within 48 hours. Policy and supported versions: SECURITY.md.
Instrumentation and caching are in place — per-node message windowing, LLM context compaction with a threshold derived from the response model's window, prompt caching on OpenAI and Anthropic, asymmetric Gemini embeddings, parallel execution of independent domains, persistent HTTP pools — all instrumented in production. The perceived response time is dominated by the LLM call cascade (seconds to tens of seconds depending on the request and the hardware); that is the optimisation programme in progress. The technical audit scores performance 7.5/10: no sustained load campaign has been executed yet, and the figures will be published when one has.
| Entry point | What it covers |
|---|---|
| GETTING_STARTED.md | Detailed installation guide |
| ARCHITECTURE.md | Complete system architecture |
| INDEX.md | The full documentation map |
| CLAUDE.md | The engineering rulebook the AI works under — its systemic rules, each paid for by a measured defect |
| Domain | Documents |
|---|---|
| Agents & LLM | ARCHITECTURE_LANGRAPH • PLANNER • SEMANTIC_ROUTER • LLM_PROVIDERS |
| HITL & registers | HITL • AI_ACT_TRACEABILITY • PROVENANCE_AND_CAPABILITIES |
| Voice & meetings | VOICE • VOICE_MODE • MEETINGS |
| Memory & knowledge | LONG_TERM_MEMORY • MEMORY_RESOLUTION • JOURNALS • GUIDE_RAG_SPACES |
| Reach | MCP_INTEGRATION • SKILLS_INTEGRATION • PLUGINS_INTEGRATION • BROWSER_CONTROL • SUB_AGENTS |
| Initiative | HEARTBEAT_AUTONOME • SCHEDULED_ACTIONS • WORKBOARD • BRIEFING_DOMAIN |
| Channels & mobile | CHANNELS_INTEGRATION • GUIDE_TELEGRAM • GUIDE_MOBILE_ANDROID • GUIDE_MOBILE_IOS |
| Security | SECURITY • AUTHENTICATION • OAUTH • RATE_LIMITING |
| Operations | CI_CD • OBSERVABILITY_AGENTS • METRICS_REFERENCE • ALERTING • runbooks |
| Costs | LLM_PRICING_MANAGEMENT • GOOGLE_API_TRACKING • USAGE_LIMITS |
| Guide | Description |
|---|---|
| GUIDE_DEVELOPPEMENT | Complete development workflow |
| GUIDE_AGENT_CREATION | How to create a new agent |
| GUIDE_TOOL_CREATION | How to create a new tool |
| GUIDE_TESTING | Testing strategy |
| GUIDE_DEBUGGING | LangGraph and log debugging |
| GUIDE_SELF_HOSTING | Production self-hosting |
301 ADR files (ADR-001 through ADR-302 — ADR-008 has no separate file) record every major architectural decision with its context, the alternatives and, increasingly, the production measurement that motivated it. Three to start with, and the full index:
- ADR-070: ReAct Execution Mode — why two execution modes rather than one
- ADR-263: Execution Authority Chain and Effect Register — how every act is claimed, closed and recorded
- ADR-184: Published Bounds and Non-Prescriptive Verdicts — an enforced-but-hidden bound is a trap, not a contract
Contributions are welcome — bug fixes, features, documentation, tests, translations in the six supported languages, performance work. Start with the Contributing Guide.
git clone https://github.com/YOUR-USERNAME/LIA-Assistant.git && cd LIA-Assistant
git checkout -b feature/my-feature
task setup # backend + frontend + git hooks
task test:backend:unit:fast # develop and test
git commit -m "feat(agents): add weather forecast agent" # Conventional Commits
git push origin feature/my-feature # then open a PR- Python: Black + Ruff + MyPy strict · TypeScript: ESLint + Prettier · Commits: Conventional Commits
- Before pushing:
task ci:fastruns every CI gate that needs no service;task pre-commitis what the git hook runs - Rules that are not stylistic: read the Systemic Rules in CLAUDE.md — each one closes a bug class measured in production, and a guard enforces most of them
| Channel | Usage |
|---|---|
| GitHub Issues | Bugs, feature requests |
| GitHub Discussions | Questions, ideas |
| liamyassistant@gmail.com | General inquiries |
Also: the documentation index, the practical guides and the operational runbooks.
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) — see LICENSE.
A commercial license is available for organizations that cannot comply with AGPL-3.0 terms: contact liamyassistant@gmail.com.
LIA stands on excellent open source work: Python, FastAPI, LangGraph and LangChain, SQLAlchemy, Pydantic, Alembic, PostgreSQL with pgvector, Redis, structlog, Edge TTS, sherpa-onnx, Docker; Node.js, Next.js, React, TypeScript, TailwindCSS, Radix UI, TanStack Query, react-i18next; Prometheus, Grafana, Loki, Tempo and Langfuse; and the Model Context Protocol, agentskills.io and Agent Plugins open standards.
LIA — Your life. Your AI. Your rules.
Built with ❤️ using Python, FastAPI, LangGraph, Next.js and Node.js