What the Sheaf API is
One word to know. In the API, the configuration you send for one decision — the models, their roles, the Ledger, and the coherence threshold — is called a pod. That is the name the endpoints and fields use, so this guide uses it too; the rest of the site just says "your configuration".
This is the HTTP API for Sheaf, the coherence layer for agentic AI. One endpoint runs a panel of AI models and returns one reconciled answer plus a coherence audit (where the models agree, and where they quietly contradict each other). You define the models (models + roles + context) and how they work together (the podType).
- Base URL:
https://api.sheaf.one - Auth: every request needs header
Authorization: Bearer <YOUR_KEY>(a key that starts withsk_pod_). - Content type:
application/json. Responses are JSON. - Keep your key server-side. Never embed it in client code.
Quickstart (smallest working call)
curl -X POST https://api.sheaf.one/api/v1/pod/run \
-H "Authorization: Bearer $SHEAF_POD_KEY" \
-H "Content-Type: application/json" \
-d '{
"pod": {
"podType": "council",
"members": [
{"id": "a", "model": "claude-opus-5", "role": "Independent assessor"},
{"id": "b", "model": "gpt-5.5", "role": "Independent assessor"}
]
},
"input": "Should we ship the feature this week?"
}'
The endpoints
| Method & path | Purpose |
|---|---|
POST /api/v1/pod/run | Run a pod (inline pod, or podId for a saved one). Sync, stream, or async. |
GET /api/v1/pod/job/{jobId} | Poll an async job's status + result. |
POST /api/v1/pod/job/{jobId}/release | Release a held async job (human approval) → its answer becomes available. |
POST /api/v1/pod/save | Save/update a pod definition → returns {podId, version}. |
GET /api/v1/pod/list | List your saved pods. |
GET /api/v1/pod/get/{podId} | Fetch one saved pod's config. |
GET /api/v1/pod/usage | Your run count, spend, and recent runs. |
All require the Authorization: Bearer header.
Latency — read this before integrating
A pod is several AI calls in one request (each mind + a synthesizer + the audit), so a run takes ~10–60 seconds depending on panel size, much longer than a single model call. This is expected. Pick a call mode accordingly:
| Mode | How | Best for |
|---|---|---|
| Sync (default) | POST /run, wait for the JSON | Quick pods; scripts; set your HTTP client timeout to ≥ 90s |
| Async | POST /run with "async": true → 202 {jobId}; then poll GET /job/{jobId}, or pass "webhook" to get POSTed the result | Backend/pipeline integrations — don't hold a connection open |
| Stream | POST /run with "stream": true → Server-Sent Events | Live UIs that show progress as each mind lands |
Async example
# 1) submit
curl -X POST https://api.sheaf.one/api/v1/pod/run \
-H "Authorization: Bearer $SHEAF_POD_KEY" -H "Content-Type: application/json" \
-d '{ "pod": { "podType":"council", "members":[{"model":"claude-opus-4-8"},{"model":"gpt-5.5"}] },
"input":"…", "async": true, "webhook": "https://your-app.com/sheaf-callback" }'
# → {"ok":true,"jobId":"…","status":"queued","poll":"/api/v1/pod/job/…"}
# 2) poll (or just receive the webhook POST)
curl https://api.sheaf.one/api/v1/pod/job/THE_JOB_ID -H "Authorization: Bearer $SHEAF_POD_KEY"
# → {"ok":true,"status":"done","result":{ …full run response… }}
The webhook receives POST {jobId, status, result} (https URLs only). Poll interval: every ~5s is fine.
Streaming events (SSE)
With "stream": true, you receive events in this order: start → member (one per mind, as it finishes) → phase → answer → coherence → usage → done. Each data: line is JSON. The done event carries the full run response.
Run request — full schema
{
// Provide EITHER an inline "pod" OR a saved "podId".
"pod": {
"podType": "council", // REQUIRED: "council" | "pipeline" | "debate" | "jury"
"members": [ // REQUIRED: 1–8 minds
{
"model": "claude-opus-5", // REQUIRED. Supported (frontier models, four labs):
// Anthropic: claude-opus-5, claude-opus-4-8, claude-sonnet-5, claude-haiku-4-5
// OpenAI: gpt-5.5, gpt-5, gpt-5-mini, o3 · Google: gemini-2.5-flash · xAI: grok-4, grok-3
"id": "skeptic", // optional, stable handle used in output + coherence conflicts
"role": "Risk skeptic", // optional, who this mind is
"context": "Focus on …", // optional, role-specific briefing
"temperature": 0.7, // optional (ignored for models that don't support it)
"maxTokens": 800, // optional per-member output cap
"required": false, // optional; if true a failure fails the run, else that mind is skipped
"apiKey": "sk-…" // optional BYO provider key; omit to use Sheaf's hosted keys
}
],
"sharedContext": "…", // optional, context every mind sees
"synthesizer": { // optional, how the models are reconciled
"model": "claude-opus-4-8", // default: claude-opus-4-8
"instruction": "Reconcile …", // default: a Sheaf reconciler prompt
"enabled": true // council default true; pipeline default false (last step = answer)
},
"coherenceAudit": true, // optional, default true (needs ≥2 live minds to produce a report)
"holdBelowCoherence": 70, // optional GATE: if the coherence score < this, the answer is WITHHELD
// and the run is HELD for human release (see "Coherence gate" below)
"responseFormat": "text", // optional: "text" (default) | "json" (answer is a JSON object string)
"retention": "logs", // optional: "none" stores only metadata+cost, not your input/answer
"debate": { "rounds": 2 }, // optional (debate only): rounds of rebuttal — default 2, max 4
"jury": { "decisionRule": "majority" } // optional (jury only): majority|unanimous|supermajority|synthesis
},
"podId": "…", // alternative to "pod": run a saved pod by id
"input": "The task/question.", // REQUIRED
"context": "Per-run context…", // optional, merged with sharedContext
"variables": { "brand": "Acme" }, // optional, fills {{brand}} placeholders in roles/context/input
"stream": false, // optional, true → Server-Sent Events
"async": false, // optional, true → 202 {jobId}; poll /job/{id} or use webhook
"webhook": "https://…" // optional (async only), https URL POSTed {jobId,status,result} on done
}
Run response — full schema
{
"ok": true,
"podType": "council",
"answer": "The reconciled answer (or a JSON string if responseFormat=json).",
"members": [
{ "id": "skeptic", "role": "Risk skeptic", "model": "gpt-5.5", "output": "…", "skipped": false }
],
"coherence": { // present when coherenceAudit ran
"score": 78, // 0–100; higher = the models align
"summary": "Mostly aligned, two real tensions.",
"agreements": ["…"],
"conflicts": [ { "between": ["skeptic","optimist"], "issue": "…", "severity": "medium" } ]
},
"usage": { "inputTokens": 3241, "outputTokens": 3457, "costUsd": 0.26, "calls": 4, "latencyMs": 49586 },
"error": null, // a string when ok=false
"held": false, // true when holdBelowCoherence tripped — see below
"heldReason": null // e.g. "coherence 58 below threshold 70" when held
}
Coherence gate — hold & release
Set holdBelowCoherence to turn the coherence audit into a control. When the panel's coherence score comes in below the threshold, Sheaf treats the result as untrusted: the answer is withheld and the run is held for a human to look before anything downstream acts on it. Above the threshold, the run completes normally with the answer and its coherence certificate.
- Sync: a held run returns
"held": true,"heldReason": "...","answer": null, and the coherence certificate (score + agreements + conflicts) so a reviewer can see exactly where the models diverged. (A sync run has nojobIdto/release— re-run itasyncwhen you want the human-release flow below.) - Async (recommended for gating): the job's
statusbecomes"held"instead of"done". The webhook is NOT fired while held (a held run is waiting for a person, by design); pollingGET /job/{jobId}shows the certificate with the answer withheld, and/releasereveals it. - Streaming can't gate — the answer streams as it's produced, so it can't be withheld. A
streamrun withholdBelowCoherenceset is rejected; usesyncorasyncto gate. - Release (human approval): once a person has reviewed the conflicts, release the run and its answer becomes available:
curl -X POST https://api.sheaf.one/api/v1/pod/job/THE_JOB_ID/release \
-H "Authorization: Bearer $SHEAF_POD_KEY"
# → {"ok":true,"jobId":"…","status":"done","released":true}
# then poll GET /job/THE_JOB_ID again — the answer is now present.
podType reference
council— every mind answers independently and blind; a synthesizer reconciles them. Use for advice, analysis, "many expert opinions → one answer." Synthesizer on by default.pipeline— minds run in order, each transforming the previous one's output (stage 1 → 2 → 3). The last stage is the answer (synthesizer off by default). Use for workflows: draft → critique → revise, or brief → script → polish.debate— minds see each other and argue over rounds, then a synthesizer converges their final positions into one answer. Round 1 is opening statements; later rounds each mind rebuts/revises the others. Set"debate": { "rounds": N }(default 2, max 4). Use when you want positions stress-tested, not just collected.members[]returns each mind's final-round position.jury— each mind returns a verdict + rationale; a foreperson aggregates them under a decision rule and reports the outcome with the vote tally. Set"jury": { "decisionRule": "..." }—majority(default),unanimous,supermajority(≥⅔), orsynthesis(decide on the merits, not by counting). Use for decisions with a clear call to make.members[]returns each juror's verdict.
debate is members × rounds model calls, so it's the slowest podType — prefer async or stream for it. (Streaming for debate/jury emits the members + result when the run completes, rather than each mind live as in council/pipeline.)Worked example — a marketing-video pipeline (Object Nirvana)
A pipeline run that turns a brief into a ready-to-produce script + shot list. Your renderer/video tools consume the JSON output; Sheaf is the reasoning layer.
curl -X POST https://api.sheaf.one/api/v1/pod/run \
-H "Authorization: Bearer $SHEAF_POD_KEY" -H "Content-Type: application/json" \
-d '{
"pod": {
"podType": "pipeline",
"responseFormat": "json",
"members": [
{"id":"strategist", "model":"claude-opus-4-8", "role":"Turn the brief into a 15s video angle"},
{"id":"scriptwriter","model":"gpt-5.5", "role":"Write the VO + on-screen script for that angle"},
{"id":"hookdoctor", "model":"claude-opus-4-8", "role":"Rewrite the first 3 seconds for retention"},
{"id":"shotlist", "model":"gpt-5.5", "role":"Output a scene-by-scene shot list with an image/video prompt per scene; return JSON {script, hook, shots:[{scene, vo, prompt}]}"}
]
},
"input": "Brief: promote a new AI note-taking app to busy founders.",
"variables": { "brand": "YourBrand" }
}'
The final stage's JSON is in answer; each stage's output is in members[]; cost is in usage.
Saving and reusing a pod
# Save (returns {ok, podId, version}); pass "podId" to update an existing one.
curl -X POST https://api.sheaf.one/api/v1/pod/save \
-H "Authorization: Bearer $SHEAF_POD_KEY" -H "Content-Type: application/json" \
-d '{ "name": "marketing-video", "pod": { "podType":"pipeline", "members":[ … ] } }'
# Then run it by id (no need to resend the config):
curl -X POST https://api.sheaf.one/api/v1/pod/run \
-H "Authorization: Bearer $SHEAF_POD_KEY" -H "Content-Type: application/json" \
-d '{ "podId": "THE_RETURNED_ID", "input": "…" }'
Notes & gotchas
- Models: frontier models from four independent labs — Anthropic (
claude-opus-5,claude-opus-4-8,claude-sonnet-5,claude-haiku-4-5), OpenAI (gpt-5.5,gpt-5,gpt-5-mini,o3), Google (gemini-2.5-flash), xAI (grok-4,grok-3). Mix providers freely — cross-vendor disagreement is the signal the coherence audit is built to catch. - Cost comes back on every run in
usage.costUsd(computed from token usage). A council of N minds = N model calls + 1 synthesizer + 1 audit. Keep pods small for latency/cost; raisemaxTokensonly if needed. - Coherence audit needs ≥2 non-skipped minds; with one mind it's omitted.
- Errors: non-2xx or
{"ok":false,"error":"…"}. 401 = bad/missing key; 429 = rate limited (retry after a moment); 402 = monthly cost cap reached. - Privacy: set
"retention":"none"on the pod to store only metadata + cost (not your input/answer). - Recommended client pattern: call from your backend, treat
answeras the result, logusage.costUsd, and surfacecoherence.conflictswhen you need to know the models disagreed before acting.
Console
A no-code console to build/run pods and watch usage: sheaf.one/pod-console.html (paste your key).
Questions, a higher rate limit, BYO-keys, or more pod types: hello@sheaf.one