Designing the Agent Loop
An agent is a loop of turns, tool calls, and results - not a single request. This is where the product became meaningfully agentic. The important change was not that the model produced more text; it was that the system could take an action, observe what actually happened, and use that evidence to decide the next action.
- Model turns, tool calls, results, and continuation
- Why the agent is a loop rather than an API request
- Provider-neutral orchestration
- Parallel variants versus multiple collaborating agents
The situation
A single model call could produce code, but it could not inspect its own output, run it, or react to a failure. In Designing the Agent Loop, I wanted to capture the real operating situation rather than describe the problem in abstract terms. What mattered to me was the moment the existing approach stopped being sufficient in normal use, because that was usually the point where the next architectural requirement became obvious.
The naive solution
Wrap the model call in a bigger prompt and hope one shot gets closer to correct. The naive option was attractive precisely because it was faster and easier to explain. I could have pushed further in that direction and probably improved the demo, but it would have optimised the visible symptom rather than the underlying system constraint.
The hidden constraint
Some failures (a missing dependency, a broken import) are only discoverable by executing the code, which a single request-response call cannot do. This constraint was easy to miss early because it did not show up in the first successful run. It appeared once the workflow had to survive repetition, failure, another user, another provider, or a return visit, which is why I now look for these second-order requirements much earlier.
The decision
Model the agent as a loop: reason, call a tool, observe the result, continue reasoning, until the task is complete or the user intervenes. I treated this as an architectural or product decision rather than a prompt tweak. The aim was to create a boundary I could reason about later, instead of relying on model behaviour to remain consistent as providers, templates, and user requests changed.
The implementation
Built an agent runner that streams turns, tool starts, and tool results over WebSockets, with each generation variant running as an independent execution, optionally against a different provider. I also tried to make the implementation concrete enough that the decision could be inspected in code and runtime behaviour. That meant explicit state, explicit policy, and observable transitions rather than a collection of hidden assumptions spread across prompts and handlers.
The tradeoff
More moving parts (event streaming, cancellation, state per variant) than a single blocking API call. I did not treat the decision as free. In most cases I was deliberately accepting more engineering, state management, or operational complexity in exchange for a smaller failure surface and a product that could survive realistic use.
The evidence
Multiple model providers could generate variants of the same brief in parallel, and the interface could show per-variant progress and errors independently. I use this evidence as a practical signal, not as a claim that the architecture is universally correct. The useful question was whether the new design changed what the system could reliably do under the conditions that had previously broken it.
The reusable lesson
If your task requires inspecting the result of an action before deciding the next action, you need a loop with tools, not a bigger prompt. The part I would carry into another build is the decision rule behind the implementation, not the exact technology choice. Vendors and frameworks will change; the underlying question about state, control, isolation, feedback, or user trust is much more reusable.
The consultant's questions
- Does this task actually require multiple turns, or is a single well-structured call enough?
- Is your orchestration layer coupled to one model provider, and what would it cost to add a second?
- What assumption in this part of the system would become dangerous if usage or tenant count increased?
- What evidence would tell me this decision needs to be revisited rather than defended indefinitely?