> ## Documentation Index
> Fetch the complete documentation index at: https://docs.protege.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Routing

> How a labelled call reaches a model, and what has to be true before a cheaper one is used.

<Warning>
  Automatic model selection is not exposed through the API yet. Today you name
  the model on every request and the gateway serves that model. The rest of this
  page describes how routes are chosen and promoted, which happens outside the
  request path while this ships.
</Warning>

Every request resolves to exactly one model.

## Choosing the model

<ParamField path="model" type="string" required>
  A catalog model id, for example `deepseek-v4-flash`. The provider-pinned form
  is accepted and normalises to the same canonical id.
</ParamField>

<Tabs>
  <Tab title="auto">
    ```json theme={null}
    { "task": "invoice_extraction", "model": "deepseek-v4-flash", "messages": [...] }
    ```

    Protégé serves the call from the cheapest route currently approved for that
    task. If the task has no approved route yet, it falls back to your account's
    default model, so it is always safe to send.

    This is the setting that lets a task get cheaper over time without a deploy.
  </Tab>

  <Tab title="Pinned">
    ```json theme={null}
    { "task": "invoice_extraction", "model": "anthropic/claude-opus-5", "messages": [...] }
    ```

    The named model serves the call. Routing is bypassed entirely.

    The call still counts toward the task's history, so pinning is the right way
    to run a frontier model in production while a cheaper route is still being
    evaluated against it.
  </Tab>
</Tabs>

## What "cheapest" means

Cheapest that **clears the task's eval**, not cheapest outright. A route is only
eligible if it scores at or above the incumbent on that task's own eval
contract. Price breaks ties among routes that qualify; it never overrides the
contract.

Without a contract there is nothing to gate on, so the workload stays on the
model you name rather than guessing.

## How a route gets promoted

<Steps>
  <Step title="History accumulates">
    Labelled calls build a trace corpus and a cost profile for the task.
  </Step>

  <Step title="Candidates are scored offline">
    Cheaper candidates are replayed against the task's eval contract. This happens
    out of band and does not touch your production traffic.
  </Step>

  <Step title="You approve">
    A candidate that clears the contract is proposed with its score and its
    measured cost delta. It does not serve traffic until you accept it.

    <Note>
      Approval is on by default and cannot be disabled for regulated tenants. No
      route change reaches production traffic without a human accepting it.
    </Note>
  </Step>

  <Step title="It takes effect">
    New calls with `model: "deepseek-v4-flash"` for that task use the new route. Pinned calls
    are unaffected.
  </Step>
</Steps>

Every promotion is versioned and reversible. Rolling back is a route change, not
a redeploy of your application.

## Reading the decision

The response tells you what actually served the call, which is the only reliable
way to know: the top-level `model` is the model that served the call.

```json theme={null}
"protege": {
  "task": "invoice_extraction",
  "route": "protege/invoice_extraction-8b",
  "cost_usd": 0.000164
}
```

Log `protege.route` alongside your own request IDs. When a task's quality moves,
that field is what tells you whether the route changed underneath it.

## When a task stops getting cheaper

Routing works by finding an existing model that is good enough. A task that has
exhausted the available models and is still expensive is the point at which
training a specialist becomes the cheaper option.

That is a separate engagement rather than an API call, and it is gated on the
same eval contract.

<Card title="See the measured runs" icon="chart-column" href="https://protege.sh/benchmarks/">
  Published benchmarks, with the runs that lost.
</Card>
