Relay-E
Concepts

Providers

Anthropic, OpenAI, OpenRouter, Ollama, MiniMax, Moonshot — pick one or stack them. Model routing picks the cheapest model that fits.

Relay-E uses the Vercel AI SDK underneath, so adding a provider is wiring an adapter into the registry. Six providers are configured as of v0.1.0.

What's wired

ProviderWhen to pickEnv var
OpenRouterSingle key, 100+ models. Recommended for most projects.OPENROUTER_API_KEY
AnthropicDirect, lowest latency for Claude. Supports prompt caching.ANTHROPIC_API_KEY
OpenAIGPT models, fallback / specific features.OPENAI_API_KEY
OllamaFully offline / on-prem. Pull models locally.OLLAMA_BASE_URL
MiniMaxChinese LLM provider — MiniMax-Text-01, MiniMax-M1.MINIMAX_API_KEY
Moonshot / KimiChinese LLM provider — moonshot-v1 series and kimi-latest.MOONSHOT_API_KEY

Set at least one. The engine throws a clear error at startup if none are configured.

OpenRouter aggregates 100+ models behind a single OpenAI-compatible API. With one key, you can route between Claude, GPT, Llama, Mistral, and more — useful when you want flexibility without managing a key per provider.

.env
OPENROUTER_API_KEY=sk-or-v1-...

OpenRouter model keys use the openrouter:<provider>/<model> convention:

modelKey: "openrouter:anthropic/claude-sonnet-4"
modelKey: "openrouter:openai/gpt-4o"
modelKey: "openrouter:meta-llama/llama-3.3-70b-instruct"

OpenRouter's pricing is per-model. The engine doesn't pre-bake every model's price — set yours in packages/providers/src/pricing.ts for the ones you use.

Anthropic — for Claude direct

.env
ANTHROPIC_API_KEY=sk-ant-...

Claude direct gets you:

  • Prompt caching (huge cost win on stable system prompts — see Token Optimisation)
  • Lower latency (no aggregator hop)
  • Specific features like extended thinking

Defaults bundled:

TierModel
fastclaude-haiku-4-5
balancedclaude-sonnet-4-6
premiumclaude-opus-4-7

OpenAI — for GPT direct

.env
OPENAI_API_KEY=sk-...
TierModel
fastgpt-4o-mini
balanced / premiumgpt-4o

OpenAI is also the embedding provider. text-embedding-3-small (1536 dims) is a sane default; switch to voyage-3 for better retrieval quality (separate Voyage API key).

Ollama — fully offline

For air-gapped dev or compliance-heavy environments:

docker compose --profile local-llm up -d
docker exec relay-e-ollama ollama pull llama3.2
docker exec relay-e-ollama ollama pull nomic-embed-text
.env
OLLAMA_BASE_URL=http://localhost:11434

Local models are slower and lower-quality than frontier ones, but useful for:

  • Local development without burning API credits
  • Air-gapped self-hosted deployments
  • Cheap classification / routing models

Tier-based routing

You don't pick a model per request — you pick a tier in the skill:

defineSkill({
  name: "...",
  preferredTier: "balanced",  // "fast" | "balanced" | "premium"
  ...
});

The router resolves the tier against the configured providers in priority order:

Anthropic ▶ OpenRouter ▶ OpenAI ▶ Ollama

If Anthropic is configured, "balanced" → claude-sonnet-4-6. If only OpenRouter is configured, "balanced" → openrouter:anthropic/claude-sonnet-4. Routing is in packages/providers/src/registry.ts.

You can also override per request:

curl ... -d '{"prompt":"...","modelKey":"claude-haiku-4-5-20251001"}'

MiniMax

MiniMax is an OpenAI-compatible Chinese LLM provider.

.env
MINIMAX_API_KEY=your-key
Model keyDescription
minimax:MiniMax-Text-01General purpose, long context (1M tokens)
minimax:MiniMax-M1Reasoning-optimised model

Moonshot / Kimi

Moonshot AI (Kimi) is an OpenAI-compatible Chinese LLM provider with large context windows.

.env
MOONSHOT_API_KEY=your-key
Model keyContextDescription
moonshot:moonshot-v1-8k8kFast, short context
moonshot:moonshot-v1-32k32kBalanced
moonshot:moonshot-v1-128k128kLong context
moonshot:kimi-latest128kLatest Kimi model, tracks upstream

Adding a new provider

The registry is small (~100 lines). To add a provider:

  1. Add the package: npm i -w @relay-e/providers your-ai-sdk-provider
  2. In packages/providers/src/registry.ts:
    • Create the client in the ProviderRegistry constructor.
    • Add models to CHAT_MODELS with provider: "yourname".
    • Add a case to providerFor(id).
  3. In pricing.ts, add per-model pricing.
  4. Done — routeBy() and chat() will use it automatically.

Embeddings

Separate from chat. Configured via EMBED_MODELS:

ModelProviderDimensions
voyage-3Voyage1024
text-embedding-3-smallOpenAI1536
text-embedding-3-largeOpenAI3072
ollama:nomic-embed-textOllama768

The schema's embedding columns are 1536-dimensional by default — match this when picking your embedding model, or migrate the column when you change.

Cost-saving tips

TrickSaving
Use fast for classification / routing50–80% on those calls
Enable Anthropic prompt caching for system prompts40–80% on repeat calls
Use OpenRouter to A/B test cheaper modelsVariable
Cap maxSteps to what your skills actually needBounds runaway loops

See Concepts → Agent Loop for cost accounting, and Reference → Token Optimisation for the full playbook.

On this page