> ## 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.

# Policies

> Choose an eligible model with a local function, selector, or hosted service.

A policy receives the normalized request and the candidates that survived capability filtering. It returns a model ID and may choose a reasoning effort.

## A local policy

```ts theme={null}
import type { RoutingPolicy } from "@mupt-ai/dari-router";

const policy: RoutingPolicy = ({ request, candidates }) => {
  const wantsTools = request.tools.length > 0;
  const preferred = wantsTools ? "anthropic/claude-sonnet-4-6" : "openai/gpt-5.4-mini";
  const selected = candidates.find((candidate) => candidate.id === preferred)
    ?? candidates[0]!;

  return {
    model: selected.id,
    reasoningEffort: selected.defaultReasoningEffort,
    reason: wantsTools ? "This candidate supports the requested tools." : "Use the fast candidate.",
  };
};
```

Policies may be synchronous or asynchronous. Router Core validates the returned model and reasoning effort. Omit `reasoningEffort` to use the candidate's default. The TypeScript field is `reasoningEffort`; wire JSON uses `reasoning_effort`.

## Inspect or serve a selection

`router.evaluatePolicy(request)` is stateless: it runs the policy without reading or writing leases and without firing hooks. Use it for previews, logs, or tests.

`router.select(request)` is the authoritative serving primitive. It reads an existing lease, applies a new lease returned by the policy, and fires `onSelection`. `router.fetch()` uses the same semantics.

```ts theme={null}
import { openAIChatRequest } from "@mupt-ai/dari-router/protocols";

const request = openAIChatRequest({
  model: "my-router",
  messages: [{ role: "user", content: "Explain cache locality." }],
});

const preview = await router.evaluatePolicy(request);
const servingSelection = await router.select(request);
console.log(preview.decision, servingSelection.decision);
```

## Self-hosted selector policy

The advanced `createDariRoutingPolicy` uses a selector model (an LLM that answers routing questions) and the deterministic policy engine to assemble evidence, ask the selector, and validate its answer. It is public from `/policy-engine` because it is more opinionated than the core policy interface.

```ts theme={null}
import { createPiRuntime, createRouter } from "@mupt-ai/dari-router";
import { createDariRoutingPolicy } from "@mupt-ai/dari-router/policy-engine";

const pi = await createPiRuntime({ apiKey: process.env.OPENAI_API_KEY! });
const policy = createDariRoutingPolicy({
  runtime: pi,
  selectorModel: "openai/gpt-5.4-mini",
  selectorContextWindowChars: 400_000,
  pricing: (model) => myPricing[model] ?? null,
  averageOutputTokensByModel: myAverageOutputTokensByModel,
});

const router = createRouter({
  models: [pi.model("openai/gpt-5.4-mini"), pi.model("openai/gpt-5.4")],
  policy,
  executor: pi,
});
```

`runtime: pi` is valid here: it configures the selector used by `createDariRoutingPolicy`. It is not a `createRouter` option.

For self-hosted `createDariRoutingPolicy`, provide your own pricing and observed output-token averages. Router Core does not ship or infer them. Cache state and model metadata remain optional; unknown cache state means the engine makes no cache-savings claim.

## Custom rules

```ts theme={null}
const policy = createDariRoutingPolicy({
  runtime: pi,
  selectorModel: "openai/gpt-5.4-mini",
  pricing: (model) => myPricing[model] ?? null,
  averageOutputTokensByModel: myAverageOutputTokensByModel,
  strategy: "custom",
  customConfig: {
    rules: [
      { when: "architecture or difficult debugging", use: "openai/gpt-5.4", thinking_level: "high" },
      { when: "simple factual questions", use: "openai/gpt-5.4-mini" },
    ],
    default: "openai/gpt-5.4-mini",
  },
});
```

The selector must return an eligible model and effort. For a fully local deterministic policy, write a `RoutingPolicy` directly; for full preparation/finalization control, use the [advanced policy engine](/framework/decision-pipeline).
