The Anatomy of an Agent Loop: Five Parts and One Gate
This month, at least seven people published long "how to build agent loops" write-ups within a few weeks of each other. Different authors, different examples, different screenshots. Strip the branding off all of them and they describe the identical machine. Anthropic's own Getting started with loops describes the same machine; ArchiveExplorer's harness walkthrough supplies the cleanest diagnostic distinction: the folder underneath the run and the cycle running inside it are separate layers.
So this is not an eighth walkthrough. This is the machine itself: the five parts every working loop is built from, and the one part that decides whether it works or just burns tokens.
A loop is five parts, not a clever prompt
A loop is a goal an agent works toward on its own, running the same cycle until a stop condition is met. It discovers what to do, does it, checks the result, and if the result is not there yet, feeds it back and goes again. You define the purpose once.
Every version that works is assembled from the same five parts, sitting on a harness.
| Part | What it does | Skip it and… |
|---|---|---|
| Trigger | Starts the run: a command, a timer, a CI event, a schedule | You ran a script once. That is not a loop. |
| Goal + stop | A finish line an outside check can confirm, plus a hard cap | It halts at "good enough," or runs until it drains your budget |
| Verifier | An independent check that passes or fails the work | The agent grades its own homework |
| Memory | A file recording done / failed / next, read at the top of every run | Every run restarts from zero |
| Permissions | A scoped allow/deny boundary the agent cannot cross | One bad cycle does something you can't undo |
Underneath all five is the harness: the model, the tools it can reach, and the context it reads before it acts. Get that wrong and the five parts multiply the wrong thing.
What the five parts look like on disk
The parts aren't abstract — they're files in a folder the agent reads before it does anything. Strip the branding off the "five-file folder" and "seven-file folder" write-ups going around and they describe the same directory; the file count only changes with how finely you split it.
| File | Which part | Its job |
|---|---|---|
CLAUDE.md / AGENTS.md | Harness + memory | Standing context read at the top of every run — stack, layout, house rules |
contract.md / PROMPT.md | Goal + stop | The one instruction each iteration works toward, and the condition that ends it |
IMPLEMENTATION_PLAN.md (or tasks.md, progress.txt) | Memory / state | What's done, in progress, failed — written before the run ends, read at the next start |
agents/verifier.md | Verifier | The separate grader — ideally a smaller, faster model — that did not write the code |
settings.json | Permissions | The allow/deny boundary and hooks the agent cannot cross |
run.sh | Trigger | The handful of lines that start one iteration, check it, and loop until the stop condition |
A working example in the wild is a single eight-line run.sh that reads the prompt and the plan file, runs one step, hands the diff to a verifier subagent told to assume it's broken, and loops until the plan reads STATUS: done. Six files, no daemon, all state on disk. That is the whole machine.
The file count is not the lever. A folder with all seven files and no real verifier is still an expensive machine grading its own homework — which is why the directory grades the gate, not the folder.
Diagnose the layer before rewriting the prompt
When a loop stalls, name the broken layer first. Repeated permission prompts, project facts being rediscovered, tools with too much scope, and the same correction returning next session are harness failures. Repeating an already-finished step, accepting plausible-but-wrong output, drifting away from the goal, and running without a clean exit are loop failures.
That distinction changes the fix. A permissions failure belongs in settings.json, not a more forceful goal prompt. A repeated iteration belongs in the state file. Confident garbage belongs at the independent evaluator gate. Drift belongs in the on-disk goal contract and stop condition. Treating all four as "the agent ignored my prompt" hides the actual control surface.
The one part that matters most: maker ≠ grader
If you only get one part right, make it the verifier.
The model that wrote the code is the worst possible judge of whether the code is correct. It has seen its own reasoning and it prefers conclusions consistent with what it just wrote. Ask it to check its work and it will agree with itself, confidently, on repeat. That is not a loop. That is an expensive machine congratulating itself all night.
A second agent, with a fresh context window, sees only the artifact and the standard. It has no stake in the first agent's choices. That single separation is most of the quality.
This is not a fringe technique. It is the design of Claude Code's /goal: when the goal is checked, a separate, smaller, faster model reads the transcript and returns done or not-done with a reason. Builder and grader are different instances on purpose. Anthropic's long-running-agents reference ships an evaluator sub-agent whose entire job is to open the evidence, run git diff, and answer PASS or NEEDS_WORK — with one rule stated outright: plausibility is not correctness. A diff that looks reasonable next to a screenshot that shows a broken layout is NEEDS_WORK.
Write the verifier like a different job, not the same prompt with "check it" appended:
You are a verifier. You did not write this code. GOAL: <the exact goal string> Given the diff and the test output, answer ONLY: PASS — every condition in GOAL is objectively met, with evidence FAIL: <the specific condition not met, and the evidence> Do not fix anything. If unsure, FAIL.
The strongest version of this doesn't trust the agent's word at all. Anthropic's reference harness includes a hook that refuses to let a test be marked "passing" until the agent has actually opened the screenshot or console log with its own eyes. The gate is a wall, not a suggestion.
Build the harness before you automate anything
A loop multiplies whatever is underneath it. Wrap one around a thin setup and you don't get autonomy — you get slop, faster.
So get one manual run reliable first. A CLAUDE.md with your standing facts. The right tools connected. A verification target that can actually fail. Only then add the trigger. Every weakness in the harness gets paid for on every single iteration, so it is the cheapest place to fix things and the most expensive place to leave them broken. (More on the guardrails in Agent Loop Safety.)
Memory, or it starts over every morning
The agent forgets everything between runs. The loop does not have to.
A small state file records what was tried, what worked, what failed, and what became a rule. Two habits make it compound instead of just grow: write to it before you walk away, and read it at the top of every run. Skip either and tomorrow re-solves today's finished work.
Keep it a control panel, not an archive. A "do not repeat" section stops the agent retrying what already failed. A "needs human review" section stops the loop quietly continuing when it shouldn't. The moment the file becomes a diary, it stops being useful.
Give it a floor it can't fall through
The fastest way to ruin a working loop is to hand it too much power the day after it starts working. It posts to Slack directly, pushes without review, closes tickets — and then one bad cycle is a mess.
Ship your first loop at the bottom of the ladder: read-only, or draft-to-a-file-only. Prove it there. A read-only loop that triages CI failures or summarizes open issues is still enormously useful, and it cannot break anything.
When you do give it hands, the boundary is a deny list and a kill switch, not good intentions:
{ "permissions": {
"allow": ["Bash(pnpm test)", "Bash(pnpm lint)", "Edit", "Read"],
"deny": ["Bash(git push*)", "Bash(rm*)", "Edit(.env)"] } }
A loop that runs unattended and cannot do anything irreversible is one you can actually leave alone.
When not to build one
A loop earns its setup cost only when all four of these are true. Miss one and a single good prompt beats it:
- It repeats — at least weekly. A one-time job is still better served by one prompt.
- "Done" is objectively checkable — a test, a diff, a number. Not "feels stronger."
- Verifying is cheaper than doing — otherwise you're back reading every diff, the exact job the loop was supposed to remove.
- The agent has real context — logs, a way to run the code and see what breaks. Without that, it iterates blind.
Most work is not loop-shaped, and that's fine. The skill is knowing which of your tasks are.
The machine isn't secret
Five parts and a gate. A trigger, a goal it can't fudge, a verifier that didn't write the work, a memory, and a boundary. The model in the middle never changes. Everything that makes a loop trustworthy is the structure you wrap around it — and the load-bearing piece is always the same: the check the writer can't talk its way past.
The fastest way to internalize it is to read one that already works. Every loop in the directory is graded A–F on exactly these parts, so you can see at a glance which ones ship with a real verifier and a real stop condition — and which ones are one bad night away from trouble. Start there, copy one, and point it at a single weekly, checkable task. If you're still deciding which kind you need, /goal vs /loop vs Ralph is the next stop.