Overview
Most AI APIs hand you one model's opinion. Sheaf convenes several — ChatGPT, Claude, Gemini, Grok, Perplexity, Meta — and has them reason in the open, challenge each other across rounds, then converge. You get both the final answer and the full audit trail of how the panel got there.
The flow is two calls:
- 1. Create —
POST …/conversation/startwith your question and the panel. Returns aconversationId. - 2. Stream — open an SSE connection to
…/conversation/{id}/stream. Each mind's turn arrives as it's produced; the converged answer arrives in aconsensus_completeevent at the end.
/v1/answers) is on the way.Base URL & authentication
https://api.sheaf.oneAll paths below are relative to that base. During the private beta there is no API
key — the endpoints are open and unauthenticated, with global rate and cost limits.
(Per-key auth ships with /v1/answers.) Calls are best made server-side;
the engine is designed for non-browser clients.
Start a conversation
/api/voices/conversation/startCreates a run and returns its id. Nothing is computed yet — the panel starts thinking once you open the stream.
Request body
| Field | Type | Description | |
|---|---|---|---|
topic | string | required | The question or prompt the panel will address. |
participants | string[] | required | The minds on the panel (≥ 2). Any of: Claude, ChatGPT, Gemini, Grok, Perplexity, Meta. |
format | string | optional | Interaction style. One of search, panel, debate, socratic, brainstorm, open. See Formats. Default open. |
numberOfRounds | integer | optional | How many times each mind speaks. 1 = fast; 2 adds a rebuttal round. Default 3. |
userGuidance | string | optional | Free-text steer for the panel (tone, focus, constraints). |
participantRoles | object | optional | Map of mind → role to assign each a distinct lens (e.g. {"Claude":"the skeptic"}). |
participantFallbacks | object | optional | Map of mind → understudy mind; if a seat fails, its understudy covers it. |
features | object | optional | allowInterruptions, allowMentions, naturalFlow, expressUncertainty — all boolean, default true. |
Example
curl https://api.sheaf.one/api/voices/conversation/start \ -H "Content-Type: application/json" \ -d '{ "topic": "Should a seed-stage startup pick AWS or GCP?", "participants": ["Claude", "ChatGPT", "Gemini", "Grok"], "format": "search", "numberOfRounds": 2 }'
Response
{ "conversationId": "7b54dbe7-43a8-4ae7-9704-db09c0a4af5d", "status": "streaming", "message": "conversation started with 4 participants" }
Stream the debate
/api/voices/conversation/{conversationId}/streamOpens a Server-Sent Events
stream. Events arrive in real time as each mind produces its turn, followed by a synthesis
phase and the converged answer. The stream closes on conversation_final_complete.
curl -N https://api.sheaf.one/api/voices/conversation/$ID/stream event: conversation_started event: participant_speaking ← Claude's turn event: participant_speaking ← ChatGPT's turn … event: consensus_complete ← the converged answer event: conversation_final_complete
Event types
Each SSE message has an event: name and a JSON data: payload. The events you'll act on:
| Event | Payload | Meaning |
|---|---|---|
conversation_started | conversationId, topic, participants, format | The run has begun. |
grounded_context | facts, sources, asOf | Live web data the panel pulled in (only for time-sensitive questions). |
participant_speaking | speaker, content, addressedTo, intent | One mind's turn. content is the text; addressedTo names who it's rebutting. |
participant_substituted | seat, servedBy | A seat's primary model failed; its understudy answered instead. |
consensus_meeting_starting | — | The panel is done; synthesis is beginning. |
consensus_complete | report, totalExchanges | The converged answer — see below. |
conversation_final_complete | — | Stream is finished; close the connection. |
error | message | Something went wrong. |
exchange, status_change, thinking, ping)
are turn boundaries and keep-alives used by the live UI — safe to ignore for a programmatic client.The converged answer
The single answer the panel agreed on arrives in the consensus_complete event,
in the report field. If you only want the answer, listen for this one event and ignore the rest:
const es = new EventSource(`https://api.sheaf.one/api/voices/conversation/${id}/stream`); es.addEventListener('participant_speaking', e => { const turn = JSON.parse(e.data); console.log(turn.speaker, '→', turn.content); // the live debate }); es.addEventListener('consensus_complete', e => { const answer = JSON.parse(e.data).report; // the one answer console.log(answer); }); es.addEventListener('conversation_final_complete', () => es.close());
Formats
The format field changes how the minds interact and what kind of result you get:
| Format | What it does |
|---|---|
search | Flat Q&A / cross-examination, optimized for a single best answer with live grounding. The demo's default. |
panel | Expert perspectives — each mind weighs in from its own angle. |
debate | Structured debate — minds are split into PRO and CON sides. |
socratic | Question-driven exploration. |
brainstorm | Collaborative idea generation. |
open | Free-flowing conversation with no imposed structure. |
Full example (Node)
// 1. create const r = await fetch('https://api.sheaf.one/api/voices/conversation/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ topic: 'Is a hot dog a sandwich? Give a verdict.', participants: ['Claude', 'ChatGPT', 'Gemini'], format: 'search', numberOfRounds: 2 }) }); const { conversationId } = await r.json(); // 2. stream — see the answer-only snippet above for the listeners const es = new EventSource(`https://api.sheaf.one/api/voices/conversation/${conversationId}/stream`);
Prefer to see it run with no code? The live explorer builds this exact request as you click, and streams the result.
Coming: a single-call answer
On the roadmapThe two-call create-then-stream flow gives you the whole deliberation. For consumers who just want the result, a single structured endpoint is coming:
// not yet live — shape subject to change POST /v1/answers { "question": "Should we pick AWS or GCP?", "mode": "debate", // quick | debate | panel "depth": 2 } → { "answer": "…", "confidence": 0.82, "minds": [ { "name": "Claude", "position": "…" }, … ], "citations": [ "…" ] }
One call, a structured result, per-key auth, and optional async + webhooks for long runs. Want it for your product? Tell us what you'd build.