Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path →
Stop prompting.
Design the loop.
In June 2026 a single idea reorganized how engineers talk about working with AI agents: stop typing prompts, and start building the system that prompts the agent for you. This is the field guide to loop engineering — the loop types, the building blocks, the stopping conditions, and the ways loops fail expensively when you skip them.
From prompting to loops
Loop engineering is the practice of designing the system that runs your AI agent in a repeating cycle — find work, do it, verify it, record it, repeat — instead of prompting the agent by hand each step. You stop being the person who types the next instruction and become the person who designs the machine that decides what the next instruction is.
"You shouldn't be prompting coding agents anymore. You should be designing loops that prompt your agents."
"I don't prompt Claude anymore. I have loops running that prompt Claude and figure out what to do. My job is to write loops."
The term went mainstream in June 2026 when Addy Osmani synthesized these ideas into a named discipline, and the framing stuck because it describes a real shift already underway: the folk version had existed for a year as the "run the agent in a while true loop" trick, and every serious agent team had independently invented pieces of it. Naming it made it designable.
The cleanest way to place it is as the third rung of a ladder, where each level contains the one below:
Prompting an agent is adjusting the heater by hand every hour. Loop engineering is installing the thermostat — you encode the goal and the check, and the system does the adjusting. The skill moves from operating to designing.
The two loops — inner and outer
The word "loop" is doing double duty here, and separating the two meanings is the key to the whole discipline. The inner loop is the agent loop itself — plan → act → observe — the ReAct-style cycle inside every harness, where the model thinks, calls a tool, reads the result, and thinks again. That loop is largely built for you by whoever ships your agent.
The outer loop is the one you engineer. It wraps the entire agent run as a single step inside a bigger cycle:
Every design decision in this handbook lives in one of those five outer stages. If your mental model of "agent" stops at the inner loop, the rest of this page is the missing half.
Both loops are easier felt than read. The Agent Loop Simulator lets you step through the inner loop and watch the context window fill and compact. Then the Loop Designer puts you in charge of the outer loop: toggle the guards, run an unattended migration, and watch the failure modes below fire live.
The four loop types
Outer loops come in four shapes, distinguished by what triggers them and what stops them. Choosing the right shape is the first real design decision — most bad loops are a goal problem forced into a heartbeat shape, or vice versa.
| Type | Fires | Good for | Stops when |
|---|---|---|---|
| Heartbeat | Continuously, on a short interval (seconds–minutes) | Monitoring logs, watching queues, service health triage | Never — it's killed, paused, or budget-capped |
| Cron | On a schedule (daily 7am, weekly Monday) | Nightly code review, dependency audits, morning triage reports | Each run ends when its batch completes |
| Hook | On an event — PR push, CI failure, Slack message | Reactive work: fix the failing build, review the new PR | Once per event, when the response is done |
| Goal | Repeatedly, until a success condition is met | Migrations, refactors, "make all tests pass" — unknown scope | The condition verifies true — or a hard iteration cap trips |
They compose. A mature setup is usually a cron loop that discovers work, hook loops that react to events, and goal loops spawned per work item — each with its own stopping rule. The goal loop is the most powerful and the most dangerous: it's the only one whose natural state is "keep going," which is why it gets its own section on stopping conditions below.
The six building blocks
Across tools, working loops converge on the same six components. Five are primitives you configure; the sixth is a discipline you maintain.
| Block | What it does | Without it |
|---|---|---|
| Automations | Scheduled or triggered runs that find work — triage CI, scan issues, audit deps — and feed a triage inbox | You remain the task dispatcher |
| Worktrees | Isolated git working directories so parallel agents never collide on files | Two agents edit one file; both branches break |
| Skills | Codified project knowledge in version-controlled instruction files, loaded on demand | You re-explain conventions every run — "intent debt" |
| Connectors (MCP) | Standardized access to external systems — issue trackers, DBs, Slack — so loops can open PRs and update tickets | The loop can think but not touch anything |
| Subagents | Separate agents (fresh context, sometimes different models) that split implementing from verifying | The model grades its own homework |
| External memory | A markdown board, state file, or tracker outside the context window recording done/next | Every run starts from amnesia and repeats work |
The same blocks exist under different names in every major harness:
Claude Code
- /loop, scheduled agents (cron), hooks, GitHub Actions
- git worktree / worktree isolation per agent
- SKILL.md files, auto- or explicitly invoked
- MCP servers + plugins
- Subagents in .claude/agents/, agent teams
Codex app
- Automations tab (project + prompt + cadence), /goal run-until-done
- Built-in worktree per thread
- SKILL.md invoked with $name
- MCP + plugins
- Subagents as TOML in .codex/agents/
The pattern to internalize: discovery (automations find work), isolation (worktrees keep parallel work safe), knowledge (skills stop you re-explaining), reach (connectors let it act), judgement (subagents verify), memory (state survives the run). Miss one and the loop leaks — usually money.
Stopping conditions & verification
The hardest part of a loop is not making it run. It's making it stop — correctly, and for the right reason.
A loop's stopping condition must be checked by machinery, not judged by the model. "The refactor looks complete" is a judgement; 0 failing tests && 0 lint errors is a condition. Models are systematically overconfident about their own completions, so a loop that lets the agent declare victory will terminate early on plausible-looking work — and a loop with no condition at all simply never stops.
Layer three guards, in order of bluntness:
| Guard | What it is | Catches |
|---|---|---|
| Hard caps | max_iterations, wall-clock limit, token budget | Runaway loops, oscillation, cost blowups |
| Verifiable conditions | Tests green, build passes, zero diff on re-run, metric under threshold | Early stopping on unfinished work |
| Independent verification | A separate verifier — test suite, reviewer subagent, different model — judges the output | Confident, wrong, "done" |
The third guard is the architectural pattern worth naming: the verification split. The agent that wrote the change must not be the agent that approves it — the same failure of incentives as a developer reviewing their own PR, except the model fails it more reliably. In practice: one subagent implements in a worktree, a second subagent with fresh context reviews against the project's skills and runs the tests, and only a pass releases the work downstream. Evaluating agent output rigorously is its own discipline — the Agent Evals handbook covers it.
A loop without a verifier is a machine for shipping plausible mistakes at scale. Everything a loop produces must pass a gate that can fail — if the result can't be measured, the loop treats it as a failure, not a pass.
State across runs
Models forget everything between runs. The loop can't. External memory — state kept outside the context window — is what turns a series of isolated agent runs into a system that makes progress. Without it you get state amnesia: the Monday run re-fixes what Friday's run fixed, the migration loop re-converts the same ten files, and iteration count stops correlating with progress.
Lightweight — start here
- A markdown board in the repo: done / in-progress / next
- A JSON checkpoint file the loop reads first, writes last
- Git itself — branches, commit messages, tags as progress markers
Heavier — when loops multiply
- An issue tracker (Linear, GitHub Issues) as the shared work queue
- A database when state outgrows files
- A triage inbox where unhandled findings await a human
Two rules make state trustworthy. First, the loop reads state before framing the task and writes state after verification — never mid-run, so a crashed run can't record work it didn't finish. Second, state records facts, not vibes: "converted auth/session.ts, tests pass" is replayable; "made good progress on auth" is amnesia with extra steps. A resume-point convention — one line saying exactly where the next run picks up — is the cheapest reliability upgrade a loop can get.
Cost engineering
Loops multiply whatever they touch — including your bill. A manual prompt costs one conversation; a heartbeat loop with a verifier subagent is dozens of model calls an hour, all day, whether or not there's work to do. A goal loop with no iteration cap can burn hundreds of dollars in an hour while making no progress at all. Cost isn't a footnote to loop engineering; it's a design axis.
Three levers, roughly in order of impact:
| Lever | How it works | Typical saving |
|---|---|---|
| Model routing | Match model tier to step difficulty: small fast models for classification and scanning, mid-tier for drafting and summarizing, frontier models only for review and decisions | 60–80% on token spend |
| Prompt caching | Loops re-send the same system prompt, skills, and repo context every iteration — exactly the shape caching rewards | 40–90% on input tokens |
| Doing less | Hook loops instead of heartbeats where events exist; cheap pre-checks ("anything new since last run?") that skip the expensive agent entirely | Often the biggest of all |
And put a budget ceiling on every loop as a hard cap, not a dashboard you check later. A loop that stops at its budget is an inconvenience; a loop you discover on the invoice is a story you tell at conferences.
The steady state to aim for: cheap models watch, expensive models act, and the most expensive model only ever reviews. If your frontier model is doing the scanning, the routing is upside down.
Failure modes & guardrails
Loops fail differently from prompts. A bad prompt wastes a reply; a bad loop compounds — all night, at full spend, in your repo.
Token runaway
A goal loop with no cap iterates forever on an unachievable condition, burning budget while producing nothing.
Guard: max_iterations + token budget as hard stops, alert on trip.State amnesia
No external memory, so each run repeats prior work; the loop is busy but not progressing.
Guard: checkpoint file or board, read-first write-last, resume-point line.Overconfident termination
The agent declares the goal met; it isn't. The loop exits on plausible-looking output.
Guard: verifiable stop conditions; a verifier that isn't the implementer.Context degradation
Long runs fill the window; compaction eats the constraints and quality decays mid-loop.
Guard: fresh subagent per work item instead of one marathon context.Silent quality drift
Each iteration passes review in isolation while the codebase slowly accretes mediocrity nobody approved.
Guard: periodic human audit of merged loop output, not just per-PR gates.Comprehension debt
The loop ships faster than you read; six weeks in, nobody on the team understands the code they own.
Guard: read what merges; keep loop throughput inside human review bandwidth.The last two failures are human, not technical, and they're the ones Osmani's write-up dwells on. Orchestration tax is the ceiling loops eventually hit: not model capability, but your bandwidth to review what they produce — parallelism past that point manufactures unreviewed changes. And cognitive surrender is the failure past the ceiling: you stop having opinions about the output entirely. The same loop produces opposite results for an engineer who understands the system deeply and one who has delegated the understanding itself.
Loops automate the prompting, not the responsibility. Verification stays yours, understanding stays yours, and design intent stays yours — the loop just stops you being the keyboard.
Design your first loop
Theory compresses into a worked example. Here is the reference architecture — a nightly triage-and-fix loop, the "hello world" of loop engineering — using every block from section 04:
And because a loop is ultimately just code, here is the entire idea in one runnable file — a goal loop for a migration, with all three guards and both state rules from section 06. Swap the claude -p line for any agent harness you use:
import json, subprocess, sys MAX_ITERATIONS = 8 # guard 1 — hard cap STATE_FILE = "loop-state.json" # external memory def load_state(): try: return json.load(open(STATE_FILE)) except FileNotFoundError: return {"queue": ["auth/session.py", "auth/token.py"], "done": []} def verified(): # guard 2 — checked by machinery, not the model return subprocess.run(["pytest", "-q"]).returncode == 0 def run_agent(task): # the whole inner loop is this one box subprocess.run(["claude", "-p", task]) for i in range(MAX_ITERATIONS): state = load_state() # read state BEFORE framing the task if not state["queue"]: print("goal met"); sys.exit(0) # verifiable stopping condition target = state["queue"][0] run_agent(f"Migrate {target} to the new session API. Done so far: {state['done']}") if verified(): # guard 3 — verifier is not the implementer state["done"].append(state["queue"].pop(0)) json.dump(state, open(STATE_FILE, "w")) # write state AFTER verification subprocess.run(["git", "commit", "-qam", f"migrate {target}"]) # bank the verified work if not state["queue"]: print("goal met"); sys.exit(0) # re-check, or a last-try success reads as "cap hit" else: # state untouched — the next iteration retries the same target subprocess.run(["git", "checkout", "--", "."]) # ...from clean code, not the failed edits print("cap hit with work remaining — escalate to a human") # end loudly, never silently
Under forty lines, and every concept in this handbook is present: the cap, the condition, the verification split (pytest judges, not the agent), read-first/write-last state, a clean retry (a failed attempt’s edits are discarded, verified ones committed), facts-not-vibes checkpoints, and a loud ending. Production loops grow worktrees, subagents, and connectors around this skeleton — they never replace it.
How to actually start, without the fleet:
Pick one recurring chore you already do — triaging CI failures, dependency bumps, flaky-test hunting. Boring and frequent beats impressive and rare. Write the skill first: the conventions you'd explain to a new teammate go in a version-controlled instruction file, because an outer loop is only as good as the context it frames (that's the L2 layer doing its job inside L3). Give it the three guards from section 05 — a cap, a condition, a verifier — before its first unattended run, not after its first incident. Run it supervised for a week, reading everything it produces; you're calibrating trust, and you'll usually fix the skill file three times in the first five runs. Then schedule it and add the next loop only when reviewing this one costs you almost nothing.
One well-guarded loop that runs every night is worth more than five clever ones you had to turn off. The engineers getting leverage from this aren't the ones with the most agents — they're the ones whose loops they can stop thinking about.
A production loop, dissected
This isn't theory to us. The videos on the Vibe Engines YouTube channel are built, quality-gated, and uploaded by an autonomous loop. Here's its anatomy, mapped to everything above.
| Concept | How our video pipeline implements it |
|---|---|
| Trigger (cron) | A scheduled system job kicks off a batch builder — deliberately not a terminal session, because a loop that dies when a laptop sleeps isn't a loop |
| Hard caps | An 11-hour wall-clock budget per batch, plus a queue governor that stops building when 6 videos are waiting to upload — production ahead of review is waste, not progress |
| Verification split | A 16-gate ship-gate scorecard judges every video before upload — motion checks on rendered frames, story-structure checks on the script, an LLM judge fact-checking the narration, a writing-craft scorer. The builder never grades itself, and unmeasurable means fail |
| External memory | A tracker file with a RESUME POINT block — every run reads it before framing work and rewrites it after shipping, so a crashed batch resumes exactly where it stopped, not where it guesses |
| Hook loop | When the platform's daily upload cap clears, a paced drainer publishes the pending queue one per hour instead of dumping it |
| Human escape hatch | A gate failure parks the video for review with its scorecard attached. Nothing ships on a red gate; nothing fails silently |
The instructive part is why each guard exists — every one was added after its absence hurt. The ship-gate exists because early videos degraded quietly: each looked fine in isolation while the batch drifted mediocre — silent quality drift, caught only by a human audit. The queue governor exists because building faster than the upload cap just manufactured a warehouse. And the resume-point convention exists because the first crashed batch re-rendered work it had already finished — state amnesia, paid for in GPU-hours.
Every failure mode in section 08 showed up in this pipeline before its guard did. Loop engineering is mostly the discipline of installing the guard before the incident instead of after — this page exists so you can skip our invoices.
Walk through the goal loop, iteration by iteration
Run the page’s migration loop against its default queue, auth/session.py then auth/token.py, with MAX_ITERATIONS = 8. Say the agent’s first attempt at session.py leaves a test red.
| i | State read first | Agent works on | pytest | State written last |
|---|---|---|---|---|
| 0 | no file yet, so the default: queue of 2, done empty | session.py | fails | nothing; no file is written |
| 1 | still the default | session.py again | passes | done: session.py; queue: token.py |
| 2 | queue: token.py | token.py | passes | done: both; queue empty |
| 3 | queue empty | nobody | not run | exits 0, “goal met” |
| alt: 2 to 7 | queue: token.py | token.py, six times | fails every time | nothing; the loop prints “cap hit” |
| alt: 7 | queue: token.py | token.py | passes on the final allowed try | queue empty; the re-check exits 0, “goal met” |
Rows 0 and 1 show write-last doing its job. The failed attempt left no record, so iteration 1 retried the same target instead of believing it was done. The alternate rows show two things the guards do not. First, the cap is shared by the whole queue, not given to each file: 8 iterations for 2 files leaves at most 6 attempts at whichever file is stuck. Second, why the queue is checked twice. If the only empty-queue check ran at the top of an iteration, a success on the last allowed iteration would fall out of the for loop into the “cap hit” message and page a human for work that is finished. The re-check straight after writing state is what prevents that false alarm.
Common mistakes when building the loop
- Retrying on a dirty tree
When the tests fail, the agent’s half-finished edits are still on disk. Leave them, and the next attempt starts from broken code, not from the last good commit. The page’s loop runs
git checkout -- .before the retry and commits each verified file, so the reset cannot throw away earlier good work.git checkoutdoes not remove new untracked files; a fresh worktree per attempt does. - The implementer can edit the verifier
If the agent can touch the tests or the lint config, deleting a failing test is the cheapest way to make
pytest -qexit 0. Protect the verifier’s files. Then add a check to the gate that fails the run if the number of tests goes down. - One poison item eats the whole budget
In the page’s loop, a first file that never passes takes all 8 iterations, and the second file is never attempted. Keep an attempt counter per item. After N failures, move the item to the human inbox and carry on with the rest of the queue.
- Overlapping runs on one state file
A nightly cron run that takes longer than a day starts again while the previous run is still going. Both read the same queue and pick the same item, and the last writer wins. Take a lock at the start, or skip the run if the previous one is still alive.
- A hook loop that triggers itself
A loop that runs on every push, and pushes, can fire itself forever. Filter out events your own bot authored. GitHub Actions blocks the simple case for you: events created with the workflow’s
GITHUB_TOKENdo not start new workflow runs, exceptworkflow_dispatchandrepository_dispatch. A personal access token or app token gets no such protection.
Where this shows up in production and interviews
- Dependency bots
Dependabot and Renovate are cron loops that predate LLM agents. They run on a schedule, open one PR per update, let CI act as the verifier, and leave the merge to a human. Their PR limits and grouping rules are the orchestration-tax ceiling, written down as config.
- Kubernetes controllers
A controller is a goal loop that never exits. It compares the desired state with the actual state, acts to close the gap, and runs again. It has to be idempotent because it may act on the same object many times. That is the design a goal loop over a work queue should copy.
- CI as the verification split
The cheapest independent verifier is the pipeline the team already trusts. A loop that opens a PR and waits for the required checks gets a judge that is not the implementer, and branch protection stops anything red from merging.
- The interview version
“Design an agent that fixes flaky tests overnight.” Name the loop type (cron to find flakes, a goal loop per test), the three guards, where state lives, the per-item attempt limit, and the budget cap. Then say what a human reviews. Picking the right shape and stop rule matters more than which model you name.
Check yourself
You want the docs site’s broken-link count back at zero after every merge. Heartbeat, cron, hook or goal?
A hook on merge, starting a goal loop that is bounded by a cap. The event already exists, so a heartbeat would pay to poll for nothing. The stop condition is checkable by machinery: the link checker reports zero.
In the page’s loop, the agent can never make auth/session.py pass. What happens to auth/token.py?
It is never attempted. All 8 iterations go to the head of the queue, and the run ends with “cap hit”. That is the poison-item failure; a per-item attempt limit fixes it.
The agent’s last message says “all tests pass”, and the loop exits on that. Which guard is missing?
The verifiable condition with an independent verifier. The agent’s claim is judgement, not a check. The loop should run the tests itself and exit only on their result.
The process is killed after the agent edits two files but before pytest runs. What does the next run do?
It reads state, finds the target still at the head of the queue, and retries it, which is correct, because state is written only after verification. But unless the loop resets the tree, the retry starts on top of the partial edits.
Quick answers
What is loop engineering?
Designing the system that prompts your agent instead of prompting it yourself: a trigger, task framing, verification, external state, and an explicit stopping condition. Popularized in June 2026 by Addy Osmani, building on Peter Steinberger and Boris Cherny.
Loop engineering vs prompt / context engineering?
Prompt engineering shapes one request; context engineering shapes everything one run sees; loop engineering shapes the repeating system around runs — when the agent fires, what it works on, how output is checked, when it stops. Each level contains the one below.
What are the four loop types?
Heartbeat (continuous interval — monitoring), cron (scheduled — nightly reviews), hook (event-triggered — CI failure, PR push), and goal (iterate until a verifiable condition — migrations). Goal loops always need a hard iteration cap.
How do you stop a loop running forever?
Three layered guards: hard caps (max iterations, budget), verifiable conditions (tests green, zero lint errors), and independent verification — a test suite or second agent, never the implementer judging its own work. A loop that also updates the agent needs a further set of rails, because narrowing does not trip any of these: self-improving agents lists them.
What tools support loops today?
Claude Code (/loop, scheduled agents, hooks, subagents, skills, worktrees, MCP), the Codex app (automations, /goal, per-thread worktrees, skills, MCP), and GitHub Actions as trigger and runtime. The primitives are converging.
This idea in other formats
Explore the topic
See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.
More Handbooks
- The Agentic AI Interview HandbookTwenty topics every senior AI engineer should be able to reason about live — from eval pipelines to reliability patterns for generative systems.Read →
- The Agent Evaluations HandbookA self-contained handbook on evaluating AI agents — theory, interactive widgets, and practical guidance. Trajectory evals, tool-use scoring, LLM-as-judge, observability, and reliability for PMs, engineers, and founders.Read →
- The Agent Patterns HandbookThe design patterns behind every LLM agent — the ReAct Thought–Action–Observation loop, tool/function calling, plan-and-execute, reflection, memory, multi-agent orchestration, and the failure modes (loops, hallucinated tools, recovery, human-in-the-loop) that break agents in production.Read →
- The Model Context Protocol (MCP) HandbookThe open standard connecting AI agents to the outside world — why M×N bespoke integrations collapse to M+N, the host/client/server roles over JSON-RPC, the three primitives (tools, resources, prompts), the connect→discover→call session lifecycle, when MCP earns its keep, and the security sharp edges (a server's output is untrusted input).Read →
- The Context Engineering HandbookThe discipline that replaced prompt-tweaking: curating everything the model sees under a finite attention budget. The anatomy of a production context window, the three taxes on an overstuffed one (context rot, cost, behavioral drift), the four operations (write, select, compress, isolate), agent-specific patterns like compaction and just-in-time retrieval, six production habits, and where it sits in the prompt → context → loop → harness stack.Read →
- The Agent Skills HandbookPackaged, on-demand expertise for AI agents: what a skill folder actually is (SKILL.md + scripts + resources), progressive disclosure and why the system prompt couldn't do it, the skills vs tools vs MCP vs fine-tuning decision table, six habits of skills that actually trigger, and why third-party skills are supply-chain dependencies to review like code.Read →