Open Weight Thoughts
All articles

· 7 min read

Your AI Agent Has Read the Entire Codebase and Would Now Like to Start Over

By K. Schneider

  • satire
  • guides

Satire notice: the following is a completely normal engineering workflow in which an AI agent reads 1.8 million lines of code, develops the serene confidence of a first-year architect with a fresh diagramming tool, and recommends deleting the application before lunch. No existing company, team, or increasingly warm GPU cluster was harmed in the preparation of this guidance.

The diagnosis arrives promptly

You ask the agent a modest question: “Where is the logic for retrying failed invoice webhooks?” It searches the repository, follows imports through seven services, indexes a folder named legacy_do_not_touch_final_v3, and returns a 4,000-word assessment. The retry logic, it explains, is “distributed across an organically evolved system of implicit state transitions.” This is technically correct, in the same way that describing a flooded basement as “a decentralized indoor water feature” is technically correct.

The agent has now seen the entire codebase. It has read the comments written during the outage of 2019, the comments that apologize for the comments written during the outage of 2019, and the TODO placed there by a developer who is now a senior vice president at a company that sells artisanal feature flags. It knows that BillingService2 calls BillingService, which calls an adapter named DefinitelyNotBillingService, which writes a row to a table named new_payments_old.

At this point, the agent is no longer interested in webhooks. It would like to discuss your values.

Phase one: establish that the past was a mistake

A capable agent begins diplomatically. It proposes “an incremental modernization plan.” The plan has six phases, each marked low risk, and each requiring the replacement of a subsystem that processes all company revenue. It notes that the existing architecture contains duplication, tight coupling, unclear ownership boundaries, legacy abstractions, insufficient tests, overly broad tests, and a file called utils.py that is “doing too much.”

This is when the team learns an important distinction: an agent can understand a codebase’s structure without understanding why that structure survived contact with customers. It can infer that two nearly identical validation functions should be consolidated. It cannot, without being told, infer that one rejects Norwegian postal codes because a payment processor once interpreted the letter Ø as a light personal challenge.

Naturally, the agent identifies three implementations of the same concept. You explain that each exists for a reason. The agent asks for the reasons. You link five incident documents, two vendor tickets, one legal interpretation, and a screenshot of a Slack message containing the words “do not deploy this on Friday.” The agent thanks you and updates its recommendation from “delete immediately” to “deprecate behind a compatibility layer before deleting immediately.”

Phase two: produce the clean architecture

The proposed replacement is beautiful. There is a domain layer, an application layer, an infrastructure layer, a policy layer, an orchestration layer, and a small memorial layer that preserves the original behavior until all stakeholders can be located. Every dependency points inward. Every type is explicit. Every function has one responsibility, except runBusiness, which coordinates the business.

The agent recommends replacing 43 services with a single modular monolith, then decomposing that monolith into 43 services only after its boundaries are proven. It recommends event sourcing because your system has events; a graph database because users have relationships; a vector database because somebody once typed the word “semantic” in an issue; and a rules engine because the business has rules. The resulting architecture diagram resembles a transit map for a city that has outlawed walking.

  • Replace the home-grown queue with a managed queue, after reproducing every undocumented home-grown queue behavior.
  • Unify all date handling in UTC, except for the jurisdictions where date handling must not be unified in UTC.
  • Remove dead code once the agent has established that none of it is secretly run by a cron job on an unlabelled virtual machine.
  • Migrate to a typed API contract, preserving the endpoint that returns HTTP 200 with an error embedded in a JPEG for backward compatibility.

Phase three: discover the hostile environment known as production

Then someone asks the smallest possible question: “What happens to the integration partner that sends XML over FTP every other Tuesday?” The agent pauses. It has found the connector. It has found the parser. It has found 14 tests, all skipped. But it has not found the contract, because the contract exists as a scanned PDF inside an email attachment forwarded to a shared mailbox whose password is maintained in a break-glass envelope beneath a commemorative office plant.

The rewrite plan now receives its first exception. Then its second. Then a temporary compatibility mode. Then a feature flag. Then an option called preserve_legacy_semantics, defaulting to true. By the end of the afternoon, the clean replacement has recreated the old subsystem with fewer comments and a more hopeful folder structure.

This is not a failure of artificial intelligence. It is the traditional fate of all systems that encounter requirements. The original codebase was not built by people who woke up yearning to create InvoiceAttemptFinalFinal. It was shaped by deadlines, partial migrations, customers with contracts, database locks, changing regulations, and one incident where the only safe fix was to add a boolean called isActuallyPaid.

How to use the agent without joining its rewrite program

The solution is not to deny the agent repository access, although putting it in a room with a single unit test and a stern note remains a valid security posture. The solution is to give it bounded work and demand evidence. Ask it to map a flow, identify callers, explain a specific invariant, draft tests around current behavior, or propose a migration that can be stopped halfway through. Treat broad refactor recommendations as design hypotheses, not archaeological verdicts.

  1. Ask what observed behavior supports each proposed change.
  2. Require a list of assumptions, especially about external consumers and data migrations.
  3. Have the agent identify the smallest reversible step before it designs the destination state.
  4. Make it write characterization tests before it touches suspicious logic.
  5. Keep a human responsible for knowing which ugly behaviors are, regrettably, product features.

The final finding

Eventually, after enough context and enough corrections, the agent may return to your original question about retrying invoice webhooks. It will explain the path accurately, flag two real risks, and suggest a narrow patch. It may even mention that the system should eventually be simplified, which is fair. A codebase is not evidence of moral weakness; it is evidence that software has had to keep working while the world changed. And the true observation worth keeping is this: AI can make understanding a large codebase faster, but it cannot remove the need to learn why the code is the way it is.