DEV Community

Cover image for A Dev's Guide to Loop Engineering: The System That Works Itself
Keerat Rashid
Keerat Rashid

Posted on

A Dev's Guide to Loop Engineering: The System That Works Itself

“You shouldn’t be prompting coding agents anymore. You should be designing loops that prompt your agents.” - Peter Steinberger

Loop engineering is built around the idea that system work itself in a loop of Act, Check, and Decides and the loop continues until a goal is achieved. The only thing human has to do is to write “loops” for the systems to work. Think of it like writing a prompt to give enough context to train the models Done right, it's the closest thing in software to a system that works itself. Done wrong, it's an infinite loop with better PR.

“Loop engineering is replacing yourself as the person who prompts the agent. You design the system that does it instead. A loop here can be thought of a recursive goal where you define a purpose and the AI iterates until complete. I believe this may be the future of how we work with coding agents.” – Addy Osmani

Loop Engineering is built over harness engineering. Harness Engineering builds the infrastructure the agent operates in. It focuses on permanent, systemic fixes: whenever the agent makes a mistake, the environment is updated so that specific error becomes structurally impossible to repeat.

This guide is for developers building that second kind of system — retry logic, polling daemons, autonomous agents, self-healing pipelines — anything that's meant to run its own loop rather than be called once and forget.

The Anatomy of a Self-Running Loop
Every loop worth engineering has the same four stages, and almost every bug in a loop-based system traces back to one of them being sloppy:

  1. Sense => observe the current state of the world.
  2. Decide => compare that state against the goal and choose the next move.
  3. Act => execute the move.
  4. Check exit => decide whether to stop or loop again. It looks trivial. It is not. Almost all the real engineering work lives inside sensing, deciding, and checking exit is usually the easy part.
  5. Sense: Don't Trust Stale State The single most common bug in loop-based systems is acting on state that's already out of date by the time you act on it. A polling loop that reads a queue depth, spends time deciding what to do, and then acts on a number that's now wrong is a classic example. Practical rules: • Re-sense right before you act, not just at the top of the loop, if there's any meaningful delay between sensing and acting. • Timestamp your state. If the decision step can't tell how old its input is, it can't tell whether to trust it. • Distinguish "no signal" from "bad signal." A sensor timeout and a sensor reading of zero are different failure modes and should never be handled the same way.
  6. Decide: This Is Where Loops Go Unstable This is the step that separates a loop that converges from one that oscillates or runs away. Three failure patterns show up constantly: Overcorrection. If your loop reacts to the full size of an error every cycle, it tends to overshoot, then overshoot back the other way. The fix, borrowed straight from control theory, is to dampen the response, react to a fraction of the error each cycle, not all of it. Compounding drift. In multi-step loops (agents especially), a small mistake in the first cycle becomes the input to the next, and errors stack on top of each other. Guard against this by periodically re-grounding against a source of truth instead of only trusting the loop's own last output. No memory of history. A loop that only looks at the current error will happily repeat the same failed move forever. A loop that only looks at the current state, with no memory at all, can't tell "getting better slowly" from "stuck." Give it a short history to check against, and look for actual progress every few cycles, not just whether the last cycle technically succeeded.
  7. Act: Make Actions Safe to Repeat If your loop might retry an action after a partial failure, and if it runs more than once, it eventually will, and that action needs to be safe to run twice. This is the difference between a retry loop that heals itself and one that quietly corrupts state on the second attempt. The general pattern: before taking an action, the loop should be able to check whether that action has already happened, and skip it if so. Payment systems solve this with idempotency keys; other systems solve it by checking current state before acting rather than assuming a blank slate. If an action truly can't be made repeat-safe, the loop needs to guarantee it only ever fires once, which is a much harder property to build and worth avoiding if a repeat-safe design is available instead.
  8. Check Exit: The Part Everyone Forgets An unbounded loop is a liability by default, not a feature. Every self-running loop needs at least two independent exit conditions, because relying on just one is how you end up debugging a process that's been running for six hours: • A success condition => the actual goal has been met. • A hard ceiling => a maximum number of iterations, a maximum wall-clock time, or a maximum cost, regardless of whether the goal was met. Both limits should be enforced in the code itself, not just something a human plans to watch on a dashboard. Dashboards don't get paged at 3am; runaway loops do. Backoff: Loop Engineering's Most Reused Pattern If your loop is retrying against something that might be struggling: a flaky API, an overloaded queue, reacting at full speed on every failure is how a brief hiccup turns into an outage. You end up hammering a system that's already struggling. The standard fix is exponential backoff with jitter: wait longer after each successive failure, and add a small random variation to that wait time. The jitter matters more than people expect. Without it, every client retries at exactly the same moment, which doesn't solve the thundering-herd problem, it just moves it to a slightly later, equally synchronized timestamp. Agent Loops: The Same Rules, Higher Stakes If you're building an LLM-based agent loop, read a tool result, decide the next action, call a tool, repeat, every rule above still applies, plus a few that matter more once the "decide" step is a model call instead of a formula: • Bound every dimension you can: maximum tool calls, maximum tokens, maximum wall-clock time, maximum cost. An agent loop with only a "the model decided it's done" exit condition will eventually hit a case where the model never decides that. • Re-ground periodically. Don't let the agent's own past outputs be its only source of truth about what's actually happening — feed it fresh tool results, not just its own earlier summaries of those results. • Make tool calls repeat-safe, same as any other retried action. An agent that reissues a "send email" call because it lost track of state should not send the email twice. • Insert a human checkpoint before high-consequence actions. This is a deliberate damping step, functionally identical to a safety interlock in industrial control loops — it exists specifically to catch the cases the automated exit conditions didn't anticipate. A Pre-Ship Checklist Before you let a loop run unattended, it should be able to answer all of these: • Can it tell the difference between "no data" and "data says zero"? • Does it re-check ground truth periodically, or only trust its own last output forever? • Is every action safe to run twice? • Does it have a hard ceiling on iterations, time, and cost — independent of its success condition? • Does its retry logic back off, with jitter, instead of hammering at a fixed rate? • If it fails to converge, does it fail loudly, or just quietly loop forever? A loop that passes all six is one you can actually trust to run itself. A loop that's missing even one of them isn't a self-running system, it's a landmine with no way to defuse itself.

Top comments (0)