AI generated code technical debt
Why undocumented decisions are the main source of technical debt in AI generated code and what to capture at the moment you make them.
the short answer
Undocumented decisions are the main source of technical debt in AI generated code, not bad code itself.

The code and tests can look clean yet hide debt because the debt is not in the code. It is in the decisions that shaped the code and were never written down.
The debt is undocumented decisions not bad code itself.
Technical debt in AI generated code rarely comes from bad code. The real debt is the absence of a record explaining why the code looks the way it does and what alternatives were rejected. When you revisit a module months later you do not see spaghetti. You see a clean interface that feels wrong for the new task. The tests pass, the types line up, but the shape fights against the change you must make. Reworking the module to fit the new feature costs a week of work. That week is interest paid on decisions that were never documented.
The issue is not that the code is wrong. The issue is that the reasoning behind it is gone. The original agent or engineer weighed options, accepted constraints and made a call. If that reasoning was never captured, the next person cannot tell whether the shape is deliberate, accidental or a compromise no longer valid. Without that context you cannot safely evolve the code without repeating the same mistakes.
Undocumented decisions also hide risk. A module might use a database table chosen for a short-lived spike rather than durability. Another might expose an internal helper because the agent assumed synchronous execution would never change. These assumptions live in logs or scratch notes that vanish when the agent session ends, so the debt stays invisible until it surfaces as a production incident or a merge conflict at 2 AM.
What to record at the moment a decision is made
The only time you can record the full context is when the decision is fresh. After that the context evaporates. Capture the following before the agent moves on.
The problem you were solving
Write a one-sentence description of the problem the agent was asked to address. Include the user impact and any non-functional requirements such as latency, memory or cost limits. Without this you cannot judge later whether a design choice still makes sense.
Options evaluated and the reason for the choice
List the main alternatives the agent evaluated and why the chosen option won. If the agent rejected a library because of licensing you need to record that, not only the final import statement. If it chose an event-driven pattern over a polling loop you need to state the trade-off between throughput and debuggability. This part is often skipped because the agent assumes the choice is obvious, yet obvious choices change as the system evolves.
Include the constraints that narrowed the options. Was the decision driven by an SLA, a legacy system, a skill gap on the team, or a budget freeze? Constraints are the first thing to become irrelevant but the last thing to be noticed when they are gone.
Assumptions made and open questions left
Write down any assumptions the agent made about the environment, the data or the future. Did it assume a cache would always be warm? Did it assume a third-party API would never add a new required field? Did it assume the team would always prefer simplicity over extensibility? Also list questions the agent deferred, such as performance characteristics it did not measure or edge cases it did not test. These are seeds of future surprises.
If the agent worked in a shared workspace with other agents, record which agent made each decision and why it was the right agent for the job. Overlap warnings arrive when an agent claims work, which the five tools and the workspace each contribute to in different ways.
Why waiting to document later fails
Documenting decisions after the fact is a losing game. The pressure to ship is high and the immediate reward is zero. By the time you revisit the decision the people who made it have moved on or forgotten the details. Even if you schedule a retro you reconstruct a sanitised version of the reasoning, omitting the messy trade-offs that actually drove the choice.
The longer you wait the more expensive the documentation becomes. You must reverse-engineer the context from commit messages, chat logs and tribal knowledge. You will miss assumptions that were never written down. The result is a document that does not reflect reality, so it is ignored or actively misleading.
When multiple agents work on the same repo they make decisions in parallel without seeing each other’s context. Each agent leaves a clean interface and passing tests but the system accumulates conflicting assumptions. Without a shared ledger of intent you cannot reconcile the differences until a runtime failure or a merge conflict forces the issue. By then the cost of correction is high and the original agents are off working on other tasks.
Tooling does not help. Code review flags syntax and style issues, not the absence of a decision log. Static analysis finds unused variables, not undocumented trade-offs. Even agents that support review workflows do not persist the reasoning behind the changes they make. The context lives and dies in the agent session.
A worked example of undocumented decisions
An agent is asked to add a new endpoint to a payments service. The existing endpoints use REST over HTTP with JSON bodies. The agent considers three options: a new REST endpoint, a GraphQL mutation and a gRPC endpoint. It chooses REST because the team knows it well and client libraries already exist.
Six months later another agent is asked to add a second payment provider. The new provider only supports gRPC and requires streaming responses for real-time status updates. The second agent sees the REST endpoint and assumes the team has standardised on REST. It writes a new REST endpoint that talks to the provider’s REST facade, adding latency and complexity. The team later migrates to the new provider and must refactor both endpoints because the original decision to use REST was never recorded.
If the first agent had recorded that REST was chosen for familiarity and client library support, the second agent would have evaluated GraphQL and gRPC from the start. The debt would have been avoided at the source instead of accumulating interest over months.
Another example is a module that caches user preferences in memory for low latency. The agent assumes the service will always run as a single process and never records the cache invalidation strategy. Later the team scales horizontally and the cache becomes inconsistent. The fix requires a distributed cache and a new invalidation protocol, both of which could have been anticipated if the assumption had been documented.
Make documentation part of the workflow
Documentation must be captured the moment a decision is made, not after. The simplest approach is to require agents to append a short rationale to the task record before they finish. That rationale should include the problem, the options, the chosen option and the constraints. It should also list assumptions and open questions. If the agent is working in a shared workspace it can use a tool like start_work to register its presence and surface scope overlaps before editing.
For teams using multiple agents the workspace should let engineers tag decisions and link them to the code they affect. When an agent inspects the workspace it should see not only the files changed but the intent behind those changes. This prevents later agents from making conflicting assumptions and makes it easier to revisit old decisions when context changes.
The key is to make the cost of not documenting higher than the cost of documenting. If the agent must fill a decision log before the task can be marked review-ready, the debt is captured at the source. Over time the workspace becomes a living record of why the code is the way it is, not only what the code does.
If you are coordinating agents across repositories or machines you need a shared workspace that persists context beyond a single session. Concord Cloud is coming soon and will provide that shared state so decisions are visible to every agent, not only the one that made them.
What ignoring undocumented decisions costs you
Ignoring undocumented decisions leads to predictable outcomes: repeated work and production incidents. Each one is a symptom of the same root cause: the system cannot evolve because the original reasoning is lost.
Repeated work happens when a later agent makes the same decision without knowing it was already made. The team ends up with duplicate implementations, each with its own bugs and edge cases. Production incidents occur when an assumption that was never recorded turns out to be false under load or scale.
The cost of these outcomes is not only the immediate remediation. It is the loss of trust in the system and the team. Engineers stop relying on the codebase and start working around it, introducing more duplication and complexity. The debt compounds until a major rewrite becomes the only option.