Open source/Zero runtime deps · your keys · your process
00/Route · Fallback · Ship

primary fails.the next one answers.

Automatic fallbacks across OpenAI, Anthropic, Groq, and local models — with attempts, cost, and cache on every response.

$terminal
live failoverrouting
res.provider
waiting
res.text

01/Providers
OpenAIAnthropicGroqOllamaMockOpenAI-compatible

“Quiet model switches get a reputation fast. We don't do quiet.

res.provider · res.attempts · res.cost
02.1/Routes

Name the tradeoff once

fast / smart / cheap — change models in one config object. Typed route names so route("smrt") fails at compile time.

routes.ts typed
const llm = createRouter({
  routes: {
    fast:  { primary: "groq/llama-3.3-70b" },
    smart: { primary: "anthropic/claude-4-5" },
    cheap: { primary: "openai/gpt-4o-mini" },
  },
  default: "smart",
})

await llm.route("fast").complete(ticket)
02.2/Library

Not a gateway. Not a proxy.

Runs in your process, with your API keys, over fetch. No hop. No signup. Nobody else sees your prompts.

package.json clean
dependencies{}
peer (optional)zod
0runtime deps
02.3/Cache

Pay for the same prompt once

Deterministic key from model plus messages. Set cache: { ttl: "24h" } and repeats come back as cached: true at zero cost.

cache ttl 24h
call 01miss$0.0042
call 02hit$0.0000
call 03hit$0.0000
res.cachedtrue
02.4/Testing

Tests without a network

The mock provider answers from a queue you control — including failures, so you can assert the fallback path instead of hoping for it.

router.test.ts offline
const llm = createRouter({
  primary: "mock/fail",
  fallbacks: ["mock/ok"],
})

const res = await llm.complete("hi")

expect(res.provider).toBe("mock")
expect(res.attempts).toHaveLength(2)
03.1/Failover

One outage never reaches your users

Attempts walk the chain in order and stop at the first success. If every provider is down you get AllProvidersFailed with each error attached.

03.2/Observability

Every response comes back priced

usage, cost, latencyMs, cached, and the full attempts trace — no wrapper, no vendor dashboard.

Providers

5openai → mock

Runtime deps

0zod optional

Public api

1 fncreateRouter

Attempts

per callfull trace

Cache

ttl + keyin-process

Cost

per responseusd
04/Connected models

Bring the models you already use

Start with one provider, add fallbacks when you need them. Any OpenAI-compatible endpoint works with a baseUrl, and local models never leave your machine.

03/Five seconds

One import.
One function.

createRouter is the entire entry point. Model strings, not classes. Same option keys at global, route, and call.

Read the guide
basic.ts ts
import { createRouter } from "llm-sdk"

const llm = createRouter({
  primary: "anthropic/claude-sonnet-4-5",
  fallbacks: ["openai/gpt-4o"],
})

const res = await llm.complete("Summarise this…")
console.log(res.provider, res.attempts)

Ship the call.
Survive the outage.

Router · fallbacks · routes · cache · cost — without an agent framework.