Skip to content

TJHLDY/roundtable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🛡️ Roundtable — The AI Boardroom for Decisive Developers

Roundtable is a multi-agent orchestration platform that helps you make complex decisions by staging a structured debate between specialized AI personas — then concludes with a Moderator's actionable verdict.

Standard LLM chat suffers from "yes-man" bias. Roundtable makes conflict a feature: a Security Reviewer argues against a Product Manager, an Architect weighs the tradeoffs, and you watch the reasoning unfold live.

status mock--first


Why it exists

  • Conflict as a feature — opposing viewpoints instead of one agreeable assistant.
  • Structured synthesis — a Moderator reviews the whole debate and recommends.
  • Visual debate flow — agents "light up" as they speak, streamed token-by-token over SSE.
  • Mock-first — explore the entire app with zero API keys and zero cost.

Features (MVP)

  • Default expert trio: Product Manager · Software Architect · Security Reviewer (or bring your own personas).
  • Live Server-Sent Events streaming with named events and a heartbeat.
  • Deterministic MockProvider — runs and tests without any LLM key.
  • Provider boundary ready for OpenRouter (swap in with no engine changes).
  • Copy transcript to Markdown for sharing the verdict.

Architecture

┌──────────────┐   POST /api/sessions      ┌────────────────────────────┐
│   React UI   │ ────────────────────────► │        FastAPI API         │
│ (Vite + TS)  │                           │  in-memory SessionStore    │
│              │   GET  /…/stream  (SSE)   │                            │
│  reducer ◄───┼─────────────────────────  │   RoundtableEngine         │
│  EventSource │   session_start, token,   │   ├─ Agent (round-robin)   │
│  AgentColumns│   turn_end, summary, done │   ├─ Moderator (synthesis) │
└──────────────┘                           │   └─ Provider (mock│OR)     │
                                           └────────────────────────────┘
  • Engine owns the transcript (shared blackboard): every agent sees all prior turns, so later speakers react to earlier ones. Fixed round-robin order, N agents × R rounds, then a Moderator synthesis.
  • Provider Protocol (async def stream(messages) -> AsyncIterator[str]) is the only LLM seam. MockProvider is deterministic; OpenRouterProvider slots in behind the same interface.
  • SSE contract: every stream ends with exactly one done or error. token deltas concatenate to turn_end.full_text.

SSE event reference

event data payload
session_start {topic, agents:[name], rounds}
round_start {round}
turn_start {round, agent}
token {round, agent, text} (incremental delta)
turn_end {round, agent, full_text}
round_end {round}
summary {text} (moderator)
done {}
error {message}

Run it locally

Requires Python ≥ 3.11 and Node ≥ 18. Two terminals.

1. Backend (FastAPI, port 8000)

cd backend
uv venv --python 3.11          # or: python -m venv .venv
uv pip install -e ".[dev]"     # installs FastAPI, uvicorn, pydantic, httpx, pytest
uv run uvicorn app.main:app --reload --port 8000

Without uv:

cd backend
python -m venv .venv && source .venv/Scripts/activate   # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
uvicorn app.main:app --reload --port 8000

Health check: http://localhost:8000/health{"status":"ok","provider":"mock"}

2. Frontend (Vite + React, port 5173)

cd frontend
npm install
npm run dev

Open http://localhost:5173, type a decision, pick rounds, hit Start Debate. The dev server proxies /api and /health to the backend — no CORS fuss.

Tests

# backend
cd backend && uv run pytest -q

# frontend (reducer + transcript logic)
cd frontend && npm test

Configuration (.env)

Copy backend/.env.examplebackend/.env. With no key set, everything runs on the mock provider.

var default meaning
ROUNDTABLE_PROVIDER mock mock or openrouter
OPENROUTER_API_KEY (empty) required when provider is openrouter
OPENROUTER_MODEL openai/gpt-4o-mini OpenRouter model id
ROUNDTABLE_CORS_ORIGINS http://localhost:5173,… allowed frontend origins

Switching to a real LLM is a config change only — the engine is provider-agnostic.

Add a new agent (< 5 lines)

Append to DEFAULT_PERSONAS in backend/app/engine/agent.py:

PersonaSpec(name="Cost Optimizer",
            persona="a finance-minded reviewer who scrutinizes spend and ROI"),

…or POST custom agents in the create-session request body. No engine changes.

Known limitations

  • In-memory sessions — state lives in a dict and vanishes on restart. Correct for a demo; add a store before production.
  • Mock provider only tonight — OpenRouter path is implemented but not exercised against the live API.
  • No auth / rate limiting — single-user local demo.
  • Frontend tests cover logic, not DOM — reducer + transcript are unit-tested; no component render tests yet.

Project layout

backend/   FastAPI app, engine, providers, tests, pyproject.toml, .env.example
frontend/  Vite React TS UI (reducer, EventSource client, components)
docs/      plans + progress log

License

MIT — see LICENSE.

About

Multi-agent debate app with configurable AI roles

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors