TypeScript SDK
Drive single models and multi-model debate from TypeScript — with the official openai and @anthropic-ai/sdk clients — and take full control of the panel with the summa block.
Summa is a drop-in for the OpenAI and Anthropic APIs, so the SDKs you already use just work: point the client at Summa's base URL and drop in your key. Both SDKs forward unknown request params, which means you get full summa-block control from TypeScript — pick your own panel and moderator, not just the presets.
Connect & install
Install whichever SDK you prefer — they both talk to Summa. Grab an API key from API Keys and pass it as apiKey (it is sent as Authorization: Bearer <API_KEY>). Never hardcode the key in committed code — read it from an env var like process.env.SUMMA_API_KEY.
Install
npm install openai
# or, to use the Anthropic client instead:
npm install @anthropic-ai/sdkCreate a key on API Keys and export it:
export SUMMA_API_KEY="sk-...".Set the client
baseURLto the Summa endpoint —https://alpha.backend.summachat.com/api/v1for the openai SDK,https://alpha.backend.summachat.com/apifor the anthropic SDK.Change modes by changing the
modelstring only — everything else stays the same.
Single mode
One fast model with full tool support (file edits, shell) — the best default for agentic coding. Use summa-fast, or any single catalog model as summa/<slug> (for example summa/openai/gpt-5).
Single — openai SDK
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://alpha.backend.summachat.com/api/v1",
apiKey: process.env.SUMMA_API_KEY, // from /developer/keys
});
const r = await client.chat.completions.create({
model: "summa-fast",
messages: [{ role: "user", content: "Hello!" }],
});
console.log(r.choices[0].message.content);Debate mode
Switch the model to summa-debate and a panel of models each answer, then a moderator synthesizes a single reply. It is slower and pricier than a single model — a 3-model debate costs roughly 3× a single call — and tools are accepted but not invoked in debate. Stream it to watch the panel deliberate; a non-streaming debate returns only the synthesized answer.
Debate — openai SDK, streaming
const stream = await client.chat.completions.create({
model: "summa-debate",
stream: true,
messages: [{ role: "user", content: "Design a rate limiter for our API." }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0].delta.content ?? "");
}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.
Switching modes is just changing the model string — the rest of your code is identical. Keep one client in a shared module and pass the mode in per call; add a summa block for a custom panel, or remove it to fall back to the model string.
One client, any mode
async function ask(model: string, prompt: string) {
const r = await client.chat.completions.create({
model, // "summa-fast" | "summa/openai/gpt-5" | "summa-debate" | "summa-debate-reasoning"
messages: [{ role: "user", content: prompt }],
});
return r.choices[0].message.content;
}
await ask("summa-fast", "Fast single-model answer.");
await ask("summa-debate", "Now let the panel debate it.");Preset panels are also just model strings:
summa-debate-coding(Claude Sonnet 4.5 moderator + GPT-5 + Gemini 2.5 Pro) andsumma-debate-reasoning(GPT-5 moderator + Claude Opus 4.1 + Gemini 2.5 Pro).The anthropic SDK streams the debate as native thinking blocks — see the custom-panel section below for the anthropic client.
Custom panel — the summa block
To pick the exact models, add a summa block to the request body. Both SDKs forward unknown params, so TypeScript needs one line to accept the vendor extension — annotate it with // @ts-expect-error. The block overrides the model string, and works on /chat/completions, /v1/messages, and /responses.
panel— 2 to 8 distinct model slugs (the same ids assumma/<slug>, without thesumma/prefix).moderator— optional; reads every panelist's answer and writes the single final reply. It must be one of the ids inpanel; omit it andpanel[0]moderates.A moderator that is not in
panel, or a panel with fewer than 2 or more than 8 slugs, returns400 bad summa block.
Custom panel — openai SDK
const stream = await client.chat.completions.create({
model: "summa-debate", // overridden by the summa block below
stream: true,
messages: [{ role: "user", content: "Review this migration plan." }],
// @ts-expect-error — summa is a Summa vendor extension
"summa": {
"panel": ["openai/gpt-5", "anthropic/claude-sonnet-4.5"],
"moderator": "anthropic/claude-sonnet-4.5"
},
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0].delta.content ?? "");
}The same block drives the @anthropic-ai/sdk client. On the Anthropic protocol each panelist's turn streams as a thinking block, then the moderator's synthesis as text.
Custom panel — anthropic SDK
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic({
baseURL: "https://alpha.backend.summachat.com/api",
apiKey: process.env.SUMMA_API_KEY, // sent as x-api-key too
});
const message = await anthropic.messages.create({
model: "summa-debate",
max_tokens: 1024,
messages: [{ role: "user", content: "Review this migration plan." }],
// @ts-expect-error — summa is a Summa vendor extension
"summa": {
"panel": ["openai/gpt-5", "anthropic/claude-sonnet-4.5"],
"moderator": "anthropic/claude-sonnet-4.5"
},
});
console.log(message.content);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 the catalog with client.models.list() (or a raw GET https://alpha.backend.summachat.com/api/v1/models). Each entry has an id and a display_name. Use any id as your model string, or — dropping the summa/ prefix — inside a panel.
List models — openai SDK
const models = await client.models.list();
for (const m of models.data) {
console.log(m.id); // e.g. "summa/openai/gpt-5" — use as-is, or drop "summa/" in a panel
}Search models — HTTP
curl -s "https://alpha.backend.summachat.com/api/v1/models?search=gpt&limit=50&offset=0" \
-H "Authorization: Bearer $SUMMA_API_KEY"
# -> { "object": "list", "data": [{ "id": "...", "display_name": "..." }], "has_more": false }Next
Browse the full catalog on Models and manage your balance on Credits. Building an agent that integrates Summa itself? Point it at https://summachat.com/llms.txt.
401— missing or invalid key.402— out of API credit; top up at Credits.400— a malformedsummablock.Billing is prepaid API credit: model token cost plus a 30% platform fee, so a 3-model debate costs roughly 3× a single model.