Send Messages and Run the Three-Stage Council Process
Blocking endpoint that triggers all 3 council stages — model responses, peer rankings, and chairman synthesis — returning results in one JSON response.
Use this file to discover all available pages before exploring further.
The message endpoint is the core of LLM Council. Posting a user message kicks off a complete three-stage deliberation: all council models answer independently (Stage 1), each model then anonymously evaluates and ranks every other model’s response (Stage 2), and finally a chairman model synthesizes a definitive answer informed by the rankings (Stage 3). The endpoint blocks until all three stages have completed and returns the full result in a single JSON response.
For a better user experience with real-time progress indicators, use the streaming endpoint instead. It emits a Server-Sent Event as each stage finishes, so your UI can update incrementally rather than waiting for the entire process to complete.
POST /api/conversations/{conversation_id}/messageSends a user message and runs the complete 3-stage council process synchronously. Expect this call to take anywhere from 30 to 120+ seconds depending on how many models are configured and their individual response latencies. All council models are queried in parallel within each stage, but Stage 2 cannot begin until Stage 1 is finished.
The user’s question or prompt. This text is sent to all council models in Stage 1.
curl -X POST \ http://localhost:8001/api/conversations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/message \ -H 'Content-Type: application/json' \ -d '{"content": "What is the difference between supervised and unsupervised learning?"}'
One entry per council model, containing that model’s peer evaluation. During Stage 2, responses are anonymized as “Response A”, “Response B”, etc., so models cannot identify their own output or other models’ outputs.
Maps anonymous labels back to model identifiers, e.g. {"Response A": "openai/gpt-5.1", "Response B": "anthropic/claude-sonnet-4.5"}. Use this to de-anonymize Stage 2 evaluations for display.
Sorted list of per-model ranking statistics, computed by averaging each model’s position across all peer evaluations. Lower average_rank is better (rank 1 = best).
The conversation_id does not correspond to a stored conversation.
If this is the first message in the conversation, a title is generated automatically and saved to disk. Subsequent calls to GET /api/conversations/{id} will return the updated title. The title is generated before the council stages begin in the blocking endpoint — in the streaming endpoint it runs in parallel with Stage 1.
If individual council models fail during Stage 1 or Stage 2, the system degrades gracefully — it continues with the models that responded successfully rather than failing the entire request. The returned arrays may therefore have fewer entries than the total number of configured models.
{ "stage1": [ { "model": "openai/gpt-5.1", "response": "Supervised learning uses labeled data where each training example has a known output..." }, { "model": "anthropic/claude-sonnet-4.5", "response": "The key distinction is whether your training data includes ground-truth labels..." } ], "stage2": [ { "model": "openai/gpt-5.1", "ranking": "Response A provides comprehensive coverage of the theory... Response B is more practical...\n\nFINAL RANKING:\n1. Response B\n2. Response A", "parsed_ranking": ["Response B", "Response A"] }, { "model": "anthropic/claude-sonnet-4.5", "ranking": "Both responses address the core question... Response A is clearer for beginners...\n\nFINAL RANKING:\n1. Response A\n2. Response B", "parsed_ranking": ["Response A", "Response B"] } ], "stage3": { "model": "google/gemini-3-pro-preview", "response": "Based on the council's evaluation, here is a synthesized answer to your question..." }, "metadata": { "label_to_model": { "Response A": "openai/gpt-5.1", "Response B": "anthropic/claude-sonnet-4.5" }, "aggregate_rankings": [ { "model": "anthropic/claude-sonnet-4.5", "average_rank": 1.25, "rankings_count": 4 }, { "model": "openai/gpt-5.1", "average_rank": 1.75, "rankings_count": 4 } ] }}