Architecture

System design, components, and how everything fits together.

System Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Nginx (SSL)                          β”‚
β”‚  k8.virtualgpt.cloud β†’ static    meet.virtualgpt.cloud β†’   β”‚
β”‚                                  static + /api/ + /ws       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚                         β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   K8s Landing Page      β”‚  β”‚      GMeet Frontend          β”‚
β”‚   (Static HTML)         β”‚  β”‚  (React + Tailwind + Zustand)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚ REST     β”‚ WS
                             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                             β”‚      GMeet Backend            β”‚
                             β”‚  Express :4000 + WS :4001     β”‚
                             β””β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”˜
                                β”‚     β”‚     β”‚     β”‚     β”‚
                             β”Œβ”€β”€β–Όβ”€β”β”Œβ”€β”€β–Όβ”€β”β”Œβ”€β”€β–Όβ”€β”β”Œβ”€β”€β–Όβ”€β”β”Œβ”€β”€β–Όβ”€β”
                             β”‚5001β”‚β”‚5002β”‚β”‚5003β”‚β”‚5004β”‚β”‚5005β”‚
                             β”‚BMADβ”‚β”‚Maryβ”‚β”‚Johnβ”‚β”‚Fredβ”‚β”‚Danaβ”‚
                             β””β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”˜
                              Agent Zero Containers / Pods
                                        β”‚
                                   OpenRouter API
                              (Kimi K2.5 / Gemini Flash)

Components

Agent Zero Instances

Each agent runs in an isolated Docker container (or K8s pod) using the agent0ai/agent-zero image. Each instance has:

  • Its own agent profile (persona, system prompt, skills)
  • Tuned model parameters (temperature, context length)
  • Shared project volume for collaboration artifacts
  • A2A server enabled for inter-agent communication
  • Web UI on port 80 (mapped to 50001–50009 externally)

GMeet Backend

An Express.js server that bridges the GMeet frontend with Agent Zero instances:

  • REST API on port 4000 β€” meeting management, agent listing, message routing
  • WebSocket server on port 4001 β€” real-time transcript streaming
  • X-API-KEY auth β€” authenticates with each Agent Zero instance using the mcp_server_token
  • Context management β€” maintains conversation context IDs for multi-turn dialogues

GMeet Frontend

A React single-page application built with Vite:

  • Lobby β€” select agents to invite to a meeting
  • AgentGrid β€” Google Meet-style grid showing active agents with avatars
  • TranscriptPanel β€” real-time conversation transcript with agent color coding
  • Controls β€” message input, send to all or specific agents
  • State management via Zustand with WebSocket sync

Nginx Reverse Proxy

Nginx handles SSL termination and routing:

  • k8.virtualgpt.cloud β†’ static files from /var/www/k8.virtualgpt.cloud/
  • meet.virtualgpt.cloud β†’ static frontend + proxy /api/ to :4000 + proxy /ws to :4001
  • Let's Encrypt SSL certificates with auto-renewal

Data Flow

  1. User opens meet.virtualgpt.cloud β†’ loads React SPA
  2. Frontend fetches agent list via GET /api/agents
  3. User creates a meeting β†’ POST /api/meetings
  4. User sends a message β†’ POST /api/meetings/:id/message
  5. Backend forwards message to selected agents via POST /api_message with X-API-KEY
  6. Agent Zero processes message using configured LLM (via OpenRouter)
  7. Response is returned to backend β†’ stored in transcript β†’ broadcast via WebSocket
  8. Frontend updates transcript panel in real time

Model Configuration

PurposeProviderModel
Chat (reasoning)OpenRoutermoonshotai/kimi-k2.5
Utility (fast tasks)OpenRoutergoogle/gemini-2.5-flash-preview
EmbeddingsOpenAItext-embedding-3-small

Models are configured via the a0-dotenv/.env file mounted into each container. See Configuration for details on switching models.

Repository Structure

agent0-bmad-k8/
β”œβ”€β”€ agents/                    # Agent profiles (9 agents)
β”‚   β”œβ”€β”€ bmad-orchestrator/     # settings.json, prompts/, SKILL.md
β”‚   β”œβ”€β”€ bmad-analyst/
β”‚   β”œβ”€β”€ bmad-pm/
β”‚   β”œβ”€β”€ bmad-architect/
β”‚   β”œβ”€β”€ bmad-ux/
β”‚   β”œβ”€β”€ bmad-po/
β”‚   β”œβ”€β”€ bmad-sm/
β”‚   β”œβ”€β”€ bmad-dev/
β”‚   └── bmad-qa/
β”œβ”€β”€ gmeet/
β”‚   β”œβ”€β”€ backend/               # Express API + WebSocket server
β”‚   └── frontend/              # React + Tailwind + Zustand SPA
β”œβ”€β”€ k8s/bmad/                  # Kubernetes manifests
β”‚   β”œβ”€β”€ namespace.yaml
β”‚   β”œβ”€β”€ configmap.yaml
β”‚   β”œβ”€β”€ secrets.yaml
β”‚   β”œβ”€β”€ deployment-template.yaml
β”‚   β”œβ”€β”€ pvc.yaml
β”‚   β”œβ”€β”€ ingress.yaml
β”‚   └── deploy-bmad.sh
β”œβ”€β”€ projects/bmad-template/    # BMAD workflow templates
β”œβ”€β”€ docker-compose.live.yml    # Live demo (5 agents)
β”œβ”€β”€ docker-compose.bmad.yml    # Full setup (9 agents)
β”œβ”€β”€ a0-dotenv/.env             # API keys (gitignored)
β”œβ”€β”€ .github/workflows/ci.yml   # GitHub Actions CI
└── README.md

Security

  • API keys are never committed to git β€” stored in .env.live and a0-dotenv/.env (both gitignored)
  • Agent auth uses X-API-KEY header with per-instance tokens
  • Web UI auth uses session-based login (configurable credentials)
  • K8s secrets store API keys as base64-encoded Kubernetes secrets
  • SSL/TLS via Let's Encrypt with auto-renewal