
# Pi

[Pi](https://pi.dev/) is a minimal, extensible terminal coding agent.
LowRouter has a provider package for it,
[`@lowrouter/pi-provider`](https://www.npmjs.com/package/@lowrouter/pi-provider).
Without the package, Pi also takes LowRouter as a custom provider in
`models.json`.

## Install the package

The package needs Pi 1.3.0 or later, which needs Node.js 22.19 or later.

```bash
npm install -g @earendil-works/pi-coding-agent@latest
pi install npm:@lowrouter/pi-provider
```

Add your key in one of two ways. You can export it:

```bash
export LOWROUTER_API_KEY=sk-lr-...
```

Or store it in Pi: run `/login` in a session and pick **LowRouter**.

Then pick a model:

```bash
pi --list-models lowrouter
pi --model lowrouter/auto/mistralai/mistral-large-2512
```

You can also switch with `/model` in a session.

What the package does:

- It reads the model list from LowRouter when Pi starts, when the
  `/model` picker refreshes, and on `pi update --models`. A new model
  shows up without a package update. Pi keeps the last list for
  offline starts.
- It lists `auto/` chat models with function calling, plus your
  account's `alias/` models. Context windows and output limits come
  from the same list, so you don't set them yourself.
- Pi shows costs in US dollars. The package uses the price of each
  model's most expensive route, so Pi's estimate is an upper bound.
  You are billed in euros, for the route that served the request.

Jurisdiction-scoped IDs such as `auto/mistralai/mistral-large-2512/eu`
and pinned routes are not in the list. To use one, add it to
`models.json` as shown below.

The package's source and release notes are on
[GitHub](https://github.com/carboniferio/pi-lowrouter-provider).

## Without the package

Verified against Pi **1.3.0**. The config below is re-run against that
release every week, including a tool call round trip.

### Configure

Add LowRouter as a provider in `~/.pi/agent/models.json`:

<!-- verify: pi-config -->
```json
{
  "providers": {
    "lowrouter": {
      "name": "LowRouter",
      "baseUrl": "https://api.lowrouter.ai/v1",
      "api": "openai-completions",
      "apiKey": "$LOWROUTER_API_KEY",
      "compat": { "supportsDeveloperRole": false, "supportsStore": false },
      "models": [
        {
          "id": "auto/mistralai/mistral-large-2512",
          "name": "Mistral Large (LowRouter)",
          "input": ["text", "image"],
          "contextWindow": 256000,
          "maxTokens": 8192
        }
      ]
    }
  }
}
```

`$LOWROUTER_API_KEY` is read from the environment, so the key stays out
of the file:

```bash
export LOWROUTER_API_KEY=sk-lr-...
pi --model lowrouter/auto/mistralai/mistral-large-2512
```

Details of this config:

- The model reference is `lowrouter/` followed by the LowRouter model
  ID. Pi splits on the first slash only, so the slashes inside the ID
  are fine.
- `baseUrl` ends in `/v1`. Pi appends `/chat/completions`.
- `contextWindow` is what Pi plans compaction around, and `maxTokens`
  caps the answer length it asks for. Without them Pi assumes 128,000
  and 16,384, which some models reject. Take both from the model
  browser.
- `compat` turns off the `developer` role and the `store` field. Some
  of the upstream hosts LowRouter routes to reject them.
- Each additional model is another entry in `models`. A scoped ID
  such as `auto/mistralai/mistral-large-2512/eu` or a pinned route goes
  in the same list.
- If the package is installed too, entries in `models.json` add to the
  package's list or replace entries that have the same ID.

## Picking a model

Pi works through tools: it reads, edits and writes files and runs
commands. Pick a model with the *function-calling* tag; [the model
browser filtered to them](/models?function_calling=yes) lists every one.

The example uses `auto/mistralai/mistral-large-2512`, served from the
EU (256k context). Other models we have run through Pi's tool loop:

- `auto/mistralai/mistral-small-2603`, a smaller, cheaper Mistral
  model served from the EU (256k context).
- `auto/openai/gpt-5.5` (1M context).

## Recommended setup

- Use a dedicated key, so Pi's spend shows separately and can be
  revoked on its own.
- Without the package, give each model its real `contextWindow` and a
  `maxTokens` within the model's output limit. The package reads both
  from LowRouter.

## Troubleshooting

- "No models available": Pi lists a provider's models only once it has
  a key. Export `LOWROUTER_API_KEY` or run `/login`, then try again.
- `pi install` fails, or the package never loads: check
  `node --version`. Pi needs 22.19 or later.
- `pi -p` in a script prints nothing and never exits: print mode reads
  piped stdin. Close it with `</dev/null`.
- A `401` naming a malformed key: the key was cut off when copied.
  Copy it again in full, or create a new one at
  [/app/keys](/app/keys).
- A `400` about output tokens: the model's output limit is lower than
  `maxTokens` (or the 16,384 default). Lower `maxTokens` for that model
  entry.
- Something else is off: run `pi -ne` to start without extensions and
  rule out a conflict with another package. `-ne` also turns off the
  LowRouter package, so LowRouter models are then available only from
  `models.json`.
