Loop engineering turned up fast. Addy Osmani named it in June, pulling together threads from Boris Cherny at Anthropic and Peter Steinberger, and O'Reilly republished it within weeks. The idea is simple enough to explain in a sentence: you stop being the person who prompts the agent, and you become the person who designs the system that prompts it. The agent acts, looks at what happened, reasons about it, and goes again, until it hits a target or fails a check.
The models got good enough to run for hours without a human turn, so the bottleneck moved. It is no longer capability. It is orchestration.
Most of the writing that has followed is about the machinery of orchestration: worktrees so parallel agents do not collide, hooks and schedules so the loop runs without you, sub-agents so the thing that writes the code is not the thing that grades it, and MCP so the agent can reach your tools. That machinery is real and it works. But it is all plumbing around one line that almost nobody is examining.
In Osmani's own example, you hand the loop a goal that reads something like this:
Then you walk away.
That line is the exit condition. It is the only thing standing between "the agent worked for six hours" and "the agent worked for six hours on the right thing".
A loop converges on whatever you can measure
This is the part that should worry you, and it is not really an AI problem. It is an old one. Any system that optimises against a measure will move towards the measure, and if the measure is a proxy for what you actually want, the system will find the gap between the two and settle in it.
A single agent turn does not have time to exploit a weak check. A loop has all night.
Give a loop "the suite is green and the linter is quiet" and it will get you there. That check is genuinely useful: it proves the code compiles, runs, and does not obviously fall over. What it cannot tell you is whether the software does the thing you wanted. Those are different questions, and only one of them is being asked.
So the failure mode of loop engineering is not the loop crashing. A crashed loop is cheap, because you can see it. The failure mode is a loop that runs perfectly, satisfies every check you gave it, reports success, and hands you software that is confidently, thoroughly wrong. It is wrong in a way that no test catches, because the tests were never asked the question. You find out in review, if you are still reading the diffs, or in production, if you are not.
The tests are not the specification, unless someone wrote one
The obvious answer is: fine, write better tests. Make the exit condition richer. Have the agent generate the tests too.
That last one is where it quietly comes apart. If the agent that misunderstood the requirement also writes the check for the requirement, it will encode its misunderstanding on both sides and then pass. The loop validates itself against its own reading of the task. Everything goes green. This is exactly why loop engineering separates the maker from the checker, and it is right to. But the separation only buys you anything if the checker is grading against something the maker did not invent. Two agents that share a premise are one agent with extra steps.
So the intent has to enter the loop from outside it. Which means someone, at some point, has to have stated what correct means, in a form precise enough for a machine to check against.
That statement is a specification. It does not become one because you called it that, or because it lives in a particular tool. It is a specification the moment it is the thing the loop is measured against. Every loop already has one. The only question is whether it was written deliberately, or whether it is an accident: a half-sentence in a Linear ticket, a test file the agent wrote last Tuesday, or the tacit assumption that whatever the model inferred from the prompt was probably close enough.
What the exit condition actually needs
If the exit condition is where intent lives, it has three properties worth being deliberate about.
It has to state intent, not just execution. "The suite is green" is a property of the code. "A user with an expired token gets a 401 and no data" is a property of the product. The second one can be checked and can be wrong, which is what makes it worth having. The first can only be green.
It has to survive between runs. Osmani is blunt about this: the model forgets everything between runs, so the memory has to be on disk. The loop starts from nothing every cycle. If the definition of correct only ever existed in the prompt you typed at 9am, it is gone by the second iteration, and the loop is now optimising against whatever it can still see, which is the tests.
It has to be maintainable by the person who knows the intent. This is the one that gets missed. The people who know what "correct" means for a payments flow are frequently not the people who will open a repository and edit a markdown file, and the reasoning behind a decision six months ago is not in the codebase at all. If the only durable place to record intent is inside the repo, then intent is only recorded by the people who live in the repo, and the loop inherits whatever they happened to understand.
Put those together and you get something with an unglamorous name. It is the specification: what the software is meant to do, why it was decided that way, and how you will know it works. Loop engineering has not made that less important. It has made it the input to an automated process that will run for hours against it without asking a follow-up question.
Where this lands for us
This is the bet Specsource is built on, so read the next paragraph with that in mind.
We keep three connected things: features, which state what the software is meant to do; decisions, which record why it was built that way and what was rejected; and tests, which say how you will know. They are structured records, they persist, and they are editable in a browser by anyone with an opinion worth capturing, including the people who will never touch the repository. An agent pulls them through our MCP server, so a loop can fetch the intent for the feature it is working on at the start of every cycle, rather than re-deriving it from the code it is about to change.
None of that removes the need for judgement, and I do not want to pretend it does. It moves where the judgement goes. Instead of reviewing the output of a loop that ran overnight, you spend the time on the thing the loop was pointed at, which is a much better place for an hour of an architect's attention. It is the same reason the code is now the cheap part: the durable asset is the articulated intent, and the loop is just the fastest consumer of it we have built so far.
The honest version of the risk
Osmani has a phrase for the failure I am circling: cognitive surrender. When the loop runs itself, it becomes very tempting to stop having an opinion and take whatever it gives back. His summary is the sharpest line in the piece, and I will not improve on it: designing the loop is the cure when you do it with judgement, and the accelerant when you do it to avoid thinking. Same action, opposite result.
The exit condition is where that choice is actually made. It is the last place a human states what correct means before handing the keys to something that will run for hours without asking. Writing it carelessly is not a small shortcut. It is the shortcut, and everything the loop does afterwards is downstream of it.
So by all means build the loop. Just be able to answer, out loud, what it is checking itself against, and who wrote that down.