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

# Framework Quickstart

> Run Router Core and serve your first routed request.

<Note>
  Router Core is not yet published to a registry. Run from `dari-router-core/` in the Dari monorepo.
</Note>

## Try The Example

<Steps>
  <Step title="Install and run">
    ```bash theme={null}
    bun install --frozen-lockfile
    bun run example
    ```

    No API key needed. It routes by prompt length using an in-memory executor.
  </Step>

  <Step title="Make a real provider call">
    ```bash theme={null}
    OPENAI_API_KEY=... bun run example:pi
    ```

    This runs through the built-in Pi runtime with a real OpenAI model.
  </Step>
</Steps>

## Create A Server

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

const apiKey = process.env.OPENAI_API_KEY;
if (!apiKey) throw new Error("OPENAI_API_KEY is required");

const pi = await createPiRuntime({ apiKey });
const router = createRouter({
  runtime: pi,
  models: [
    pi.model("openai/gpt-5.4-mini"),
    pi.model("openai/gpt-5.4"),
  ],
  policy: ({ request, candidates }) => {
    const promptLength = JSON.stringify(request.items).length;
    const preferred = promptLength > 500
      ? "openai/gpt-5.4"
      : "openai/gpt-5.4-mini";
    return {
      model: candidates.find((c) => c.id === preferred)?.id
        ?? candidates[0]!.id,
      reason: "Route longer requests to the larger model.",
    };
  },
});

Bun.serve({ port: 3000, fetch: router.fetch });
```

Send a request:

<Tabs>
  <Tab title="OpenAI">
    ```bash theme={null}
    curl http://localhost:3000/v1/chat/completions \
      -H 'Content-Type: application/json' \
      -d '{
        "model": "my-router",
        "messages": [{"role": "user", "content": "Explain cache locality."}]
      }'
    ```
  </Tab>

  <Tab title="Anthropic">
    ```bash theme={null}
    curl http://localhost:3000/v1/messages \
      -H 'Content-Type: application/json' \
      -d '{
        "model": "my-router",
        "max_tokens": 256,
        "messages": [{"role": "user", "content": "Explain cache locality."}]
      }'
    ```
  </Tab>
</Tabs>

The response includes the chosen model in `dari_routing` and the `X-Router-Selected-Model` header. The incoming `model` is a caller-facing router name — it does not force the policy to pick that model.

## Use From A Sibling Project

<Steps>
  <Step title="Build the package">
    ```bash theme={null}
    (cd ../dari-router-core && bun install --frozen-lockfile && bun run build)
    ```
  </Step>

  <Step title="Add the dependency">
    ```json theme={null}
    { "dependencies": { "@dari/router-core": "file:../dari-router-core" } }
    ```

    ```bash theme={null}
    bun install
    ```
  </Step>
</Steps>

The package emits ESM in `dist/`. It requires Bun or Node.js 22.19+ and uses web-standard `Request`, `Response`, and `AbortSignal`. Bun can serve `router.fetch` directly; Node needs a Request/Response adapter.

## Next Steps

<CardGroup cols={2}>
  <Card title="Models" icon="cube" href="/framework/models">
    Declare candidates and eligibility.
  </Card>

  <Card title="Policies" icon="brain" href="/framework/policies">
    Write routing policies.
  </Card>

  <Card title="Pi Runtime" icon="shield-halved" href="/framework/pi-runtime">
    Credentials for multiple providers.
  </Card>

  <Card title="Custom Executors" icon="code" href="/framework/custom-executors">
    Integrate another SDK.
  </Card>

  <Card title="Protocols And Streaming" icon="signal" href="/framework/protocols-and-streaming">
    Request and streaming details.
  </Card>
</CardGroup>
