The agent loop is: model produces a tool call, you execute it, feed the result back, repeat until it stops. The termination condition is the model deciding it is done. That is not a termination condition — it is a hope.
The loops that do not terminate
A search tool returns nothing, so the model rephrases and searches again. And again, with slight variations, indefinitely. Or two tools disagree and it alternates between them trying to reconcile. Or a transient API error comes back as a result rather than an exception, and the model retries it forever.
None of these look like bugs in testing, where inputs are well-formed and tools work.
Three ceilings, all mandatory
Iterations. A hard cap on turns through the loop. Ten is generous for most tasks. Hitting it is a failure with a clear reason, not a slow crawl.
Tokens. Cumulative across the conversation, including tool results, which are usually what actually blows the context. Cap it and fail cleanly rather than discovering the limit as a provider error mid-task.
Wall clock. Everything above can pass while a single tool hangs. A deadline for the whole interaction, checked before each step.
budget
max_iterations 10
max_tokens 120_000
deadline_ms 45_000
max_cost_minor 500
Check all four before every step. Exceeding one ends the run with a specific reason recorded.
Detect the spin
Cheaper than any of the above and catches the common case: hash each tool call with its arguments. The same hash twice in a row, or three times in a window, means the agent is stuck. Break the loop and escalate.
Most non-termination is literally the same call repeated. You do not need loop detection theory, you need a set.
Failing is a product decision
When a budget is hit, what the user sees matters. “I could not complete this — here is what I tried and who to contact” is a usable outcome. A timeout, a spinner, or a truncated half-answer is not.
Record which budget was hit and on what input. That table is the backlog: repeated iteration-cap hits on one query shape usually means a tool is returning something the model cannot use, which is a fixable bug rather than a limit to raise.