Docs/Overview/Platform at a Glance

Platform at a Glance

One page for the shape of the whole system: who talks to it, where the requests land, what runs where when you self-host it, and the two design facts that explain most of the surprises engineers hit on day one.

System context

flowchart TB
    subgraph users["Users & channels"]
        TU["Tenant users (web console)"]
        PA["Platform operators (web-admin)"]
        EU["Channel end-users (WhatsApp, Telegram, email, voice)"]
        EX["External agents & API clients (REST, MCP, A2A)"]
    end

    EDGE["Caddy (Compose domain overlay) or Kubernetes Ingress"]

    subgraph app["Application services"]
        WEB["web :3000 (tenant console)"]
        WADM["web-admin :3001"]
        KC["keycloak :8080 (realm agentic-ai)"]
        CORE["core :8080 (modular monolith)"]
        CI["code-intel :8090 (optional)"]
        AB["app-builder :8091 (optional)"]
        SC["sidecar :8001 (internal)"]
    end

    subgraph opt["Opt-in services (Compose profiles / Helm values)"]
        RP["redpanda :9092"]
        TMP["temporal :7233 + temporal-ui"]
        LK["livekit + voice-agent"]
        TS["tool-sandbox :8095"]
        MCPR["mcp-stdio-runner :8097"]
        LF["langfuse (tracing)"]
    end

    subgraph data["Data"]
        PG[("PostgreSQL 16 + pgvector + AGE (schema-per-tenant)")]
        RD[("Valkey (Redis API)")]
        S3["SeaweedFS or any S3 API"]
    end

    LLM["LLM providers (tenant BYOK or operator-configured pool)"]

    TU --> EDGE
    PA --> EDGE
    EU --> EDGE
    EX --> EDGE
    EDGE --> WEB
    EDGE --> WADM
    EDGE --> KC
    EDGE --> CORE
    EDGE --> CI
    EDGE --> AB
    WEB --> CORE
    CORE --> PG
    CORE --> RD
    CORE --> S3
    CORE --> SC
    CORE --> RP
    CORE --> TMP
    CORE --> MCPR
    CORE --> TS
    CORE --> LK
    CORE --> LLM
    CORE --> LF
  

Figure 1 — system context for a self-hosted install. Locally every service is reached on a localhost port; with a domain, Caddy (Compose) or your Ingress (Helm) terminates TLS for app., admin., api. and auth. on <your-domain>.

Layers

LayerComponentsStack
EdgeNone locally; Caddy with automatic Let's Encrypt in the Compose domain overlay; Ingress or Gateway API with HelmCaddy 2.8, your ingress controller
Frontendsweb tenant console + public site, web-admin platform-operator consoleNext.js (SSR)
API / corecore/app — the modular monolith; ~193 REST controllers, SSE/AG-UI streaming, webhooks, inbound MCP server, A2A agent cardSpring Boot 3.4, Java 21, 42 Maven modules
Satellite servicessidecar (knowledge/ML), code-intel (codebase RAG), app-builder, mcp-stdio-runner, voice-agent, tool-sandbox, rl-trainer — all under services/Python FastAPI, Node, LiveKit
Data & infrastructurePostgreSQL 16 + pgvector + Apache AGE (schema-per-tenant), PgBouncer (session mode), Valkey, Redpanda, Temporal, Keycloak 26, SeaweedFS, LangfuseBundled containers or your managed equivalents
External providers~14 LLM providers via tenant BYOK or an operator-configured platform pool; Sarvam/ElevenLabs for Indic voice; optional payment gateways (off by default)HTTP APIs
ObservabilityPrometheus, Grafana, Loki, Promtail, Alertmanager (profile observability); Langfuse LLM tracing (profile tracing)Grafana stack, Langfuse

The two architectural facts that explain most surprises

1 · Schema-per-tenant

Every tenant is a Postgres schema, resolved from the request's tenant context via SET search_path. Shared platform state lives in the control-plane schema. The hard consequence: PgBouncer must run in session pooling mode — transaction pooling hands a connection mid-session to another tenant's search_path and reads the wrong tenant's data. The Full Compose tier runs PgBouncer as the pgbouncer service on port 6432, configured for session pooling.

2 · One Flyway version namespace

Migrations live in two directories — core/app/src/main/resources/db/migration/controlplane/ (shared, once) and …/tenant/ (per schema) — but they are validated as a single version space. A controlplane/V227 and a tenant/V227 collide even though the folders differ. Before picking a number, check the maximum in both folders; scripts/ci/flyway-lint.sh is the CI gate that catches collisions.

Technology stack

ConcernChoiceWhere
Backend runtimeJava 21, Spring Boot 3.4, Maven multi-module (42 modules, one JAR)core/
Async/runtime splitSame modules, three assemblies: app (API), app-worker (Temporal), app-jobs (scheduled sweeps); shape-api/shape-jobs Spring profilescore/app*
FrontendsNext.js (SSR); public settings from the runtime environment or optional build argsweb/, web-admin/
Python servicesFastAPI on Python 3.12 — embeddings/OCR/rerank/transcription, codebase RAG, app generationservices/sidecar/, services/code-intel/, services/app-builder/
Primary datastorePostgreSQL 16 + pgvector + Apache AGE; schema-per-tenantdeploy/postgres/ image, CNPG in Helm
Connection poolingPgBouncer, session modeCompose pgbouncer:6432
Cache / quotasValkey (Redis API)Compose valkey:6379
EventingRedpanda (Kafka API), opt-in; DB outbox relays in coreprofile events
Durable workflowsTemporal server + UI; app-worker assemblyprofile temporal
IdentityKeycloak 26, realm agentic-ai, dual-issuer JWT validationdeploy/keycloak/
Object storageSeaweedFS S3 gateway (Full), local disk (Lite), or any S3 APISTORAGE_*
LLM accessSpring AI dynamic ChatClients; ~14 providers BYOK + optional operator pool; decision model for cost routingcore/providers, core/chat
LLM observabilityLangfuse (profile tracing); every call also writes llm_call_log in the tenant schemainternal
Untrusted codeMCP STDIO packages spawn on mcp-stdio-runner; tenant code executes in tool-sandbox — never inside core:8097, :8095
DeploysSigned multi-arch images and OCI Helm charts on GHCR from release.yml; scripts/vegaduta for Composedeploy/, .github/workflows/

Request path, in two sentences

A browser hits Caddy or your Ingress → web (server-rendered); the page's client JS then calls api.<your-domain> (or localhost:8080) → core:8080 → PgBouncer → Postgres. An agent turn inside core runs guardrails → tool resolution (MCP / custom code / built-ins) → the tenant's BYOK provider or the platform pool → LlmMetricsAdvisor, which writes an llm_call_log row and emits an OTLP span to Langfuse when tracing is on.

Go deeper

System Architecture — the layered internals of the monolith and its satellites · Service Topology — the runtime map, service by service · Glossary — every term used above.