What a Stuck Agent Loop Looks Like From the Outside
Monitoring for uptime misses the expensive loops that complete successfully but waste resources.
Correspondent · · 3 min read · Updated

# What a Stuck Agent Loop Looks Like From the Outside
The dashboard showed the agent as healthy. Requests were completing. Latency was normal. Cost per request had crept up by a factor of six, and the reason took a while to find because nothing about the failure looked like a failure — it looked like a slightly more expensive success.
## A stuck loop doesn't crash, it just spends
The agent's task loop called a research tool, evaluated whether it had enough information, and either answered or called the tool again with a refined query. For a narrow class of ambiguous questions, the refinement step produced a query that was semantically different from the previous one but retrieved functionally the same results — close enough that the "do I have enough information" check kept saying no, different enough that a naive duplicate-query check didn't catch it. The agent would cycle through six, eight, sometimes eleven research calls before something in the accumulated context finally tipped the evaluation to yes, or a hard iteration cap kicked in and forced an answer.
From the outside, this produces a completed request, a correct-looking answer, and a cost and latency number that's an outlier without being an error. Nothing throws. Nothing logs a failure. The only signal is a distribution shift in a number nobody was watching per-request, because per-request cost variance is exactly the kind of thing that gets averaged away in a dashboard built to show system health, not task-level efficiency.
## The metrics that catch this aren't the ones built for uptime
Standard reliability monitoring — error rate, latency percentiles, availability — is built around the assumption that a bad outcome looks different from a good one. A stuck-but-eventually-completing loop breaks that assumption completely. It needed a metric nobody had originally instrumented: tool-calls-per-completed-request, tracked as a distribution rather than an average, so a long tail of expensive-but-successful requests would show up as a shape change rather than get smoothed into a mean that still looked fine.
Once that metric existed, the stuck-loop pattern was visible immediately as a second hump in what should have been a tight, low distribution. It had almost certainly been happening for weeks before anyone noticed, because "average tool calls per request" — the number that had been tracked — barely moved. A small percentage of requests eating eleven calls each doesn't move an average much. It moves a tail, and averages don't show tails.
## Fixing the loop meant giving it a way to notice itself
The actual fix wasn't a tighter iteration cap — that just converts a slow, expensive success into a fast, wrong failure once the cap is hit before real convergence. It was giving the "do I have enough information" evaluation access to a similarity check against its own prior queries, so that a refinement producing near-duplicate results would be recognized as non-progress and trigger a different strategy — broadening the query instead of narrowing it again — rather than another iteration of the same unproductive move.
The broader lesson sits uncomfortably with how most agent monitoring gets built: uptime and error-rate dashboards are designed to catch the failures that look like failures. A loop that burns budget while still returning a correct answer will sail through every one of those checks clean. The only way to catch it is to instrument for cost and iteration count as first-class signals before you need them, because by the time a stuck loop is expensive enough to show up in a monthly bill, it's been running silently for a long time.

