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

# Dari Auto Router

> Use Dari's hosted routing intelligence in your self-hosted router.

The Dari Auto Router is a hosted routing policy. Instead of writing your own selector, you send Dari the candidates and the conversation — Dari's routing model picks the best model for each turn and bills your org per call.

<Note>
  The Auto Router is a paid service. You need a Dari API key with billing enabled. Self-hosted routing without the Auto Router is free and works without any network calls — use a [custom policy](/framework/policies) instead.
</Note>

## Quickstart

Drop `createAutoRouter` into `createRouter` as the policy. That's it.

```ts theme={null}
import { createAutoRouter, createPiRuntime, createRouter } from "@dari/router-core";

const pi = await createPiRuntime({
  apiKey: ({ provider }) => {
    const key = process.env[`${provider.toUpperCase()}_API_KEY`];
    if (!key) throw new Error(`Missing ${provider.toUpperCase()}_API_KEY`);
    return key;
  },
});

const router = createRouter({
  models: [
    pi.model("openai/gpt-5.6-sol"),
    pi.model("anthropic/claude-sonnet-5"),
  ],
  policy: createAutoRouter({ apiKey: process.env.DARI_API_KEY! }),
  runtime: pi,
});

const response = await router.fetch(
  new Request("https://your-app/v1/chat/completions", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      model: "dari/routing",
      messages: [{ role: "user", content: "Write a palindrome function" }],
    }),
  }),
);
```

The `apiKey` resolver receives `{ provider, model, api, purpose }`, so one runtime can serve every declared provider. `pi.model()` fills in each model's capabilities from Pi's catalog — see [Models](/framework/models).

## How It Works

Every request goes through three phases — the first two run locally, only the selection call hits Dari:

<Steps>
  <Step title="Prepare">
    Router Core narrows your models to compatible candidates based on capabilities, tools, and request shape. This runs in your process.
  </Step>

  <Step title="Select">
    The Auto Router sends the candidates and conversation to `https://routing.dari.dev/v1/auto-router/select`. Dari's routing model evaluates them and returns a decision. This is the only network call — it's one HTTP request per turn.
  </Step>

  <Step title="Execute">
    Router Core dispatches the selected model to your executor (Pi runtime or custom). The response flows back through the same protocol.
  </Step>
</Steps>

### What The Selection Call Contains

The selection call carries no provider credentials — Dari never sees your model API keys. It does receive the conversation text verbatim: system prompts, user and assistant turns, tool arguments and results, and readable reasoning text are all part of the selector input, alongside the candidate list, eval scores, and cost estimates. Before the call, image bytes are replaced with an `<image omitted>` placeholder and encrypted reasoning continuations are stripped. Request `metadata`, `user`, and `prompt_cache_key` never leave your process.

The [anonymous selection protocol](/framework/decision-pipeline#anonymous-selection) hides model names from the routing policy — it does not hide conversation content from Dari.

## Leases

The Auto Router supports multi-turn leases. When the routing model commits to a model for N turns, the decision includes `leaseTurnsRemaining` and Router Core skips the selection call for subsequent turns in the same conversation.

<Accordion title="How leases work">
  1. Turn 1: The Auto Router selects `gpt-5.6-sol/high` with a 10-turn lease.
  2. Turns 2–10: Router Core serves the same model without calling Dari. You're not billed for these turns.
  3. Turn 11: The lease expires. The Auto Router evaluates the conversation again and may pick a different model or renew.
</Accordion>

Leases are managed automatically — no configuration needed. The routing model decides whether to lease based on conversation context. Lease state lives in `createRouter`'s lease store — in-memory by default; pass a [`leaseStore`](/framework/overview#operational-options) to share leases across processes. On ephemeral or replicated hosts (Cloud Run, Lambda), use a shared store: every lease lost to a cold start is a billed re-selection on the next turn — see [Serverless Deployments](/framework/overview#serverless-deployments).

<Note>
  Lease short-circuiting requires a `prompt_cache_key` on your requests so Router Core can correlate turns within a conversation. Without it, every turn calls `/select` and leases are reported on each decision but not skipped.
</Note>

## Thinking Traces

The routing model's reasoning is included in the response as a `thinking` field. It's accessible from the routing decision's details:

```ts theme={null}
const selection = await router.select(request);
const details = selection.policyDetails as { selectorOutput: string };
const parsed = JSON.parse(details.selectorOutput);
console.log(parsed.thinking); // "I chose gpt-5.6-sol because the request needs deep reasoning..."
```

## Configuration

`createAutoRouter` accepts all options that `createDariRoutingPolicy` accepts, except `selector`, `runtime`, `selectorModel`, and `selectorContextWindowChars` (those are managed by the Auto Router) and `strategy`/`customConfig`. Custom routing rules are rejected with a configuration error — the hosted Auto Router serves only the default policy. For custom rules, self-host the selector with [`createDariRoutingPolicy`](/framework/policies#custom-rules-strategy) or use the [managed platform](/router/overview).

```ts theme={null}
createAutoRouter({
  apiKey: process.env.DARI_API_KEY!,
  endpoint: "https://routing.dari.dev/v1/auto-router", // default; override for testing
  pricing: (model) => modelPricing[model],          // your model pricing for cost estimation
  evals: yourEvals,                                 // optional benchmark evals
})
```

The endpoint defaults to `https://routing.dari.dev/v1/auto-router`. Override it for local development or testing — the client appends `/select`, and tolerates an endpoint pasted with a trailing slash or `/select` already on it. To build a compatible endpoint, decode the POSTed body with the exported `decodeUntrustedSelectorRequest()` wire codec.

## Pricing

The Auto Router bills per selection call. Each call to the `/select` endpoint counts as one billable event, regardless of how many candidates are evaluated or how many tokens the conversation contains (max 8k tokens per call).

Usage appears in your Dari dashboard under the `dari/auto-router` model with provider `dari`.

## When To Use The Auto Router

<CardGroup cols={3}>
  <Card title="Use Auto Router" icon="sparkles" href="#quickstart">
    You want Dari's routing intelligence without managing a selector model. You're fine with one network call per turn (or fewer, with leases).
  </Card>

  <Card title="Use A Custom Policy" icon="gear" href="/framework/policies">
    You want full control over model selection, need offline routing, or have domain-specific rules that don't require an LLM selector.
  </Card>

  <Card title="Use The Managed Platform" icon="cloud" href="/router/overview">
    You want Dari to host everything — routing, execution, billing, and telemetry. No self-hosting required.
  </Card>
</CardGroup>
