Skip to main content

Your AI Agent's Debug Loop Costs Grow Quadratically, Not Linearly — Here's the Math

8 min readDora NodaDora Noda
Share
On this page

An agent that deploys, checks a status, reads a log, retries, and rolls back — five ordinary tool calls — doesn't cost 5x a single call. It costs about 3.2x more than that estimate would suggest. Push the same loop to 50 steps and the overrun exceeds 30x. At 200 steps, a routine length for an overnight build-failure debug session, it tops 100x. None of that comes from the model getting more expensive per token. It comes from how the loop is built.

The mechanism is almost embarrassingly simple, and once you see it, every "why did last night's autonomous debug run cost $40 for what should have been a $2 job" ticket makes sense. It has nothing to do with the task getting harder, the model getting slower, or the agent going in circles — the loop can execute a clean, monotonically-improving sequence of retries and still rack up a bill an order of magnitude past what a human budgeting per-tool-call would have expected.

If you're building or operating a deploy-from-chat MCP server — where an agent's own tool calls are deploy, check-status, read-logs, retry, rollback — this is the curve that turns a routine debug loop into an unbounded bill. And it's specifically the multi-step debug case, not the one-shot "deploy and confirm it's up" case, that this curve punishes hardest: exactly the workload an agent-operated platform exists to handle.


Why the cost curve is quadratic, not linear

LLM APIs are stateless. Every request stands alone — the model has no memory of the previous call. So an agent loop that wants to "remember" what happened three tool calls ago has exactly one option: resend the entire conversation history, every single turn.

That means step 1 sends the system prompt and tool schemas. Step 2 sends all of that again, plus step 1's tool call and result. Step 3 resends everything through step 2, plus its own turn. By step n, you're resending n copies of the base prompt and re-billing every prior tool result n minus its position times.

The cumulative input-token cost across an n-step loop follows:

text
T(n) = n·s₀ + p·n(n-1)/2

where s₀ is the fixed base (system prompt + tool schemas) and p is the tokens a typical step appends (a tool call plus its result). The first term is linear — that's the part your intuition correctly anticipates. The second term is quadratic, and it's the one that blindsides people: it grows as , with nothing to do with the model's per-token price.

A skeptical reader's first objection is fair: doesn't the multiplier just depend on what numbers you plug in? It does — so here's the curve under three different tool-output sizes, from a terse status-only agent to one that dumps full build logs on every step. The comparison in every case is "what the loop actually gets billed" against "what a non-resending, purely necessary loop would cost" (the base prompt once, plus each step's new content, with nothing re-sent):

Tool-output size (tokens/step)Multiplier at 5 stepsMultiplier at 50 stepsMultiplier at 200 steps
Terse (status JSON only, ~400 tok/step)4.0x28.8x104x
Typical (mixed status + log excerpt, ~1,200 tok/step)3.2x26.1x101x
Log-heavy (full build-log dumps, ~3,000 tok/step)2.6x25.2x100x

(Base prompt held at 4,000 tokens across all three — a system prompt plus five tool schemas for deploy/check-status/read-logs/retry/rollback is a realistic size.)

The specific multiplier moves with how chatty your tool outputs are, but the shape doesn't: every configuration lands in the same neighborhood as the widely-cited "~3x at 5 steps, ~30x at 50, ~100x at 200" figures, and every configuration converges toward the same ~100x by step 200 regardless of per-step verbosity. That convergence is the point — at high step counts, the quadratic term dominates so completely that it stops mattering whether your tool outputs are terse or verbose. The curve is quadratic by construction, not by coincidence of what numbers you chose.


What this actually costs a deploy-from-chat MCP server

Generic percentages are easy to shrug off. Here's the same math run against Claude Sonnet 5 pricing ($3 per million input tokens; $2 during the introductory window through August 2026) for a "typical" debug loop — the mixed-verbosity row above, base prompt 4,000 tokens, ~1,200 tokens appended per step from a deploy/check-status/read-logs/retry/rollback MCP tool contract:

StepsTokens actually billedTokens a non-resending loop would needCost billed (@ $3/MTok)Cost a non-resending loop would pay
532,00010,000$0.10$0.03
20308,00028,000$0.92$0.08
501,670,00064,000$5.01$0.19

At 5 steps the overrun is pocket change. At 50 — a realistic length for a stubborn build failure the agent is retrying against, checking, reading logs on, and occasionally rolling back — the loop bills 26x more than the tool calls it actually made. That's before accounting for output tokens, which aren't resent but still add up over 50 model responses.

Scale that to the hundreds of debug sessions a self-hosted platform's fleet runs in a week, across every tenant's failed builds, and a per-tool-call cost model that ignores this curve is off by more than an order of magnitude. The "50-step multiplier exceeds 30x, 200-step tops 100x" finding isn't a benchmark curiosity — it's the actual shape of an MCP server's bill once a debug session runs long enough for a human to have walked away and let the agent keep retrying overnight.


The fix that doesn't work, and the one that does

The obvious first response is prompt caching — Anthropic's cached input tokens cost roughly 10% of the standard rate on a read, against a 1.25x (5-minute TTL) or 2x (1-hour TTL) premium on the write. That's a real, substantial saving on the dollars per resent token. It is not a fix for the quadratic token-count growth itself.

Caching cheapens re-processing the same prefix; it doesn't shrink the prefix. The conversation history still grows by one tool call and result every step, and the resent portion is still Θ(n²) tokens. A cache write still has to happen on any turn whose prefix changed since the last cached checkpoint — which, in a loop that's constantly appending new tool results, is every turn past the cache's TTL.

Caching moves the curve down; it doesn't bend it. A 50-step loop that would have billed $5.01 in raw tokens might land closer to $1–2 with aggressive caching — still 5–10x the $0.19 a non-resending loop would need, because the number of tokens being re-billed hasn't changed. Only their unit price has.

What actually bends the curve is bounding what gets resent in the first place, and there are two API-level mechanisms built for exactly this:

  • Server-side compaction (compact_20260112, beta header compact-2026-01-12, available on Claude Sonnet 5 and the current Opus tier) summarizes earlier conversation history automatically once it crosses a trigger threshold — the default is 150K tokens — replacing dozens of resent tool-call turns with a single compact summary block. The caller must append the full response.content back on every turn, not just the extracted text, or the compaction state silently breaks.
  • Context editing (clear_tool_uses_20250919, beta header context-management-2025-06-27) prunes stale tool results outright once they're no longer relevant to the current step — the difference from compaction is that it clears rather than summarizes, which is cheaper and appropriate when a tool result's specific content stops mattering (a build log from three retries ago) but its outcome still does.

Either one turns the term back toward linear by capping how much of the history actually gets resent past a threshold, instead of letting it accumulate forever.


The state problem that bounding history creates

Here's the part a platform's own MCP server design has to own, and it's not optional: the moment you start summarizing or clearing tool-call history mid-loop, the agent can no longer trust its own context to know the truth. If the last-known-good deploy ID or the current rollback depth lived only in a tool result three retries back, and that turn got compacted into "several retries occurred, last one failed," the agent's next rollback call is now guessing.

The fix isn't to avoid bounding history — the cost curve makes that untenable past a few dozen steps. It's to never make history the source of truth for anything that would be dangerous to get wrong. A deploy/rollback MCP tool contract should expose a get-current-deploy-state call that returns the last-known-good deploy ID and rollback depth fresh, server-side, on every query — not something the agent is expected to remember correctly from a resent (or worse, summarized) transcript. Bound the history for cost. Keep infrastructure-mutating state authoritative and queryable, not resent.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. If you're building agent-facing deploy tooling and want to see how a Render-compatible API handles exactly this kind of state design, star the repo on GitHub or deploy your first app today.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex