-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
dev-mondoshawan edited this page Apr 15, 2026
·
1 revision
This document describes the technical architecture of the Dissensus AI Debate Engine.
┌─────────────────────────────────────────────────────────────────────────┐
│ CLIENT BROWSER │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐ │
│ │ CIPHER Column │ │ PRISM Column │ │ NOVA Column │ │
│ │ (Red/Skeptic) │ │ (Blue/Synthesizer)│ │ (Green/Advocate) │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────────────┘ │
│ ↑ EventSource (SSE) │
└───────────────────────────┼─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ NGINX (SSL/Reverse Proxy) │
│ - SSL termination │
│ - Static asset serving │
│ - Proxy to Node.js │
└───────────────────────────┬─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ NODE.JS / EXPRESS SERVER (:3000) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────────────┐ │
│ │ Routes │ │ Debate │ │ Card │ │ Metrics │ │
│ │ /api/* │──│ Engine │──│ Generator │ │ Dashboard │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────────────────────────────────────────┐ │
│ │ Agents │ │ AI Provider APIs │ │
│ │ (CIPHER, │──│ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │ │
│ │ NOVA, │ │ │ DeepSeek │ │ Gemini │ │ OpenAI │ │ │
│ │ PRISM) │ │ └──────────┘ └──────────┘ └────────────────┘ │ │
│ └─────────────┘ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
The main application server built on Express.js:
| Feature | Implementation |
|---|---|
| Protocol | HTTP with Server-Sent Events (SSE) |
| Port | Configurable via PORT env var (default: 3000) |
| Security | Helmet headers, rate limiting, input validation |
| Static Files | Serves public/ directory |
Key endpoints:
-
GET /api/debate/stream— SSE streaming debate endpoint -
POST /api/debate/validate— Preflight validation -
GET /api/providers— Available AI providers/models -
GET /api/health— Health check -
GET /api/metrics— Usage analytics -
POST /api/card— Generate shareable debate cards
The core orchestration logic:
- Multi-provider support — OpenAI, DeepSeek, Google Gemini
- Streaming architecture — Real-time token delivery via SSE
- 4-phase execution — Structured debate progression
- Context accumulation — Each phase builds on prior context
Personality definitions and system prompts for the three agents:
- CIPHER — Skeptic/red-team prompts
- NOVA — Advocate/optimist prompts
- PRISM — Synthesizer/referee prompts with structured verdict format
Generates shareable PNG images of debate verdicts for social media sharing.
In-memory analytics tracking:
- Debate counts by provider
- Recent topics
- Error rates
- Public dashboard at
/metrics
User submits topic
↓
POST /api/debate/validate
↓
├─ Check topic length (3-500 chars)
├─ Validate provider/model
└─ Verify API key (user or server)
GET /api/debate/stream?topic=...&provider=...&model=...
↓
├─ Set SSE headers (text/event-stream)
├─ Apply rate limiting (10/min prod, 100/min dev)
└─ Initialize DebateEngine instance
Phase 1: Independent Analysis
├─ All 3 agents run in parallel
├─ Each analyzes topic independently
└─ Results stored in debateContext.phase1
Phase 2: Opening Arguments
├─ Sequential execution (CIPHER → NOVA → PRISM)
├─ Each presents formal position
└─ Results stored in debateContext.phase2
Phase 3: Cross-Examination
├─ CIPHER challenges NOVA
├─ NOVA counters CIPHER
├─ PRISM challenges both
└─ Results stored in debateContext.phase3
Phase 4: Final Verdict
├─ CIPHER final statement
├─ NOVA final statement
├─ PRISM delivers definitive verdict
└─ Results stored in debateContext.phase4
Each agent response is streamed chunk-by-chunk:
// Server sends: data: {"type":"agent-chunk","phase":1,"agent":"cipher","chunk":"The..."} data: {"type":"agent-chunk","phase":1,"agent":"cipher","chunk":" primary..."} data: {"type":"agent-done","phase":1,"agent":"cipher"} // Client receives via EventSource: es.addEventListener('message', (e) => { const data = JSON.parse(e.data); appendChunk(data.agent, data.chunk); });
| Layer | Technology |
|---|---|
| Framework | Vanilla JavaScript (no framework) |
| Styling | Custom CSS with CSS variables |
| Streaming | Native EventSource API |
| State | In-memory JS objects |
| Storage | localStorage for API keys |
┌─────────────────────────────────────────────────────────────┐
│ Header: Provider Selector | Model Selector | API Key Input │
├─────────────────────────────────────────────────────────────┤
│ Topic Input │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ CIPHER │ │ PRISM │ │ NOVA │ │
│ │ 🔴 Red │ │ 🔵 Blue │ │ 🟢 Green │ │
│ │ │ │ │ │ │ │
│ │ Skeptic │ │ Synthesizer │ │ Advocate │ │
│ │ Column │ │ Column │ │ Column │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Phase Indicator | Progress Bar | Share Button │
└─────────────────────────────────────────────────────────────┘
| File | Purpose |
|---|---|
public/index.html |
Main application shell |
public/js/app.js |
Debate controller, EventSource handling |
public/css/styles.css |
Cyberpunk theme, responsive layout |
public/metrics.html |
Public analytics dashboard |
app.use(helmet({ contentSecurityPolicy: false, // Allows inline event handlers crossOriginEmbedderPolicy: false }));
| Endpoint | Production | Development |
|---|---|---|
/api/debate/stream |
10/min | 100/min |
/api/card |
20/min | 100/min |
/api/metrics |
120/min | 300/min |
- All user input sanitized via
toString().trim() - No user content rendered as HTML
- API keys never logged or stored server-side
User API Key → Client-side only → Sent directly to AI provider
↓
Server Key (.env) → Server memory only → Used when user key absent
Server-side keys are never exposed to clients — only a boolean hasServerKey is sent.
| File | Description |
|---|---|
server/index.js |
Express server, routes, SSE streaming |
server/debate-engine.js |
4-phase debate orchestration, provider configs |
server/agents.js |
Agent personality definitions and system prompts |
server/card-generator.js |
PNG card generation for social sharing |
server/metrics.js |
In-memory analytics and dashboard data |
server/debate-of-the-day.js |
Trending topic selection |
public/index.html |
Main UI |
public/js/app.js |
Frontend debate controller |
public/css/styles.css |
Cyberpunk theme styles |
package.json |
Dependencies and scripts |
Internet → Nginx (443) → Node.js (:3000)
↓
Static assets
SSL termination
Rate limiting
Reverse proxy
| Environment | TRUST_PROXY | TRUST_PROXY_HOPS |
|---|---|---|
| VPS + Nginx | unset (default) | 1 |
| Direct (no proxy) | 0 | — |
| Cloudflare | unset | 1-2 |
For deployment details, see the Getting Started guide and VPS-DEPLOY.md