Architecture
How ProxifAI is built — a single Go binary that merges seven services, an embedded React SPA, and a Postgres + NATS data plane.
ProxifAI ships as one Go binary with an embedded React SPA. A fresh deploy needs PostgreSQL and Docker — nothing else. Internally, the binary merges what used to be seven services so every subsystem shares a process, a database, and an in-memory event bus.
The single-binary thesis
Most AI-native developer platforms are stitched together from a project tracker, a Git host, a CI runner, an agent orchestrator, and a vector store — each with its own database and its own auth. ProxifAI collapses that stack into one process so AI has a unified context and operators have one thing to run.
┌────────────────────────────────────────────────────────────────────┐
│ proxifai (Go binary) │
│ │
│ React SPA REST/RPC API Background workers │
│ (go:embed) (chi.Mux, 400+ (~20 goroutines: │
│ endpoints) workflows, dispatch, │
│ pipelines, inbox, │
│ Forge (Git) Pipelines (CI/CD) reaper, port-detect) │
│ Issues / Plan Workflow engine │
│ Knowledge base Agent dispatch NATS JetStream │
│ Inbox + SSE LLM gateway (embedded) │
│ Port proxy Code intelligence │
│ │
├────────────────────────────────────────────────────────────────────┤
│ PostgreSQL 16 · Docker daemon │
└────────────────────────────────────────────────────────────────────┘
A separate pfai CLI binary talks to the server over HTTP. Enterprise deployments can swap the Docker runtime for Kubernetes and add SaaS-only services (account-api, cluster-manager, cost-tracker) without changing the OSS core.
What’s inside the binary
The single binary subsumes services that used to live separately. Each is now an internal/ package:
| Subsystem | Package | Replaces |
|---|---|---|
| Core API + handlers | internal/core/ | server-go |
| Forge (Git, PRs, releases) | internal/forge/native/ | server-go |
| Pipelines (CI/CD runner) | internal/pipelines/ | — |
| Workflow engine + bridge + DLQ | internal/workflows/ | — |
| Triggers (event rules) | internal/triggers/ | — |
| Agent dispatch + run events | internal/dispatch/, internal/agentevents/ | — |
| Container instances | internal/instances/ | vm-manager |
| Port proxy (Envoy xDS, WS-TCP bridge) | internal/portproxy/ | port-proxy |
| Inbox (notifications, SSE) | internal/inbox/ | inbox-service |
| Knowledge base (RAG) | internal/knowledgebase/ | knowledge-base |
| LLM gateway | internal/llmgateway/embedded/ | llm-gateway |
| Code intelligence | internal/codeintel/ | gitnexus (rebuild) |
| Credits + LLM usage | internal/credits/, internal/llmusage/ | — |
| Embedded NATS | internal/natsembed/ | — |
| Auth (JWT + OIDC) | internal/auth/ | — |
| Reaper, supervise | internal/reaper/, internal/supervise/ | — |
The CLI lives at cmd/pfai/ (a thin wrapper over internal/pfai/) and ships as a separate ~14 MB binary.
Tech stack
| Layer | Technology |
|---|---|
| Language | Go 1.25.6 |
| HTTP router | chi — unified chi.Mux for REST + Git protocol + embedded SPA |
| Database driver | pgx (? → $N rewriting via internal DBWrapper) |
| Database | PostgreSQL 16 (CloudNativePG operator in production) |
| Event bus | NATS JetStream — embedded by default, external via NATS_URL |
| Search | Meilisearch (full-text), Qdrant (vector) — both optional |
| Embeddings | HuggingFace TEI (bge-small-en-v1.5 local, bge-m3 prod) |
| Frontend | React 19, Vite 6, Tailwind CSS 4, Radix UI, TipTap editor |
| Real-time UI | WebSocket (Git terminal) + Server-Sent Events (inbox, run logs) |
| Auth | JWT with HS256; OIDC provider (Keycloak) optional for SSO |
| Container runtime | Docker (OSS); Kubernetes (Enterprise, behind //go:build ee) |
| LLM providers | OpenAI, Anthropic, Google Gemini (configurable via internal/llmgateway/dbprovider) |
| Edge / TLS | Cloudflare tunnel (production); plain HTTP for local |
Startup sequence
cmd/proxifai/main.go runs a 13-step boot:
Database — connect to PostgreSQL via pgx, run core + service-specific migrations (inbox uses its own pgx-native schema).
Embedded NATS — start nats-server with JetStream in-process, or attach to external NATS via NATS_URL.
Auth — set JWT_SECRET, derive BASE_URL / SERVER_URL env vars from PORT.
Seed data — create the default org and admin user; seed default agents, inbox items, requests, initiatives, sprints, planner data, example workflows, built-in event types. Backfill the unified Flows projection so legacy agent/pipeline/trigger/webhook/mention runs show up in workflow_execution.
Streams + workers — ensure NATS streams (PIPELINES, AGENT_DISPATCH, AGENT_RUN_EVENTS, EVENTS, LLM_USAGE, INSTANCE_*); start the workflow runner, scheduler, timeout enforcer, HITL scheduler, and stale-workspace cleanup.
Credits — optional client to account-api for usage enforcement (Enterprise / SaaS).
Instances — initialize Docker (OSS) or Kubernetes (EE) runtime; start container create / start / stop / delete consumers, heartbeat, event processor, outbox relay, stuck reconciler, port detector, execution reaper.
Reaper — sweeper for stale agent containers (default 2h threshold).
Git GC — periodic repo garbage collection for the native forge.
Port proxy — start xDS gRPC (:18000) for Envoy, WS-TCP bridge (:8082), and the leader-elected health checker.
Inbox workers — TTL expiry and snooze/wake.
Router — assemble a unified chi.Mux: middleware (auth, request ID, panic recovery), 400+ API endpoints, the Git smart-HTTP protocol, and the embedded SPA via go:embed.
HTTP — listen on PORT, wait for SIGINT/SIGTERM for graceful shutdown.
The full sequence and shutdown ordering live in cmd/proxifai/main.go.
Architectural patterns
Event-driven core, transactional outbox
Subsystems publish to NATS JetStream and consume via durable workers. Database writes that need to fan out (e.g. agent execution events) use a transactional outbox: write the row + an outbox entry in one PostgreSQL transaction, then a relay goroutine ships it to NATS. Crashes between commit and publish are recovered by the relay on restart.
Pluggable container runtime
internal/instances/runtime defines a runtime interface implemented by:
- Docker (
runtime/docker) — used by OSS and local development - Kubernetes (
runtime/k8s) — Enterprise, gated behind//go:build ee - noop — testing
The runtime is selected at boot via RUNTIME_TYPE. Workers, schedulers, and reapers are runtime-agnostic.
Unified workflow execution
Every long-running operation — agent run, pipeline, trigger evaluation, webhook delivery, @agent mention — is mirrored into workflow_execution via the workflows/bridge package. Future iterations move them to running on the workflow engine itself (Phase 3, gated by PROXIFAI_AGENT_ENGINE_DRIVEN).
Subdomain routing for agent ports
Agent containers expose dynamic ports. The port-proxy subsystem auto-detects exposed ports inside running containers and pushes Envoy xDS config so traffic to {instance-id}-{port}.proxif.ai reaches the right container. PostgreSQL LISTEN/NOTIFY keeps the xDS cache fresh across replicas.
Embedded SPA, single deployable
The React frontend builds to static assets, gets go:embed-ed into the binary at compile time, and is served by the same chi.Mux that handles the API. There’s no separate web server to deploy.
Required vs optional dependencies
| Dependency | Required? | Notes |
|---|---|---|
| PostgreSQL 16 | Required | Single database; DATABASE_URL env var |
| Docker daemon | Required in OSS | For agent containers; Kubernetes replaces this in EE |
| NATS | Optional | Embedded by default; set NATS_URL for external |
| Envoy | Optional | Only needed if you expose agent ports externally |
| Qdrant + Meilisearch | Optional | Required only if KB_ENABLED=true |
| HuggingFace TEI | Optional | Required only if you ingest content into the knowledge base |
| Keycloak | Optional | Enables OIDC/SSO; built-in JWT works without it |
| LLM provider keys | Optional | Anthropic/OpenAI/Gemini keys go in the LLM gateway |
Repository layout
proxifai/ module: github.com/proxifai/proxifai-oss
├── cmd/
│ ├── proxifai/main.go single-binary entrypoint (13-step boot)
│ └── pfai/main.go CLI thin wrapper
├── internal/
│ ├── core/ API handlers (~93 files), models, store
│ ├── forge/native/ bare-git driver, ~90-method Forge interface
│ ├── instances/ container lifecycle (Docker/K8s)
│ ├── portproxy/ xDS, WS-TCP bridge, health, store
│ ├── inbox/ notifications, SSE, snooze/expiry
│ ├── knowledgebase/ RAG: embedding + Qdrant + Meilisearch
│ ├── llmgateway/embedded/ multi-provider LLM router
│ ├── codeintel/ knowledge graphs, blast radius
│ ├── workflows/ engine, scheduler, HITL, bridge, DLQ
│ ├── pipelines/ CI/CD runner (ConnectRPC)
│ ├── agents/, agentevents/, dispatch/ agent execution + event timeline
│ ├── triggers/ event-rule evaluator
│ ├── credits/, llmusage/ usage tracking + billing hooks
│ ├── integrations/ webhooks, Slack, MCP
│ ├── auth/ JWT + OIDC fallback
│ └── server/router/ chi.Mux assembly
├── ee/ Enterprise features (build tag: ee)
├── migrations/ SQL migrations
├── web/ React SPA (Vite, embedded via go:embed)
└── ui/ shared `@proxifai/ui` component library
The legacy sibling repos vm-manager/, port-proxy/, inbox-service/, knowledge-base/, and llm-gateway/ still exist on disk for historical reference but are not part of the OSS deploy — their code lives under internal/ now.
Where to go next
Run ProxifAI locally with Docker Compose in under 2 minutes.
Organizations, projects, issues, agents — the terms everything else builds on.
The engine that powers triggers, agent runs, and pipelines under one roof.
Authentication, errors, and the REST surface.