# Auto Router (/docs/auto-router)

Set `model` to `auto` and OhMyGPT picks a model for each request from what the latest user message asks for: a fast, low-cost model for short, simple turns, a capable general model for most work, and a frontier model when the turn asks for proofs, algorithms, architecture or debugging. `ohmygpt/auto` and OpenRouter's `openrouter/auto` work the same way.

```bash
curl https://api.ohmygpt.com/v1/chat/completions \
  -H "Authorization: Bearer $OHMYGPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "auto",
    "messages": [{"role": "user", "content": "hi"}]
  }'
```

The response's `model` names the model that answered:

```json
{
  "model": "deepseek/deepseek-v4.1-flash-1017",
  "choices": [{"message": {"role": "assistant", "content": "Hi! How can I help you today?"}}]
}
```

You pay that model's standard price; the router adds no fee. Auto works on Chat Completions, Responses and Messages, streaming or not. Endpoints that don't generate chat replies, such as Embeddings, reject it with `400 unsupported_endpoint`.

## Conversations [#conversations]

Send `prompt_cache_key` and the conversation stays on one model, so its prompt cache keeps working. Within a conversation the router can move up to a stronger model when a later turn is harder, and never moves back down:

| Turn | Model |
|---|---|
| `hi` | `deepseek/deepseek-v4.1-flash-1017` |
| `Prove that there are infinitely many primes, briefly.` | `openai/gpt-6.1-sol` |
| `thanks` | `openai/gpt-6.1-sol` |

Without `prompt_cache_key`, each request is routed on its own.

## Options [#options]

Add an `auto-router` entry to `plugins`, as on OpenRouter:

```json
{
  "model": "auto",
  "plugins": [{
    "id": "auto-router",
    "allowed_models": ["openai/*", "google/*"],
    "excluded_models": ["openai/gpt-5.4-nano"],
    "cost_tier": "low"
  }],
  "messages": [{"role": "user", "content": "explain why the sky is blue"}]
}
```

| Field | Effect |
|---|---|
| `allowed_models` | Only pick from these models. `*` matches any part of an ID, as in `openai/*`. |
| `excluded_models` | Never pick these models, even if `allowed_models` matches them. |
| `cost_tier` | `low` picks one step cheaper than the request would otherwise get, `high` one step stronger; `medium` is the default. |

A `cost_tier` other than these, or lists that leave no model, return `400 invalid_parameter` naming the field. The `auto-router` entry is not sent on to the model.
