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

# Smart Auto

> Let Xynthis pick the model per call — how the router decides, and the arithmetic behind it.

`Auto` is an entry in the model picker. Selecting it hands per-call model choice to a router instead of pinning one provider. The router costs no inference: it never asks an LLM which model to use, because doing so would make Auto slower and more expensive than just picking one yourself.

## What it actually optimises

The obvious framing is "use a smarter model for harder prompts". That is not the main problem Auto solves.

In practice the models available to you at any moment are usually cloud frontier near-peers with no quality spread worth arbitraging. What actually costs you turns is a provider being rate-limited or returning errors. So Auto treats **availability and health as hard filters**, and treats quality as a preference on top.

Three things follow from that, and they are worth knowing before you turn it on:

* Routing is structural, not semantic. It reads the shape of the turn, never the meaning of your prompt.
* On a pool of near-peers the router often reports **low confidence**, and that is correct — it means the models really are interchangeable for that turn.
* If you ask for a local-only route and no local model is available, Auto **refuses** rather than quietly sending your prompt to the cloud.

## Turning it on

From the CLI:

```bash theme={null}
xynthis models set auto            # balanced (the default policy)
xynthis models set auto:fast
xynthis models set auto:deep
xynthis models set auto:private
```

Or in `~/.xynthis/config.toml`:

```toml theme={null}
[models]
active = "auto"    # or auto:balanced | auto:deep | auto:fast | auto:private
```

From the app, pick **Smart Auto** at the top of the model picker. It appears whenever at least one provider is available.

Anything that doesn't parse as `auto[:policy]` is a manual target and bypasses the router completely, so existing configs are unaffected. **Picking a specific model in the picker is a hard override** — Auto is off until you select it again.

## The four policies

A policy changes exactly two weights: how much the router values speed, and how much it values raw model strength. Nothing else.

| Policy          | Favours                                                  | Use when                                                                   |
| --------------- | -------------------------------------------------------- | -------------------------------------------------------------------------- |
| `auto:balanced` | Strength, with some weight on speed                      | Default. General work.                                                     |
| `auto:fast`     | Speed, strength barely counted                           | Long tool-driven loops where latency compounds                             |
| `auto:deep`     | Strength only, speed ignored                             | Architecture, hard debugging, anything you'd hand-pick your best model for |
| `auto:private`  | Same weights as balanced, but restricted to local models | Work that must not leave the machine                                       |

<Warning>
  `auto:private` is a hard constraint, not a preference. If no local model is available and healthy, the router returns **no feasible model** and the turn fails rather than falling back to a cloud provider. That is deliberate. Set up a [local model](/guides/local-models) before relying on it.
</Warning>

## How a decision is made

Three stages, in order.

**Stage 1 — feasibility.** A hard filter that produces the set of models allowed to run this turn. A model must be available, healthy, reachable with usable credentials, have enough context capacity for the transcript, support the tool mode the turn needs, and satisfy the privacy requirement.

Feasibility is computed *before* scoring, and no score can re-admit a model the filter excluded. That is the safety property — it is what makes `auto:private` trustworthy.

**Stage 2 — scoring.** Every surviving candidate gets a utility score (below).

**Stage 3 — selection.** Highest score wins. Ties break on stable input order, so the same inputs always produce the same route.

## The arithmetic

The score for a model $m$ on a turn $z$:

$$
S(m,z) \;=\; \Phi(d,q) \;+\; w_s\,\sigma(m) \;+\; w_q\,\kappa(m) \;+\; R \;-\; C \;-\; X
$$

Each term, concretely.

**Depth fit** $\Phi(d,q)$ — how well the model's strength class matches the reasoning depth the turn needs:

|              | Frontier | Mid | Light |
| ------------ | -------- | --- | ----- |
| **Deep**     | 1.0      | 0.3 | −0.5  |
| **Standard** | 0.8      | 0.7 | 0.2   |
| **Trivial**  | 0.4      | 0.6 | 0.7   |

The `Trivial` row inverts on purpose. A one-line summary after a tool call gains nothing from a deliberate model, and paying its latency is a real cost.

**Speed** $\sigma$ and **strength** $\kappa$:

| $\sigma$ (latency class) |     | $\kappa$ (strength class) |     |
| ------------------------ | --- | ------------------------- | --- |
| Fast                     | 1.0 | Frontier                  | 1.0 |
| Standard                 | 0.5 | Mid                       | 0.6 |
| Deliberate               | 0.0 | Light                     | 0.3 |

**Policy weights** $(w_s, w_q)$ — the only thing a policy changes:

| Policy     | $w_s$ (speed) | $w_q$ (strength) |
| ---------- | ------------- | ---------------- |
| `fast`     | 1.0           | 0.2              |
| `deep`     | 0.0           | 1.0              |
| `balanced` | 0.35          | 0.8              |
| `private`  | 0.35          | 0.8              |

**Risk escalation** $R = 0.5$, applied when the turn is high-risk **and** the candidate is a Frontier model. High-risk work escalates regardless of policy, including under `auto:fast` — a wrong destructive edit costs far more than the latency saved.

**Access cost** $C = 0.6$, applied when the route is *not* prepaid. This is not spend-optimisation. It exists so that if you already hold a Claude or ChatGPT subscription, you aren't silently routed through purchased Xynthis credits and **charged twice for the same capability**. Your own API key counts as prepaid.

**Switch cost** $X = 0.25$, applied to any candidate that isn't the model that handled the previous turn. This matters *because* the models are near-peers: without it, scoring noise alone would flip the model every turn.

### Confidence is a margin, not a probability

$$
c \;=\; \operatorname{clamp}\!\left(\frac{S(m^*) - S(m_{\text{runner-up}})}{2},\; 0,\; 1\right)
$$

with $c = 1$ when only one candidate is feasible. Near-peers routinely tie, and a low number there is the honest answer: it means the choice genuinely didn't matter. Reporting high confidence for a 0.01 margin would be fabricated.

### Worked example

Pool: one Frontier/Deliberate model and one Mid/Fast model. Policy `balanced`, no incumbent, both prepaid, low risk.

Trivial turn (a summary after tool results):

```
frontier = 0.4 + 0.35·0.0 + 0.8·1.0 = 1.20
mid/fast = 0.6 + 0.35·1.0 + 0.8·0.6 = 1.43   ← wins
confidence = (1.43 − 1.20) / 2 = 0.115
```

Deep turn, same pool:

```
frontier = 1.0 + 0.35·0.0 + 0.8·1.0 = 1.80   ← wins
mid/fast = 0.3 + 0.35·1.0 + 0.8·0.6 = 1.13
confidence = (1.80 − 1.13) / 2 = 0.335
```

## How the turn is classified

Structural signals only — no inference, and **your prompt text is never inspected to infer intent**:

| Signal       | How it's derived                                                                                                    |
| ------------ | ------------------------------------------------------------------------------------------------------------------- |
| Depth        | `Trivial` if the last message is purely tool results; `Deep` if destructive tools are offered; otherwise `Standard` |
| Risk         | `High` if destructive tools are offered, else `Low`                                                                 |
| Privacy      | Always taken from your policy. Never inferred from a prompt.                                                        |
| Tools        | Whether the turn offers tools at all                                                                                |
| Context size | Transcript length ÷ 4                                                                                               |

## Health tracking

The router learns provider health from real failures during the session:

* A **429 or quota error** marks the provider rate-limited and evicts it immediately.
* **Other failures** are counted; a provider is evicted on the second one. A single 5xx is routinely transient, and evicting on it would make routing flap.
* **Any success clears the record**, so one bad minute can't bench a provider for the rest of the session.

Failures are only recorded after the normal retry path has already given up, so an eviction means genuinely unusable, not transient.

<Note>
  Health is only learned from providers actually called. A provider that is rate-limited but untouched this session still looks healthy until the first call fails. Discovering it costs one failed call.
</Note>

## When it falls back

The router never returns a model that failed the feasibility filter.

| Situation                                    | Result                                                 |
| -------------------------------------------- | ------------------------------------------------------ |
| No feasible candidate under `auto:private`   | Fails with no feasible model — never substitutes cloud |
| No feasible candidate under any other policy | Falls back to your last manual model choice            |
| Router error of any kind                     | Falls through to the pre-Auto selection path           |

## What Auto deliberately does not do

Three signals are absent from the score, and the omission is a design decision rather than unfinished work — each needs observed success statistics that don't exist yet, and inventing them would produce confident-looking numbers with nothing behind them:

* **Uncertainty.** Penalising models the router has merely seen too little of, rather than models it has seen fail.
* **Domain specialty.** Knowing that one model is genuinely better at, say, Rust than another.
* **Routing entropy.** Detecting that the router can't separate the candidates at all, and responding by adding verification or asking you, instead of picking arbitrarily.

Until those are measured, Auto optimises for what it can actually observe: availability, health, depth fit, latency, and not charging you twice.

## Related

* [Model providers](/guides/models) — configuring the pool Auto chooses from
* [Local models](/guides/local-models) — required for `auto:private`
