Agent Timeout Strategies: Bounding a Loop That Cannot Stop
AI Agents

Agent Timeout Strategies: Bounding a Loop That Cannot Stop

An agent has no instinct for when it has taken too long. The four limits worth setting, where to put them, and how to fail without losing the work.

An agent loop has no natural end. It stops when the model declines to call a tool, and the model has no sense of elapsed time, accumulated cost or whether it is still making progress. Every bound on a running agent is one you imposed.

Most teams impose one: a maximum turn count. It is the least informative of the available limits, and on its own it produces the worst failure mode — a session that stops halfway with no explanation and no salvageable output.

Four limits, four different jobs

A tool call timeout bounds one action. Its job is to stop a hung command from consuming the entire session, and it should be tight enough that a hang is detected in a minute rather than an hour.

A turn ceiling bounds the loop. Its job is to catch runaway sessions, and it needs to be generous, because legitimate long tasks exist and a tight ceiling truncates them silently.

A wall-clock limit bounds the whole run. Its job is to make the system predictable for whatever is waiting on it, which is a scheduling concern rather than a correctness one.

A cost ceiling bounds spend. It is the only limit that maps directly to the thing you actually care about, and it is the one most often missing. Agent token budgets covers setting it.

Progress beats duration

Duration limits cannot distinguish a productive long run from a stuck one, so they are always either too tight for real work or too loose to catch failure quickly.

A progress check does distinguish them. Track whether anything observable changed on each turn: files modified, tests executed, new information added to the working set. Several consecutive turns with no change means the agent is not going to finish, whatever the turn count says.

With a progress detector in place you can set the turn ceiling generously, because the detector catches the failure case long before the ceiling does. Without one, every ceiling is a compromise between two bad outcomes. Detecting agent loops covers implementing the check.

Choose tool timeouts from measurements

Tool timeouts get set to round numbers that nobody validated, and the round number is usually wrong in the direction that hurts.

Record the duration of every tool call for a week and look at the distribution per tool. A file read finishing in milliseconds and a test suite taking minutes should not share a limit; setting one number for both means either the read hangs for minutes or the suite is killed while healthy.

Set per-tool limits above the observed tail with headroom, and watch what gets killed afterwards. A test runner cut off while working is worse than no timeout, because the model reads the failure as a broken test and starts editing tests to make it pass.

Kill the process group rather than the direct child. A runner that spawns workers leaves them behind, and they will still be there competing for the machine several runs later. Agent shell access safety covers the execution side.

The error message decides what happens next

A timeout that returns a generic failure invites the model to run the same command again, which is a loop with a slow clock.

Say what happened specifically: the command exceeded its limit and was terminated, this is not a failure of the command itself, and a different approach is required. That phrasing changes the model's next action, which a bare error does not.

Where a partial result exists, return it. A test run killed at the limit still produced output, and the first failures in that output are usually enough for the model to proceed without re-running anything. Agent error recovery patterns covers writing errors the model can act on.

Terminate with a handover, not a stack trace

The default behaviour at a limit is to stop, which throws away everything the run learned. That is a waste of the entire cost of the session.

Instead, treat the limit as a trigger for a final summarising turn: what was attempted, what state the workspace is in, what remains. One extra model call converts a dead run into a resumable one.

Leave the workspace in a defined state as well. A run killed mid-edit leaves files half-written and the next attempt starts from something worse than where it began. Committing to a scratch branch, or stashing, costs nothing and preserves the option to continue. Long running agents covers checkpointing more thoroughly.

Distinguish limits from failures in the metrics

A run that hit a ceiling is not the same event as a run that errored, and merging them hides the more actionable signal.

Record which limit fired, on which turn, and what the state was. Aggregate weekly. A rising rate of turn-ceiling terminations usually means tasks are being scoped too large rather than that the ceiling is too low.

Watch the distribution rather than the average. If most runs finish in a fraction of the ceiling and a few reach it, the ceiling is correct and those few runs are a distinct failure worth investigating individually. Agent observability and tracing covers collecting this.

A default set

Per-tool timeouts drawn from measured durations with headroom, killing the process group. A generous turn ceiling paired with a no-progress detector that fires after three or four idle turns. A wall-clock limit matching whatever is waiting on the run. A per-run cost ceiling set from the observed tail.

On any of them: specific error text, a summarising final turn, and a workspace left in a state the next attempt can build on.

Common questions

Is a turn limit enough to bound an agent?

No. A turn limit cannot tell a productive long run from a stuck one, so it is either too tight for real work or too loose to catch failure quickly. Pair a generous ceiling with a no-progress detector that fires after a few turns with no observable state change.

How should a tool timeout be chosen?

From measured durations per tool, set above the observed tail with headroom. A file read and a test suite should not share a limit. Kill the process group rather than the direct child, or spawned workers survive the timeout.

What should happen when an agent hits a limit?

Not a bare stop. Spend one more model call summarising what was attempted, the workspace state and what remains, and leave the workspace committed or stashed so the run is resumable rather than discarded.

Similar articles

Agent Token Budgets: Capping Spend Without Capping Capability
AI Agents
AI Agents·8 min read

Agent Token Budgets: Capping Spend Without Capping Capability

An unbounded agent can spend arbitrarily much on one task. How to set budgets that stop runaway sessions without killing legitimate long ones.

Read
Detecting Agent Loops Before They Burn Your Budget
AI Agents
AI Agents·8 min read

Detecting Agent Loops Before They Burn Your Budget

A stuck agent repeats the same failing action until something stops it. How to detect repetition cheaply and what to do once you have.

Read
Agent Audit Logging: What to Record and What to Redact
AI Agents
AI Agents·9 min read

Agent Audit Logging: What to Record and What to Redact

When an agent does something surprising, the log is the only account of what happened. What a usable agent audit record contains, and what it must not.

Read