Skip to Content

Design decisions

The choices that shaped zerd, each with its reason and trade-off.

The choices that shaped zerd, with the reason behind each. Several started as a mistake that showed up in a real session.

1. Enforce in code, ask in the prompt only for taste

A prompt that says "never read .env" is a request. zerd puts rules where the model cannot talk its way past them: the tool registry is the only way to run a tool, and the guard, workspace confinement and approval checks sit in front of every call, for the main agent, sub-agents and parallel workers alike. Trade-off: more code to maintain than a paragraph in a prompt, but a jailbroken or confused model still can't leave the folder.

2. The author never grades its own work

The model that wrote a change is the worst judge of it. Review runs in a separate context, with read-only tools, on a different model when routing allows. Same idea for the challenger and the advisor (below). Trade-off: extra model calls. They are spent only where a mistake is expensive (a diff, a risky design question).

3. Reviewers are cheap to fool, so a second agent tries to refute them

Early reviews read like confident fiction: plausible chains of reasoning about code that did not behave that way. So a finding is a claim, not a result. Each claim goes to a verifier whose job is to disprove it; confirmed HIGHs are run in a throwaway copy of the change to see the defect happen, and one that does not reproduce is capped at MEDIUM with what was tried shown beside it. Findings citing a file that doesn't exist are dropped before anyone reads them. Trade-off: a review costs more and takes longer. The reader gets fewer, truer findings.

4. A hallucination check that is not a model

Every path and path:line in the final answer is looked up in the real tree. A made-up file or a line past the end of a file goes back for one correction; whatever is still unverified is shown as a warning. It is a few dozen lines of code and catches a whole class of confident wrongness for free.

5. Cheapest evidence first

Tools are ordered by cost: search (ranked files), then outline (symbols), then read_file(symbol=...), then grep. The scout, the prompt and the tool descriptions all push the model down that ladder, because a 1,300-line file read to find one function is tokens that every later call re-sends.

6. Never send the same thing twice

read_file remembers which lines the model has seen and returns only new ones, or a diff if the file changed. Cleared or capped tool output isn't lost: it goes to an archive and the model gets an id (r7) to recall_result. Compaction deterministically lists files read and modified. The goal is that the model never has to guess what it used to know.

7. Failure has a defined next step

Checks fail, so repair. Repair fails, so escalate to the strong model. A loop is detected, so escalate. Quota hits one provider, so fail over to another and block the first for the session. Budget runs low, so one last tool-free call turns the work so far into an answer. Nothing falls over silently, and nothing ends in "the model said it was fine".

8. Only remember what cannot be invented

Memory stores what you told zerd and what verified runs changed. It does not store the model's opinions about your repo, because those are exactly what drifts and compounds. Lessons are plain text in your AGENTS.md, so you can read, edit and commit them.

9. Pi mode is the default: fewer rails, simpler agent

zerd started with many guards: call caps, aggressive clearing of old results, a scout before every task. Measured against a simple agent (seven plain tools, a tiny prompt, files read whole), the guards often cost more than they saved. So pi mode is on by default, copied from how the pi coding agent works: a small tool set, no call caps, results cleared only near the window, compaction only close to the limit. --no-pi brings back the guarded setup (scout, reference check, parallel tasks). Safety and correctness layers stay on in both. Lesson: every rail needs to pay rent. We measured, and removed what didn't.

10. Different brains for different jobs

One model for everything wastes money and one model for the review shares the author's blind spots. Routing is by role (default, fast, strong, summarize, review, advisor, challenge), each a fallback chain. Adding a model needs no code. The advisor and challenger default to a different model family than the author on purpose.

11. Plain files, outside the repo, atomic

Sessions, traces, archived results, learned lessons and review memory live in the user data dir, not in your project. Writes are temp-file + rename, so a kill mid-write never leaves a truncated session. Traces are JSONL so a bad run can be replayed line by line.

12. Say what you did not do

The answer states the review scope (working tree, last 3 commits, PR #42), lists every fallback (PR base unknown, fetch failed), says when passing checks don't exercise the change, and labels guesses as [guess]. A harness that proves its work has to be equally clear about where it couldn't.

On this page