Skip to content

Give each agent its own model

You’re about to map a part of feedmill you don’t know yet. The repo carries something north of a hundred feed configs, each one declaring how a particular source’s dates, GUIDs, and content fields are shaped, and you need to know where in the parser code every one of those date layouts actually gets consumed — because the timezone bug you’re chasing might live in any of them. That’s a wide, dumb sweep: read a lot of files, grep for a pattern, report back. It is exactly the kind of work a cheap, fast model finishes for pennies.

So watch what it costs when you don’t think about which model does it. You’re sitting on the build agent with your strong reasoner behind it — the one you want for the actual timezone fix — and you fire off the scan:

> find every place in the parser package where we call time.Parse or
otherwise turn a feed's raw date string into a time.Time, and list
the file and the layout string used at each one

It works. It reads thirty-odd files, walks the configs, and comes back with a clean table. But it did all that bulk reading and pattern-matching on a frontier reasoning model billed at frontier rates — you paid reasoning prices for grep work. Do that twenty times across a week of exploring an unfamiliar codebase and the waste isn’t a rounding error; it’s most of your bill, spent on the cheapest kind of task you have.

The fix: send the scan to a cheap, read-only scout

Section titled “The fix: send the scan to a cheap, read-only scout”

OpenCode ships a built-in subagent for precisely this. explore is a fast, read-only agent — it cannot modify files, so handing it a codebase sweep carries no risk of a stray edit — and you invoke it by @mention right in your prompt:

> @explore find every place in the parser package where we call
time.Parse or turn a feed's raw date string into a time.Time, and
list the file and the layout string used at each one

OpenCode spawns explore in its own child session with its own context window, runs the scan there, and returns a summary to your main thread — your build session’s context stays clean instead of filling up with thirty files of parser source. That isolation alone is worth the @mention. But by default, when explore has no model of its own, it runs on the model of whichever primary agent invoked it — which is very likely your expensive one. The lever this lesson is about is the next step: give explore its own model, a cheap one, so the scan is cheap by construction every time you reach for it.

Every OpenCode agent — built-in or your own — is configurable through a markdown file with YAML frontmatter, and one of the fields is model. Set it and that agent overrides the default; leave it off and the agent inherits a model — but which model depends on what kind of agent it is. A primary agent with no model set uses the globally configured model. A subagent like explore with no model set inherits the model of the primary agent that invoked it — not the global default. That’s exactly why pinning a model on explore is what makes it cheap: otherwise it rides along on whatever your build agent is using. The value is a provider/model-id string, the same shape you’ve used everywhere else in this chapter.

To override a built-in agent, drop a file with its name into your agents directory — .opencode/agents/explore.md in the project, or ~/.config/opencode/agents/explore.md for every project on the machine. (The singular .opencode/agent/ still loads too, as a backwards-compat alias, but agents/ is the canonical form.) You only have to specify the fields you’re changing; OpenCode merges your file field-by-field over the built-in definition, so the rest of explore’s built-in setup (read-only, the right tools) stays as shipped.

---
description: Fast read-only codebase scout
model: anthropic/claude-haiku-4-5
---

That’s the whole change. The next time you @explore anything, the scan runs on the cheap model and your wallet stops noticing it. Meanwhile your default build agent — the one your top-level prompts run on, and the one that’ll handle the actual timezone fix — is untouched, still pointed at the strong reasoner. You’ve split the spend exactly where it should split: cheap throughput for reading, strong reasoning for changing.

Why this is the move, not just a tidy trick

Section titled “Why this is the move, not just a tidy trick”

The shape you’ve just set up — a cheap, read-only explore and a strong build — is the canonical OpenCode posture, and it pays back every time you scale work out across agents. Reading is the cheap, high-volume half of agentic coding: scanning, grepping, mapping, summarizing. Changing is the expensive, low-volume half: the reasoning that has to be right because it touches your code. A single model has to be priced for the hard half, so running the easy half through it is pure overpayment. Per-agent model lets you stop doing that without thinking about it again — the routing is baked into who does the work, not decided fresh on every prompt.

Dial the judgment by hand once and both leaks price themselves — the pinned expensive default and the false economy of running everything cheap. Per-agent models are this widget’s left dial made permanent: the scout lives on the light setting, the build agent on the capable one.

A lumpy day: four kinds of task, and two dials on each — which model answers, and how much effort it spends thinking. Everything starts where most people leave it: pinned to the expensive corner. Re-dial each task and watch what the day costs.

  • copy tweaksmechanical · five today

    Fix the onboarding typo, reword two error strings, update the footer year — one obvious answer each.

    modeleffort
    top dollar, one answer

    The most expensive corner on the board, spent on work the cheap corner ships identically. This is where a pinned dial leaks.

  • pattern-following endpointsmechanical · three today

    Add list/create endpoints that mirror the handler in the next file over.

    modeleffort
    premium for boilerplate

    Nothing about list/create forks or surprises; the expensive reasoning has nothing to grip. Reserve this corner.

  • the intermittent failurehard · once, thankfully

    A test that fails one run in five, timing-dependent, with the cause three files from the symptom.

    modeleffort
    matched — spend it here

    A genuine reasoning problem: timing-dependent, cause far from symptom, no pattern to copy. This corner exists for exactly this task.

  • the design forkhard · once

    Choose how rule conflicts resolve in the categorisation engine — several defensible designs, one gets built on.

    modeleffort
    matched — the wrong call costs a rewrite

    Several reasonable designs, and whichever wins gets built on. The delta between corners here is noise next to the cost of unpicking a bad choice later.

first runs495 unitsredo tax0 unitsvs the matched day1.9×

Everything ships — no failures, no redo tax — and the day still costs 1.9× what it should. That’s the quiet leak of a pinned dial: the mechanical work bills like hard work, five and three times over. Dial it down to the cheapest corner that ships it; the hard problems keep their budget.

Units are illustrative — one unit is roughly the light model running a small task at low effort. A capable model bills ~5× per token; high effort generates ~3× the tokens; the ratios are the point, not the prices. The redo tax counts an underpowered task’s failed attempts plus the escalation you do anyway — not the hour you spend reading confident wrong answers, which is the real bill.

It also composes with what’s coming. When a later chapter fans a big job out across subagents, every one of those workers inherits the model you pinned to it, so the cheap-scout / strong-builder split scales for free instead of being a choice you re-make per task. And it’s a genuine OpenCode differentiator: a single-vendor agent can dial effort up and down, but it can’t put a structurally cheaper model behind the cheap work, because it only has the one vendor’s lineup. OpenCode can reach across 75+ providers for the scout and keep a frontier reasoner on the build loop — different models, different providers, different prices, one session.

One caveat worth stating plainly: a cheaper scout is cheaper because it’s weaker. For a mechanical sweep — “list every call site of this function” — that’s a fine trade. Don’t quietly let it creep into work that needs judgment; if a scan turns into “and figure out which of these is the bug,” that’s reasoning, and reasoning belongs back on the strong model. Pin the model to match the kind of work the agent does, and re-check the fit when the work changes.

Two providers wired, models switchable mid-session, and now a model pinned to each agent so the cheap and strong work route themselves. Next, point both at the same task at once and let them argue: Run two providers side by side.