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.
- 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.
- 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.
┌──────────────┐ 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.MockProvideris deterministic;OpenRouterProviderslots in behind the same interface. - SSE contract: every stream ends with exactly one
doneorerror.tokendeltas concatenate toturn_end.full_text.
| 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} |
Requires Python ≥ 3.11 and Node ≥ 18. Two terminals.
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 8000Without 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 8000Health check: http://localhost:8000/health → {"status":"ok","provider":"mock"}
cd frontend
npm install
npm run devOpen http://localhost:5173, type a decision, pick rounds, hit Start Debate.
The dev server proxies /api and /health to the backend — no CORS fuss.
# backend
cd backend && uv run pytest -q
# frontend (reducer + transcript logic)
cd frontend && npm testCopy backend/.env.example → backend/.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.
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.
- 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.
backend/ FastAPI app, engine, providers, tests, pyproject.toml, .env.example
frontend/ Vite React TS UI (reducer, EventSource client, components)
docs/ plans + progress log
MIT — see LICENSE.