Curriculum › Agentic Architecture & Orchestration · 27% of the exam

Agentic loops and termination conditions

What you'll be able to do

  • Name the three kinds of termination condition a production loop needs
  • Explain why a structurally verifiable done-signal beats a text heuristic
  • Set a max-iteration cap that fails safe instead of failing silent
  • Decide when a bounded loop is the right call instead of an open-ended agent

What you’ll be able to do

  • Name the three kinds of termination condition a production loop needs
  • Explain why a structurally verifiable done-signal beats a text heuristic
  • Set a max-iteration cap that fails safe instead of failing silent
  • Decide when a bounded loop is the right call instead of an open-ended agent

What you need to know

An agent loop is a liability until you’ve bounded it

Mechanically, an agent loop is nothing exotic: call the model, execute whatever tool it asked for, feed the result back, call the model again, repeat until it stops asking for tools. That mechanism has no opinion about when to stop. Left alone, it will keep going as long as the model keeps producing tool_use blocks — which a confused model can do indefinitely.

At developer scale this is a bug. At architect scale it's a class of incident: a loop that doesn't terminate burns tokens, burns wall-clock time, and if any tool call has a side effect, burns real-world state on every extra pass. The job of an architect is to design the boundary before the loop ships, not to discover it in a bill.

Three termination conditions, not one

A production loop needs all three of these, because each one catches a different failure:

  • A success condition — a specific, checkable signal that the task is actually done. Not "the response looks complete," but a structural marker: a particular tool was called (submit_answer()), a particular field was populated, a schema validated.
  • A ceiling — a hard cap on iterations, tokens, or wall-clock time, independent of whether the model thinks it's done. This is the fallback for when the success condition never fires.
  • A cost/side-effect guard — a limit on how many times a side-effecting tool (one that sends an email, writes a row, calls a paid API) can fire within one loop, separate from the general iteration cap.

Shipping only the first is the most common gap. The success condition handles the happy path; the ceiling is what protects you when the model gets stuck in a retry-and-fail cycle it can't see its own way out of.

The done-signal has to be structural, not textual

before — termination inferred from prose
if "the report is complete" in response.text.lower(): stop_loop()
after — termination is a structural event
if last_tool_called == "submit_report" and report_schema.validate(tool_input): stop_loop() elif iterations >= MAX_ITERATIONS: stop_loop(reason="ceiling_reached") flag_for_review()

A text heuristic breaks the moment the model phrases things slightly differently, and it can be satisfied by a model that just says it's done without having actually produced a valid result. A structural signal — a specific tool call, a schema that validates — can't be talked past.

When a bounded loop beats an open-ended agent

Not every task should get an open-ended agent loop at all. If the shape of the work is fixed and enumerable — the same five steps every time, in the same order — a bounded loop (or a plain workflow) is more reliable and cheaper to reason about than letting the model decide the path on every run.

Reach for an open-ended loop when the number of steps genuinely can't be known in advance — the model has to explore, and how far it goes depends on what it finds. Reach for a bounded structure when you already know the steps and just need the model to fill in judgment at each one. Architecturally, this is a cost and reliability decision as much as a capability one: an unnecessary open-ended loop pays for flexibility you never use.

Key concept

A loop with no hard stop isn’t flexible — it’s unbounded liability. Design the termination condition before the loop, and make the done-signal something a schema can check, not something a human has to read.

When a scenario describes a runaway cost or an agent that "just kept going," the fix is almost never a smarter prompt — it's a missing ceiling.

Practice scenario

ScenarioA research agent is meant to stop once it has enough sources to answer a question, but on some runs it keeps searching for 40+ iterations before a support engineer manually kills it.
Work it through, then open this

The loop is missing a ceiling, not a smarter stop-prompt. “Enough sources” is a judgment call the model can defer indefinitely if nothing forces a decision. Add a hard iteration cap that forces a “submit with what you have” tool call once reached, and make the actual success condition a structural one — a specific submit_findings tool call with a minimum source count — rather than the model’s own sense of sufficiency.

Build exercise — Add a real termination boundary to a loop

Intermediate · 25 min

What you’ll learn

  • Separating a success condition from a ceiling
  • Making a done-signal structurally checkable
  • Designing a safe-fail path for when the ceiling is hit
  1. Take an existing or hypothetical agent loop and write down its current stop condition in one sentence.

    • Why: Most loops have an implicit stop condition nobody wrote down, which is why it’s easy to miss that it’s just “the model decided.”
    • You should see: Either a structural condition already in place, or a gap where the loop relies on the model’s own judgment with no fallback.
  2. Add a hard iteration ceiling and a defined behavior for what happens when it’s hit — not just “stop,” but “stop and do X” (flag for review, return partial results, alert).

    • Why: A ceiling that just halts execution silently is only half a fix; someone or something needs to know it fired.
    • You should see: A named fallback path, not a bare stop.
  3. Replace any text-based completion check with a structural one — a specific tool call or a schema validation.

    • Why: Text heuristics are the most common source of loops that never terminate cleanly.
    • You should see: A condition that a unit test could assert on, not one that requires reading model output.

Exam traps

Trusting the model to decide when it’s done with no enforced fallback

Works until the one run where it doesn’t, and there’s nothing else in the design to catch it.

Treating “the text looks finished” as a termination signal

Text heuristics can be satisfied by a model that says it’s done without having done it. Use a structural signal instead.

Setting max_iterations low enough to silently truncate real work

A ceiling that fires on legitimate tasks looks like a bug in the model when it’s actually a bug in the cap.

Building an open-ended agent for a task with a fixed, enumerable shape

If you already know the steps, a bounded structure is cheaper and more reliable than paying for exploration you don’t need.

Logging a runaway loop instead of stopping it

Observability tells you it happened after the cost is spent. The ceiling is what prevents the cost in the first place.

Sources

Quick check

An agent loop is designed to stop once the model "decides the task is complete," with no other exit condition. What is the architectural risk?