A Team of Agents Built a System in a Week and Left €15M of Unmaintainable Code
That case study comes from Software Improvement Group’s analysis of 30,000 enterprise systems, and the number that gets quoted is the token bill, somewhere between €10M and €15M for one week of autonomous agent work. The number that should get quoted is the second half of the sentence, which is that the resulting code was described as nearly unmaintainable.
The bill was paid once. The code has to be lived with.
The shape of the problem
Traditional technical debt is a choice. An engineer under time pressure knows they are cutting a corner, and usually leaves some trace of having decided it, in a comment or a ticket or at minimum in somebody’s memory.
AI generated debt accumulates without anybody deciding anything. The code passes its tests, looks reasonable in review, and carries duplicated logic, missing abstractions, unhandled edge cases and architectural choices that quietly conflict with the rest of the system. Nothing in the process flags any of it, because every individual change was locally defensible.
The forecasts caught up with this quickly. Roughly 75% of technology decision makers are expected to face moderate to severe technical debt driven by AI assisted development, around 67% of developers report increased debugging time, and 81% of executives already say technical debt is constraining their AI results. The tools adopted to accelerate development are now the reason development is slowing.
The compounding is the part worth internalising. In year one the debt is invisible, because tests pass and velocity looks healthy. In year two the accumulated duplication and missing abstractions start to bite, bug fixes take longer because nobody understands the code, and new features have to work around decisions an agent made months earlier. Unmanaged, maintenance costs reach something like 4 times traditional levels by year two, and the curve is not linear.
Why generation without grounding produces debt by default
An agent writing a function has to work out what the surrounding system already does before it can decide how to fit into it. If it cannot see that, it does the only available thing and writes something self contained that works.
Self contained code that works is exactly what debt looks like at the moment of creation.
It reimplements a helper that already exists three directories over, because it could not find the existing one. It picks a pattern that contradicts the convention the rest of the service uses, because the convention was never written down anywhere it could read. It adds a fourth implementation of a thing that already had three, one live, one behind a flag that has been off since March, and one waiting for deletion, with nothing in the repository marking which is which.
Every one of those is a locally correct decision made without the information that would have changed it.
There is a review side to this as well. Volume went up by an order of magnitude and the number of people able to review it did not move at all. Razorpay’s internal platform reports roughly 1,000 pull requests created a week automatically, around 100 merged with zero human review, and 1 in 3 reviews completed end to end without a human comment. At that throughput, debt entering the codebase is not caught by attention, because there is not enough attention available to catch it.
The step that is missing
Almost every proposed answer to this operates on the model rather than on the codebase. Better prompts, stricter instruction files, more skills, a larger context window, a more capable model.
The information the agent is missing is not in any of those places. It is in the code that already exists, and it has to be extracted from the code before an agent can use it.
ByteBell is a verification layer generated on top of a codebase of any size below 10 million files, and that extraction is the whole product.
Cheap open source models read every file once at indexing time. An agent detects the boundaries of each language element, stores them separately, then analyses each one in the context of its file, its module, its repository and across every repository. For each file the layer records what it does, why it exists in business terms, what users lose if it fails, the capabilities it provides, its edge cases, the contracts it provides, its preconditions, and the specific places where the behaviour is genuinely undecided. All of it in plain English with the file and the line kept on every claim.
What that changes at the two moments that matter
Before the code is written. An agent connected to the layer writes against the contracts your repositories already have rather than against a guess. Given a request to add a nullable field to a subscription model and stop counting cancelled subscriptions in revenue, it sees that the definition of an active subscription already lives in the billing package rather than the API layer, that the reporting service reads the same shape, and that a mobile client decodes the payload strictly so an unknown field fails the parse there. The change lands in 4 files rather than 1, and the fourth is the one that would otherwise have become next year’s incident. That is where accuracy of code above 93% comes from, and it arrives at roughly 80% less token spend.
Before the code merges. We trace what a change touches, generate tests for it, run them, then review each modified file against what that file promised at the indexed base rather than against what the diff claims it changed. Collateral damage is checked across the other repositories reading the same helper before anyone approves. A full pass came to 87,001 tokens at $0.11.
That second step is what stops debt entering rather than cataloguing it afterwards. Reviewers read a short list of real problems instead of 3,000 lines, which is the only version of review that survives this throughput.
It also finds the debt you already have
The layer is derived from running code rather than written forward, so it reports what a system currently does rather than what somebody intended it to do.
That surfaces a category of thing nobody was tracking. Asked whether a feature already existed, the layer returned a shipped worker with a full queue and retry path gated by a flag that had been off in every environment since March, a closed pull request containing the interface for the same feature abandoned after two reviewers flagged pagination limits, and a documentation page describing a limit the code stopped enforcing 11 commits earlier. About 70% of that feature already existed, and the remaining work was the interface rather than the engine.
Rebuilding what you already have is one of the largest and least visible forms of debt, and it stays invisible precisely because finding out requires reading code nobody has read.
The cost of preventing it against the cost of carrying it
Indexing runs about 0.89, against roughly $30 for the same work by brute force.
Set that against maintenance costs reaching 4 times traditional levels by year two, or against a single week of ungrounded agent work costing eight figures in tokens and producing something nobody wants to maintain.
The honest limitation
The layer prevents a specific class of debt, which is code written without knowledge of what already exists and what it promised. It does not fix bad architecture, it does not refactor anything on your behalf, and it will not rescue a system that was already unmaintainable before agents touched it. Indexing that estate tells you accurately how bad the situation is, which is useful and is not the same thing as fixing it.
A derived layer can also be wrong about what code means, which is why every claim carries a file and a line, and why there is a window after a push where a claim can lag the branch. We also do not cover every language, and Mojo is not indexed today.
This is what ByteBell builds
If this is your problem, index the service your team complains about most and read what comes back. If the derived description surprises the people who own it, you have found the gap that every agent working in that service has been guessing across.
ByteBell is the verifiable context layer for code. We run the LLM compiler pattern, a one time pass where a model reads every file and lowers it into a verifiable code IR capturing purpose, business context and cross repository relationships, on your own infrastructure through Docker, with your source never leaving your environment. Every engineer, on any copilot, queries the same representation through a single MCP url, and every agent edit is checked against it before it lands, using per file SHA-256 diffing so only what actually changed gets examined again. Across 46 Kubernetes ecosystem repositories and 150,000 files we measured roughly 10% higher accuracy at 70% lower cost, on about a fifth of the tokens.