Skip to main content

Command Palette

Search for a command to run...

The Competence Debt of Agentic Coding

AI can write more of the code. The harder question is whether we can still understand the systems it builds.

Updated
22 min readView as Markdown
The Competence Debt of Agentic Coding
M
Engineer. Researcher. Builder. I build things for web, experiment with AI, and interested in research.

A coding agent can now inspect a repository, implement a feature, modify multiple files, run tests, fix failures, and prepare code for review.

That is a remarkable change in software development.

It also creates a problem that is easy to miss when we measure AI primarily by how much code it can produce:

What happens when a codebase grows faster than the developers' understanding of it?

I think we need a name for that gap.

Competence debt.

Technical debt accumulates when implementation choices make a system harder to change later. Competence debt is different. It accumulates when a team delegates implementation faster than it develops or preserves the ability to reason about what was implemented.

  • The code may work.

  • The tests may pass.

  • The pull request may look perfectly reasonable.

But fewer people can explain why the system is designed that way, predict where it will fail, or confidently change it when the requirements stop matching the happy path.

That distinction is becoming more important as AI-assisted development turns into agentic software engineering.

And it suggests that the debate about whether developers should still "write code themselves" is asking the wrong question.

The scarce resource is no longer typing.

It is engineering judgment.


From Code Completion to Implementation Delegation

AI coding tools have moved through several levels of abstraction remarkably quickly.

Autocomplete suggested the next few lines.

Chat interfaces generated functions and explained errors.

Repository-aware assistants could modify larger pieces of an application.

Coding agents increasingly take entire engineering tasks: inspect the codebase, plan changes, edit files, execute commands, run tests, respond to failures, and return something resembling a finished implementation.

OpenAI, for example, describes Codex as capable of working on features, refactors, migrations, debugging, and other engineering tasks end to end. The important change is not that an LLM can produce syntax. We crossed that bridge some time ago.

The important change is delegation.

We are beginning to delegate parts of the implementation process itself.

That can be enormously useful. But delegation changes what the human needs to know.

A developer writing an authentication flow manually has to encounter a series of decisions:

Where does authentication state live?

Which layer owns authorization?

What happens when a token expires halfway through an operation?

How does the UI distinguish unauthenticated, unauthorized, loading, stale, and failed states?

Which errors are safe to expose?

What should be retried?

What happens across multiple tabs or devices?

An agent can make many of those decisions on your behalf.

That is exactly the attraction.

It is also the risk.


Argument That Goes Slightly Too Far

This article started with a video from Philipp Lackner titled If you don't type code yourself, you're falling behind.

Lackner demonstrates an application he says he built largely using AI agents. His argument is interesting precisely because he is not rejecting AI development.

He argues that his previous experience manually implementing concepts such as databases, modular architecture, and build tooling is what allows him to use agents effectively now. He already has a model of what good implementation should look like, so he can inspect what the agent produces, identify problems, and redirect it.

His concern is what happens when developers skip that earlier stage entirely.

If AI generated the architecture you are trying to learn, how do you know whether the architecture is good?

If you have never debugged the underlying mechanism, how confidently can you debug the generated version?

And if the agent keeps fixing problems for you, at what point are you evaluating its reasoning rather than simply accepting another plausible answer?

Those are legitimate questions.

But I would separate them from a stronger claim: that developers must physically type every concept themselves before using AI.

The available evidence does not establish that.

Developers can learn through debugging, code review, experimentation, reverse engineering, documentation, pair programming, and guided use of AI. There is no good reason to turn manual typing into a ritual.

The deeper insight is not that keyboards build expertise.

It is that struggle with the system builds a mental model of the system.

You need opportunities to make predictions, encounter failures, discover why your assumptions were wrong, and revise your understanding.

AI can participate in that process.

It can also quietly remove much of it.


Generation Isn't Comprehension

Imagine asking an agent to implement a real-time notification feature.

The first version works.

The backend emits events. The frontend subscribes. Notifications appear immediately. Tests pass.

Done?

Not necessarily.

  • Now the application reconnects after losing network access.

  • Does it replay missed events?

  • Can the same event arrive twice?

  • What happens when a user opens two tabs?

  • Can an event arrive before the initial API request finishes?

  • Does the client state reconcile with the server state, or do both become competing sources of truth?

  • What happens when the user loses permission while the connection remains open?

  • Does reconnecting create duplicate listeners?

None of these problems requires exotic computer science.

They are ordinary production software problems.

And that is precisely why they matter.

A generated implementation can be locally convincing while leaving system-level questions unresolved.

The dangerous case is therefore not obviously broken AI code.

Broken code is relatively friendly. Tests fail. Exceptions appear. Something tells you to investigate.

The harder case is plausible code built on assumptions nobody inspected.

Software architecture diagram titled “Simple Feature, Complex Reality.” A simple real-time task UI sits above four connected system components: React/Next.js client, API/backend, WebSocket/SSE real-time channel, and PostgreSQL database. Arrows show API requests, initial data fetches, event publishing, database writes, and change-data capture. Five overlaid failure paths highlight reconnect failures, duplicate events, stale client state, expired permissions, and a race between the initial API fetch and live events, illustrating how simple visible behavior depends on complex interactions across system boundaries.

The Evidence on AI Productivity

There is another reason to be cautious about treating generated code volume as engineering progress: research on AI assisted development does not produce one simple productivity story.

GitHub reported a randomized controlled study in which developers using Copilot produced code that scored better on several measures, including readability and maintainability. That is useful evidence against the simplistic argument that AI-generated code is inherently low quality.

But it does not settle the broader question.

A 2025 randomized controlled trial by METR studied 16 experienced open-source developers completing 246 real tasks in repositories they already knew. With the AI tools available during that study, developers took 19% longer when AI use was allowed even though they believed AI had made them faster.

That result needs an important update.

By February 2026, METR said its newer experiment had become difficult to interpret because developers increasingly did not want to work without AI, agentic workflows made time measurement harder, and task selection was changing. METR explicitly said it was likely that developers were receiving more benefit from AI in early 2026 than its earlier experiment had measured, while warning that the newer data could not reliably quantify the effect.

That evolution is more interesting than either headline.

AI tools are changing quickly enough that even measuring productivity has become a moving target.

And productivity itself is not one variable.

  • Are we measuring time to first implementation?

  • Time to an accepted pull request?

  • Number of tasks completed?

  • Review time?

  • Defect rate?

  • Maintainability six months later?

  • Value delivered?

A developer who generates a feature in 30 minutes but leaves two hours of verification work has not necessarily achieved a 4x productivity improvement just because the implementation would once have taken two hours.

The unit of measurement matters.

So does the time horizon.


Agentic Coding Creates Supervisory Engineering Work

One of the most useful concepts emerging from recent research is that AI may not simply eliminate engineering work. It can move the work.

A 2026 longitudinal study of professional software engineers described a shift away from creation toward verification activities and proposed the term “supervisory engineering work” for directing, evaluating, and correcting AI output.

That description matches the direction of agentic development remarkably well.

If an agent writes the implementation, human effort moves toward:

  • defining the task correctly,

  • specifying constraints,

  • supplying relevant context,

  • reviewing architectural decisions,

  • evaluating generated changes,

  • designing meaningful tests,

  • diagnosing failures,

  • and deciding whether the result should ship.

This is not necessarily a bad trade.

For an experienced engineer, it can be excellent.

If I already understand a pattern, delegating repetitive implementation can free attention for the parts where judgment matters more.

But supervisory engineering contains an uncomfortable dependency:

You need enough competence to supervise.

Otherwise, "review the agent's code" becomes circular advice.

  • Review it against what?

  • A passing test suite?

  • The agent's own explanation?

  • Another agent's review?

  • A pull request that looks idiomatic?

Those are useful signals. None automatically establishes that the implementation fits the larger system.


The Review Paradox

This creates what I think of as the review paradox of agentic coding:

The more implementation you delegate because you do not understand it, the less qualified you may be to evaluate the implementation you receive.

Suppose I ask an agent to introduce a caching layer into a system I understand well.

  • I can inspect cache invalidation.

  • I can question the key design.

  • I can identify data that should not be cached.

  • I can reason about stale reads.

  • I can challenge whether caching belongs at that layer at all.

The agent saves implementation time while I retain architectural ownership.

Now imagine I ask it to introduce caching because I barely understand caching but know the application "needs to be faster."

The output may look equally polished.

But my relationship to it is completely different.

I am no longer delegating implementation.

I am delegating a decision I cannot properly evaluate.

That is where competence debt begins.


What Competence Debt Looks Like

Competence debt does not mean "AI wrote this code."

That would make the term useless.

A team could generate most of its implementation with agents and still maintain excellent system understanding.

The debt appears when implementation ownership and understanding separate.

You can look for it through a few symptoms.

A developer can describe what a component does but not why its boundary exists.

Nobody is confident changing generated infrastructure without asking an agent first.

A bug produces repeated prompt-and-patch cycles instead of a causal explanation.

Tests are accepted because they pass rather than because someone understands what behaviors they establish.

Architecture becomes an accumulation of locally reasonable agent decisions rather than a coherent set of deliberate constraints.

Generated abstractions remain because removing them feels riskier than understanding them.

The team knows the repository in fragments, while the agent increasingly becomes the only practical interface to the whole thing.

None of these guarantees failure.

Together, however, they create an uncomfortable engineering condition:

The software remains modifiable, but human understanding of how to modify it safely is shrinking.

Chart showing system complexity rising faster than human system understanding as implementation is increasingly delegated to AI, with the widening gap labeled competence debt.

Passing Tests Are Necessary. They Are Not Architectural Understanding.

Agentic workflows make automated verification more important, not less.

But we should be precise about what tests tell us.

A passing test tells us that the implementation satisfied the behavior represented by that test under the tested conditions.

It does not tell us that the test suite captured the important conditions.

Recent evidence illustrates the distinction.

A July 2026 preprint examining 4,882 agent generated pull requests found that agents included test changes in only about half of the pull requests that modified code under test. Existing tests often left changed executable lines uncovered, particularly in the Python repositories studied. Error-handling constructs were among the most consistently under-tested areas.

That study is a preprint, so its conclusions deserve the appropriate caution. But the failure mode is worth paying attention to.

An agent can generate code.

An agent can generate tests for that code.

The tests can pass.

And we still need someone or some independent evaluation process to ask whether the right behavior was tested.

This is an evaluation problem, not merely a generation problem.

That distinction should sound familiar to anyone working with LLM systems more broadly.

Producing an answer and establishing that the answer is trustworthy are different tasks.

Code generation is no exception.


Architecture Hides: The Boundaries

The highest risk delegation is not necessarily the most complicated looking code.

Often it is the code sitting at boundaries.

Consider a frontend displaying the status of a long running AI job.

At first, the requirement sounds trivial:

Show a loading state until the job finishes.

Then reality arrives:

  • The user refreshes the page.

  • The WebSocket disconnects.

  • The backend finishes while the client is offline.

  • Two browser tabs receive different state.

  • The job fails after partial output has already appeared.

  • The user cancels while a completion event is in flight.

  • The API reports one state while a delayed socket event reports another.

Now the problem is no longer a spinner.

It is a state synchronization problem.

A coding agent can implement each requested behavior individually. The engineering question is whether those behaviors belong to a coherent state model.

  • Which source is authoritative?

  • Which transitions are legal?

  • Which events are idempotent?

  • How does recovery work?

  • What does the user see while truth is temporarily uncertain?

These decisions are architecture.

They are also exactly the kind of decisions that can disappear inside a sequence of successful prompts.

The feature keeps working.

Until several individually reasonable assumptions meet each other.

Then everyone gets to enjoy distributed state management on a Tuesday afternoon.


Should Developers Still Code Manually?

Yes, but not because manual typing has magical properties.

Manual implementation is useful when it forces you to engage with a mechanism you do not yet understand.

If I am learning a new framework, database abstraction, concurrency model, state-management pattern, retrieval system, or agent architecture, generating the entire implementation immediately may optimize the wrong thing.

I get the artifact before I have acquired the model that lets me reason about the artifact.

In that situation, writing part of it myself can be valuable.

So can deliberately breaking it.

  • Tracing requests.

  • Inspecting network calls.

  • Changing an assumption and predicting what will happen.

  • Writing a test before asking the agent for the implementation.

  • Reading the documentation instead of asking for a summary.

  • Reimplementing a small version from first principles.

  • Removing a generated abstraction and observing what breaks.

  • Explaining the data flow without opening the repository.

The objective is not to prove that I can survive without AI.

The objective is to build enough understanding that AI becomes leverage rather than dependency.

That gives us a better rule than "never generate what you haven't hand-coded."


The Delegation Test

Before delegating a meaningful implementation to a coding agent, I would ask six questions.

1. Can I define the boundary?

I should know what this component or service owns and what it explicitly does not own.

If I cannot define the boundary, the agent will effectively define it for me.

2. Can I state the important invariants?

What must remain true regardless of implementation?

For authentication, perhaps authorization must always be enforced server-side.

For payments, an operation might need to be idempotent.

For synchronized state, there needs to be a defined source of truth.

Without invariants, "working code" is an underspecified target.

3. Can I predict the important failure modes?

I do not need to predict every bug.

I should be able to name the failures that would materially change the design: retries, concurrency, stale data, partial completion, permission changes, network interruption, malformed input, or dependency failure.

4. Can I evaluate the architecture, not just the diff?

A generated change can be clean in isolation and wrong for the repository.

Does it introduce another state-management mechanism?

Duplicate an existing abstraction?

Put business rules in the UI?

Create unnecessary coupling?

Ignore an established error model?

The question is not simply, "Is this code good?"

It is, "Does this code belong here?"

5. Can I design a test that could prove the agent wrong?

If all my tests reproduce the agent's assumptions, I have built a confirmation loop.

Good evaluation requires trying to falsify the implementation.

What boundary condition would expose the design?

What state transition is most likely to break?

What assumption should I deliberately violate?

6. Could I debug the system if the agent disappeared?

Not rebuild every line from memory.

Debug it.

Could I trace the data flow?

Locate the responsible layer?

Form a hypothesis?

Inspect the relevant state?

Explain why the failure occurred?

If the answer is no, I have probably delegated more understanding than I should have.

The Delegation Test” showing a six-step software engineering decision framework: 1) Define the boundary, 2) State the invariants, 3) Predict failure modes, 4) Evaluate architecture, 5) Design falsifying tests, and 6) Debug without the agent. The steps lead to a decision: “Does the mental model exist?” A green “Yes” path leads to “Delegate implementation — when the mental model exists,” while a red “No” path leads to “Learn / experiment first — when it does not.

AI Should Compress Implementation, Not Eliminate Learning

There is a tempting conclusion to all of this: perhaps experienced developers get AI and junior developers should avoid it.

I don't think that follows.

AI can be an extraordinary learning tool.

  • Ask it why an implementation failed.

  • Ask for three competing architectures and compare their trade-offs.

  • Ask it to critique your design.

  • Ask it to generate adversarial test cases.

  • Ask it to explain an unfamiliar repository.

  • Ask it for a minimal reproduction.

Then verify those explanations against documentation, code behavior, and experiments where the distinction matters.

The important variable is not whether AI participates.

It is whether the learning loop still requires the developer to predict, inspect, test, explain, and revise.

Used that way, an agent can accelerate learning.

Used differently, it can accelerate the production of artifacts while leaving understanding almost stationary.

That is competence debt in its simplest form:

The system learns to grow faster than the engineer learns to understand it.


Senior Engineers Aren't Automatically Safe Either

It would also be convenient to frame competence debt as a junior-developer problem.

That would be wrong.

Experience helps because existing mental models make generated output easier to evaluate.

But agents also make it easier for experienced engineers to operate outside their strongest domains.

  • A frontend engineer can suddenly generate infrastructure.

  • A backend engineer can generate a complex interface.

  • An application developer can generate deployment configuration.

  • A machine-learning researcher can generate a production API.

Sometimes that is exactly what we want.

But AI's ability to make unfamiliar code look familiar can blur an important distinction:

I can understand this code is not the same claim as I understand this domain.

The further we move outside our competence, the more important external verification becomes: documentation, domain experts, stronger testing, static analysis, security review, observability, and explicit uncertainty.

Agentic coding expands what an individual can attempt.

It does not automatically expand what that individual is qualified to approve.


The Engineering Skill That Becomes More Valuable

If agents continue improving, some implementation skills will probably become less economically scarce.

That does not imply engineering becomes less technical.

It changes where technical depth pays.

A developer working effectively with coding agents needs to become better at:

  • Problem decomposition. Giving an agent a large vague requirement is still giving the system a large vague requirement.

  • Architecture. Someone needs to decide boundaries before locally sensible implementations harden into accidental structure.

  • Specification. Agents are much easier to evaluate when success is defined before generation begins.

  • Testing and evaluation. Faster generation increases the value of trustworthy feedback loops.

  • Debugging. When generated implementations fail in unfamiliar ways, causal reasoning becomes more useful than another patch.

  • Observability. Systems we produce faster need to remain inspectable after they ship.

  • Product judgment. Generating the feature is increasingly cheap. Deciding whether the feature solves the right problem is not.

  • Technical taste. Not aesthetic preference, but the accumulated judgment that tells you when an abstraction is earning its complexity.

In other words, AI can reduce the cost of implementation while increasing the relative value of judgment.

That is a very different future from "developers no longer need to know how code works."


The Metric I Would Watch

Teams adopting coding agents will naturally measure output.

  • Pull requests completed.

  • Tickets closed.

  • Lead time.

  • Lines changed.

  • Agent acceptance rate.

  • Those numbers are useful.

But I would add another question to engineering reviews:

Is our ability to explain and modify the system growing at roughly the same rate as the system itself?

That is harder to put on a dashboard.

You can still look for proxies.

  • Can engineers explain critical data flows?

  • How often do generated changes require follow-up fixes?

  • Do reviewers understand why an abstraction exists?

  • Can someone debug failures without immediately handing the problem back to an agent?

  • Are tests derived from system requirements or mostly generated alongside the implementation?

  • How concentrated is architectural knowledge?

  • How frequently do engineers discover that a generated component duplicates something already in the codebase?

The goal is not to punish AI usage.

Quite the opposite.

If agents dramatically increase implementation capacity, engineering organizations need feedback mechanisms that scale with that capacity.

Otherwise we optimize the easiest part to measure the amount of software produced while quietly losing control over the harder part: our ability to reason about it.


Vibe Coding To Agentic Engineering

"Vibe coding" was useful terminology because it captured a new behavior: describing what you want, accepting generated changes, and iterating until the software appears to work.

That can be perfectly reasonable for prototypes, experiments, throwaway tools, and low-consequence projects.

The mistake is treating the same relationship with code as sufficient for every system.

Production engineering adds constraints that demos are allowed to ignore.

  • Security.

  • Recovery.

  • Observability.

  • Maintainability.

  • Data integrity.

  • Permissions.

  • Migration.

  • Performance.

  • Accessibility.

  • Cost.

And the wonderfully inconvenient fact that users will eventually do something nobody included in the prompt.

Agentic engineering therefore needs to be more than sophisticated vibe coding.

It needs a different contract between developer and agent:

Delegate implementation aggressively when the feedback loop is strong. Delegate architectural judgment cautiously. Never delegate responsibility invisibly.

That does not mean humans must manually type every line.

It means somebody still has to own the mental model.


The Real Risk Isn't Forgetting Syntax

Developers have always moved up abstraction layers.

Assembly did not make machine behavior irrelevant.

Garbage collection did not make memory irrelevant.

Frameworks did not make HTTP irrelevant.

Cloud platforms did not make distributed systems irrelevant.

Each abstraction allowed us to ignore some implementation details most of the time.

But when the abstraction leaked, understanding what sat underneath remained valuable.

Coding agents may become another enormous abstraction layer.

Perhaps one of the largest we have introduced.

That makes the question of what developers should memorize less interesting.

I am not particularly worried about whether a developer remembers the exact syntax for an API an agent can retrieve in seconds.

I am much more interested in whether that developer understands the system well enough to notice when a perfectly valid API call is being made in the wrong architecture.

The future of software engineering is unlikely to be humans competing with agents over who can type code faster.

Agents have already made that contest rather silly.

The more important contest is between implementation speed and understanding.

If implementation wins by too much, we accumulate competence debt.

And unlike a compiler error, competence debt does not announce itself immediately.

  • The software keeps shipping.

  • The repository keeps growing.

  • The agents keep producing convincing patches.

Everything looks fine until someone has to understand why the system behaves the way it does.

Then the debt comes due.


A Practical Challenge

Take one substantial AI-generated change from your recent work.

Do not ask the agent to explain it. Instead, map it yourself.

  • Where does the data enter?

  • Where is state owned?

  • What assumptions must remain true?

  • What are the three most important failure modes?

  • Which test would expose the weakest assumption?

  • And if production broke tonight, where would you start debugging?

If those answers are clear, the agent probably gave you leverage.

If they are not, generating another patch may not be the next step.

Understanding the one you already have probably is.