Loop Engineering Without the Hype
A feedback loop where an agent plans, acts, verifies, and stops. The useful definition, the hard part (the verify step), and when not to bother.
Loop engineering is a feedback loop where an agent — human, automated, or AI — receives a goal, gathers context, takes the smallest useful action, verifies whether that action moved toward the goal, retains what it learned, and either continues or stops. That is the whole definition. It is not a product category. It is not a paradigm shift. It is structured iteration with explicit contracts at every step. The term is being used to mean everything from a retry block in a Python script to full autonomous reasoning chains, which makes it nearly useless as a signal. So let us make it useful again by naming the parts, finding where they break, and being honest about when the whole architecture is overkill.
The Minimal Loop Structure
A loop that actually works has six components. Leave any one out and you have a runaway process, a stalled agent, or a verification theater that produces confidence without accuracy.
Goal — what done looks like, stated in measurable terms. Not "improve the token system." Something like: "all design token files pass CSS build without errors." Vague goals make every verify step ambiguous. If you cannot write a failing test for your goal, your goal is not ready.
Context — what the agent needs to know before acting. The current state of the system, relevant constraints, any prior failures from previous iterations. This is the part most people underspecify. An agent acting without context is just guessing with extra steps.
Action — the smallest useful unit of work. Resist the urge to make actions large. A large action means a large verify step, and large verify steps are where loops go to die. Check one file. Run one build. Change one value. The granularity of your action determines the granularity of your feedback.
Verify — how you check whether the action achieved the goal. This is harder than it looks, which we will get to.
Memory — what the agent retains between iterations. Which files were checked. Which errors recurred. What was already attempted and failed. Without memory, a loop is stateless and will repeat mistakes indefinitely.
Stop condition — when to exit. This must cover two cases: success and failure. A loop with only a success exit is a process that runs until it hits a resource limit. That is not a workflow. That is a problem waiting to become an incident.
Why Most Loops Break at the Verify Step
The action step is where most of the design energy goes. It is satisfying to build. The verify step is where most loops actually fail.
The difficulty scales inversely with how objective your goal is. Verifying "does this function return the correct value" is easy — run a test. Verifying "does this token value look right in dark mode" is not a test problem, it is a judgment problem. And "does this layout feel balanced" is not even a judgment problem with a stable answer — it changes depending on who is looking and what surrounds it.
Most people design their verify step for the easy case and quietly hope it holds for the hard ones. It does not. What happens instead is verification theater: the loop runs, something checks, a result is logged, and the loop exits with "pass." But the check was not actually measuring what the goal required. The loop completed without doing the work.
The fix is to be brutally specific about what verify can and cannot measure. If your verify step cannot produce a falsifiable result, your loop cannot be trusted. Either tighten the goal until verify becomes tractable, or accept that a human needs to be in the loop at that step. That is not a failure of the architecture. That is the architecture being honest.
The Stop Condition Problem
Loops that lack explicit failure conditions do not stop gracefully — they exhaust their resources and halt, or they churn until someone notices and kills the process. Both outcomes are worse than a clean exit with a report.
A failure stop condition requires you to decide, in advance, what "this is not working" looks like. That is uncomfortable because it means acknowledging upfront that the loop might not succeed. But that discomfort is exactly the forcing function you need. If you cannot define failure, you have not understood the problem well enough to automate it.
A good stop condition looks like: "exit after three consecutive failures on the same file, log which step failed and why, and surface the report." Not "keep trying until it works." Not "run until the token budget is gone."
A Practical Example: Design Token Validation Loop
When building the token system for this portfolio, I needed to validate that every design token file produced valid CSS output. The files were generated from a source-of-truth JSON, transformed through style-dictionary, and consumed by a PostCSS build. Any token value that failed resolution — a circular reference, a missing alias, a type mismatch — would silently produce broken CSS without an obvious error.
A shell script with a for loop would have caught most of it. But the failure modes were varied enough that I wanted the loop to retain context across iterations and adjust which checks it ran based on prior results. Here is what the structure looked like:
Goal: Every token file in /tokens/ resolves without errors in the CSS build. Measurable: zero stderr output from PostCSS. Zero broken var() references in the compiled output.
Context: List of token files. Current build error log. Which files passed on the previous iteration (so the loop does not re-check clean files).
Action: Run the CSS build against one token file. Capture stdout and stderr. Check the compiled output for unresolved var() references using a regex scan.
Verify: Did PostCSS exit with code 0? Does the compiled file contain any var(--token-name) references where --token-name is not defined in the same output? Both conditions must pass.
Memory: A running list of files that have passed. A list of files that have failed with their error signatures. A count of consecutive failures on the current file.
Stop condition: All files pass — exit with a success report. OR: three consecutive failures on the same file — exit with a failure report that names the file, the error type, and the iteration on which it first appeared. Do not continue past three failures. The problem needs a human at that point.
This loop ran cleanly. It found two circular references and one missing semantic alias that the build tooling was swallowing silently. None of those would have surfaced in a normal build run.
What Loop Engineering Is Not
It is not magic. It is not autonomous. It is not "AI doing your job." Every part of the loop — the goal definition, the context specification, the action granularity, the verify criteria, the memory schema, the stop conditions — requires a human to define it precisely before the first iteration runs. The loop executes the structure you built. It does not build the structure for you.
The automation buys you speed and consistency in the execution. It does not buy you insight into what to execute.
The Honest Question to Ask First
Before building a loop: would a shell script with a for loop do this?
If the answer is yes, write the shell script. It will be faster to build, easier to debug, and obvious to the next person who reads it. Reserve loop engineering for cases where the iteration needs to be stateful, where the verify step requires reasoning that exceeds what a static check can do, or where the stop conditions are complex enough to warrant explicit management.
The architecture earns its complexity when the problem genuinely requires it. Otherwise you are just adding ceremony to a for loop and calling it a workflow.