Why did our agent run for 40 minutes and produce nothing?
The agent has no step budget, no token budget, and no way to recognize it is stuck. A failing tool call stays in its context and keeps looking like a reasonable next try. The agent keeps trying variations of the same failed approach. Something external, such as a timeout or a human, finally stops it.
Also known as runaway agent, infinite tool-call loop
What does this look like in production?
- A run's duration or token spend is an order of magnitude above the median for the same task type
- The trace shows the same tool called repeatedly with slightly varied arguments and no forward progress
- The agent eventually times out or hits a platform limit rather than reaching a terminal state on its own
- Cost per completed task has a long, expensive tail that the average masks
Why does it happen?
An agent loop keeps calling the model with the accumulated transcript and executing whatever tool call comes back, until the model decides to stop. Without an explicit budget or progress check, nothing external forces a stop. The model has no reliable internal signal that six failed tries should mean give up or escalate. It tends to read that history as a reason to try again with slightly different arguments. The failed tool result sits in context looking like fresh information. The model reasons forward from it as if a new attempt might work.
This compounds because each attempt adds more failed context. The model keeps re-reading it and reasoning over it. The constraint that caused the failure never changes. Nothing in a typical agent harness distinguishes "still making progress" from "looping." Both look like ordinary next steps from the model's point of view.
How do you confirm it's this?
- Plot steps-per-run and token-spend-per-run as distributions, not averages, and look at the p99 relative to the median
- Count runs where the same tool is called with near-identical arguments more than twice in a row
- Check whether any run in your logs ended by timeout or platform limit rather than a model-issued terminal action
- Compare cost per completed task against cost per attempted task. A large gap means failed runs are eating budget without a matching signal
How do you fix it?
- Set a hard step and token budget per run
Cap the number of tool calls and total tokens a single run can use. Force a terminal state when the cap is hit: success, failure, or escalation. Do not let the loop continue indefinitely.
- Deduplicate identical or near-identical calls
Detect when the agent is about to repeat a call it already made with the same effective arguments. Short-circuit it and force a different strategy or a stop, so there is no silent retry.
- Terminate or escalate after N no-progress steps
Define what progress means for the task: new information or changed state. Stop the loop or hand off to a human once several consecutive steps show none.
- Record a terminal reason on every run
Every run should end with an explicit, logged reason (succeeded, failed, budget-exceeded, no-progress-timeout). You can then measure how often each reason fires without inferring it from raw duration.
What this doesn't cover
A long run is not always a broken one. Some tasks genuinely need many steps. Use this diagnosis when duration or cost is out of proportion to task complexity and the trace shows repetition without new information. A run that is merely slow does not qualify.
Sources
- Google - Implementing SLOs
The method for setting a service-level objective our release scoreboard follows. Retrieved 2026-08-24.
- Google - Error Budget Policy
The error-budget policy pattern our release gate borrows. Retrieved 2026-08-24.
A Ship Audit runs this full checklist against your actual system and hands back a written, prioritized plan.