dissent serve. It provides a browser-based interface for running debates, browsing transcripts, and managing configuration.
Starting the Server
Pages
Debate view (/) — chat-style interface for running debates. Type a query, configure the panel and rounds, and watch responses stream in via WebSocket. Each agent’s response appears as a chat bubble with the agent identity label. Synthesis renders as a distinct bubble after all rounds complete.
Dashboard (/dashboard) — browse saved transcripts from ~/.mutual-dissent/transcripts/. View debate details and export transcripts as JSON or markdown.
Settings (/settings) — view and edit provider API keys, model aliases, routing configuration, and debate defaults. Changes are written to ~/.mutual-dissent/config.toml.
Technology Stack
- Backend: Starlette with Jinja2 templates and uvicorn
- Frontend: DaisyUI + Tailwind CSS (CDN), vanilla JavaScript
- Streaming: WebSocket for real-time debate events
- Markdown rendering: marked.js + DOMPurify (CDN)
- No build step — all frontend dependencies loaded via CDN
WebSocket Protocol
The debate page communicates via WebSocket at/ws/debate. Events:
| Direction | Type | Description |
|---|---|---|
| Client → Server | debate_start | Initiates a debate with query, panel, synthesizer, rounds |
| Server → Client | debate_status | Round progress updates |
| Server → Client | debate_response | Individual agent response with agent identity |
| Server → Client | debate_synthesis | Final synthesized answer |
| Server → Client | debate_done | Debate complete with transcript ID |
| Server → Client | debate_error | Error during debate execution |
Architecture
The web application entry point ismutual_dissent.web.app. Routes are defined in web/routes.py, WebSocket handling in web/websocket.py, templates in web/templates/, and static assets in web/static/. The dark theme uses DaisyUI’s OKLCH color system with custom overrides in app.css.