# Intelligent routing

Select models automatically without silently widening privacy constraints.

Use `model: "/auto"` when AnonRouter should choose an eligible model for the
request. The values `auto` and `anonrouter/auto` are accepted aliases, and any
model string containing a `*` glob (for example `meta-llama/*`) also triggers
automatic selection over the matching routes.

For a goal-specific model ID that also works in apps with only a model field,
see [choose a router](/routers): Cheap, Fast, Coding, Uncensored, TEE, and Free.

This page covers choosing a model. To choose which provider serves a model, and
how AnonRouter fails over between providers, see
[provider routing and failover](/provider-routing).

```json
{
  "model": "/auto",
  "messages": [
    {
      "role": "user",
      "content": "Review this distributed system design."
    }
  ],
  "routing": {
    "strategy": "balanced",
    "max_cost_usd": 0.02
  }
}
```

The ticket you issue must also be automatic. Request a ticket with the same
`/auto` or glob `model`, then send the completion with the matching value.

## The routing object

The optional `routing` object shapes the candidate set and the choice:

| Field             | Values                                         | Purpose                                                        |
| ----------------- | ---------------------------------------------- | -------------------------------------------------------------- |
| `strategy`        | `cost`, `balanced`, `quality`                  | Trade off model quality against price. Defaults to `balanced`. |
| `privacy_classes` | array of `anonymous`, `private`, `tee`, `e2ee` | Restrict eligible privacy tiers.                               |
| `max_cost_usd`    | number                                         | Drop candidates whose worst-case cost exceeds this.            |
| `allow`           | array of glob patterns                         | Restrict candidates to matching models or providers.           |
| `exclude`         | array of glob patterns                         | Remove matching models or providers.                           |

`strategy` controls quality and price, not privacy. `cost` prefers cheaper,
lower-tier models, `quality` prefers the highest quality tier, and `balanced`
sits between them and can step up for complex prompts.

```json
{
  "model": "meta-llama/*",
  "messages": [
    {
      "role": "user",
      "content": "Analyze this TypeScript API."
    }
  ],
  "routing": {
    "exclude": ["*/*-guard"],
    "strategy": "cost"
  }
}
```

Exclusions always win, and `allow`/`exclude` patterns match against both the
`provider/model` form and the bare model id.

## Privacy is never widened

When `privacy_classes` is omitted, the eligible set defaults to the
privacy-preserving tiers (`private`, `tee`, `e2ee`). Automatic routing never
silently adds a weaker tier. To let `/auto` also consider Anonymous routes, you
must ask for it explicitly:

```json
{
  "model": "/auto",
  "messages": [{ "role": "user", "content": "Summarize this text." }],
  "routing": {
    "privacy_classes": ["anonymous", "private"]
  }
}
```

If no model satisfies the constraints, the request fails closed rather than
downgrading to a route you did not allow.

> **Choose a TEE or E2EE path explicitly**
>
> `/auto` does not select TEE or E2EE routes. For plaintext TEE inference, use
> an explicit TEE model or the [TEE Router](/routers). E2EE requires an explicit
> model and its provider-specific encryption and verification flow.

A TEE privacy label alone does not make an ordinary OpenAI client verify
attestation. See [TEE verification and encrypted inference](/tee-verification)
for the checks a verifying client performs and the provider-specific limits.
E2EE requests are bound to their provider and do not fall back to another route.

Automatic selection respects [context limits and output budgets](/context-limits).
An explicit output cap is preserved; AnonRouter does not shorten or summarize
the prompt to make it fit.

## Model suffixes

Add a suffix to a model id to choose how its provider route is picked, without
a `provider` object:

| Suffix      | Picks                                                                               |
| ----------- | ----------------------------------------------------------------------------------- |
| `:cheapest` | The cheapest route first. `:floor` is the same.                                     |
| `:fastest`  | The highest-throughput route first. `:nitro` is the same.                           |
| `:private`  | Only Private or stronger routes, most private first (E2EE, then TEE, then Private). |
| `:tee`      | Only TEE or E2EE routes.                                                            |
| `:e2ee`     | Only E2EE routes.                                                                   |

```json
{
  "model": "deepseek/deepseek-v4.1-flash-1017:private",
  "messages": [{ "role": "user", "content": "Summarize this contract." }]
}
```

`:private`, `:tee` and `:e2ee` are guarantees. If the model has no route at that
level, the request fails instead of using a weaker one.

A suffix never weakens your saved privacy settings. With a Private floor on your
account or workspace, `:cheapest` picks the cheapest Private route. Without one,
it picks the cheapest route at any privacy level you allow.

E2EE routes still need the encrypted client flow described in
[TEE verification and encrypted inference](/tee-verification).

Use one suffix per model id. A second suffix, or any suffix not listed here or
under free models below (for example `:online` or `:thinking`), makes the id
unknown and the request fails with `model_not_found`.

### Free models (`:free`)

`:free` is different from the suffixes above. It does not change how a model is
routed. It names a separate free model, `creator/model:free`, which exists only
where AnonRouter lists one; adding `:free` to a model without a free version
returns `model_not_found`. A free model does not combine with another suffix
(`400 free_variant_id_invalid`) and is never picked by `/auto`. Free models run
on Anonymous routes and need the account opt-in. See [free models](/free-models)
for setup, limits and errors.

## Response headers

Successful requests report the actual selection:

* `x-anonrouter-selected-model` is the chosen `provider/model`.
* `x-anonrouter-routing` is `auto` when a model was selected automatically, or
  `exact` when you named a single model.

The response body's `model` field is also rewritten to the selected model. Any
classification the router computes to make the choice is used in memory and is
not stored as durable usage metadata.

## Saved routing preferences

An account can save default routing behavior that applies when a request does not
override it. Preferences are managed with a session.

| Method | Endpoint                      | Description                                       |
| ------ | ----------------------------- | ------------------------------------------------- |
| `GET`  | `/v1/routing/effective`       | List models the caller's saved preferences allow. |
| `GET`  | `/v1/routing/preferences`     | Read saved routing preferences.                   |
| `PUT`  | `/v1/routing/preferences`     | Replace saved routing preferences.                |
| `POST` | `/v1/routing/preview`         | Preview a routing decision for a sample prompt.   |
| `POST` | `/v1/routing/eligible-models` | List models eligible for draft preferences.       |

Preferences carry a `privacy_level` that maps to a default privacy set:

* `open` allows `anonymous`, `private`, `tee`, and `e2ee`.
* `balanced` allows `private`, `tee`, and `e2ee`.
* `maximum` allows only `tee` and `e2ee`.

A `pool_mode` of `all`, `include`, or `exclude` with `model_patterns` narrows the
default candidate pool, and `strategy` sets the default quality tradeoff.

These are defaults for `/auto` only. A workspace can also set a
[privacy boundary](/workspaces#privacy-boundary) (`privacy_boundary`) that
applies to every request. `/auto` never goes below it: when the boundary is
stricter than `privacy_level`, `/auto` uses the boundary, and an `/auto`
selection below it is refused with `403 privacy_boundary_not_met`.
