CustomLabs
Agents & tools

Why did our agent run for 40 minutes and produce nothing?

Updated First published

Markdown

Answer

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

Symptoms

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
Root cause

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.

Detect

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
Fix

How do you fix it?

  1. 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.

  2. 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.

  3. 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.

  4. 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.

Limits

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

  1. Google - Implementing SLOs

    The method for setting a service-level objective our release scoreboard follows. Retrieved 2026-08-24.

  2. Google - Error Budget Policy

    The error-budget policy pattern our release gate borrows. Retrieved 2026-08-24.

Not sure if this is the one?

A Ship Audit runs this full checklist against your actual system and hands back a written, prioritized plan.

Book a Ship Audit →

Source: https://customlabs.io/failure-modes/unbounded-agent-loop/

↑↓ navigate ↵ select esc close