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.
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) anddeploy/compose/docker-compose.yml(Full, with profiles);docker-compose.domain.ymladds 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.
| Service | Container port | Host port (Compose) | Lite | Full (profile) | Helm chart |
|---|---|---|---|---|---|
| core | 8080 | 8080 | yes | core set | core (+ migrate Job) |
| web | 3000 | 3000 | yes | core set | web |
| web-admin | 3001 | 3001 | — | core set | web-admin |
| keycloak | 8080 | 8180 | yes (dev-file store) | core set (+ keycloak-db) | keycloak (bundled) or any OIDC issuer |
| postgres (pgvector + AGE) | 5432 | 5432 | yes | core set (+ pgbouncer 6432, db-roles) | postgres (CloudNativePG) or external |
| valkey | 6379 | 6379 | yes | core set | valkey or external Redis API |
| seaweedfs (S3) | 8333 | 8333 | — (local disk) | core set | seaweedfs or external S3 |
| sidecar | 8001 | 8001 | profile rag | core set | sidecar |
| core-worker / core-jobs | — | none | — | temporal / jobs | core-worker / core-jobs |
| temporal, temporal-ui, temporal-postgresql | 7233, 8080 | 7233, 8088 | — | temporal | external Temporal (global.temporal) |
| redpanda (Kafka API) | 9092 | 9092 | — | events | external Kafka |
| prometheus, grafana, loki, promtail, alertmanager, valkey-exporter | 9090, 3000, 3100, —, 9093, — | 9090, 3003, 3100, —, 9093, — | — | observability | Prometheus Operator objects (rules shared with Compose) |
| langfuse web/worker + postgres, clickhouse, valkey, S3 | 3000 | 3002 (web) | — | tracing | your OpenTelemetry endpoint |
| livekit, voice-agent | 7880/7881, UDP 50000-50100 | same (LIVEKIT_BIND_ADDR) | — | voice | voice-agent |
| code-intel (+ code-intel-docker, privileged) | 8090 | 8090 | — | code-intel | code-intel |
| app-builder | 8091 | 8091 | — | builder | app-builder |
| tool-sandbox | 8095 | none | — | sandbox | tool-sandbox |
| mcp-stdio-runner | 8097 | none | — | tools / browser / sandbox | mcp-stdio-runner |
| rl-trainer | 8095 | 8095 | — | rl | rl-trainer |
| caddy (edge) | 80, 443 | 80, 443 on PUBLIC_BIND_ADDR (default all interfaces) | — | domain overlay | your Ingress / Gateway |
3. How services find each other
| Path | Compose | Helm |
|---|---|---|
| Browser to any app | localhost ports, or with the domain overlay the subdomains app., admin., api., auth. (plus codeintel., builder., livekit.) on BASE_DOMAIN, routed by Caddy | Ingress (or Gateway API) hostnames from values |
| core to sidecar, S3, sandboxes, Temporal, Kafka | Compose DNS (sidecar, seaweedfs, tool-sandbox:8095, mcp-stdio-runner:8097, temporal, redpanda) | Kubernetes Services, or the external endpoints you configure |
| core to Postgres | pgbouncer:6432 (Full, session pooling) or postgres:5432 (Lite) | CNPG or external Postgres |
| JWT validation | Issuer PUBLIC_AUTH_URL/realms/agentic-ai; keys fetched from http://keycloak:8080; KEYCLOAK_ADDITIONAL_ISSUERS for extra issuers — see ADR-0005 | Same rule; any OIDC issuer |
| Traces | core to langfuse-web on the observability network (profile tracing) | your OTLP endpoint |
4. Stateful services and replica pinning
| Service | State | Constraint |
|---|---|---|
| postgres | All tenant and control-plane data; schema-per-tenant | PgBouncer must stay in session mode because tenants are selected via search_path |
| keycloak | Realm, 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 storage | Helm core.replicaCount must stay 1 until every replicaReadiness flag is true (render fails otherwise); rollouts use maxUnavailable: 0 |
| core-jobs | None of its own | Exactly one replica unless leader election is enabled (not every sweep is proven safe to run twice) |
| seaweedfs | seaweedfs-data volume | Single 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
deploy/README.md— tiers, profiles, essential vs plug-and-play services.deploy/compose/docker-compose.yml,lite.yml,docker-compose.domain.yml— services, ports, networks, volumes.deploy/helm/README.md,deploy/helm/charts/core/values.yaml,charts/core-jobs/values.yaml— replica guards.