Preventing agent loops and runaway spend.

The short answer

A runaway agent loop is stopped by reading repetition as state rather than as text, and severing the loop locally before the next upstream call is made. Gubernaut hard-stops a saturating loop at turn 4 with no upstream tokens spent on the stopped call, which cut spend by up to 95.9% on a pre-registered battery, and by 79.8% in the weakest of seven measured configurations across four model families.

Why do LLM agents loop?

An LLM agent loops when its own last output becomes the strongest signal in its next input. A retry, a re-plan or a restated goal feeds the same frame back into the context, and because nothing raises an error, the loop is billable work that looks like progress from outside the process.

Agentic workloads make this worse than a single chat turn does, because the agent is the thing generating its own next prompt. Nobody is in the loop to notice that the last four steps said the same thing.

How much does a runaway loop cost?

On a pre-registered saturating-loop battery the governed arm paid 4.1% to 20.2% of the ungoverned bill on seven measured configurations across four model families, a reduction of 79.8% to 95.9%. The largest measured gap was GPT-5.6 Sol at $0.1669 ungoverned against $0.0068 governed. Both arms made the same number of attempts.

ModelUpstreamUngovernedGovernedGoverned share
GPT-5.6 LunaOpenAI$0.0921$0.015516.8%
GPT-5.6 SolOpenAI$0.1669$0.00684.1%
Claude Fable 5Anthropic$0.3861$0.02035.2%
Claude Haiku 4.5OpenRouter$0.8211$0.166020.2%
Llama 4 ScoutOpenRouter$0.1075$0.00948.8%
Gemma 4 26BOpenRouter$0.0214$0.003415.9%
Gemma 4 26BGemini (native)57,297 tok4,236 tok7.4%

OpenRouter rows are the upstream's own metered usage cost rather than our token math. The Gemini (native) row is free-tier, so it is a token delta and carries no dollar claim. Both arms make the same number of attempts, so the ratio is the measurement.

Source: Pre-registered receipts benchmark, 2026-07-19. Scored output of harness/report.py.

The full 12-row table

How do I detect a loop before it costs money?

Detecting a loop by string matching fails the moment the agent paraphrases itself. Gubernaut tracks repetition as a bounded number carried across turns, so a semantically repeated frame raises perseveration even when the wording changes, and the repetition veto caught 10 out of 10 calm loops in testing.

Source: HARDTEST v1.0 release gates, 2026-07-24.

At what point should the loop be stopped?

Gubernaut changes posture at turn 3 and hard-stops at turn 4 in the pre-registered battery, identically on every run because the controller is input-deterministic. Stopping earlier risks severing a legitimate retry, and stopping later means paying for laps that were never going to converge.

Source: Pre-registered receipts benchmark, 2026-07-19. Scored output of harness/report.py.

Will stopping a loop break the agent?

A hard stop arrives as a governed refusal through the normal response path rather than as a thrown error, so the host process stays up. In clean-room testing against the published ElizaOS core the host exited zero after a hard stop, and a new call afterwards succeeded normally.

Source: HARDTEST v1.0 release gates, 2026-07-24.

Why not just set a spend cap?

A spend cap acts after the money is committed and cannot tell a loop from a busy afternoon, so it protects the invoice by cutting benign traffic at the same moment it cuts the runaway. A governor reads the agent's own state per turn and severs only the saturating pattern, which is why benign completion stayed at 99.0% while a saturating loop stopped at turn 4.

  1. 01

    Spend cap or budget alert

    Acts after the spend is committed, and treats every request alike. Useful as a backstop, not as control.

  2. 02

    Retry limit at the call site

    Bounds one call site. An agent that re-plans instead of retrying walks straight past it, because each lap is a new call.

  3. 03

    Calming system prompt

    Measured: paid 117% to 192% of baseline spend in a pre-registered ablation, so it cost more than doing nothing on that battery.

  4. 04

    Deterministic governor

    Reads state per turn and severs the saturating pattern only. Paid 23% to 63% of baseline in the same ablation, and hard-stops at turn 4.

Source: Pre-registered ablation, 2026-07-21, gpt-5.6-sol, N=3.

Why not just cap the number of iterations at the gateway?

An iteration cap counts turns, and a count cannot separate a stuck agent from a working one. The cap has to sit high enough that it does not kill a legitimate long task. So it does not fire until most of the money is already spent, and when it fires it cuts the good run and the runaway on the same rule. A governor reads repetition and escalation as state instead, so what triggers it is the pattern rather than the length: measured on the published batteries, 10/10 calm loops caught by the repetition veto and 0/30 false severs on the benign battery. The same batteries record 5/5 missed INHIBIT on calmly worded, non-lexicon hostility on that corpus, which the v0 lexicon sensor does not read as hostile, which is a sensor-recall limit rather than a control-boundary breach. The two are complementary: a cap is a sound backstop for the invoice, and it is not control.

Source: docs/LIMITS.md, thegubernaut/gubernaut, tag v1.0.0

What about an agent that gives inconsistent answers under pressure?

Inconsistency under provocation is what the validation record measures. Across 4 frontier families the regulated arm was calmer in 15 of 16 generator×judge cells by sign and 13 of 16 at p<.05, with one cell, GPT generating and Gemini judging, a flat null at −0.04. Regulation constrains the conditions a reply is written under, and does not make a stochastic model deterministic.

Source: Pre-registered cross-family evaluation. Paper: arXiv 2607.24339, DOI 10.5281/zenodo.21303518.

Does this work with LangChain, LlamaIndex or AutoGen?

Yes, and all three were tested end to end rather than assumed compatible. 5/5 frameworks adopt in one line, hard-stop a loop, and fail closed on a dead proxy, installed from the published artifacts only: OpenAI SDK, LangChain, LlamaIndex, Microsoft AutoGen, ElizaOS. Each sets a base URL on its OpenAI client, so the framework keeps talking to what it believes is an OpenAI endpoint while every turn passes the controller on the way out.

Source: HARDTEST v1.0 release gates, 2026-07-24.

The install guides for each runtime

How do I add this to an agent I already run?

Install one package and change one configuration line: pip install gubernaut-sdk, start the local proxy in front of the upstream you already call with gubernaut-proxy --upstream https://api.openai.com, then set client = OpenAI(base_url="http://localhost:8000/v1"). Only that last line touches your own code, and 5/5 frameworks were verified adopting exactly that way.

Install guides

Last reviewed 2026-08-07 · paper arXiv 2607.24339, DOI 10.5281/zenodo.21303518