Architecture

A technical overview of how Gumm is designed and how the components interact.


High-level diagram

┌──────────────────────────────────────────────────────┐
│                      Frontend                         │
│         Chat · Modules · Brain · History              │
│                  (Nuxt 4 + TailwindCSS)               │
└─────────────────────────┬────────────────────────────┘
                          │ HTTP / SSE
┌─────────────────────────▼────────────────────────────┐
│                 Backend (Nitro + Hono)                 │
│                                                        │
│  ┌───────────┐  ┌────────────────┐  ┌──────────────┐ │
│  │   Brain   │  │ Module Registry│  │Context Window│ │
│  │ (identity │  │  (hot-swap     │  │ (system      │ │
│  │  memory)  │  │   file watcher)│  │  prompt)     │ │
│  └─────┬─────┘  └───────┬────────┘  └──────┬───────┘ │
│        │                │                   │         │
│  ┌─────▼────────────────▼───────────────────▼──────┐  │
│  │                SQLite (LibSQL)                   │  │
│  │  conversations · messages · memory · modules     │  │
│  │  events · brain_config · api_connections         │  │
│  └──────────────────────────────────────────────────┘  │
│                                                        │
│  ┌─────────────────┐    ┌─────────────────────────┐   │
│  │      Redis      │    │   Rate Limiter / Cache   │   │
│  │  (rate limits,  │    │   (in-memory fallback    │   │
│  │  auto-memory)   │    │    when Redis is down)   │   │
│  └─────────────────┘    └─────────────────────────┘   │
└─────────────────────────┬────────────────────────────┘
                          │ HTTPS
               ┌──────────▼──────────┐
               │     OpenRouter      │
               │   (LLM Gateway)     │
               │  GPT-4 · Claude     │
               │  Mistral · Llama    │
               └─────────────────────┘

Technology stack

ComponentTechnology
RuntimeBun v1.1+
FrameworkNuxt 4 (SSR/SPA hybrid)
Server engineNitro with Hono router
Frontend styleTailwindCSS
DatabaseSQLite via LibSQL + Drizzle ORM
Cache / StateRedis (redis-stack-server)
Authnuxt-auth-utils (encrypted session cookie)
LLM gatewayOpenRouter
ContainerDocker (oven/bun:alpine)

Request flow (chat message)

  1. User sends a message via the web UI or CLI
  2. Guardrail check — sensitive data patterns (credit cards, API keys, etc.) are detected and stripped before proceeding
  3. Context window is assembled: system prompt (identity + memory + knowledge) + conversation history
  4. Module tools — all active module tool definitions are appended to the payload
  5. Request is sent to OpenRouter
  6. OpenRouter response is streamed back
  7. If the response contains tool calls, they are executed:
    • The tool name is matched to the owning module in the registry
    • The module’s handler(toolName, args, ctx) function is called
    • The result is fed back into the conversation
  8. The final assistant message is stored in SQLite and returned to the user
  9. Auto-memory runs in the background — a lightweight LLM call extracts personal facts from the exchange and stores them in memory

Module system

The Module Registry is a singleton that:

  • Watches modules/official/ (bundled, read-only)
  • Watches modules/user/ (Docker volume, hot-reloaded)
  • Validates each module’s manifest.json against a Zod schema
  • Uses await import('path?t=' + Date.now()) for cache-busted dynamic imports
  • Checks the database for the module’s enabled/disabled status before importing

When a module file changes on disk, the registry detects it and reloads the module without restarting the server.

If a module throws during load, the error is caught and the module is marked with status error — the rest of the system continues running.


Database schema (key tables)

TablePurpose
conversationsChat conversation metadata (id, title, timestamps)
messagesIndividual messages — role, content, tool calls
memoryPersistent key-value facts (namespaced, typed)
modulesModule registry — metadata, status, source
brain_configAll configuration entries (key/value JSON)
api_connectionsOAuth connection metadata (tokens stored encrypted)
eventsEvent log for inter-module communication
user_secretsUser-facing secret vault (salted hash for passwords)
schedulesRegistered CRON jobs from modules

Security layers

See the full Security document. In brief:

  1. VPN Guard middleware — rejects non-VPN IPs when network mode is active
  2. Session auth — bcrypt password + encrypted cookie for all API routes
  3. Rate limiter — Redis-backed sliding window on chat and auth endpoints
  4. Guardrail — DLP pattern matching strips secrets before they reach the LLM
  5. Module isolation — failed modules don’t crash the server
  6. Telegram whitelist — only allowed chat IDs can send messages

Networking

Gumm has Tailscale and NetBird built into the Docker image. The VPN daemon starts automatically when auth credentials are configured via the dashboard. The entire configuration is done through the UI — no host-level setup is required.

Port binding is controlled by VPN_BIND_IP in .env. When set to a VPN IP, the GUmm port is only reachable from VPN peers.