The AI Model Routing Field Guide

Automatic Model Routing Without the Open Wallet

When, why and how to fence automatic model routing so it saves you money instead of quietly spending it.

Brett Kraiger · September 2026

ChatGPT, Claude and Gemini are not the only options

You probably use one of the big AI apps: ChatGPT, Claude, Gemini, Copilot, Grok. You installed it, you pay the subscription, and that app is the model as far as your day is concerned.

You may have heard there are others: DeepSeek, Qwen, Kimi, a long list of open and cheaper models, many from China, some very good at some things. You do not know how to get at them, and you suspect it involves being a programmer.

It does not. Every one of those models sits behind an API (a way for software to call it), and there are services that put dozens of them behind one account, one key and one bill.

OpenRouter is one of those services. Venice is another.

Point a tool at one of those accounts and you can try a cheap model one day and a dear one the next, with no new subscription for each.

Two things change when you step out of the app. First, you pay per request, by the token (roughly a word of text in or out), instead of a flat monthly fee, so a bad habit costs real money and a good one costs almost nothing.

Second, you have to choose the model, and the menu has dozens of names on it. This guide is about those two things: how to control the spend, and how to stop choosing by hand.

Services like OpenRouter give you more control over both than the apps ever did.

What automatic routing actually does

Router

A router decides which of those models answers your prompt, so you stop picking one from a dropdown. OpenRouter is one account and one API key in front of dozens of models from different companies. This guide talks about OpenRouter specifically, because that is what I built on; the same principles apply to any service that routes between models.

Auto

OpenRouter's general router. It classifies your prompt into a task type (its own labels look like content_writing, code:debugging, agent:multi_step_planning), then picks from the eligible models using what OpenRouter's users have spent on that task type over the trailing seven days. One setting handles writing, code, analysis and tool use.

Pareto

OpenRouter's second router, and the alternative to Auto. Coding only.

It ignores the task type and instead picks the cheapest available model that clears a coding benchmark percentile you set (min_coding_score, low to high). Auto follows the market; Pareto follows a leaderboard.

I use Auto for daily work and Pareto as a weekly read-only comparison.

Preset

A saved, named configuration on your OpenRouter account that you call as if it were a model: "model": "@preset/everyday". It can hold the model or router, which company is allowed to serve it, the price ceiling, fallbacks and parameters.

Change the preset and every tool pointed at it changes with it. OpenRouter's own docs: "Presets are named configurations that encapsulate all the settings needed for a specific use case."

The fence
The part you add on top: a price ceiling (max_price) plus a named allow-list of models the router may choose from. With the fence, the router still picks for you, inside a paddock you built.

Why I built this

I have been hitting the usage ceiling on both my Claude and my Codex subscriptions most weeks. The work is real; the ceilings are the problem.

The next step is more of that work running through OpenRouter and tools like OpenCode, on other models and APIs. OpenCode is the coding assistant I work in; any tool that can point at OpenRouter behaves the same way.

Paying Claude and Codex API prices for all of it would cost more than the subscriptions did. Cheaper models have to carry some of the load.

That opens the question I did not want to spend my days on: which cheaper model, for which work. Quality and cost trade off against each other, the answer changes by task, and the menu changes every week.

The fence is my answer to the part of that question I can hand off. The router picks among the cheap models for me; I only decide how cheap is allowed and which names are in the pool.

From there, in one sitting, I:

  • built three named presets on the OpenRouter account
  • tested whether the fence actually held
  • found a wrinkle in how OpenRouter's own Preset API stores settings
  • replaced two toy test prompts with nine real ones
  • built a small weekly scout that checks the market for me

What guessing the model costs you

You are probably carrying some version of the same trade-off: a subscription ceiling you keep bumping into, or an API bill that stings when you check it. The cheap models are good enough for more of your work than you think, and genuinely bad at some of it, and guessing which is which, model by model, is a hobby.

Default to the cheapest option out of habit and some of the work gets worse. Default to the model you trust and you pay frontier prices for a one-line edit.

The fence turns "which model" into two smaller questions you can answer once: how much am I willing to pay, and which names would I accept. That leaves the quality experiment as the only thing still worth your attention.

The four decisions a router makes for you

There are four decisions buried inside "pick a model," and a router makes all four whether you notice or not.

  1. Classify the work: Auto sorts it into a task type, or Pareto benchmarks it against a coding score.
  2. Select an eligible model from your allow-list.
  3. Enforce a price ceiling.
  4. Pick which company (the provider) actually serves the chosen model.
your promptwrite, code, plan classify task~30 task typesAuto or Pareto filter modelsallow-listcost tier enforce pricehard ceilingfail closed providerprice + uptime one serving model is returned; fallbacks wait behind it
The full route: classify with Auto or benchmark with Pareto, filter to your allow-list, enforce the ceiling, then pick a provider.

The ceiling is max_price, a cap on input and output price per million tokens. It is the one hard boundary in the whole system. Any model above it is simply not eligible, no matter how the classifier or the benchmark ranks it.

Each pool also carries a cost tier: low, medium or high. The tier tells Auto which price band to aim for. The model it serves inside that band can still move from one week to the next, so the ceiling matters more than the tier.

Provider routing runs last, picking which company actually serves the model you ended up with, since the same model is often hosted by more than one provider at different prices. Naming the models you will accept, setting the ceiling before the router runs, and reading what it served you afterwards: that is the whole fence.

When to use it: the decision rule

This setup is shaped for you if you can tick all five:

Shaped for: mixed writing, code, and analysis; agent tool use; image understanding, if you add one multimodal model to the pool.

Not shaped for: reproducibility-critical pipelines, where you need the same model every time and should pin one directly. Image generation, which needs a different kind of tool entirely.

Also not shaped for teams who already have strong personal evals, since a fenced pool duplicates work your evals already do better. Nor for coding-only shops, who may get more out of Pareto with a cap than a general pool that has to account for writing and analysis it never sees.

When not to use it

TaskWhy it failsUse instead
Reproducibility-critical pipelineThe pool that served you can change from one week to the next as trailing spend shifts, even with the same allow-listPin one model directly
Image generationAuto and Pareto route text and code models onlyA dedicated image tool
A team with strong personal evals alreadyA fenced pool re-solves a problem your evals already answerYour own evals
Coding-only workA general pool carries writing and analysis weight it never needsPareto with a price cap

Those are the places this setup fails by design. It has also failed by accident a few times in my own testing, and those traps are worth naming as a pattern, no person attached:

  • Treating a cost tier as a fixed budget.
  • Taking naked Pareto's "High" setting as "the best cheap model," when what it actually chose, with no ceiling attached, was Claude Fable, a frontier model many times the price of its own Low pick.
  • Promoting a model into a pool because it did well on a toy probe.
  • Automating the step-up to frontier models when that decision should stay manual.
  • Letting a coding benchmark quietly rewrite a pool that also has to serve writing and analysis.

Venice: a monthly plan instead of paying per request

Venice is a separate provider with its own API, outside OpenRouter entirely. Their own line: "Private, unrestricted access to all the leading AI models across text, image, video, and audio, behind one API key." The API is a drop-in replacement for the OpenAI chat endpoint, based at https://api.venice.ai/api/v1, and Venice documents integrations for Claude Code, Cursor and Codex CLI.

Billing is the real difference. OpenRouter meters every request against the ceiling you set. Venice sells plans instead, each with a monthly allowance of credits, its unit of pre-paid usage:

  • Free: $0
  • Pro: $18 a month, "100 credits / month for video, music, premium models, and API"
  • Pro Plus: $68 a month, "7,500 credits / month" and "2-month credit banking"
  • Max: $200 a month, "22,500 credits / month" and "3-month credit banking"

Venice's own summary of the choice: "Pay as you go at published model rates, or choose Pro Plus with $75 in monthly API spend and two-month banking, or Max with $225 and three-month banking."

Privacy is the other half of the pitch: "Zero data retention (Private mode)" and hardware-verified private inference are both listed across the paid tiers.

What Venice does not give you:

  • Auto
  • Pareto
  • a preset with a price ceiling attached

The fence idea still applies, but you build it differently: the plan itself is the ceiling.

The honest frame, at the time of writing: if your monthly spend is steady, a flat plan may suit you better than a meter. If your spend is spiky or small, the meter with a ceiling, the setup the rest of this guide covers, is cheaper.

Getting started in ten minutes

  1. Open an OpenRouter account.
  2. Create one preset called Everyday, set to the Auto model, with a price ceiling attached.
  3. Select that preset in your tool's model picker.
  4. Send one real prompt from your actual work, not a test line.
  5. Read the response to see which model served it and what it cost. Do that for a week before you add a second preset.

Spend controls: limits and alerts on your key

OpenRouter runs on credits, not a subscription: you pre-pay, and every request draws the balance down. You can set an auto top-up that fires on its own; their own words: "the balance is replenished when it gets below the set threshold."

Each API key can carry its own credit limit (limit), with an optional daily reset at midnight UTC (limit_reset). One key per tool means one ceiling per tool, on top of whatever ceiling the fence itself enforces.

The Activity page in your account shows usage filtered by model, provider and key, so you can see where the spend actually went, not just the total.

My own auto top-up is deliberately small: $10. I get a notification every time it fires, and the gap between those notifications is my alarm.

Four or five days apart is a normal week. Every half hour means something is looping, or a model has slipped through the fence, and I stop and look.

Cheap to set up, and in a normal week it catches nothing, which is what a good alarm mostly does.

These controls sit underneath everything else in this guide. The fence decides which model answers; the key limit and the top-up size decide how wrong that can go before you hear about it.


From here on it gets technical. If you stop here you already have the decision rule, the traps, and the ten-minute start.

How: the presets and the config

I built three named presets on the OpenRouter account, each one a pool of four models behind a hard price ceiling: Everyday as the default, Quality as a manual step-up, Frontier stays manual.

$

Everyday

Default. Ordinary writing, coding, analysis and tool work.

ROUTER TIER: LOW · HARD CAP: $1 / $5 PER 1M
DeepSeek V4 FlashGLM 5.3 FlashGPT-5.6 LunaGemini 3.8 Flash
$$

Quality

Manual step-up. Planning, specifications, hard debugging and review.

ROUTER TIER: MEDIUM · HARD CAP: $1.25 / $5 PER 1M
DeepSeek V4 ProGLM 5.3Kimi K2.7 CodeGemini 3.8 Flash
$$$$

Frontier

Manual only. A conscious choice for high-value work, made by hand every time.

ROUTER TIER: HIGH · HARD CAP: $10 / $50 PER 1M
Claude Sonnet 5Claude Fable 5.1GPT-5.6 SolGPT-6 Astra
PoolRoleModelsHard cap (input / output per 1M tokens)
EverydayDefaultDeepSeek V4 Flash, GLM 5.3 Flash, GPT-5.6 Luna, Gemini 3.8 Flash$1 / $5
QualityManual step-upDeepSeek V4 Pro, GLM 5.3, Kimi K2.7 Code, Gemini 3.8 Flash$1.25 / $5
FrontierManual onlyClaude Sonnet 5, Claude Fable 5.1, GPT-5.6 Sol, GPT-6 Astra$10 / $50

Each cap sits just above the list prices of the models I wanted in that pool, so the pool can hold them and nothing dearer.

OpenRouter carries the Auto settings in a block it calls a plugin: the cost tier and the allow-list travel there. Its Preset API kept the model choice and the price ceiling when I saved a preset, but dropped the plugin settings, the cost tier and the allow-list, every time.

So the allow-list and cost tier now live in the OpenCode model entry, and the price ceiling lives in the preset. Two places, on purpose, because the Preset API would not hold both in one.

{
  "model": "openrouter/auto",
  "plugins": [{ "id": "auto-router", "cost_tier": "low",
                "allowed_models": ["deepseek/...", "z-ai/...", "openai/...", "google/..."] }],
  "provider": { "sort": "price", "allow_fallbacks": true,
                "max_price": { "prompt": 1, "completion": 5 } }
}

Here is what a preset call actually looks like against OpenRouter's chat completions endpoint, with the preset called as if it were a model:

POST https://openrouter.ai/api/v1/chat/completions
{
  "model": "@preset/everyday",
  "messages": [{ "role": "user", "content": "Write a concise, credible opening paragraph for a consulting proposal to a cautious small-business owner." }]
}

The response, trimmed to the fields that matter, from the scout's first production probe:

{
  "model": "deepseek/deepseek-v4-flash-0731",
  "usage": { "cost": 0.0000267 },
  "openrouter_metadata": {
    "requested": "openrouter/auto",
    "strategy": "auto",
    "summary": "strategy=auto, available=31, selected=OpenInference"
  }
}

Auto's task label for that prompt was content_writing. Three fields are worth reading off every response: model says which brain answered, openrouter_metadata.summary says which host and how many models were eligible, and usage.cost says what it cost. That is the whole feedback loop.

A Pareto call is the same shape with "model": "openrouter/pareto-code" and a min_coding_score in place of an allow-list, and the response's strategy field reads pareto instead of auto.

I tested the fence before trusting it two ways. A deliberately fake entry in the allow-list failed with "no models match", rather than falling back to something outside it.

A request that would only have been servable by Claude Fable, sent under the Everyday ceiling, failed too, instead of quietly escalating to a model above the price cap. Neither test found a hole.

The first probes I ran through it were a one-line welcome message and a toy JavaScript function. Both proved the router was alive and nothing else; neither told me anything useful about how it would behave on real work.

I replaced them with nine realistic prompts: three writing, three code, three analysis, pulled from the kind of work I actually do.

Once the fence held, I built a weekly scout that re-runs the nine prompts through OpenRouter every week and only lets a model join a pool after it has proven itself twice, a week apart.

Why: the numbers

Every number in this section is mine, from the OpenRouter account. Pareto's Low, Medium and High settings are its own dial (min_coding_score), not Auto's cost tiers; they share names by coincidence and control different things.

Naked Pareto, one toy coding prompt, no ceiling attached:

SettingModel servedProbe cost
LowGemini 3.8 Flash$0.000183
MediumGPT-5.6 Sol$0.000532
HighClaude Fable 5.1$0.002480

Auto with no allow-list, one prompt per cell:

Tier / taskModel servedProbe cost
Low / writingDeepSeek V4 Flash$0.000096
Low / codeGLM 5.3 Flash$0.000029
Low / analysisDeepSeek V4.1 Flash$0.000071
Medium / writingGemini 3.8 Flash$0.000173
Medium / codeGLM 5.3 Flash$0.000029
Medium / analysisClaude Sonnet 5$0.000530

Medium picked Claude Sonnet 5 for the analysis prompt: a tier is a band, and this is the band reaching its top in production.

Pareto High with a hard ceiling attached:

Cap in / out per 1MResult
$1 / $5Gemini 3.8 Flash
$0.70 / $3No eligible endpoint, failed closed
$0.30 / $1.50DeepSeek V4 Flash

The production run sent nine real prompts through the Auto Low and Auto Medium tiers, plus three capped Pareto probes as a read-only coding comparison. All 21 requests succeeded and no pool needed changing afterwards.

WorkAuto Low servedAuto Medium served
Writing (conversion copy, editing, plain explanation)DeepSeek V4 Flash x3Gemini 3.8 Flash x2, DeepSeek V4.1 Flash x1
Code (debugging, implementation with tests, service architecture)DeepSeek V4.1 Flash x3GLM 5.3 Flash x3
Analysis (risk ranking, option comparison, implementation plan)DeepSeek V4.1 Flash x2, GLM 5.3 Flash x1DeepSeek V4.1 Flash x2, GLM 5.3 Flash x1

The three Pareto probes ran alongside this, capped at the Quality tier's ceiling: all three of Pareto's settings served Gemini 3.8 Flash. They are a read-only comparison, not part of either Auto tier.

Auto Low cost $0.00031735 across its nine requests, Auto Medium $0.00077654 across its nine, and the three Pareto probes $0.00080925. All 21 requests together came to $0.00190314, about 0.19 cents.

The scout: keeping the pools current every week

Auto follows the trailing seven days of spend, so the model it favours for a task type shifts as the market shifts, and new models arrive most weeks. A fenced pool curated by hand goes stale in the same way a printed price list does.

Neither of the obvious fixes works: hand-curate forever, or drop the fence and let Auto roam.

The answer is to use OpenRouter's own routing as market evidence for what belongs in your pools, and to let a rule, rather than Auto's mood that week, decide when the pools change. Ask Auto every week what it would pick for your real work, watch which models keep winning, and promote the ones that keep winning.

What the scout does:

  • runs as a scheduled job on my machine (launchd on the Mac; Task Scheduler on Windows, cron on Linux) and calls OpenRouter directly; no assistant is woken to run a timer
  • sends the nine real prompts (three writing, three code, three analysis) through Auto at the Low tier and again at the Medium tier
  • records, per request, the model served, Auto's own task label, the host that served it, and the cost
  • runs Pareto at Low, Medium and High as a read-only coding comparison, under the Quality cap
  • applies the admission rule: a model must win at least two of the nine in one run, and do it again the following week, stay under the pool's ceiling, and not be on the frontier deny-list (Claude Fable, Claude Opus, GPT-6 Astra by name) before it can join a pool
  • when a model clears that rule, rewrites the pool, re-saves the OpenRouter presets and updates the OpenCode model entry itself; the Frontier pool is excluded from this and only changes by hand
  • ejects a model I have rated bad from the pools on the next run, whatever the market says
  • posts the resulting menu, what changed, and the run's cost to Slack
9 real promptsLow + Medium observemodel + task + cost admission ruletwo wins, twiceceiling + deny-list curated poolsthe fence the scout applies the change; my ratings on real sessions can eject a model next week
The scout writes to the presets; I do not. My hand is in the rule (two wins, twice, under the ceiling, off the deny-list) and in the good or bad ratings I leave on real sessions, which can eject a model the market still favours. Everything below the Frontier gate then moves on its own, and the Slack message is how I find out it moved.

What one run looks like: the 18 Auto observations from the production run, one row per prompt per tier:

PromptTierTask labelModel servedHostCost
writing: conversion copyLowcontent_writingDeepSeek V4 FlashOpenInference$0.0000267
writing: conversion copyMediumcontent_writingGemini 3.8 FlashGoogle AI Studio$0.0002505
writing: editingLowcontent_writingDeepSeek V4 FlashOpenInference$0.0000271
writing: editingMediumcontent_writingGemini 3.8 FlashGoogle AI Studio$0.0002513
writing: plain explanationLowqa_knowledgeDeepSeek V4 FlashOpenInference$0.0000275
writing: plain explanationMediumqa_knowledgeDeepSeek V4.1 FlashMorph$0.0000374
code: debuggingLowcode:debuggingDeepSeek V4.1 FlashMorph$0.0000409
code: debuggingMediumcode:debuggingGLM 5.3 FlashCoreWeave$0.0000416
code: implementationLowcode:general_implDeepSeek V4.1 FlashMorph$0.0000379
code: implementationMediumcode:general_implGLM 5.3 FlashCoreWeave$0.0000382
code: architectureLowagent:multi_step_planningDeepSeek V4.1 FlashMorph$0.0000391
code: architectureMediumagent:multi_step_planningGLM 5.3 FlashCoreWeave$0.0000395
analysis: riskLowsecurity_auditDeepSeek V4.1 FlashMorph$0.0000388
analysis: riskMediumsecurity_auditDeepSeek V4.1 FlashMorph$0.0000388
analysis: comparisonLowdevopsGLM 5.3 FlashCoreWeave$0.0000400
analysis: comparisonMediumdevopsDeepSeek V4.1 FlashMorph$0.0000392
analysis: planningLowagent:multi_step_planningDeepSeek V4.1 FlashMorph$0.0000394
analysis: planningMediumagent:multi_step_planningGLM 5.3 FlashCoreWeave$0.0000401

Auto's task labels do not match my own categories. "Code: architecture" and "analysis: planning" both landed as multi-step planning, and the risk analysis prompt was read as a security audit. That is why I record Auto's label rather than trusting my own.

The same prompt cost up to nine times more at Medium than at Low for writing, and about the same for code. The tier step-up is worth it for some work and not others.

The scout writes to the presets; I do not. My hand is in the rule (two wins, twice, under the ceiling, off the deny-list) and in the good or bad ratings I leave on real sessions, which can eject a model the market still favours.

Everything below the Frontier gate then moves on its own, and the Slack message is how I find out it moved.

Six rules for fencing a router

  1. Set the ceiling before you pick the pool. It is the only hard boundary in the system, and without one, Pareto's High setting reached for Claude Fable on a plain coding prompt, at nearly fourteen times the cost of its own Low pick.
  2. Keep the allow-list and the price ceiling in separate places on purpose, if your tool's preset system drops plugin settings the way OpenRouter's did. The model entry holds the allow-list and cost tier, the preset holds the cap.
  3. Test the fence before you trust it. A fake entry in the allow-list should fail with a clear "no models match", and a request priced above the ceiling should fail too, instead of escalating quietly.
  4. The ceiling is what to trust; the tier name is only a label. Medium still chose Claude Sonnet 5 for one analysis prompt and stayed inside its cap anyway.
  5. Promote a model from real work; a toy probe only proves the router is alive.
  6. The scout's admission rule, two sightings, two wins, frontier names barred outright, is what keeps a pool from drifting.

Three patterns that work

Three fenced pools, one manual gate above them. Everyday runs by default on the cheapest ceiling. Quality is a manual step-up with a slightly higher cap and stronger models in the same price range.

Frontier, the four dearest names, sits behind a decision I make by hand, every time, on purpose. Auto and Pareto cannot reach it.

The two-places config split. The allow-list and cost tier live in the OpenCode model entry, the ceiling lives in the OpenRouter preset, because the Preset API silently drops one on save.

The lesson generalises. After any preset or config save, replay the actual request and read what came back, rather than trusting the save confirmation.

A dropped field serves the wrong model silently, with no error to flag it, until you check.

The weekly scout with a two-and-two bar. It runs the production run again every week without me, holds to the admission rule, and applies the changes itself.

The worked example is the production run itself: nine real prompts through two tiers, three capped Pareto probes, 21 requests, one bill under a fifth of a cent.

A fence stops the router from reaching for the priciest model in the room. It does not pick the right model for the work; you still read what it served you, and the four names in each of these pools will be wrong before long.

Primary sources

Primary sources:

Numbers are a September 2026 snapshot and will move. OpenRouter and the named models are trademarks of their respective owners; this guide is independent.

The same preset works from any tool that can point at OpenRouter. The interface you type into and the model behind it are separate settings; this build ran through OpenCode, but the fence itself does not care what sits in front of it.

Tell me what you found

Run your own nine prompts through two tiers and tell me what served them and what they cost. If a price or a model name in this guide has moved since this snapshot, say so and I will update the guide.

Get the next field guide by email.

Ready to see what this looks like
applied to your business?

The AI Opportunity Assessment gives you a complete picture of where AI can create real leverage in your specific operation - and where it can’t.