Route the cheap work to the cheap model
Here’s the backlog sitting in front of you on stash right now, and it’s deliberately lumpy:
- Re-extract every URL saved before the readability fix. A few hundred rows: fetch the page, run it through the (now-corrected) extractor, overwrite the stored text. Mechanical. Every row is the same shape of work.
- Redesign how the extractor handles the sites it still mangles. One judgment call with real branches - which signals to trust when a page has no clean
<article>tag, how far to fall back before giving up and storing the raw text. Get it wrong and you’re back here next month with the same bug.
Run both through the same pinned model at the same reasoning depth and you’re either overpaying on the sweep or underthinking the redesign. Pi actually gives you two separate levers to avoid that, and they’re worth naming separately because they compound.
The two dials
Section titled “The two dials”Which model answers - set by defaultModel (and defaultProvider) in settings.json, or picked mid-session:
/modelopens the full model picker.Ctrl+Lopens the same selector as an overlay, without leaving what you’re typing.Ctrl+Pcycles through whatever’s in yourenabledModelsallow-list - the curated shortlist from the last lesson, not every model every provider exposes.
How hard it thinks - Pi calls this the thinking level, and it’s a first-class setting, not a hidden knob: off | minimal | low | medium | high | xhigh | max, set globally via defaultThinkingLevel, cycled mid-session with Shift+Tab, and - if a provider’s defaults don’t fit - retuned per level with thinkingBudgets (a custom token allocation for each rung of the scale).
Neither dial cares what the other is set to. That’s the point: a cheap model at high thinking and a frontier model at off are both real, useful, and completely different tools. The re-extraction sweep wants a cheap model at low or off - there’s nothing to reason about, only rows to process. The extractor redesign wants your strongest model at high - a wrong call here is a rewrite, same as it would be anywhere else in this course.
That’s the general shape of the trap, and it’s not hypothetical on stash: pin both dials to the expensive corner out of habit and the sweep alone - a few hundred cheap, mechanical rows - bills like the redesign did. Pin them to the cheap corner instead and the redesign gets a shallow pass at a problem that forks, which is the worse mistake: you ship a confident wrong answer and pay for the rewrite anyway.
Actually adding the cheap model
Section titled “Actually adding the cheap model”enabledModels and defaultModel only help once a cheap option is defined for Pi to route to. That’s models.json, and it’s usually easier to have Pi do the editing than to hand-write the provider block yourself - it can read its own docs and figure out the shape a new provider needs. Say you want to add a low-cost coding model behind an OpenRouter-style API key, for the sweep work specifically:
> add a custom provider to models.json for a cheap coding model I can route the stash re-extraction backlog to, then tell me where to paste the API keyPi identifies that this isn’t a login-subscription provider the way OpenAI or GitHub Copilot are - it needs a models.json entry with its own baseUrl, api shape, and an apiKey field, plus (depending on how the key resolves) a matching entry in auth.json:
{ "providers": { "cheap-coder": { "baseUrl": "https://openrouter.ai/api/v1", "api": "openai-completions", "apiKey": "$OPENROUTER_API_KEY", "models": [ { "id": "some-cheap-coding-model", "name": "Cheap coder", "reasoning": true, "contextWindow": 128000 } ] } }}apiKey resolves three ways - a literal string, a $ENV_VAR interpolation, or a !command whose stdout it uses - so you’re not forced to put the key in the file at all. Paste the key yourself; don’t ask Pi to read the file back and confirm it took. Agents that can read files can also print them, verbatim, to whatever terminal you’re sitting in - including one you might be sharing or recording. If a key is ever echoed back to you in plaintext, treat it as burned and rotate it, on principle, whether or not you think anyone else saw it.
Once the provider’s live, /model shows it in the picker and Ctrl+P cycles it if it’s in enabledModels. Point the re-extraction sweep at it, low thinking, and let it run through the backlog for a fraction of what the frontier model would have billed for the same mechanical rows. Keep the extractor redesign on your strongest model at high - that one still earns every token.
To make this concrete: a 50-file rename sweep might cost $0.30 on a cheap model vs. ~$4 on a frontier model. A design review on the same codebase might cost $0.80 on the frontier model and produce noticeably better output. The routing habit is about spending the $4 only where it earns its keep. (These numbers are illustrative - model pricing changes frequently, so treat them as order-of-magnitude guidance, not quotes.)
Routing between hosted models is one lever. There’s a more extreme version of “cheap” available too: a model that costs nothing per token because it’s running on the machine in front of you. See what that actually buys you - and where it runs out of room.