Skip to content
Published on

Loop Design — Between Infinite Loops and Giving Up Early

Share
Authors

The agent that repeated the same call forty times

Imagine a transcript, from a harness with no retry cap, in which an agent tries to read a nonexistent file forty times in a row. It is a constructed example, but the assembly is realistic. The failure comes back as a raw exception string, so the model does not know the cause; not knowing the cause, it repeats the same attempt; with no cap, nothing stops it. The opposite failure exists too. A harness with zero retries throws away a task it could have finished over one transient network error.

The goal of loop design is to cut a path between these two cliffs. How much to retry, on what grounds to stop, and where to raise things when stuck. All three are harness decisions deployed as code.

The loop is the heart of the harness

Borrowing the distinction from Anthropic's agent-building guide, an agent is a system in which the model decides its own next action based on feedback from the environment. The loop is why the guide recommends agents for open-ended problems whose steps cannot be predicted, and why it warns that costs grow and errors can compound. Tool results provide ground truth at every step, but how that ground truth is consumed is up to the harness.

The same guide recommends explicit stopping conditions, such as a maximum number of iterations. It sounds like obvious advice, but operations usually break at exactly this obvious layer. The more freedom the loop has, the more the stopping rules become the safety valve of the system.

The retry cap: neither zero nor infinity

A retry is a purchase whose value depends on the kind of failure. For transient failures, a few retries buy the task back cheaply; for structural failures, every retry is wasted money. The problem is that the model often cannot make that distinction on its own. The failure return format from part 3 reappears here. In a harness that returns causes and alternatives, a retry becomes exploration of a different path; in a harness that returns only exception strings, a retry is a repeat purchase of the same failure.

So the order matters. Raise the cap before fixing the failure return, and what you get is a loop that circles the same spot at higher cost. As for the cap itself, the safe move is to start low, matched to the volatility of the task, and raise it only when evidence arrives.

Three stopping conditions: fixed steps, goal checks, confidence

Stopping rules come in three families. Fixed steps end the run after a set count. Free to implement and budget-predictable, but it holds on to finished tasks and lets go of unfinished ones. A goal check writes the stopping condition as code: stop when the tests pass, when the artifact satisfies the schema. The loop stops leaking, at the upfront cost of having to state the goal in verifiable form. Confidence-based stopping asks the model how sure it is and stops on that value.

MAX_STEPS = 20  # tune to task complexity

for step in range(MAX_STEPS):
    action = model.next_action(context)
    if action.kind == "finish":
        if goal_check(workspace):  # write the stopping condition as code
            break
        context.add("goal_check failed: 2 tests are still red")
        continue
    context.add(run_tool(action, retries=3))
else:
    escalate("step cap reached", summary=context.progress_note())

The three families are not exclusive. The safe combination in practice is a goal check as the primary stopping condition with fixed steps as the outer safety valve.

The trap in confidence-based stopping

Confidence stopping is attractive. No goal has to be written as code, and it is fast and cheap. The trap sits exactly there. Self-reported confidence is an utterance, not a verification, and a model can be confidently wrong. In that case the loop terminates normally while holding a wrong answer — the worst kind of failure, the kind that never shows up in the record as a failure.

If you use confidence, the safe move is to change its role: a routing signal, not a stop signal. Low confidence becomes a trigger to run one more round of cheap verification or to raise the case to a human, while the stopping itself is decided by a verifiable goal check. Confidence is a reference input, not the judge.

Escalation: stuck should not mean done

When a stopping condition fires and the task is unfinished, you need a next destination. If there is none, the progress so far simply evaporates. There are two destinations. One is a human — and the value there comes from the specificity of the question. Not "I am stuck" but "which schema is correct, A or B", with a progress summary and options attached, so that one human answer restarts the loop. The other is a subagent: throw away the polluted context and have the subproblem solved again in a clean window — which, as part 2 showed, carries a serious token cost.

Anthropic's multi-agent system retrospective lists the failures of this layer concretely: agents over-investing effort in simple queries, endless searches, duplicated work. The prescriptions are also loop-side: scale effort to the complexity of the query, and when delegating, state the objective, output format, and task boundaries. Escalation is not exception handling; it is a standard part of loop design.

Practice it yourself

Tier 3 of the harness engineering RPG, "Loop design", is the exercise for this post. Combine the four retry policies from none to unbounded, the three stopping conditions, and the three escalation paths, and you will meet both the scenario where confidence stopping wins cheaply and the one where it ends confidently wrong.

References

  • Building effective agents — Anthropic, 2024-12-19 — the definition of agents as systems that proceed on environmental feedback, the advice to use them for open-ended problems, the cost and compounding-error warnings, and the recommendation of stopping conditions such as a maximum number of iterations are in this post.
  • How we built our multi-agent research system — Anthropic, 2025-06-13 — loop failures such as over-investment in simple queries, endless searches, and duplicated work, and the prescription of explicit task boundaries, are in this post.
  • The forty-repeats story at the top and the loop code in the body are constructed for explanation.