An agent gets stuck in a loop when it keeps taking an action that doesn't change its state — a failing tool call, an oscillation between two positions, or a goal with no defined stop condition. You detect it by watching for repeated identical tool calls and flat state, then respond by capping iterations and escalating to a human or fallback path.
Quick Answer: Agent loops happen when there's no signal telling the agent it has failed or succeeded. Detect them by tracking call fingerprints and state deltas across turns; stop them with a hard iteration ceiling plus an automatic escalation path.
An agent that "won't quit" isn't a bug in the model — it's a gap in the spec. Language models don't have an innate sense of futility. If nothing in the loop tells them "this isn't working, stop," they will retry the same failing action with unshakeable confidence, sometimes for hundreds of turns, until a token budget, a rate limit, or a human notices the bill. This piece walks through why loops start, what to instrument so you catch them in minutes instead of days, and how to design the stop conditions that make the whole problem structurally smaller.
Why agents loop in the first place
Agents loop because the control logic driving them lacks a way to distinguish "still making progress" from "stuck," so they keep re-executing whatever action seemed reasonable last turn. There are three recurring root causes: a repeated failing action, an oscillation between two or more states, and a goal with no explicit stop condition. Each has a different fix, so diagnosing which one you're facing matters before you patch anything.
Repeated failing action is the simplest case. The agent calls a tool, gets an empty or error response, and — because its prompt tells it to "keep trying until you find the answer" — calls the exact same tool with the exact same arguments again. A search tool that returns zero results doesn't tell the agent to change its query; it just returns nothing, and the agent's only instruction is to keep searching. Five identical calls to the same search string is the textbook version of this failure.
Oscillation is subtler. The agent alternates between two or more states because each one looks locally better than the other from the model's immediate vantage point. A coding agent might repeatedly add a dependency, get a build error, remove it, get a different error, and re-add it — cycling rather than converging. Unlike the repeated-failure case, the tool calls aren't identical, so naive duplicate detection misses it; you need to watch the state trajectory, not just the call log.
No stop condition is the structural version of the problem. If the agent's goal is written as an open-ended aspiration ("find the best possible answer") rather than a testable condition ("stop when you've found three sources or made five search attempts"), the agent has no internal reason to ever declare victory or defeat. This is less a runtime bug and more a spec defect — see how to write an agent goal without drift for how to phrase goals so they're checkable rather than aspirational.
How the three causes differ
| Loop type | What repeats | Detection signal | Typical fix |
|---|---|---|---|
| Repeated failing action | Identical tool call + arguments | Call fingerprint matches N times in a row | Force query mutation or escalate after 2-3 identical failures |
| Oscillation | A small cycle of 2-4 distinct states | State hash reappears after a short period | Detect cycles, not just duplicates; break with a random perturbation or human check |
| No stop condition | Nothing specific — the agent just keeps working | Iteration count exceeds any reasonable task size | Add an explicit, testable stop condition to the spec |
Detection signals: what to actually instrument
You detect a runaway agent by tracking two things across every turn: whether the current action is a near-duplicate of a recent one, and whether the environment's observable state has changed at all. Neither signal alone is sufficient — duplicate detection misses oscillation, and state-change detection misses an agent that's technically doing "different" but equally useless things.
Track a rolling window of tool-call fingerprints. Hash the tool name plus its normalized arguments for the last 5-10 calls. If the same fingerprint appears more than twice in that window, you have a strong loop signal — this catches the "re-searching the same query five times" case directly, since the fifth identical call to a tool that already returned nothing is functionally certain to return nothing again.
Track state deltas, not just actions. After each tool call, diff the observable environment state (files changed, API response shape, page content, whatever the agent's world model tracks) against the prior turn. A run of three or more turns with zero meaningful state delta — regardless of whether the actions look different — is loop behavior even when duplicate-call detection stays quiet.
Watch for cycle periods, not just immediate repeats. Oscillation between states A and B looks like A-B-A-B, which a same-as-last-turn check won't catch. Keep a short state history (last 6-8 states) and check whether the current state matches one from 2-4 turns back; a repeating period is a cycle, independent of whether any single pair of adjacent turns looks identical.
- Identical-call counter: increments on exact fingerprint match, resets on a genuinely new call
- No-progress counter: increments on any turn with zero state delta, resets on real progress
- Cycle detector: flags when current state matches a state from N turns back, for small N
- Wall-clock / token budget tracker: a coarser backstop that fires even when the above three miss something novel
None of these signals require inspecting the model's internal reasoning — they're all observable from the outside, which is why they're cheap to bolt onto an existing agent loop without touching the prompt.
Responses: cap iterations and escalate, don't just detect
Detecting a loop is only useful if something happens next, so every agent needs a hard iteration ceiling and a defined escalation path for when a loop signal fires. The response should scale with confidence: a soft signal nudges the agent to try something different, while a hard signal stops execution and hands off to a human or a fallback.
- Set a hard iteration cap per task, sized to the task's realistic complexity — not a global default reused everywhere. A lookup task might cap at 5 turns; a multi-step research task might reasonably need 30. An unbounded "keep going until done" instruction is the single most common way a stop condition gets skipped.
- On the first loop signal, nudge before you kill. If the identical-call counter hits 2, inject a system message forcing the agent to change its approach — reformulate the query, try a different tool, or explicitly state what it will do differently. This resolves a meaningful share of loops without human involvement.
- On a second or persistent signal, escalate rather than retry again. Escalation can mean pausing for human review, falling back to a simpler deterministic path, or returning a clear "I couldn't complete this, here's what I tried" response instead of a fabricated answer.
- Log the full trace on escalation, not just the final state — the sequence of fingerprints and state deltas that triggered the loop detector is exactly what a human needs to diagnose whether the tool, the prompt, or the goal was the actual defect.
- Treat repeated escalations on the same task type as a spec signal, not a one-off. If the same tool keeps triggering loop detection across many runs, the fix belongs in the agent's spec or its tool access, not in another prompt patch. This is where least-privilege agent tool access matters — an agent with too many overlapping tools has more ways to oscillate between "equivalent" options that all look plausible.
Detection response matrix
| Signal strength | Example | Response |
|---|---|---|
| Soft (1 duplicate call) | Second identical search in a row | Log it, no action yet |
| Medium (2-3 duplicates or no state change for 3 turns) | Third identical search, or 3 turns with no file changed | Inject a forced-variation instruction |
| Hard (iteration cap reached, or cycle detected 2+ times) | 5th identical search, or A-B-A-B repeating | Halt, escalate to human or fallback |
Designing loops out at the spec stage
The cheapest place to fix a runaway loop is before the agent runs at all, by writing testable stop conditions and iteration budgets directly into the spec rather than patching them in after a production incident. A spec that says "search until you find relevant results" invites exactly the failure mode this article is about; a spec that says "search up to 3 times with query variation, then report what you found" does not.
This is one reason the five-part agent spec structure treats stopping conditions as a first-class section alongside goal, tools, and guardrails — not an afterthought bolted on after a goal statement. If you're new to structuring agent specs at all, the complete guide to agentic workflows covers where stop conditions sit relative to the rest of the design.
Writing a good stop condition is itself a design skill, not just a number. A useful stop condition is:
- Testable, not aspirational — "3 failed attempts" beats "reasonable effort"
- Specific to the task's real complexity — a data-lookup agent and a multi-step research agent shouldn't share one default cap
- Paired with a defined failure output — what the agent says when it stops without succeeding matters as much as when it stops
- Reviewed against the tool's actual failure modes — if a search tool sometimes needs retries with different phrasing to succeed, don't cap at 1 attempt and call it thorough
Framing this well also borrows from adjacent PM disciplines: understanding what "done" looks like for the underlying task is a jobs-to-be-done exercise as much as an engineering one, and mapping where an agent's failure would land in a user's broader experience is exactly the kind of thing a customer journey map is built to surface.
Catching runaway loops before they reach production
Loop detection built at runtime is a safety net; the spec is where the real fix lives, because an agent designed with explicit iteration limits tied to its stop conditions never needs the safety net to fire in production. Prodinja's Agentic Workflows tool ties iteration limits directly to the stopping conditions defined in the spec, so a "won't quit" failure mode is something you catch while designing the agent, not something a monitoring dashboard flags after it's already burned a budget in production. It's designed to walk you through defining those limits as part of the spec itself, not as a separate afterthought layered on after the agent is already running.
That doesn't replace runtime monitoring — a well-specified agent can still hit an unanticipated tool failure — but it does mean the most common category of loop, the one caused by an unspecified stop condition, gets caught at design time instead of discovered by an on-call engineer.
Key Takeaways
- Loops have three distinct root causes — a repeated failing action, an oscillation between states, and a missing stop condition — and each needs a different detection approach.
- Duplicate-call fingerprints catch repeated failures, but miss oscillation; you also need state-delta tracking and cycle detection over a short history window.
- Detection without response is incomplete — pair every loop signal with a graduated response: nudge on a soft signal, escalate on a hard one.
- Iteration caps should scale with task complexity, not use one global default across every agent in your system.
- The cheapest fix is at the spec stage — a testable stop condition written into the agent's goal prevents most loops before the agent ever runs.
- Repeated escalations on the same task type are a spec signal, not something to patch away with another prompt tweak.
Frequently Asked Questions
How do you know if an AI agent is stuck in an infinite loop?
Watch for identical tool calls repeating within a short window and for the environment's observable state staying flat across several turns. If either persists for more than 2-3 turns, or a state repeats in a short cycle, treat it as a loop rather than normal iteration.
What causes an agent to keep retrying the same failed action?
Usually the agent has no signal that the action failed meaningfully — a tool returns an empty result instead of an error, or the agent's instructions say to "keep trying" without specifying how many times or what to change. Without a testable stop condition, retrying looks identical to making progress from the model's perspective.
What's the difference between agent loop detection and just setting a timeout?
A timeout is a coarse backstop that eventually stops any runaway process, but it doesn't tell you why the agent got stuck or let it recover gracefully. Loop detection — tracking call fingerprints and state deltas — catches the problem earlier and can trigger a nudge or a clean escalation instead of an abrupt cutoff.
How many retries should an agent be allowed before escalating?
There's no universal number — it depends on the task and the tool's real failure modes, but 2-3 identical attempts before forcing a change of approach, and a hard cap sized to the task's realistic complexity, is a reasonable starting point. A single global cap reused across very different agent types tends to be too tight for some and too loose for others.
Can prompt engineering alone fix runaway agent loops?
Prompt changes can reduce some loops, but they can't replace an explicit, testable stop condition and an iteration cap, because the model has no external mechanism to enforce a limit it wasn't given. Structural controls — call-fingerprint tracking, state-delta checks, hard caps — catch what prompt wording alone reliably misses.