Configure OpenRouter Provider
OpenRouter is a unified gateway that exposes 100+ LLMs behind a single OpenAI-compatible API — Claude, GPT, Gemini, Llama, Mistral, and others — with one API key and one endpoint.
Omnia’s Provider custom resource treats OpenRouter like any other OpenAI-compatible endpoint. Two Omnia features combine to make this work:
spec.baseURL— point the OpenAI wire format at OpenRouter.spec.headers— set theHTTP-RefererandX-Titleattribution headers that OpenRouter uses for leaderboards and rate-limit tiers.
Prerequisites
Section titled “Prerequisites”- An OpenRouter account with an API key (create one at openrouter.ai/keys).
- Omnia operator installed in the cluster.
1. Create a Secret for the API key
Section titled “1. Create a Secret for the API key”kubectl create secret generic openrouter-credentials \ --namespace agents \ --from-literal=OPENAI_API_KEY='sk-or-v1-...'Omnia’s openai provider reads OPENAI_API_KEY by default; OpenRouter’s key slots in there directly. If you already use direct-OpenAI in another Provider, use a different secret name or key — see Migrate Provider Credentials for per-Provider isolation.
2. Create the Provider
Section titled “2. Create the Provider”apiVersion: omnia.altairalabs.ai/v1alpha1kind: Providermetadata: name: openrouter namespace: agentsspec: type: openai model: anthropic/claude-sonnet-4 # OpenRouter model ID baseURL: https://openrouter.ai/api/v1
headers: HTTP-Referer: https://your-app.example.com # Required for leaderboard attribution X-Title: omnia # Appears in OpenRouter analytics
credential: secretRef: name: openrouter-credentials
capabilities: - text - streaming - tools - jsonHow the headers reach the wire
Section titled “How the headers reach the wire”When the runtime creates the underlying PromptKit provider, spec.headers is passed through providers.ProviderSpec.Headers. PromptKit’s openai provider (which type: openai resolves to) applies custom headers to every /chat/completions request via its ApplyCustomHeaders helper — including streaming and tool-calling requests. Collisions with built-in headers (e.g. Authorization) are rejected at request time so you can’t accidentally break auth.
3. Verify the Provider is Ready
Section titled “3. Verify the Provider is Ready”kubectl get provider openrouter -n agents -o widekubectl get provider openrouter -n agents -o jsonpath='{.status.conditions}' | jq .Both SecretFound and CredentialConfigured conditions should be True. OpenRouter does not respond to unauthenticated GET / requests, so the EndpointReachable condition may be omitted or show a 401 — either is considered reachable (a 401 proves the endpoint is up).
4. Using with AgentRuntime
Section titled “4. Using with AgentRuntime”Reference the Provider from an AgentRuntime like any other:
apiVersion: omnia.altairalabs.ai/v1alpha1kind: AgentRuntimemetadata: name: my-agent namespace: agentsspec: promptPackRef: name: my-pack providers: - name: default providerRef: name: openrouter facade: type: websocketChoosing a model
Section titled “Choosing a model”OpenRouter’s model IDs follow the <vendor>/<model> pattern. Examples:
Omnia spec.model | Hosted model |
|---|---|
anthropic/claude-sonnet-4 | Anthropic Claude Sonnet 4 |
openai/gpt-4o | OpenAI GPT-4o |
google/gemini-2.0-flash-exp | Google Gemini 2.0 Flash |
meta-llama/llama-3.1-70b-instruct | Meta Llama 3.1 70B |
Full list: openrouter.ai/models.
Custom pricing (optional)
Section titled “Custom pricing (optional)”OpenRouter’s pricing can differ from the first-party API. Supply spec.pricing if you want Omnia’s cost tracking to reflect OpenRouter’s actual rates:
spec: pricing: inputCostPer1K: "0.003" outputCostPer1K: "0.015"If omitted, PromptKit falls back to built-in pricing for the underlying model family (e.g. Anthropic’s public list prices for a claude-sonnet-4 request). For production cost tracking against OpenRouter invoices, set the pricing explicitly.
Troubleshooting
Section titled “Troubleshooting”401 Unauthorized on every request. Check that the secret value uses an sk-or-v1-... OpenRouter key — a direct-OpenAI sk-... key will not work against openrouter.ai. Verify with kubectl get secret openrouter-credentials -n agents -o jsonpath='{.data.OPENAI_API_KEY}' | base64 -d | head -c 12.
Rate limits / attribution missing. OpenRouter’s free tier and leaderboards key off the HTTP-Referer and X-Title headers. If you omit them, requests still succeed but you’ll hit the unattributed rate limit and your app won’t appear on the leaderboard.
headers map is immutable error at request time. This is PromptKit rejecting a custom header that collides with one the provider sets itself (most commonly Authorization). Remove that key from spec.headers.
See also
Section titled “See also”- Provider CRD reference —
spec.headers— full field semantics and collision rules. - Migrate Provider Credentials — per-Provider secret isolation.
- OpenRouter docs — Quickstart — OpenRouter’s own getting-started.