Skip to content
Mike Reams
← Blog

Post ·

Two Tiers: Spend the Expensive Model Only on Judgment

Split long-running AI work by how much reasoning it needs: a strong model for judgment and schema, a cheaper model running bounded skills, and one rule that decides between them.

Diagram: an architect tier on the strongest model handles schema, synthesis and decisions above an operator tier running many small repeatable skills, with escalations flowing up.Diagram: an architect tier on the strongest model handles schema, synthesis and decisions above an operator tier running many small repeatable skills, with escalations flowing up.

Most of the work an AI does in a long-running practice is not thinking. It is pulling an export, diffing it against a register, updating a status, writing a log line and committing. Running that on the most capable model you can buy is like having your chief architect do data entry. It works. It is also the most expensive way to get the job done, and not the most reliable.

The AI-maintained knowledge base behind my architecture practice runs as two tiers over one shared vault, split by how much reasoning each task needs.

The two tiers

  • The architect tier runs on the strongest model. It owns the schema and operating contract, new kinds of content, synthesis across domains, decision records, and executive framing. It also writes the skills the other tier runs.
  • The operator tier runs on a cheaper, faster model. It runs a registry of bounded, repeatable skills — reconciles, refreshes, ingest against an existing template — and handles day-to-day capture and questions. It may only write inside its own lane.

Both tiers read and write the same vault. Neither talks to the other directly. Git, the resume page and the log are the whole coordination layer.

The split rule

One rule decides which tier a task belongs to:

Deterministic step: do it. Ambiguity, contradiction or a schema question: write it to the backlog and stop.

That rule is what makes a cheaper model safe to run unattended. It never has to be clever, because anything that needs cleverness is, by definition, not its job.

In practice the operator handles re-ingesting exports against a template it already knows, weekly reconciles, dashboard and status refreshes, filing a meeting note, answering a question with citations, and running a script and ingesting the output. It escalates new entity types or schema changes, synthesis that crosses domains, decisions that set precedent, any finding with no safe default, and any change to the skills themselves.

Put the judgment upstream

The design principle that made the operator tier work is simple: the judgment happens before the skill runs, not during it. An operator skill never decides what the right disposition for an application is. It applies a disposition list that a person already ratified. It never writes a narrative; it leaves a clearly marked placeholder for the architect tier to fill.

Every operator skill follows the same shape:

  • Trigger or cadence. An event, like an export landing, or a schedule.
  • Source. The one input it reads.
  • Numbered steps with literal commands, not descriptions of intent.
  • One output location. Its lane. Nothing else.
  • A verification gate. Counts reconcile, nothing orphaned, running it twice changes nothing. The model compares against the gate; it does not judge whether the gate matters.
  • A stop condition. The specific situations where it writes to the backlog and halts.
  • A commit. Pushing is the handoff.

A lesser model is very good at following a numbered procedure with a check at the end. It is much less good at deciding what the procedure should have been. So I do not ask it to.

Guardrails that keep one shared memory clean

  • Propose first. The operator shows the diff and waits for a go before writing. That is the safety valve for a less capable model.
  • Claim a lane. Before starting, a session marks the lane it is working in. If a lane is taken, it stops. Cooperative, not locked, and it has been enough.
  • One writer per hot file. The resume page, index and backlog are integrated by the architect tier only.
  • Pull before, push after. Git is the only real conflict resolver, so every session starts and ends in sync.
  • Log every run in a fixed shape. What it did, what it decided, what it blocked on, which check passed, and the commit. Searching for one line prefix gives the full audit trail of every agent run.

And the architect tier does not grade its own output either. Anything that will travel goes through a separate skeptical reviewer first.

As it grows, the risk is concurrency, not size

I expected the vault to get harder to manage as it grew past a thousand pages. It did not. What caused trouble was two sessions writing the same file at the same time. Lanes, single-writer files and pull-push bracketing solved that. Resist the urge to build one mega-skill that does everything; small skills with one trigger, one source and one output are easier to trust, test and replace.

Copy this: the operator contract and a skill template

The block I paste at the start of every operator session:

You are the Operator. Boot per CLAUDE.md: read CLAUDE.md, NOW.md, the
active inbox and the last log entry. Claim a lane in NOW.md before working.

- Propose first: show the diff and wait for my go before writing.
- Stay in your lane. Never touch the schema, decision records, NOW.md,
  index.md or inbox.md.
- Deterministic step: do it. Ambiguity, contradiction or a schema
  question: write it to inbox.md and stop.
- Log every run in the standard shape, then commit.

The shape every operator skill follows:

---
name: <skill-name>
description: <one line: when to use this>
---

Trigger:   <event, e.g. "new export in raw/exports/"> or <schedule>
Source:    <the one input it reads>
Output:    <the one file or folder it writes - its lane>

Steps:
1. <literal command or action>
2. <literal command or action>
3. <literal command or action>

Verify (compare, don't judge):
- <counts reconcile: rows in = rows written>
- <no orphans>
- <running it twice changes nothing>

Stop and escalate if:
- <the specific ambiguous case> -> write to inbox.md, stop.

Log:
## [YYYY-MM-DD] agent-run | <skill> | <lane>
- did:     <what changed, with counts>
- decided: <judgment calls inside the procedure>
- blocked: <what was escalated, or "none">
- verify:  <the check that passed>
- commit:  <message>

Try it

  1. List the repeatable jobs your AI does every week. Most of them are probably deterministic.
  2. Write each one as a numbered procedure with a verification gate and a stop condition.
  3. Move those to a cheaper model. Keep the strongest model for the work that genuinely needs judgment.
  4. Make escalation the default for anything the procedure does not cover.

You pay less, and the work gets more predictable, because each tier only ever does the kind of work it is good at.