An AI agent is not magic. Strip away the frameworks and every agent is the same shape: a loop. The model thinks, picks a tool, calls it, reads the result, and thinks again. Think, act, observe, repeat.
The loop is simple to write. We wrote one in about 220 lines of standard-library Python, no framework, no API key, fully offline. The interesting part is not the loop. It is what keeps the loop from hurting you.
Where loops go wrong
A loop with a model inside it fails differently from ordinary code:
- It can spin. The model keeps choosing the same failing tool, forever, at per-token prices.
- It can thrash. A flaky tool times out, the model retries instantly, the retries hammer the tool, and the failure gets worse.
- It can wander. With no budget, a ten-step task quietly becomes a ninety-step task, and nobody notices until the bill or the latency graph arrives.
None of these are model problems. They are loop-design problems, and they have loop-design answers.
The three controls
Our demo loop ships with three controls, because production loops need all three:
1. A step budget. The task gets a maximum number of tool calls (12 in the demo). When the budget runs out, the loop stops and reports partial progress instead of pretending. A budget turns an infinite failure into a bounded, observable one.
2. A per-tool retry budget with backoff. A flaky tool gets a small number of retries (3 in the demo), spaced out. Retries absorb transience; the cap prevents a retry storm. In the demo's healthy run, the flaky tool fails twice and succeeds on its third attempt, inside its budget, and the task completes in 4 tool calls.
3. A circuit breaker. If a tool keeps failing in the same way, the breaker trips and the loop stops early rather than burning the whole step budget on a dead end. In the demo's stuck run, the breaker trips at step 3 of 12. The loop fails fast, loudly, and cheaply, which is exactly what you want at 2 AM.
What to notice when you run it
Run the demo both ways. The healthy task shows the boring path: budget barely touched, one retry absorbed, done. The stuck task shows the design working: the breaker, not the budget, is what ends it, and the log tells you which tool failed, how many times, and why the loop stopped.
Then change one number at a time. Raise the retry budget and watch the stuck task get slower to fail. Remove the breaker and watch it burn all 12 steps. The lesson lands because you caused it.
The production version
In a real system, the same three controls exist, with better tailoring: budgets per task type, retries with jitter and idempotency keys, breakers per tool with half-open probes, and every loop iteration traced so a runaway is visible in minutes, not invoices. Frameworks will sell you the loop. The controls are the engineering, and they are yours to design.
The rule this project keeps proving, across our whole Agent Engineering track: autonomy is earned per action, not granted per agent. A loop you can bound is a loop you can trust.
AI School 369 · Production AI, explained simply.
From Layer by Layer, our free newsletter: one concept, one working project, every Tuesday and Friday.
Subscribe free: layer-by-layer.kit.com · Run the projects: GitHub
Shekar Kaki