# How to Stop AI Agents from Infinite Loops and Runaway Costs > Prompting cannot prevent agent loops. You need deterministic circuit breakers at the application and gateway layers to stop runaway token costs. Source: https://www.starboxai.ai/en/insights/ai-news/2026-11-12-ai-agent-infinite-loop-prevention/ (Starbox AI Insights, updated 2026-11-12) ## Why Prompts Cannot Stop an AI Agent Doom Loop An AI agent enters an infinite loop when a model repeatedly invokes a failing tool, usually with identical arguments, because nothing in the runtime environment instructs it to halt. In standard agent execution loops, a run finishes only when the model produces a final text response without requesting another tool call. If an external API or internal database goes down, the resulting timeout or error message feeds straight back into the conversation history. The agent's baseline instruction—to complete the assigned goal—remains active. From the model's perspective, retrying the call appears to be the correct next action. Unless you write code that tracks and caps execution attempts, the model will not stop on its own. This behavior compounds financial risk. Each retry resends the entire conversation context, including every prior error payload. In benchmark logging by OpenRouter, an agent's input context expanded from 131 tokens to 3,262 tokens across turns, quadrupling the cost per turn. Left unchecked overnight across parallel user sessions, an autonomous loop can run up bills reaching thousands of dollars. Hoping that prompt instructions like "do not retry if an error occurs" will protect production systems is an operational mistake. OpenRouter tested six models across 18 unconstrained runs: four of the 18 runs looped continuously until hitting an arbitrary 40-step safety limit. Looping is also erratic. When tested three times on the exact same input, Grok 4.7 made 41 calls in run one, 12 in run two, and 41 in run three. Controlling autonomous agents requires deterministic code: fingerprinting tool calls, normalizing inputs, capping session costs, and locking down gateway quotas. | Failure Mode | Why Prompting Fails | Deterministic Fix | | :--- | :--- | :--- | | **Identical Tool Retries** | Models do not count execution turns internally. | Application-level call fingerprinting and execution ladder. | | **Argument Evasion** | Models alter whitespace or casing to circumvent blocks. | Input normalization rules (`loopKey`). | | **Non-Repeating Runaway Steps** | Models try novel arguments or alternate tools indefinitely. | Hard step limits and cost caps (`stopWhen`). | | **Application Process Crashes** | Code bugs bypass internal application checks. | API gateway credit limits and provider-side budget caps. | --- ## Layer 1: Fingerprint Tool Calls with Doom-Loop Detection The first defensive layer monitors repetitive tool executions inside your agent loop. OpenRouter's Agent SDK (`@openrouter/agent` 0.11.0) introduces doom-loop detection by fingerprinting each tool request using its name and arguments. To prevent simple formatting shifts from evading detection, arguments must be canonicalized by reordering JSON keys before hashing. A repeat call is counted only after the model receives the previous tool response and still asks for the same tool. If an agent executes five identical parallel calls in a single turn, they count as one invocation. The detection ladder uses a progressive threshold: 1. **Observe (Streak = 2):** Flags that consecutive identical calls are occurring. 2. **Block (Streak = 3):** Skips execution and returns a deterministic tool error informing the model that retrying will not help and it must wrap up. 3. **Stop (Streak = 6):** Terminates the entire session automatically with `reason: doom_loop`. Across 18 benchmark runs on six models, turning on doom-loop detection blocked all six models on their third identical call. Total tool invocations fell from 314 to 64, and overall spend decreased from $0.29 to $0.05. In 16 of the 18 runs, the session concluded cleanly after just two real tool executions because the model accepted the blocking error and generated an end-state response. --- ## Layer 2: Normalize Arguments with loopKey to Prevent Evasion When an application blocks a model from calling a tool, advanced LLMs often attempt to follow the instruction by slightly modifying the input payload. Because standard hashing uses exact string matching, slight payload variations yield different fingerprints and reset the repetition streak. During testing, Mistral Large 4 hit this failure mode five times across nine runs with detection enabled, reaching the 40-step cap three times simply by alternating identifiers like `INV-2291` and `inv-2291`. Similarly, GPT-6 Luna bypassed exact-string checks by appending trailing spaces and newlines. Because the models had only one tool available, tweaking input syntax was their only method to keep attempting the task. ``` Model Request 1: fetch_invoice({ id: "INV-2291" }) -> Failed (Timeout) Model Request 2: fetch_invoice({ id: "INV-2291" }) -> Failed (Timeout) Model Request 3: Blocked by Doom-Loop Detector Model Request 4: fetch_invoice({ id: "inv-2291" }) -> Treated as new call! Model Request 5: fetch_invoice({ id: "INV-2291 " }) -> Treated as new call! ``` To resolve this, define a `loopKey` function or schema on each tool definition: - **Strip irrelevant formatting:** Normalize casing, eliminate trailing whitespaces, and remove prefixes so that `inv-2291`, `INV-2291`, and `INV-2291 ` resolve to the single identifier `2291`. - **Isolate key business fields:** If a model increments an arbitrary timeout parameter on each retry, ignore that field and track only the operational identifier (`loopKey: ['invoice_id']`). - **Support intentional polling:** If a tool's explicit purpose is continuous polling (such as checking an asynchronous job status), disable detection explicitly with `loopKey: false`. Applying input normalization in the benchmark allowed five out of six runs to shut down cleanly after two real tool invocations. --- ## Layer 3: Hard Caps on Turn Counts and Session Budgets Tool fingerprinting only intercepts repeated arguments. If an agent reacts to an error by trying completely different queries, inventing parameters, or cycling through every tool in its schema, its call fingerprint will never repeat. You must configure session-level termination conditions (`stopWhen`) evaluated after every execution round: - **Step Cap (`stepCountIs`):** A strict ceiling on the total number of turns an agent can take. If production tasks typically complete in four to six turns, setting a step limit of 15 leaves adequate buffer while preventing runaway 40-turn cycles. - **Cost Cap (`maxCost`):** A financial ceiling that sums real-time token spend (`usage.cost`) returned by model providers. Because late-stage turns process significantly larger context windows than early turns, a cost cap acts as the more sensitive financial tripwire. When a stop condition triggers, agent frameworks should reject new tool calls and allow one final turn with tool calling disabled so the model can deliver an explanatory message to the user. If you prefer immediate termination without paying for a final response, set `allowFinalResponse: false`. Even without specialized agent SDKs, standard Python or TypeScript runtimes calling the Chat Completions API can track per-tool call counts and cumulative usage costs directly. In OpenRouter's Python test on Mistral Large 4, an application-level accumulator stopped runaway sessions within four steps at under $0.002 across all runs. --- ## Layer 4: Gateway-Level API Key Credit Limits Every mechanism discussed in Layers 1 through 3 runs inside your application code. If a deployment contains an uncaught exception, a junior developer disables the execution caps during testing, or a worker process spawns hundreds of independent sessions that each stay just beneath the `maxCost` limit, application-level checks will not prevent a massive billing spike. The fourth layer must sit outside your application infrastructure at the API gateway: - **Set hard dollar limits:** Assign an absolute spend limit to each API key in your gateway or provider dashboard. - **Automate reset windows:** Configure `limit_reset` schedules (daily, weekly, or monthly). Daily limits resetting at midnight UTC prevent a runaway system from consuming an entire monthly budget in hours. - **Include third-party accounts:** If using Bring-Your-Own-Key (BYOK) routing, verify that your gateway enforces limits on those provider keys (`include_byok_in_limit: true`), as many systems exclude them by default. - **Isolate keys per environment or tenant:** Issue dedicated API keys to separate agent microservices, internal departments, or client accounts so an outage or loop in one pipeline cannot exhaust credits for other business operations. When an API gateway enforces limits, it calculates the worst-case token expense (prompt tokens plus `max_tokens`) before routing each request. If the projected cost exceeds the key's remaining credit, the gateway drops the request immediately with an HTTP 402 code and metadata setting `limit_source: "openrouter_key_limit"`. Your backend code can catch this specific error source to alert operations teams. --- ## Enterprise AI Agent Safeguard Checklist At Starbox AI, we treat autonomous workflows as production distributed systems rather than creative experiments. Whether deploying marketing automation pipelines, managing multi-agent teams, or delivering Enterprise AI Adoption (FDE) consulting for clients, agent reliability demands structural constraints. Use this configuration checklist before moving any tool-calling agent to production: ``` [ ] Application Layer: Tool Call Fingerprinting - Arguments canonicalized (JSON keys sorted). - Streak ladder set (Observe: 2, Block: 3, Stop: 6). - Block responses instruct the model to report errors rather than retry. [ ] Application Layer: Argument Normalization - Case, whitespace, and formatting stripped via tool-level loopKey. - Non-essential mutable arguments (timeouts, retry counts) omitted from hash. - Intentional polling tools explicitly designated (loopKey: false). [ ] Runtime Layer: Session Bounds - Hard limit set on total turns (e.g., stepCountIs <= 15). - Hard limit set on cumulative dollar spend per session (maxCost). - Graceful degradation handled (allowFinalResponse configured). [ ] Gateway Layer: Credit and Quota Control - Dedicated API keys assigned per agent workflow. - Rolling spend limits enforced (daily or weekly budget limits). - Gateway error handling catches HTTP 402 and routing limit headers. ``` Autonomous agents deliver immense productivity, but only when their operational boundaries are locked down. Do not rely on prompt phrasing to control execution flow. Implement deterministic circuit breakers in your code and gateway configurations so that tool failures result in safe termination instead of unbounded costs.