Models and providers
Declaring which models an application may use, and where their keys live.
Models are declared once, by the names your own code refers to them by, so swapping the provider behind one is a configuration change rather than a search across every call site.
import { anthropic, defineModels, groq } from "@highx/core";
export const models = defineModels({
default: anthropic({
model: "claude-sonnet-4-5",
pricing: { inputMicrosPerToken: 3, outputMicrosPerToken: 15 },
}),
fast: groq({
model: "llama-3.1-8b-instant",
pricing: { inputMicrosPerToken: 0.05, outputMicrosPerToken: 0.08 },
}),
});An API key is never in the config. Each declaration names a binding, which
highx secret fills in — a key in a config file is a key in your git history.
Supported providers
| Preset | Protocol | Default key binding |
|---|---|---|
anthropic() | Messages | ANTHROPIC_API_KEY |
openai() | Chat Completions | OPENAI_API_KEY |
openrouter() | Chat Completions | OPENROUTER_API_KEY |
deepseek() | Chat Completions | DEEPSEEK_API_KEY |
groq() | Chat Completions | GROQ_API_KEY |
zai() | Chat Completions | ZAI_API_KEY |
moonshot() | Chat Completions | MOONSHOT_API_KEY |
Anthropic is the only provider that is not OpenAI-shaped, which is why there are two adapters and not seven. Everything else differs by URL alone.
Anything else
openaiCompatible({
provider: "myco",
baseUrl: "https://api.myco.com/v1",
model: "myco-large",
pricing,
})Every preset above is this function with a URL filled in, so a provider HighX has never heard of needs no release to be usable.
Gateways
A gateway sits in front of a provider rather than replacing it, so it keeps that provider's protocol, model, and key — only the URL changes.
cloudflareAiGateway({
accountId: "…",
gateway: "production",
upstream: anthropic({ model: "claude-sonnet-4-5", pricing }),
})Routes are mapped to Cloudflare's own path vocabulary explicitly, so an upstream it has no route for is a build error rather than a URL that 404s at the first model call. Known routes: anthropic, openai, groq, deepseek, openrouter.
vercelAiGateway() is its own OpenAI-shaped endpoint rather than a wrapper, and
takes AI_GATEWAY_API_KEY.
Per-model options
anthropic({
model: "claude-sonnet-4-5",
pricing,
cachePrompt: true, // cache the stable prefix of each request
maxOutputTokens: 4096,
reasoning: { effort: "medium" },
})cachePrompt is worth real money on an agent run, where the system prompt and
tool schemas are resent every turn and only the tail changes — see
what it costs. reasoning is declared per model because it is
a property of the model: one that cannot reason ignores it, and one with no
budget answers from instinct.
Pricing is required per declaration and is never looked up from a table HighX ships. Prices change, and a framework's stale price table would silently mis-bill every application that trusted it — so the number lives next to the model it describes, where you can correct it in one place.
Verifying a provider
Every test in the repository uses a scripted model or a stubbed fetch. That
proves the adapters agree with their author; it cannot prove the wire format
agrees with the provider.
ANTHROPIC_API_KEY=… GROQ_API_KEY=… bun run verify:providersOne real exchange per configured provider: a plain completion, a tool call, the same streamed, and the tool-result turn — plus a check that the token counts are internally consistent. A provider whose key is absent is skipped rather than failed, and the failures it reports are the quiet kind: a usage count that is always zero, tool arguments that do not reassemble, a tool-result turn the provider rejects.