Python SDK
Drive single models and multi-model debate from the official openai or anthropic Python SDKs — just point base_url at Summa.
Connect & install
Summa is drop-in compatible with the SDKs you already use. Keep the openai SDK and point base_url at Summa's OpenAI-compatible endpoint, or keep the anthropic SDK and point it at the Anthropic-compatible endpoint. Your existing code barely changes.
install
pip install openai anthropicCreate an API key in API Keys, then export it so the SDK picks it up. Summa authenticates with the same Authorization: Bearer <API_KEY> header both SDKs already send.
shell
export SUMMA_API_KEY="YOUR_API_KEY"OpenAI-compatible base:
https://alpha.backend.summachat.com/api/v1Anthropic-compatible base:
https://alpha.backend.summachat.com/api(the SDK appends/v1/messages)The Anthropic endpoint also accepts an
x-api-keyheader — either works.
Single mode
Start with summa-fast: one fast model with full tool support (file edits, shell) — the best default for agentic coding. Everything you know about the openai SDK works unchanged.
single.py — openai SDK
from openai import OpenAI
client = OpenAI(base_url="https://alpha.backend.summachat.com/api/v1", api_key="YOUR_API_KEY")
r = client.chat.completions.create(
model="summa-fast",
messages=[{"role": "user", "content": "Hello!"}],
)
print(r.choices[0].message.content)Want a specific catalog model instead of the fast default? Pass summa/<slug> — for example model="summa/openai/gpt-5". Single models keep full tool support.
Debate mode
Switch model to summa-debate and a whole panel of models each answers, then a moderator synthesizes ONE answer. It's slower and pricier than a single model, but the quality on hard problems is the point. Turn on stream=True to watch the panel deliberate live.
debate_stream.py — openai SDK
from openai import OpenAI
client = OpenAI(base_url="https://alpha.backend.summachat.com/api/v1", api_key="YOUR_API_KEY")
stream = client.chat.completions.create(
model="summa-debate",
stream=True,
messages=[{"role": "user", "content": "Design a rate limiter for a public API."}],
)
for chunk in stream:
delta = chunk.choices[0].delta.content or ""
print(delta, end="", flush=True)You'll feel the debate. On a summa-debate request the panel streams a live transcript — a short header, then each model's turn as it finishes, then a ── Synthesized answer ── divider before the moderator's final answer streams token by token. No more staring at a frozen stream while the panel thinks.
A non-streaming debate returns the synthesized answer only — no transcript. Stream if you want to watch the panel think. Tools are accepted in debate mode but are NOT invoked.
Prefer a curated panel? Two presets ship ready to go: summa-debate-coding (Claude Sonnet 4.5 moderator + GPT-5 + Gemini 2.5 Pro) and summa-debate-reasoning (GPT-5 moderator + Claude Opus 4.1 + Gemini 2.5 Pro). Just change the model string.
Switching modes is literally one string — nothing else in your code changes:
Fast single model:
model="summa-fast"A specific catalog model:
model="summa/openai/gpt-5"Preset debate:
model="summa-debate"(orsumma-debate-coding/summa-debate-reasoning)A fully custom panel: add
extra_bodywith asummablock — it overridesmodelentirely.
Custom panel
This is where the Python SDK shines. Pass a summa block via extra_body — the openai SDK forwards it verbatim — and you get full control of exactly which models debate. The summa block OVERRIDES the model string, so model can be anything.
custom_panel.py — openai SDK
from openai import OpenAI
client = OpenAI(base_url="https://alpha.backend.summachat.com/api/v1", api_key="YOUR_API_KEY")
stream = client.chat.completions.create(
model="summa-debate",
stream=True,
messages=[{"role": "user", "content": "Review this schema migration for foot-guns."}],
extra_body={
"summa": {
"panel": ["openai/gpt-5", "anthropic/claude-sonnet-4.5"],
"moderator": "anthropic/claude-sonnet-4.5"
}
},
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="", flush=True)The block itself is just JSON:
the summa block
{
"summa": {
"panel": ["openai/gpt-5", "anthropic/claude-sonnet-4.5"],
"moderator": "anthropic/claude-sonnet-4.5"
}
}panel: 2 to 8 distinct model slugs. These are the same ids assumma/<slug>but WITHOUT thesumma/prefix.moderatoris optional and MUST be one of the panel slugs — it reads every panelist's turn and writes the single final answer. Omit it andpanel[0]moderates by default; a moderator that isn't on the panel is a400.The same
extra_bodyworks onchat.completionsand theresponsesendpoint too.
The anthropic SDK
Already on the anthropic SDK? Re-point base_url and pass the same summa block through extra_body. On the Anthropic protocol the debate is even richer: each panelist's turn streams as a native thinking block, then the synthesized answer streams as text.
anthropic_debate.py — anthropic SDK
import anthropic
client = anthropic.Anthropic(base_url="https://alpha.backend.summachat.com/api", api_key="YOUR_API_KEY")
with client.messages.stream(
model="summa-debate",
max_tokens=1024,
messages=[{"role": "user", "content": "Compare optimistic vs pessimistic locking."}],
extra_body={
"summa": {
"panel": ["openai/gpt-5", "anthropic/claude-sonnet-4.5"],
"moderator": "anthropic/claude-sonnet-4.5"
}
},
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)You'll feel the debate. On a summa-debate request each panelist's turn streams as a thinking block as it lands — you watch the models deliberate in real time — and then the moderator's synthesized answer streams as normal text. In Claude Code, press Ctrl+O to expand the live thinking.
Get models
List everything you can route to. With the openai SDK call client.models.list(); or hit GET /models directly with search, limit, and offset to filter and page.
models.py — openai SDK
from openai import OpenAI
client = OpenAI(base_url="https://alpha.backend.summachat.com/api/v1", api_key="YOUR_API_KEY")
for m in client.models.list().data:
print(m.id)or straight over HTTP
curl -s "https://alpha.backend.summachat.com/api/v1/models?search=gpt&limit=50&offset=0" \
-H "Authorization: Bearer $SUMMA_API_KEY"The response is { object: "list", data: [{ id, display_name, ... }], has_more }. Use any id as your model string. To put that model in a custom panel, drop the leading summa/ from its id.
Next
Browse everything you can route to in Models, and manage your prepaid balance in Credits. Building an agent that integrates Summa on its own? Point it at https://summachat.com/llms.txt — a machine-readable llms.txt describing every endpoint and mode.
Common errors: 401 means a missing or invalid key; 402 means you're out of API credit — top up at Credits; 400 means a bad summa block. Billing is prepaid: model token cost plus a 30% platform fee, so a 3-model debate costs roughly 3x a single model.