This service routes LLM calls across three paid providers plus a local Ollama, with automatic failover, rate-limit tracking, persistent logging, and a manual override. The free tiers this gateway grew up on (GitHub Models, Groq, Cerebras, NVIDIA NIM) were retired in 2026-08 โ GitHub Models answers 410 and the others' quotas kept breaking runs. Below: how to use it, what each provider offers, and how to get keys.
Using the gateway
Python (built-in client)
from client import LLM, ask
# one-shot
print(ask("Explain transformers in 3 lines"))
# explicit provider (shortcut keys: g, o, or, oa)
print(ask("hi", provider="or")) # openrouter
print(ask("hi", provider="g")) # gemini
# full client
llm = LLM()
r = llm.chat("hi", provider="gemini", max_tokens=128, temperature=0.5)
print(r["text"], r["provider"], r["latency_ms"])
# streaming
for chunk in llm.stream("count to 5"):
print(chunk, end="", flush=True)
HTTP (OpenAI-style)
curl http://localhost:8111/v1/chat \
-H "Content-Type: application/json" \
-d '{"prompt": "hello", "provider": "g", "max_tokens": 128}'
Shortcut keys
| Key | Provider | Aliases |
|---|---|---|
g | Gemini | gem, gemini |
o | Ollama (local) | oll, ollama |
or | OpenRouter | opr, openrouter |
oa | OpenAI | oai, openai |
The retired providers' shortcuts (gr, c,
gh, n) still resolve, but land on an unregistered
provider unless you resurrect one via .env.
Without provider, the gateway tries them in failover order (configurable via LLM_ORDER in .env). Explicit provider = no failover (errors surface immediately).
Provider overview
1. Gemini (Google AI Studio, paid tier)
- Best models:
gemini-3.1-pro,gemini-3.1-flash,gemini-3.1-flash-liteโ default,gemini-2.5-flash - Context: 1M tokens in / 65K out
- Paid Tier 1 (Flash-Lite): thousands of RPM; the gateway paces itself at
150 RPM ยท 1M TPM ยท 10K RPD โ a deliberate under-estimate,
raised in
costhelm/routing/core.pyonce the account's real tier is confirmed
Get a key:
- Go to aistudio.google.com/app/apikey
- Sign in with your Google account
- Click Create API key โ pick or create a project โ copy the
AIzaโฆkey - Attach the project to a billing account for paid-tier limits
2. OpenRouter one key, many models
- Paid credits unlock the full catalog (300+ models). Default:
meta-llama/llama-3.3-70b-instructโ default ($0.13/$0.40 per Mtok at the 2026-08 catalog rate) - Gotcha: OpenRouter's
openai/gpt-oss-120bendpoint 400s onreasoning: "off"โ "Reasoning is mandatory for this endpoint" โ which is why the old Groq STANDARD-rung model did not survive the host move - Paid accounts are credit-metered with no fixed published RPM; the gateway paces itself at 60 RPM ยท 500K TPM ยท 5K RPD as a deliberate under-estimate
Get a key:
- Go to openrouter.ai
- Sign in with Google or GitHub
- Keys โ Create Key โ copy the
sk-or-โฆkey - Add credits โ without them only
:freemodels answer, under tight daily caps
3. OpenAI
- Default:
gpt-5.6-terraโ default ($2.00/$12.00 per Mtok). The bare aliasgpt-5.6routes tosol, the dearest of the family โ name the variant you mean - Context: 922K in / 128K out
- Never free at any tier; the gateway paces itself at 60 RPM ยท 200K TPM as a deliberate under-estimate
Get a key:
- Go to platform.openai.com/api-keys
- Create new secret key โ copy the
sk-proj-โฆkey - Fund the account โ usage tier (and real rate limits) grow with spend
4. Ollama (local)
- Runs on your machine โ zero rate limits, zero cost, 0ms cooldown
- Default:
gemma4:31b
Set up:
- Install: ollama.com โ download for your OS
- Pull a model:
ollama pull gemma4:31b(orllama3.2,phi4, etc.) - Verify:
ollama list - The gateway auto-detects via
OLLAMA_URL(default:http://localhost:11434) โ but registers only whenOLLAMA_MODELis set
Retired free tiers
Groq, Cerebras, NVIDIA NIM and GitHub Models are still supported by the code
but carry no keys and sit outside the default routing. Their old free-tier
pacing rows remain in costhelm/routing/core.py; set a key and add the
name back to LLM_ORDER to resurrect one. Note the Groq key also
powered the Whisper speech-to-text provider, which is dark while the key is
absent.
Summary table
RPM/RPD/TPM here are the gateway's self-imposed pacing from
costhelm/routing/core.py โ deliberate under-estimates of each paid
account's real limits, because too low only throttles locally while too high
buys 429s. Raise them once the accounts' real tiers are confirmed.
| Provider | Default model | RPM | RPD | Other limits |
|---|---|---|---|---|
| Ollama | gemma4:31b | โ | โ | local, unlimited |
| Gemini | gemini-3.1-flash-lite | 150 | 10,000 | 1M TPM ยท 1M ctx |
| OpenRouter | meta-llama/llama-3.3-70b-instruct | 60 | 5,000 | 500K TPM ยท credit-metered |
| OpenAI | gpt-5.6-terra | 60 | โ | 200K TPM ยท 922K in / 128K out |
Configuration (.env)
The gateway reads from .env. All keys are optional โ providers without keys are skipped.
GEMINI_API_KEY_1=... # numbered slots become a gemini_1..gemini_N pool
GEMINI_MODEL=gemini-3.1-flash-lite
OPEN_ROUTER_API_KEY=... # note the underscore: OPEN_ROUTER, not OPENROUTER
OPENROUTER_MODEL=meta-llama/llama-3.3-70b-instruct
OPENAI_API_KEY=...
OPENAI_MODEL=gpt-5.6-terra
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=gemma4:31b # ollama registers only when this is set
LLM_ORDER=ollama,gemini,openrouter,openai
COSTHELM_PORT=8111
openai goes last in LLM_ORDER on purpose: the order is a
failover ring, so the dearest provider belongs at the end of it. The bare alias
gpt-5.6 routes to sol, the most expensive of the family โ
name the variant you mean.
HTTP API reference
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/chat | Send a chat request (with optional provider, model, stream) |
| GET | /v1/providers | List configured providers, shortcuts, default models, limits |
| GET | /v1/status | Live RPM/RPD/TPM usage per provider, today's stats |
| GET | /v1/calls?limit=100&provider=&status= | Recent call log |
| GET | / | Dashboard |
| GET | /help | This page |
How failover works
- Caller sends request (with or without
provider). - Router estimates token usage from prompt length.
- Walks providers in
LLM_ORDER, skipping any that:- Are inside their per-provider cooldown window (a fixed per-provider
seconds value in
costhelm/routing/core.py, 1 s for the paid providers, 0 for local Ollama) - Have hit RPM, RPD, TPM, or daily token cap
- Have a
max_ctxsmaller than the prompt
- Are inside their per-provider cooldown window (a fixed per-provider
seconds value in
- First eligible provider gets the call. On 5xx / timeout / 429 โ moves to next.
- If
provider=...was explicitly set, no failover โ error surfaces. - Every call (success or fail) is logged to
gateway.dbwith provider, model, tokens, latency, status.