Loop Engineering Is a Pattern, Not a Feature
This site uses cookies to understand how visitors find us.<br>You can accept or decline non-essential cookies.
Decline<br>Accept
Menu
manifesto<br>docs<br>blog<br>roadmap<br>registry
GitHub
Discord
install.sh
Yesterday everyone was doing agentic map-reduce. Today everyone is doing loop<br>engineering. Tomorrow someone will be selling you the next big thing, and the<br>price of admission will once again be your money and your architecture.
Here’s the cycle in the AI infrastructure world in 2026, in case you’ve<br>managed to miss it: a useful technique emerges from practice, gets a name,<br>and within a few weeks there are a dozen products where that technique is<br>the feature. Each product is a walled garden with its own way of doing<br>things, its own configuration structure, its own opinions about what you can<br>and cannot do. And to get the technique, you adopt the garden.
Doing this around loops is especially bold, because a loop is about as<br>basic as programming constructs get. An agentic loop is: call a model, look<br>at what came back, decide whether to go around again. That is not a product<br>category! That is a while statement.
With iii, loop engineering is something you implement from a pattern, not<br>a feature or a product that you have to buy or adopt net-new.
This post shows what that looks like.
The turn orchestrator, and the trouble with agentic orchestration
The centerpiece of every loop-engineering solution is the turn<br>orchestrator: the thing that runs a turn of the loop and exposes lifecycle<br>hooks, such as on turn start, on tool call, on turn complete. These hooks are<br>key places where you attach your own logic.
There are multiple ways to implement the orchestration layer. Harnesses like<br>Claude Code and Codex are fully agentic, meaning the AI model decides<br>everything on every turn. If the model is the decision-maker for every<br>single loop, that means a lot of LLM calls, resulting in latency and cost,<br>but most importantly a degree of variance in the results it produces.
LLMs are probabilistic. Imagine that you have a workload where the model is<br>scanning a bunch of files for security vulnerabilities. To know that you’re<br>done processing all files, you may need to compare the list of processed<br>files with the list of all files, and see if the lists are identical. Now,<br>ask one of the current flagship LLMs whether two lists of files are<br>identical, and sometimes you’ll get the correct answer — but some of the<br>time the answer will be wrong. As a result, an LLM-orchestrated loop that<br>relies on file list comparisons may finish too early, or too late, or not at<br>all. Not ideal!
For open-ended work, using LLM as a turn orchestrator may be an acceptable<br>solution because the benefits, such as the LLM being able to judge a fairly<br>broad set of criteria to know whether a turn is done or not, outweigh the<br>possible mistakes.
But the vast majority of the work being orchestrated won’t be so open-ended<br>— it will be numerical and mechanical and rather straightforward. In such<br>scenarios using an LLM to evaluate whether a loop is over is wasteful,<br>expensive, slow, and inconsistent.
An alternative to fully agentic orchestration
We already have something that’s better than an LLM at judging inputs with<br>consistency, speed, low cost, and high accuracy: functions!
You don’t have to use an LLM as a turn orchestrator 100% of the time.<br>Despite what the currently most popular harnesses may have led you to<br>believe, it is OK to not be fully agentic all the time.
In fact, most turn orchestration doesn’t need an LLM and instead are<br>better off as a simple function.
Following a file list example from above: if, in order to know whether you<br>are done, you need to compare two lists of files and tell whether they are<br>identical — most programming languages already have a suitable pattern in<br>their standard library. Sort and compare. One or two function calls,<br>superfast, basically free, and correct every time.
Orchestrating a turn with triggers and functions in iii
For the readers new to iii: it is an unreasonably simple approach to<br>software engineering. In iii, everything is a Worker, a Function, or a<br>Trigger.
I used the iii harness, which works directly with these iii primitives, to<br>set up a workflow that scans a GitHub repository for security<br>vulnerabilities.
If I were using the LLM-driven orchestration that’s standard for other<br>harnesses on the market, this would have generated extra LLM calls for each<br>turn and added cost and latency. But in this example, iii uses a function to<br>tell whether a turn is complete.
I started with this prompt:
Scan a GitHub repository for real security vulnerabilities and give me a live dashboard of the results.
Repository and sub-tree: https://github.com/wonderwhy-er/DesktopCommanderMCP/tree/main/src/handlers
Work out how to do this with whatever workers and coordination you have available — I'm describing the outcome, not the implementation.
Outcomes I want:
Cover the...