Docs/Architecture/Service Topology & Runtime Map

Service Topology & Runtime Map

Every runtime service this repository ships, how it is placed by Docker Compose (Lite and Full tiers) and by the Helm charts, how the pieces reach each other, which are stateful, and which are pinned to one replica.

What "verified" means on this page
Facts are read from the declared configuration: deploy/compose/*.yml, deploy/helm/charts/*/values.yaml and deploy/README.md. Your running stack reflects the profiles and values you chose; check it with scripts/vegaduta status or kubectl get pods.
Compose
deploy/compose/lite.yml (Lite) and deploy/compose/docker-compose.yml (Full, with profiles); docker-compose.domain.yml adds Caddy and public URLs
Kubernetes
Umbrella chart deploy/helm/charts/vegaduta; each dependency bundled or bring-your-own (preview)
Related
System Architecture · Docker Compose stack · Ports & Service Matrix

1. Runtime map

flowchart LR
  U["Browser / API clients"] --> EDGE["Caddy (domain overlay) or Ingress"]
  subgraph APP["app tier"]
    WEB["web 3000"]
    WADM["web-admin 3001"]
    KC["keycloak 8080"]
    CORE["core 8080"]
    AB["app-builder 8091 (builder)"]
    CI["code-intel 8090 (code-intel)"]
  end
  subgraph AGENT["agent-io / sandboxes"]
    SC["sidecar 8001"]
    TMP["temporal 7233 (temporal)"]
    RP["redpanda 9092 (events)"]
    LK["livekit + voice-agent (voice)"]
    TS["tool-sandbox 8095 (sandbox)"]
    MCP["mcp-stdio-runner 8097 (tools)"]
  end
  subgraph DATA["data tier"]
    PGB["pgbouncer 6432"]
    PG[("postgres 5432 pgvector + AGE")]
    VK[("valkey 6379")]
    S3["seaweedfs S3 8333"]
    KDB[("keycloak-db")]
  end
  EDGE --> WEB
  EDGE --> WADM
  EDGE --> KC
  EDGE --> CORE
  EDGE --> CI
  EDGE --> AB
  CORE --> PGB --> PG
  CORE --> VK
  CORE --> S3
  CORE --> SC
  CORE --> TMP
  CORE --> RP
  CORE --> LK
  CORE --> TS
  CORE --> MCP
  KC --> KDB
  AB --> CI
  AB --> CORE

Browsers call core, keycloak, code-intel and app-builder directly at their public hostnames; web and web-admin do not proxy API calls for the browser (see ADR-0007 for how the URLs reach the client bundle). Profile names are shown in parentheses; services without one are in the Full core set.

2. Service matrix

Host ports are bound to 127.0.0.1 (BIND_ADDR) unless noted and can be changed with the *_HOST_PORT variables. The Full compose file defines 37 services.

ServiceContainer portHost port (Compose)LiteFull (profile)Helm chart
core80808080yescore setcore (+ migrate Job)
web30003000yescore setweb
web-admin30013001—core setweb-admin
keycloak80808180yes (dev-file store)core set (+ keycloak-db)keycloak (bundled) or any OIDC issuer
postgres (pgvector + AGE)54325432yescore set (+ pgbouncer 6432, db-roles)postgres (CloudNativePG) or external
valkey63796379yescore setvalkey or external Redis API
seaweedfs (S3)83338333— (local disk)core setseaweedfs or external S3
sidecar80018001profile ragcore setsidecar
core-worker / core-jobs—none—temporal / jobscore-worker / core-jobs
temporal, temporal-ui, temporal-postgresql7233, 80807233, 8088—temporalexternal Temporal (global.temporal)
redpanda (Kafka API)90929092—eventsexternal Kafka
prometheus, grafana, loki, promtail, alertmanager, valkey-exporter9090, 3000, 3100, —, 9093, —9090, 3003, 3100, —, 9093, ——observabilityPrometheus Operator objects (rules shared with Compose)
langfuse web/worker + postgres, clickhouse, valkey, S330003002 (web)—tracingyour OpenTelemetry endpoint
livekit, voice-agent7880/7881, UDP 50000-50100same (LIVEKIT_BIND_ADDR)—voicevoice-agent
code-intel (+ code-intel-docker, privileged)80908090—code-intelcode-intel
app-builder80918091—builderapp-builder
tool-sandbox8095none—sandboxtool-sandbox
mcp-stdio-runner8097none—tools / browser / sandboxmcp-stdio-runner
rl-trainer80958095—rlrl-trainer
caddy (edge)80, 44380, 443 on PUBLIC_BIND_ADDR (default all interfaces)—domain overlayyour Ingress / Gateway

3. How services find each other

PathComposeHelm
Browser to any applocalhost ports, or with the domain overlay the subdomains app., admin., api., auth. (plus codeintel., builder., livekit.) on BASE_DOMAIN, routed by CaddyIngress (or Gateway API) hostnames from values
core to sidecar, S3, sandboxes, Temporal, KafkaCompose DNS (sidecar, seaweedfs, tool-sandbox:8095, mcp-stdio-runner:8097, temporal, redpanda)Kubernetes Services, or the external endpoints you configure
core to Postgrespgbouncer:6432 (Full, session pooling) or postgres:5432 (Lite)CNPG or external Postgres
JWT validationIssuer PUBLIC_AUTH_URL/realms/agentic-ai; keys fetched from http://keycloak:8080; KEYCLOAK_ADDITIONAL_ISSUERS for extra issuers — see ADR-0005Same rule; any OIDC issuer
Tracescore to langfuse-web on the observability network (profile tracing)your OTLP endpoint

4. Stateful services and replica pinning

ServiceStateConstraint
postgresAll tenant and control-plane data; schema-per-tenantPgBouncer must stay in session mode because tenants are selected via search_path
keycloakRealm, users, clients (keycloak-db in Full, keycloak-data volume in Lite)The realm JSON is imported only once; the live realm is the source of truth afterwards
core (API)Stateless apart from Postgres, Valkey and object storageHelm core.replicaCount must stay 1 until every replicaReadiness flag is true (render fails otherwise); rollouts use maxUnavailable: 0
core-jobsNone of its ownExactly one replica unless leader election is enabled (not every sweep is proven safe to run twice)
seaweedfsseaweedfs-data volumeSingle node in the bundled setup

5. Compose network segmentation

The Full compose file uses six bridge networks: data-tier (postgres, pgbouncer, valkey, seaweedfs, keycloak-db, plus keycloak and core), observability (Langfuse, Loki, Promtail, Grafana, Prometheus, Alertmanager, valkey-exporter, seaweedfs, core), app (web, web-admin, keycloak, app-builder, core), agent-io (sidecar, code-intel, app-builder, livekit, voice-agent, redpanda, temporal*, rl-trainer, plus keycloak and core), sandbox-net (tool-sandbox, core) and mcp-stdio-net (mcp-stdio-runner, core). The Helm charts render per-component NetworkPolicy objects instead.

Evidence & references