An engineer directs an AI assistant assembling modular computer components from a blueprint, beside historical punch cards.

Software Engineering Is Moving Up a Layer. Again.

October 13, 2026

Software engineering is moving up a layer of abstraction. AI agents make it easier to turn a design into code, and this is a much bigger jump than moving from one programming language to another. We can now delegate parts of implementation that previously required a person to express the solution explicitly. The fundamental job remains: understand the problem, choose a structure that fits it, and establish that the resulting system behaves correctly.

The profession has a long history of handing mechanical work to better tools. Punch cards, assemblers, compilers and managed runtimes each changed the relationship between the engineer and the machine. AI continues that history while expanding the scope of what we can delegate.

From punch cards to managed runtimes

For many early programmers, writing software involved preparing decks of punched cards and submitting them for execution. The Computer History Museum documents their use as an input and storage medium for programs. Cards could hold assembly or higher-level source code; they were the physical interface through which programmers delivered instructions to the machine.

Assembly provided a symbolic way to work with machine instructions. An assembler translated mnemonics and symbolic references into machine code, but the programmer still worked close to the processor: registers, instructions and explicit control flow remained central to expressing the solution.

Before high-level languages became practical, programmers worked much closer to machine instructions. IBM’s history of Fortran describes how its commercial release in 1957 allowed mathematical expressions to be translated automatically into machine code. Developers could express computations at a level closer to the problem and let the compiler handle the lower-level representation.

Languages and runtimes continued to take over responsibilities. JavaScript, like other garbage-collected languages, handles memory allocation and reclamation automatically. Developers generally create objects and let the runtime recover memory when those objects become unreachable, instead of explicitly allocating and freeing it.

Memory management still happens. Developers still need to care about retained references, unbounded caches and memory pressure. But much of the bookkeeping has moved below the level at which they normally write application logic.

Across these changes, more machine detail moved into tools and runtimes. Engineers could spend more attention on the behavior they wanted to express. The underlying system still needed a coherent design.

AI is a much bigger jump

A compiler takes a solution already expressed in a formal language and translates it. A garbage collector manages memory according to runtime rules. Both remove work while leaving the programmer responsible for explicitly describing the program’s logic.

An AI agent can take a task description, inspect an unfamiliar repository, propose an approach, write changes across several files, run tests and revise the result. It operates across decisions and activities that previously sat on the programmer’s side of the abstraction boundary. That is why the jump is much larger than another language or runtime improvement.

This also changes who can participate in implementation and how experienced engineers divide their time. More work can begin with intent, examples and constraints, while the tool supplies an initial solution and its code. Architects can explore alternative structures with less manual implementation effort.

The compiler comparison captures the direction of the change: more translation is delegated. It does not capture its full magnitude. Agents interpret incomplete intent and propose solutions, so their abstraction boundary is broader and less predictable than the boundary around a conventional compiler.

Acknowledge the size of the shift, then judge it by the engineering work it enables. The methods and economics can change radically while the obligations to design, verify and operate a useful system remain.

Easier expression leaves the design problem intact

Fred Brooks gave us a useful distinction in No Silver Bullet: the essential difficulty of specifying and designing software, and the accidental difficulty introduced by the way we represent and implement it. Higher-level languages removed substantial implementation friction without making the underlying design decisions disappear.

Agents can reduce that friction further. They can also help investigate a design, compare alternatives and find mistakes. But the availability of suggestions does not remove the need to resolve conflicting requirements or justify a tradeoff.

Take a payment-processing service. Producing an endpoint, database migration and queue consumer can be straightforward with an agent. Deciding what happens when a payment provider times out after accepting a charge is still a system-design problem.

A retry may duplicate a charge. Refusing to retry may leave an order in an uncertain state. An idempotency key helps only if its scope, persistence and provider behavior support the guarantee you need. You also need a way to reconcile local state with the provider’s state after a crash.

The agent can implement those decisions. It may even propose them. But if the requirements never specify how uncertainty should be handled, a plausible implementation can quietly become the product policy.

That was a risk when humans wrote every line, too. Faster generation simply gives an unexamined assumption less time to attract attention.

The architectural pattern still has to earn its place

Cheaper implementation makes more patterns accessible. An agent can scaffold a modular monolith, introduce an event consumer or generate service clients. It can make it cheaper to explore alternatives before committing to one.

It does not make those alternatives equivalent.

For a small team whose core operations share transactional data, I would generally start with a modular monolith and explicit boundaries. Splitting it into services should answer a concrete requirement: independent deployment, isolation, ownership or scaling. The fact that an agent can generate six services is a poor reason to operate six services.

Similarly, asynchronous messaging earns its complexity when buffering, decoupling or latency requirements justify it. It also introduces questions about duplicate delivery, ordering and recovery. Generating a consumer faster does not change those properties.

DORA’s research on loosely coupled teams emphasizes the ability to implement, test and deploy independently. That is a useful architectural objective because it describes what a structure enables. A pattern name on a diagram is much less informative.

My view is that agents increase the value of clear boundaries. A bounded change with explicit contracts is easier to delegate and easier to check. If changes routinely cross unclear ownership and data boundaries, producing them faster can increase the integration burden.

DORA’s 2025 report describes AI as an amplifier of an organization’s existing strengths and weaknesses. That finding supports the broader argument, although it does not prove that any particular architecture will work better with agents.

The abstraction is useful, but it is less reliable

A conventional compiler translates a formally defined language and is expected to preserve its specified semantics. An agent often interprets incomplete intent, infers missing details and uses external tools. Its output can look coherent while implementing the wrong assumption.

GitHub’s application card for Copilot Agents acknowledges hallucinations and the need to review and validate generated outputs. This matters to the analogy: we are moving to a higher abstraction, but the translation boundary needs more explicit verification.

Dijkstra argued in The Humble Programmer that abstraction should let us reason precisely at a new semantic level. That is a better goal for agent-driven work than writing shorter, vaguer requests.

For the payment service, a useful specification would state that the same logical request must not create multiple charges; a timeout must preserve an explicit uncertain state; and recovery must consult the provider before deciding whether to retry. Those are behavioral obligations an implementation can be checked against.

Tests, static analysis and review remain part of the process. They need to check the requirement independently of the generated implementation. Asking an agent to write both sides does not establish correctness if both encode the same mistaken assumption.

Less manual coding does not guarantee faster delivery

There is evidence that AI assistance can improve productivity. Three randomized field experiments covering 4,867 developers reported a pooled 26.08% increase in completed tasks. The individual experiments were noisy, and the intervention was a coding assistant rather than a fully autonomous engineering agent.

The result is not universal. METR’s early-2025 study of 16 experienced maintainers completing 246 tasks found that allowing AI increased completion time by 19%. Its February 2026 update suggested that tools were likely helping more, but selection effects made the size of that improvement difficult to estimate reliably.

These studies measure different settings and outcomes. They support a practical conclusion: measure accepted changes and total delivery effort, including review and rework. Code generation can become easier while another part of delivery becomes the bottleneck.

The strongest case for agents does not need a promise that every task becomes faster. It is enough that more implementation work can be delegated, alternatives can become cheaper to explore, and engineers can spend less attention on mechanical translation.

Engineering moves with the abstraction

The workflow is changing substantially. Engineers increasingly specify, delegate, inspect and refine changes instead of expressing every detail themselves. The economics of implementation are changing with it.

The fundamental obligations remain recognizable: understand the domain, select an architecture for its constraints, establish correctness, and keep the system operable as it changes.

Use agents to make implementation cheaper. Use that freedom to choose the structure the job deserves and to verify it more thoroughly. As code becomes easier to produce, the decisions that give it purpose become more consequential.

Key takeaways

  • AI coding is a much bigger abstraction jump than earlier language improvements: agents can interpret intent and propose implementations, while engineering responsibility remains.
  • Cheaper implementation makes architectural alternatives easier to explore; requirements and operational tradeoffs still determine the right pattern.
  • Precise contracts, invariants and independent verification are essential when agents interpret incomplete intent.
  • Measure accepted outcomes and total delivery effort, including review and rework, rather than code volume alone.
Daniel Arroyo
By Daniel Arroyo
Chief Technical Officer