Skip to main content
@dari/router-core puts multiple LLMs behind one endpoint. It accepts OpenAI Chat Completions and Anthropic Messages requests, picks a model with your policy, executes it, and responds in the caller’s protocol.
@dari/router-core is a preview package. It is not yet published to a registry. Examples assume a Dari monorepo checkout with dari-router-core/.

How It Works

Framework Or Managed Platform

Both share routing concepts. The difference is who owns the operational layer.

Router Framework

You host the endpoint, provide credentials, write the policy, and own auth, rate limits, routing state, telemetry, and billing.

Managed Platform

Dari hosts the endpoint and manages credentials, routing state, retries, fallbacks, telemetry, billing, and speculative routing.
Use the managed router quickstart for a hosted endpoint. Use the framework when you want full control.

The Three Boundaries

Models — declare candidates with capabilities. pi.model() fills this from Pi AI’s catalog, or declare manually for custom executors. Policies — receive the normalized request and eligible candidates, return one model and optionally a reasoning effort. Use a heuristic, a learned model, a remote service, or createDariRoutingPolicy. Executors — call the selected model. The built-in Pi runtime handles catalog models. Custom executors replace it per-model for other SDKs or transports.

Two API Levels

createRouter()

Web-standard fetch() handler and select() method. Best for most apps.

Phased API

prepareRoute() and finalizeRoute() as separate steps. For custom orchestration like speculative routing.

Operational Options

createRouter() takes a few optional knobs for running in production. All are host-injected — the framework still reads no env vars, database, or clock source of its own.
  • leaseStore — storage for multi-turn lease commitments. Defaults to an in-memory store with a 30-minute TTL; inject a persistent implementation to share leases across processes. Methods may return values or promises, and read-modify-write atomicity under concurrent requests is the store’s responsibility. Store failures are non-fatal — a throwing or rejecting store never fails the request: failed reads route as if no lease exists, failed writes serve without persisting, and failed deletes fall back to the turn/TTL expiry.
  • hooks — lifecycle callbacks for telemetry, billing, and logging: onSelection, onCompletion, onStreamClose, and onError. onSelection observes the policy’s decision before execution; the other hooks receive the selection actually served, so after a fallback their decision names the fallback model. Hooks are fire-and-forget and isolated — a throwing hook never affects the request or stream, and onStreamClose reports only finishReason and usage (streamed output is not buffered).
  • fallback{ enabled, requiresDifferentProvider } opt-in cross-model retry when the selected model’s executor fails.
  • generateId — override wire-ID generation (defaults to crypto.randomUUID()), useful for deterministic tests or host-correlated IDs.

Serverless Deployments

The default in-memory lease store assumes a single long-lived process. On serverless platforms (Cloud Run, Lambda, Fly machines), instances scale to zero and requests fan out across replicas, so in-memory leases are lost on every cold start and fragmented across instances. Nothing breaks — the policy just re-selects — but you lose provider prompt-cache affinity, and with the Auto Router every lost lease is a billed re-selection on the next turn. Inject a shared store instead. examples/lease_stores.ts in the package ships copy-paste Redis and Postgres LeaseStore implementations written against minimal structural client types, plus a runnable demo of a lease surviving a router restart (bun run example:lease-stores).

Quickstart

Run the examples and serve your first request.

Models

Declare candidates and understand eligibility.

Policies

Write routing policies.

Pi Runtime

Execute provider calls with injected credentials.

Custom Executors

Integrate another SDK or transport.