Sheaf API · Integration Guide

Integration Guide

The full reference for wiring the Sheaf API into your product: endpoints, request and response schemas, call modes, the coherence gate, and pod types. Written so a coding agent can integrate it with no further questions.

Handing this to a coding agent (Claude Code, Cursor, Devin)? Give it the raw Markdown at sheaf.one/pod-integration.md — the whole file, no further questions needed. This page is the same content, laid out for reading.

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).

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 & pathPurpose
POST /api/v1/pod/runRun 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}/releaseRelease a held async job (human approval) → its answer becomes available.
POST /api/v1/pod/saveSave/update a pod definition → returns {podId, version}.
GET /api/v1/pod/listList your saved pods.
GET /api/v1/pod/get/{podId}Fetch one saved pod's config.
GET /api/v1/pod/usageYour 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:

ModeHowBest for
Sync (default)POST /run, wait for the JSONQuick pods; scripts; set your HTTP client timeout to ≥ 90s
AsyncPOST /run with "async": true202 {jobId}; then poll GET /job/{jobId}, or pass "webhook" to get POSTed the resultBackend/pipeline integrations — don't hold a connection open
StreamPOST /run with "stream": true → Server-Sent EventsLive UIs that show progress as each mind lands
For a production integration, prefer async + webhook — fire the run, get notified when it's done. Don't make a user wait on a synchronous call, and don't let a default 30s client timeout kill the request.

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: startmember (one per mind, as it finishes) → phaseanswercoherenceusagedone. 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.

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.
This is the whole point of a panel as a gate: a single model hands you a confident answer either way; the gate is what tells you this case was actually a coin-flip between strong models, and holds it.

podType reference

Latency note: a 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

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