Pi
Pi is a minimal, extensible terminal coding agent. Add Merge Gateway as a provider and Pi can reach every model Gateway supports through a single API key, with routing policies, cost governance, and full request observability in the Gateway dashboard.
Pi builds its model picker from the provider you write in models.json. It does not call Gateway to discover models, so the picker shows exactly the entries you configure, and nothing else. That leaves two ways to set it up, and you can combine them:
- Route through a policy. A single
default_routingentry, and Gateway picks the vendor and model for every request - List models. One entry per model, when you want to choose the model by hand in the picker
Before you start
-
Install Pi (needs Node 20 or newer):
npm install -g --ignore-scripts @earendil-works/pi-coding-agent -
Grab an API key from gateway.merge.dev/api-keys (an organization key, or a project API key to scope Pi usage to a project) and export it:
Route through a policy
Gateway’s routing policies choose the vendor and model per request based on your rules (cost, performance, or prompt complexity). Point Pi at the policy instead of at a model and you change models by editing the policy, never the agent config.
A request that names a model is served by that model. Gateway skips policy model selection entirely, so a policy has no effect on requests where the picker chose a specific model. default_routing is how you hand that choice back to the policy.
Add the provider
Create or edit ~/.pi/agent/models.json:
default_routing is a Gateway model name, not a placeholder. Requests that carry it are handed to the routing policy on the key’s project, or to your organization default when the key is not scoped to a project.
apiKey uses Pi’s $VAR syntax, so it picks up the MERGE_GATEWAY_API_KEY you exported. The file reloads each time you open the model picker, so you can edit it without restarting Pi.
Pick it in the picker
Run pi in your project, then /model, type merge to filter, and select Gateway routing policy.
Send a test message
Ask Pi to make a small code change. Streaming, tool calls, and file edits all work, and the request shows up in your Gateway dashboard within a few seconds, labelled with the model the policy chose.
Set contextWindow to the smallest context window a model in your policy can have. Pi compacts the conversation against the number you give it, so a value above what the serving model accepts lets Pi send a prompt that model cannot take.
List specific models
To choose models by hand, give each one its own entry. Every id is a Gateway provider/model name from GET /v1/models:
contextWindow, maxTokens, and input are worth setting on every entry. Pi has no registry to fall back on for a custom provider, so an entry without them is capped at 128K context, 16K output, and text only, which understates most models. Add cost (input and output per million tokens) if you want Pi to show spend estimates.
Generate the list from the catalog
Rather than writing entries by hand, build the file from the catalog. This writes every chat model Gateway offers you, with real limits, modalities, and prices, and keeps the default_routing entry at the top of the picker:
The second command merges the block into models.json rather than replacing the file, so any other providers you have configured survive, and the merge-gateway model list is replaced wholesale each time you re-run it.
limit=500 is the largest page /v1/models serves. If the response comes back with "has_more": true, pass its next_cursor as ?cursor= to fetch the rest.
Re-run both commands whenever you want to pick up models added to your catalog. Pi reads this file, it never queries Gateway for the list, so a model added today does not appear in the picker until you regenerate.
Caveats
The picker shows what you configured, nothing more
Pi reads the model list for a custom provider from models.json at startup and each time you open the picker. It never queries GET /v1/models, so adding a model to your Gateway catalog does not make it appear in Pi. Re-run the generator above, or add the entry yourself.
Output limits
maxTokens in models.json is what Pi asks Gateway for. When a request lands on a model whose own output ceiling is lower, Gateway lowers the request to that ceiling instead of letting the vendor reject it, so a single maxTokens works across a policy that spans models with different limits. Keep it at or below the largest output you actually want to pay for.
Reasoning models
Gateway forwards reasoning_effort to the upstream vendor, and some vendors reject it. The compat.supportsReasoningEffort: false above stops Pi from sending it, which is the safe default. Mark a model "reasoning": true so Pi shows it as reasoning-capable in the picker.
Tool calling
Pi is agentic and relies on tool calls to read and edit files. Tool calling works through Gateway for any model whose capabilities.supports_tool_calling is true on the chosen vendor route. If you route through a policy, keep the policy on tool-capable models. See Tool calling.
Persisting the configuration
The export MERGE_GATEWAY_API_KEY=... above lives in your shell, so it applies only to that terminal. To persist it, add the same line to your shell profile (~/.zshrc, ~/.bashrc, or ~/.config/fish/config.fish). The models.json provider persists on its own.