Why Agents Loop (and Why Loops Kill Budgets)
In November 2025, two LangChain agents at a venture-backed SaaS company looped at each other for eleven days and produced a $47,000 OpenAI bill. Nobody touched a keyboard. The loop is the thing that makes an agent an agent โ and the thing that quietly turns it into a fire.
The Loop Is the Whole Point
If you remove the loop from an agent, you get a workflow with an LLM step. That's it. Everything we call "agentic" โ autonomy, problem-solving, plan-and-execute, multi-step reasoning, tool orchestration โ depends on the loop. The model takes an action, observes a result, decides what to do next, takes another action, observes again, and continues until either the goal is satisfied or the runtime makes it stop.
This is powerful. It is also the single greatest source of cost, latency, and reputational risk in production agents. The dirty secret of 2026 is that almost every catastrophic agent incident โ the $47K loop, the 47-customer email blast, several quieter five-figure overruns that never made the news โ was a loop failure of one kind or another. Not a model failure. Not a prompt failure. A loop failure.
Production agent engineering, distilled: the loop must terminate, and you must know what it's going to cost before it does.
Reading a Trace Without Being an Engineer
Operator-builders often get told "go look at the trace" and panic because traces look like programmer output. They are not. A trace is a transcript of what the agent thought, what it did, and what it saw. You can read one with the same skills you use to read a chat conversation. Here is what a trace actually contains, in plain English.
The anatomy of a trace
Every iteration of the agent's loop produces three lines of trace output (sometimes four):
- Thought: what the model "reasoned" โ usually a sentence or two of plain English. ("I need to find the customer's order history to answer their refund question.")
- Action: the tool the model decided to call, with its arguments. (
search_orders(customer_id="cus_abc123", limit=10)) - Observation: what the tool returned. ("3 orders found: ord_001 ($120, shipped), ord_002 ($45, refunded), ord_003 ($89, pending)")
- (Sometimes) Tokens / cost / latency: the model call's metered output.
Read fifty of these in sequence and you have an entire run. Read the first ten and you usually know whether the agent is on a healthy path or has wandered into a loop spiral. The skill is not technical; it's the same pattern-matching skill you use to read a Slack thread where two people are talking past each other.
What a healthy trace looks like
- Iter 1. Thought: "Customer asks about refund for ord_002. Let me look it up." Action:
get_order(ord_002). Observation: "$45 refunded on 2026-04-12." - Iter 2. Thought: "Refund was processed last month. Customer probably wants to know where the money is." Action:
check_refund_status(ord_002). Observation: "Refund completed, sent to Visa ending 4242." - Iter 3. Thought: "I have enough to answer." Action:
final_answer. Observation: (none โ loop ends.)
Three iterations. Two tool calls. Cost: probably $0.01 with Sonnet, $0.001 with Haiku. Total time: maybe 4 seconds. This is what every operator-builder is trying to produce.
What an unhealthy trace looks like
- Iter 1. Thought: "Customer asks about refund for ord_002." Action:
get_order(ord_002). Observation: "Order not found." - Iter 2. Thought: "Maybe the ID is different. Let me search by customer." Action:
search_orders(customer="abc123"). Observation: "No customer found." - Iter 3. Thought: "The customer must exist. Let me try the CRM." Action:
search_crm("abc123"). Observation: "Result truncated, see logs." - Iter 4. Thought: "Let me re-search with a different filter." Action:
search_crm("abc123", verbose=true). Observation: "Result truncated, see logs." - Iter 5. Thought: "Maybe I need the original order ID." Action:
get_order(ord_002). Observation: "Order not found." - Iter 6. Thought: "Let me search the customer again." Action:
search_orders(customer="abc123"). Observation: "No customer found." - ...
This is a loop. Notice the pattern: the agent keeps trying the same set of tools with slight argument variations, getting the same unhelpful observations, and never updating its plan. It is stuck. It has no way out because nothing in the loop changes meaningfully between iterations. Without a max-iteration cap, this runs forever โ or until the tokens run out.
Why Agents Loop (the Mechanics)
Loops happen for a specific cluster of reasons. Knowing them is the difference between a builder who patches symptoms and one who fixes architecture.
Cause 1: Ambiguous observation
The tool returns something the model cannot make sense of. Maybe an HTTP 500, maybe "result truncated," maybe an empty array. The model retries, sometimes with a slight argument change, sometimes identically. Each retry consumes tokens and gets the same result. Fix: tools should return semantically distinct results for "found nothing" vs "error" vs "you need more privilege" vs "data is paginated."
Cause 2: Missing required information with no escalation path
The agent needs information it doesn't have and there's no way to ask a human. So it keeps searching for the information using the tools it does have. The right design is to give the agent an explicit ask_human(question) tool with an HITL fallback. Without it, the agent runs in circles trying to derive what it can't derive.
Cause 3: Conflicting state across systems
System A says the order is shipped. System B says it's pending. System C says it doesn't exist. The agent tries to reconcile, fails, re-queries, fails again. This is the multi-system reconciliation trap. Fix: when the model detects state conflict, it should escalate, not keep trying.
Cause 4: Recursion through inter-agent or sub-agent calls
The November 2025 $47K incident was this. Agent A could call Agent B as a tool; Agent B could call Agent A. They pinged each other for clarifications, each clarification produced new context that triggered another clarification request, and there was no per-graph budget. Fix: cross-agent budgets and explicit recursion limits at the orchestration layer.
Cause 5: Self-doubt or reflexion loops
Modern agent patterns (Reflexion, self-critique, Tree-of-Thoughts) deliberately ask the model to evaluate its own work and possibly re-do it. This is often valuable. But without a stop criterion, the agent can endlessly second-guess and rewrite. Fix: bounded reflexion โ at most N self-critique cycles before committing.
Cause 6: Tool returns lead the agent to invent new sub-problems
The agent's tool returns a piece of information that triggers a new search, which returns more information, which triggers another search, and so on. Each search is locally justified; in aggregate, the agent is fractally exploring a problem instead of solving one. Fix: explicit goal-tracking โ the agent should periodically check "have I made progress on the original goal in the last N steps?"
The $47K Incident, Step by Step
Let's walk through the November 2025 LangChain incident publicly enough that you can recognize the same pattern when it shows up in your environment.
Setup. A B2B SaaS company built two LangChain agents. Agent A was the "pricing watcher" โ it monitored competitor pricing pages weekly. Agent B was the "benchmark writer" โ it updated an internal Airtable with normalized pricing data. Each agent had a tool to call the other. The team's mental model was that this was a workflow: A watches, A pings B, B writes. Done.
Trigger. A scheduled run kicked off Agent A on a Sunday evening. Agent A fetched competitor pricing, found an ambiguous price (a "starting at $X, contact for enterprise" page). Agent A asked Agent B for clarification on how to record this. Agent B asked Agent A for the exact page snippet. Agent A re-fetched, got the snippet, sent it. Agent B asked for the URL. Agent A sent it. Agent B asked for the timestamp. Agent A sent it. Each message added context. Each context addition triggered a new ambiguity that triggered a new question.
Escalation. Both agents had iteration caps of 50. But the cap was per-agent-per-call. Every time Agent B pinged Agent A, that was a new call with a fresh 50-iteration budget. The cap never bound the cross-agent loop.
Duration. The loop ran from Sunday evening until the following Thursday โ eleven days. The team was on Thanksgiving holiday. There was no daily $-spend alert. The OpenAI billing dashboard showed daily anomalies but nobody was watching.
Discovery. A finance person noticed the OpenAI invoice projection had jumped from $800/month to $47,000 over a single week. They paged the engineering team. The engineer-on-call killed the agents by revoking the API key โ which is the only real kill switch when caps don't bind.
Postmortem findings. Three architectural gaps: (1) no cross-agent budget, only per-call caps; (2) no real-time cost alerting; (3) no out-of-band kill switch that could be triggered without a deploy. The team did not lose any data; they simply lost $47,000 in tokens and three engineers' weekends.
The lesson is not "don't use LangChain." LangChain didn't fail. The lesson is: caps that bind one part of the system don't bind the whole system. Budgets must be global.
How Loops Burn Tokens (and Why It Compounds)
The math is worse than it looks because token cost compounds across loop iterations. Here's why.
The compounding effect
On iteration 1, the model sees: system prompt + tool definitions + user request. Maybe 1,500 input tokens. It emits 200 output tokens (thought + action). Total: 1,700 tokens.
On iteration 2, the model sees: everything from iteration 1, plus the observation from the tool, plus its own thought and action. Now: 1,500 + 200 + 300 (observation) + 200 (output) = 2,200 input tokens, plus 200 output. Total: 2,400 tokens.
On iteration 5: input is 1,500 + 4 ร 500 (accumulated history) = 3,500 tokens. Output 200. Total: 3,700.
On iteration 20: input is approaching 12,000+ tokens. Each call now costs roughly 6x what the first call did. On iteration 50, input is 25,000+ tokens per call, with the call cost approaching 15x the first call.
This is why a runaway loop doesn't just cost N times the first call โ it costs roughly Nยฒ times. A 50-iteration loop is not 50x cost; it can be 200-500x cost. The $47K incident over eleven days was driven heavily by this compounding.
The "context as cost" rule
For operator-builders, the practical rule is: the cost of an agent run grows with the square of the number of iterations, not linearly. This means iteration caps need to be aggressive. A 10-iteration cap is reasonable. A 30-iteration cap is suspicious. A 100-iteration cap means you have no real cap.
The Runaway Loop Kill-Switch Checklist
This is the artifact you should configure for every production agent before it ships. Tape it up. Walk through it. Sign your name at the bottom.
1. Max iterations cap
Set explicitly. Default in most platforms is generous (n8n: 10, Lindy: variable, LangChain: 15 historically, often unset). Override to match the genuine maximum needed. For most ops agents, that's 8-12. For research agents, 20-30. Above 30, you are admitting the agent might not converge and that should trigger HITL.
2. Per-run token cap
Set a hard cap on total tokens used per run (input + output combined). The platform should refuse to make the next model call when the cap is exceeded. For most ops agents, 50K-150K tokens per run is plenty. The $47K incident's runs each consumed millions.
3. Wall-clock cap
Maximum wall-clock time the run is allowed. For most user-facing agents, 60 seconds. For background batch agents, 5-15 minutes. The wall-clock cap catches the case where each individual iteration is fast but they accumulate.
4. Per-run dollar cap
Translate iteration + token caps into a hard dollar number per run. If the per-run cost is $0.50 and you process 10,000 runs a day, that's $5,000/day. Know this number before you ship. Some platforms (LangSmith, Helicone, Langfuse, Arize) instrument it for you; in n8n or Lindy, you may need to compute it in a downstream node.
5. Daily and weekly aggregate caps
Per-run caps don't catch "10,000 runs per hour" attacks (intentional or accidental). Set daily and weekly aggregate caps with alerting at 50%, 80%, and 100% of budget. If you go over budget, runs are throttled, not silently consumed.
6. Cross-agent / cross-call recursion limit
If your agent can invoke other agents, set a global depth limit. Agent A โ Agent B โ Agent C is fine. Agent A โ Agent B โ Agent A is the loop that ate $47K. Track the call graph at the orchestration layer.
7. Per-tool error budget
If the same tool errors three times in a row in the same run, the agent must escalate or halt โ not retry forever. This catches the "ambiguous observation" loop cause.
8. Repetition detection
If the agent makes the same tool call with the same arguments more than twice in a run, suspect a loop. Some platforms detect this automatically; otherwise, you can add a guard tool that watches the call history.
9. Real-time cost alerting
Cost should be visible in real time, not in a monthly invoice. Wire up Slack/PagerDuty alerts at daily-budget thresholds. The $47K incident lasted eleven days because no real-time alert fired.
10. Out-of-band kill switch
A way to stop all agent runs immediately, without deploying code. The simplest: revoke the agent's API key. The cleanest: a feature flag that the agent checks before each model call. The most robust: a network-level kill (the agent loses access to the model endpoint). Whichever you choose, have one, and test it before you need it.
Reflexion vs. Runaway: When Loops Are Good
Not every long loop is bad. Some of the most impressive agent capabilities โ Devin debugging an issue across a codebase, Claude Code refactoring a module, Cursor's agent mode iterating on test failures โ depend on long loops. The difference between productive long loops and runaway loops is whether each iteration makes progress.
The progress test
Healthy loops show monotonic progress: each iteration either (a) reduces uncertainty, (b) accomplishes a sub-goal, or (c) commits to a decision. The trace shows the agent learning something new each step. The work narrows.
Unhealthy loops show no progress: each iteration repeats prior work, re-queries the same systems, or asks the same self-doubt question. The trace shows the agent oscillating between options without converging. The work expands.
Diagnostic: count distinct tool-call signatures
A useful trick: count the number of distinct tool calls (tool name + key argument) in a run. If the run has 30 iterations but only 4 distinct tool calls, the agent is looping. If it has 30 iterations and 25 distinct tool calls, it is exploring productively (though you should still cap iterations).
Vendor Defaults: What Caps Ship By Default
For the major platforms operator-builders use in 2026:
- n8n AI Agent node: default max iterations was 10 historically; the Feb 2026 schema change kept that. No default token cap. No default wall-clock cap.
- Lindy autonomous: caps must be set per-agent; defaults are generous to "preserve agent flexibility."
- Salesforce Agentforce: the Reasoning Engine has internal iteration limits but per-org override exists; default for many actions is "unbounded within reason," which is not a real cap.
- Copilot Studio autonomous agents: tunable; default depends on connector; not all expose a token cap UI.
- LangChain / LangGraph: defaults vary by version;
max_iterationshistorically defaulted to 15 but was easy to unset accidentally. - OpenAI Assistants / Responses API agents: default to fairly conservative iteration limits but no native dollar cap.
- Claude Code, Devin: rate-limited by Anthropic / Cognition platform; per-run caps are higher than ops use cases need.
Translation: no platform ships with all six caps set safely by default. You have to configure them. Treat that as the deploy gate.
What Good Looks Like
A production-grade agent has the following operational properties:
- Every run completes within a known max iteration count, max token budget, and max wall-clock time.
- Per-run cost is bounded and known before the run starts.
- The runtime emits real-time cost telemetry to a queryable store.
- Daily and weekly $-spend caps trigger alerts at 50/80/100%.
- The same tool call with the same arguments cannot fire more than 2-3 times per run without escalation.
- Cross-agent / sub-agent invocations are bounded by a global depth limit.
- There is an out-of-band kill switch that has been tested in the last 90 days.
- Traces are inspectable by anyone on the ops team, not just engineers.
None of these are aspirational. They are the bare minimum to ship in 2026 without risking a $47K weekend.
Key Takeaways
- The loop is the whole point โ and the whole risk. Without it, you have a workflow. With it, you have everything from autonomy to runaway cost.
- Traces are readable. Thought, action, observation. Read ten and you know whether the agent is converging or spiraling.
- Loops happen for six predictable reasons: ambiguous observation, missing info with no escalation, cross-system conflict, inter-agent recursion, reflexion without bounds, fractal sub-problem exploration.
- Cost compounds quadratically. A 50-iteration runaway loop costs roughly 200-500x a single call. Caps must be aggressive.
- The $47K incident is the canonical 2026 lesson. Per-call caps don't bind cross-agent loops. Budgets must be global. Real-time alerts and out-of-band kill switches are non-negotiable.
- Ten-item kill switch checklist: max iterations, per-run token cap, wall-clock cap, per-run dollar cap, daily/weekly aggregate caps, cross-agent recursion limit, per-tool error budget, repetition detection, real-time cost alerting, out-of-band kill switch. Configure all ten before ship.
- Good loops show progress. Bad loops show repetition. Count distinct tool-call signatures. If iteration count is high but distinct calls are low, you're looping, not exploring.
- No platform ships safely by default. You have to set the caps. Treat that as the deploy gate.
Skill.re