Blog/AI Is Making Coding Cheap. Software Engineering Is the New Bottleneck.

AI Is Making Coding Cheap. Software Engineering Is the New Bottleneck.

By Daniel OspinaΒ·Oct 18, 2026 Β·agent-memory epistemic-memory memory-systems
Share 𝕏 in f wa
𝕏 in wa

I recently spent five days unable to merge a single pull request.

I had more than 100 PRs piling up. My coding agents had created so much interconnected complexity in the CI pipeline that the whole development process had become paralyzed.

The absurd part was that I had agents actively trying to fix it. But every time I sent one to investigate, it would get sidetracked by another problem, attempt a local fix, and often create yet another PR that couldn't merge.

More work was being done. More code was being written. More problems were being addressed.

And the situation kept getting worse.

Eventually, I changed my approach, using multiple agents in parallel to investigate different parts of the problem rather than relying on a single hierarchical orchestration process. That helped me untangle the mess, but only after I started dogfooding our product as a shared layer for the agents to organise their learnings.

The experience exposed something much more fundamental about agentic software development.

We are getting remarkably good at making agents execute individual tasks. We are not nearly as good at making them maintain a coherent understanding of the broader systems they're building.

And as coding becomes cheaper, that distinction is becoming increasingly important.

Coding is getting cheaper. Engineering isn't.

There's a difference between writing code and engineering software.

Writing code means translating requirements into executable instructions. Of course, this can require considerable creativity and problem-solving. But given sufficiently clear requirements, constraints, and acceptance criteria, the work can often be decomposed into relatively independent tasks.

This is where coding agents are becoming extraordinarily capable.

Software engineering involves something broader: understanding the problem being solved, designing a coherent system around it, making trade-offs, anticipating consequences, and continuously revising that design as our understanding evolves.

A software engineer doesn't simply ask, "How do I implement this feature?"

They also ask:

These questions aren't necessarily harder because they require more intelligence. They're harder because they require a broader and more persistent understanding of the system.

And the distinction matters economically.

As the cost of implementation falls, the relative importance of deciding what to implement, how the pieces should fit together, and when previous decisions need revisiting increases.

We are shifting from a world where execution was often the bottleneck to one where coherent decision-making increasingly becomes the constraint.

There is already evidence of the gap.

In CodeTaste, a 2026 research paper presented at ICML, researchers examined whether coding agents could carry out the structural refactorings that human developers had made in real codebases.

The agents performed relatively well when the desired refactoring was specified in detail. But they often struggled to identify which refactoring was appropriate when given a broader area to improve.

Executing a good architectural decision is not the same as discovering which architectural decision should be made.

Death by a thousand plans

This problem becomes more pronounced as we move from individual coding agents to multi-agent systems.

Imagine five agents working on different parts of a product.

One is implementing authentication. Another is building permissions. A third is handling user invitations. Two others are building administrative interfaces and audit logs.

Each agent receives a task, defines a plan, implements its changes, and passes its tests. Everything looks productive.

But perhaps the authentication agent introduces one representation of user identity, the permissions agent creates another, and the invitations agent invents a third abstraction to deal with temporary membership.

Each choice may be defensible within its assigned task. Together, they introduce unnecessary complexity into the architecture.

The problem is not necessarily a lack of coding ability. It's local optimization at the expense of global coherence.

William David Louth explores this problem in his essay, *Agentic Coding: Death by a Thousand Plans*.

One of his central observations is that the decomposition of work into separate tasks can gradually become the architecture itself.

Boundaries originally introduced for coordinating agents harden into technical boundaries. Decisions made to simplify task allocation become permanent abstractions.

And once an agent has completed its assigned task, reopening the broader architectural question becomes expensive. It risks invalidating work that has already been declared finished.

So the system rewards local completion and discourages global reconsideration.

This is a familiar organizational problem.

We've known for decades that teams optimizing their own KPIs can collectively undermine the goals of the organization.

Sales maximizes contracts. Operations minimizes costs. Product maximizes feature delivery. Each department succeeds according to its own metrics while the company becomes less effective.

In organizational design, we address this through shared objectives, coordination mechanisms, and an understanding of how individual decisions contribute to the larger mission.

With coding agents, we're rediscovering the same problem at machine speed.

A thousand obedient agents can be just as dysfunctional as a thousand poorly coordinated employees, except the agents can produce a lot more code before anyone notices.

Software engineering is theory building

This distinction is not new.

In 1985, computer scientist Peter Naur published *Programming as Theory Building*90032-8), one of the most insightful essays on what it actually means to develop software.

Naur challenged the idea that the main product of programming is source code or documentation.

Instead, he argued that the essential activity is developing a theory of how the system solves a problem.

The code is an expression of that theory, but it is not the theory itself.

Consider an experienced engineer working on a mature codebase.

They may know that a particular abstraction looks unnecessarily complicated but exists because of an obscure customer requirement.

They may remember that the team deliberately rejected a seemingly cleaner design because it created unacceptable consistency problems.

They may recognize that two apparently unrelated features are manifestations of the same underlying business concept.

Much of this understanding isn't visible in the code.

And even when decisions are documented, knowing that a decision was made is not necessarily the same as understanding the reasoning that produced it.

A good engineer carries a mental model of the system: its purpose, structure, constraints, history, and the relationships among its parts.

That model is continuously revised.

Sometimes implementing a feature reveals that the original abstraction was wrong. Sometimes a new customer requirement invalidates a decision made months earlier. Sometimes a bug exposes an assumption nobody realized they were making.

Engineering is not simply executing a theory. It is building and revising that theory through interaction with the system.

Now consider what happens when development is distributed across dozens or hundreds of short-lived agents.

Each agent forms some understanding of the problem within its context window. It makes decisions, produces code, and terminates.

The code persists.

The task log persists.

Perhaps a summary of the decisions persists.

But much of the reasoning that connected the problem, its constraints, and the chosen solution disappears with the session.

The next agent must reconstruct that understanding from whatever artifacts remain.

We're automating the production of software faster than we're developing the infrastructure to preserve the understanding behind it.

Why better instructions aren't enough

One response to this problem has been to give agents increasingly elaborate instructions.

We create agents.md files, architectural guidelines, coding standards, skills, custom agents, and increasingly sophisticated orchestration workflows.

These are useful. Clear constraints and automated verification can prevent many mistakes.

But they run into an old management problem.

Following the rules is not the same as understanding why the rules exist.

Suppose an engineering team establishes a rule that all new data access must go through a specific caching layer.

There may be an excellent reason for that rule. Perhaps the database was struggling under heavy read traffic, and the caching layer was introduced to protect it.

An agent instructed to follow that rule will dutifully use the cache.

But what happens when the application introduces a requirement for immediate revocation of access permissions?

The original caching strategy may now introduce unacceptable delays in enforcing those changes.

An agent that merely remembers the rule may keep applying it.

An agent that understands the reasoning behind the rule can recognize that a new requirement changes the trade-off.

It can ask whether the rule still applies, whether an exception is needed, or whether the architecture itself should be reconsidered.

This is management 101.

Good managers don't simply give employees instructions. They communicate objectives, context, constraints, and the rationale behind decisions so people can exercise judgment when circumstances change.

We need to do something similar for agents.

And there is another problem: even excellent instructions are often downstream of an architectural decision.

When we divide a project into tasks, we've already made assumptions about how the system should be decomposed.

Making those tasks more precise can improve execution. It doesn't necessarily make the decomposition correct.

At some point, an agent needs enough understanding of the system to challenge the task itself.

The missing piece isn't more memory. It's better reasoning over memory.

A natural response is to give agents persistent memory.

And there's been an explosion of products attempting to solve this problem.

Some maintain Markdown files summarizing what happened. Others use vector databases to retrieve relevant information from previous sessions. Knowledge graph systems add structure by connecting entities and facts.

These approaches solve an important problem: agents can access information that would otherwise disappear when their context window resets.

But retrieval is only part of what we need.

Imagine an agent asks:

Why did we choose architecture A?

A conventional memory system may retrieve a document explaining that architecture A was selected because of requirements X and Y.

That's useful.

Now imagine requirement X changes.

What should happen?

A retrieval system can find documents related to X. It might even surface the original architectural decision.

But it doesn't necessarily know which conclusions depend on X, whether those conclusions remain justified, or which other decisions need reconsidering.

That requires more than similarity search.

It requires an explicit model of the logical relationships between what the system knows.

And simply moving information from Markdown into a knowledge graph doesn't automatically solve the problem.

A graph of entities and relationships can still be little more than a structured filing cabinet.

The important distinction is whether the relationships represent meaningful dependencies that can support reasoning and revision.

Consider a chain of decisions:

Customer need β†’ Product requirement β†’ Technical constraint β†’ Architectural decision β†’ Implementation

In reality, the relationships are more complex than a linear chain. A single architectural decision might depend on several assumptions, support multiple requirements, and conflict with other design choices.

When new evidence arrives, we need to understand how it affects this interconnected model.

If an assumption becomes less credible, which conclusions become questionable?

If two sources disagree, what evidence supports each position?

If a constraint disappears, which design decisions might now be unnecessarily complicated?

And if one agent discovers that an earlier assumption was wrong, how does that discovery affect the work being done by other agents?

The goal is not merely to retrieve the right information. It's to understand what that information implies.

From memory to a cognitive layer

This is the direction we're pursuing with Tortoise.

Rather than approaching agent memory primarily as storage and retrieval, we're building what we think of as a β€œcognitive layer” that enables collective reasoning, memory, and learning.

The idea is to give agents a logical model of how different pieces of knowledge depend on one another.

At the core is a graph of beliefs, evidence, and logical relationships.

Claims can support or contradict one another. Decisions can be connected to the assumptions and trade-offs that motivated them. Confidence can evolve as evidence accumulates, with changes propagating through explicit dependencies.

Consider the earlier caching example. A team made a decision based on the belief that eventual consistency was acceptable for a particular operation. That belief supported an architectural choice, which in turn informed several implementation decisions.

Months later, a new requirement establishes that some permission changes must take effect immediately.

In a conventional memory system, those two pieces of information might coexist until an agent happens to retrieve both and recognize the conflict.

In a cognitive system, the new requirement can challenge the original assumption, affecting the confidence of dependent conclusions and making the relevant architectural decisions candidates for reconsideration.

This doesn't mean an agent should automatically rewrite the entire architecture.

The purpose is to make the implications explicit, so agents and humans can investigate, reason, and decide without having to reconstruct the entire history from scratch.

The same principle extends beyond software architecture.

A business strategy depends on assumptions about customers, markets, costs, and competition. Product requirements depend on assumptions about users and their problems. Operational processes depend on assumptions about how the organization works.

All of these are interconnected systems of beliefs that need to evolve as new information arrives.

We're particularly interested in making that reasoning persistent and shareable across agents.

Not just five agents with access to the same documents, but five agents capable of building on a common model of the problem they're solving.

Making reasoning more explicit, traceable, and computable is a meaningful step toward agents that can sustain complex work over time.

From orchestration to shared understanding

Today, much of the discussion around multi-agent systems focuses on orchestration.

How do we divide tasks? Which agent should do what? How do agents communicate? How do we verify their work?

These are important engineering questions.

But coordination and shared understanding are not the same thing.

An orchestrator can tell an agent what to do. It doesn't automatically provide the context needed to evaluate whether that task still makes sense.

A dependency graph can indicate that task B must happen after task A. It doesn't necessarily explain why the tasks were separated, what assumptions informed that choice, or when the separation should be reconsidered.

And a shared memory store can make information accessible to everyone without ensuring that everyone reasons from a coherent set of assumptions.

As agent teams grow, these distinctions become increasingly consequential.

Imagine a system where one agent discovers a new requirement that undermines an architectural choice.

That discovery should not remain confined to its session or its assigned task.

Other agents working on dependent components should be able to recognize that their plans may need revision.

The planning process itself should be open to reconsideration.

And ideally, the system should distinguish between information that merely changed and information whose change has meaningful consequences elsewhere.

This is a different ambition from simply making agents faster at completing tasks.

It's about enabling agents to participate in the ongoing process of systems engineering.

We need to change what we measure

Much of how we evaluate coding agents still emphasizes localized success.

Can the agent implement a feature? Fix a bug? Pass a test suite? Resolve a GitHub issue?

These are valuable measurements, but they tell us relatively little about whether the resulting system becomes easier or harder to maintain.

A 2026 study, *Is Agent Code Less Maintainable Than Human Code?*, explored what happens when agents have to build on code previously written by other agents.

The researchers found that the share of downstream tasks resolved fell by up to 13.1% when agents worked on agent-authored code rather than comparable human-authored code.

That doesn't establish that agent-generated software is universally less maintainable. But it illustrates why evaluating individual tasks is insufficient.

The quality of an engineering decision is partly revealed by what happens next.

Can future changes be made cleanly?

Do abstractions remain coherent?

Can new requirements be incorporated without unnecessary complexity?

Can the system distinguish between an implementation bug and a flawed architectural assumption?

And, perhaps most importantly for autonomous agents:

When new evidence challenges an earlier decision, can the agents identify what needs to change and explain why?

These are the kinds of capabilities we'll need to evaluate as agentic development evolves.

We should be measuring not just how quickly agents produce correct code, but how effectively they maintain and improve the systems they're responsible for.

The next frontier is agentic software engineering

None of this means coding agents are inherently incapable of architectural reasoning.

They can already contribute to architecture, challenge requirements, identify design flaws, and propose sophisticated solutions.

The problem is sustaining that reasoning across time, tasks, agents, and changing circumstances.

A capable model with incomplete or outdated context can still make a poor decision.

A sophisticated orchestrator built around flawed assumptions can coordinate an enormous amount of counterproductive work.

And a memory system that retrieves everything an agent has ever done may still fail to preserve the understanding needed to decide what should happen next.

As implementation becomes cheaper, the leverage from getting architectural decisions right becomes greater.

This has implications for how we build software teams, how we evaluate agents, and what infrastructure we give them.

We will still need good models, testing, verification, documentation, and orchestration.

But we also need agents that can maintain an evolving conception of the systems they're building: their goals, constraints, assumptions, decisions, and the relationships connecting them.

Agents that don't just execute plans, but have enough context to question and improve those plans.

Agents that don't just remember previous decisions, but understand the reasoning behind them.

Agents that can learn collectively rather than repeatedly rediscovering the same lessons.

The question is shifting from how much code can our agents write? to how much of the system can our agents understand and safely evolve?

The next breakthrough in agentic coding won't be measured only in lines of code, completed tasks, or agents running in parallel.

It will be measured in how well agents can engineer coherent systems, and keep them coherent as they change.

That's the transition from coding to systems engineering. And it's why we believe the future of agent memory needs to look less like a filing cabinet and more like a cognitive layer.

More from the blog β†’ Follow Tortoise updates via RSS.