Components
Data Flow
- CLI or Web UI calls
run_debate(query, config)with optional panel, synthesizer, rounds overrides - Orchestrator resolves defaults, initializes a
DebateTranscript, and opens aProviderRoutercontext - Initial round — orchestrator fans out
format_initial(query)to all panel models in parallel viacomplete_parallel() - Reflection rounds — for each round, each model receives
format_reflection(query, own_response, others_responses); all models run in parallel - Synthesis — the designated synthesizer receives the full formatted transcript via
format_synthesis() - Scoring — if
ground_truthis provided, the synthesizer scores its own output as judge - Stats — token counts, per-model costs (from OpenRouter pricing API), and routing decisions are aggregated into
metadata.stats - Transcript — the completed
DebateTranscriptis serialized to JSON and saved to disk
Key Modules
| Module | Responsibility |
|---|---|
orchestrator.py | Debate lifecycle, round management, parallel dispatch |
providers/router.py | Routing decisions, provider selection, fan-out |
providers/anthropic.py | Direct Anthropic API client |
providers/openrouter.py | OpenRouter API client |
config.py | Configuration loading, alias resolution, key management |
models.py | DebateTranscript, DebateRound, ModelResponse, ExperimentMetadata |
types.py | Vendor, RoutingDecision, RoutedRequest |
transcript.py | JSON serialization, file storage, listing, loading |
cli.py | Click command group, output formatting dispatch |
web/app.py | Starlette application entry point |
prompts.py | Prompt templates for initial, reflection, and synthesis rounds |
scoring.py | Ground-truth scoring via judge model |
pricing.py | OpenRouter pricing cache, cost computation |
Async Model
The orchestrator and provider layer are fully async. All model calls within a single round execute concurrently viaasyncio.gather. The CLI runs the event loop with asyncio.run(). The web UI runs on uvicorn’s async event loop.