# Configure OpenRouter provider

Point an Omnia `Provider` at [OpenRouter](https://openrouter.ai) so an agent can use any model it hosts with one API key.

OpenRouter speaks the OpenAI wire format, so the Provider uses `type: openai` with `spec.baseURL` set to OpenRouter and `spec.headers` carrying its attribution headers.

## Prerequisites

- An OpenRouter API key, created at [openrouter.ai/keys](https://openrouter.ai/keys).
- The Omnia operator installed in the cluster.

## 1. Create a secret for the API key

The Secret must be in the same namespace as the Provider.

```bash
kubectl create secret generic openrouter-credentials \
  --namespace agents \
  --from-literal=OPENAI_API_KEY='sk-or-v1-...'
```

`OPENAI_API_KEY` is the key the controller looks for by default on a `type: openai` Provider. To use another key name, set `spec.credential.secretRef.key`.

## 2. Create the provider

```yaml
apiVersion: omnia.altairalabs.ai/v1alpha1
kind: Provider
metadata:
  name: openrouter
  namespace: agents
spec:
  type: openai
  model: anthropic/claude-sonnet-4                # OpenRouter model ID
  baseURL: https://openrouter.ai/api/v1

  headers:
    HTTP-Referer: https://your-app.example.com    # attribution; replace with your app's URL
    X-Title: omnia                                # name shown in OpenRouter analytics

  credential:
    secretRef:
      name: openrouter-credentials

  capabilities:
    - text
    - streaming
    - tools
    - json
```

The model IDs here are illustrative. Take the exact ID from [openrouter.ai/models](https://openrouter.ai/models); it has the form `<vendor>/<model>`.

Do not put `Authorization` or any other header the OpenAI provider sets itself in `spec.headers`. The request fails with `custom header "Authorization" collides with built-in header set by provider`.

## 3. Set pricing for non-OpenAI models

Cost tracking uses `spec.pricing` when set. Without it, PromptKit prices only models in its built-in OpenAI table, after stripping the vendor prefix: `openai/gpt-4o` is priced as `gpt-4o`, but `anthropic/...`, `google/...` and `meta-llama/...` models are unpriced. Set the rates from OpenRouter's model page:

```yaml
spec:
  pricing:
    inputCostPer1K: "0.003"    # illustrative; use OpenRouter's current rates
    outputCostPer1K: "0.015"
```

## 4. Use it from an AgentRuntime

```yaml
apiVersion: omnia.altairalabs.ai/v1alpha1
kind: AgentRuntime
metadata:
  name: my-agent
  namespace: agents
spec:
  promptPackRef:
    name: my-pack
  providers:
    - name: default
      providerRef:
        name: openrouter
  facades:
    - type: websocket
```

## Verify

```bash
kubectl get provider openrouter -n agents \
  -o jsonpath='{range .status.conditions[*]}{.type}={.status} {.reason}{"\n"}{end}'
```

`SecretFound` and `CredentialConfigured` should be `True`. `EndpointReachable` should also be `True`: the controller probes `baseURL` without credentials, and any HTTP response, including a 401, counts as reachable. `False` means the connection itself failed (DNS, timeout or refused), and the Provider phase becomes `Unavailable`. `CredentialValid` reports a request to `baseURL` + `/models` (`https://openrouter.ai/api/v1/models`) sent with the key.

## Troubleshooting

### 401 Unauthorized on every request

Check that the secret holds an OpenRouter key (`sk-or-v1-...`), not an OpenAI key. Check the first characters without printing the whole key:

```bash
kubectl get secret openrouter-credentials -n agents \
  -o jsonpath='{.data.OPENAI_API_KEY}' | base64 -d | cut -c1-9
```

### Requests succeed but OpenRouter does not attribute the app

Check that `HTTP-Referer` and `X-Title` are set in `spec.headers`.

## Related pages

- [Provider reference](/reference/core/provider/#headers) for `baseURL`, `headers`, `pricing` and the status conditions.
- [OpenRouter quickstart](https://openrouter.ai/docs/quickstart) for OpenRouter's own setup.