The Next Rung on the Ladder of Abstraction
The history of software development is, in large part, the history of moving up a ladder of abstraction. At each rung, programmers have surrendered some direct control over the machine in exchange for the ability to tell it to do more.
The least abstracted form of computing available to a software programmer is machine code: numerical instructions executed directly by a processor. Even machine code is technically an abstraction over transistors, electrical signals and the physical architecture of the chip. Nonetheless, from the programmer’s perspective, it is close to the bottom. Early programmers had to think in terms of memory addresses, processor instructions and the exact movement of data through a specific machine.
Assembly language created the first major step upward. Instead of remembering numerical operation codes, programmers could use names and symbols. An assembler translated those symbols into machine instructions. Assembly was easier for humans to understand, but the relationship generally remained one-to-one: the programmer still wrote something approximating one line for every instruction executed by the computer. Higher-level languages such as Fortran introduced a more dramatic breakthrough. A compiler could translate one comparatively understandable statement into many machine instructions.
This is the basic pattern that has repeated throughout the history of software. Each new layer compresses more mechanical work into a smaller unit of human intention.
What Abstraction Actually Means
Abstraction is often described simply as “hiding complexity” which is partly explanatory. Abstraction is the process of taking a complicated system and exposing only the parts necessary to use it for a particular purpose.
A driver does not need to understand combustion chemistry in order to press the accelerator. A person using a microwave does not need to understand the behavior of electromagnetic radiation in order to heat a burrito. Similarly, a programmer calling a function named sort() does not need to manually instruct the processor to compare pairs of values and move data between memory locations until the list is ordered.
An abstraction is therefore something like a contract. The programmer provides an instruction at the higher layer, and the lower layers agree to carry it out. Provided the contract holds, the programmer can stop thinking about the implementation and begin thinking about the objective.
Good abstractions increase what might be called semantic density: the amount of intention contained in a single instruction. A machine-code instruction may move one value from one location to another. A Python function might download a file, process its contents and place the results in a database. The programmer using Python is not necessarily smarter than the machine-code programmer. The programmer has simply inherited several generations of accumulated work.
From Machine Instructions to Human Intentions
The ascent from machine code to assembly language allowed programmers to think in symbols rather than numbers. The ascent from assembly to compiled languages allowed them to think in mathematical operations, data structures and logical procedures rather than individual processor instructions. Operating systems then abstracted away much of the difficulty of interacting with memory, storage, displays and networks. Libraries allowed programmers to reuse solutions created by others. Frameworks allowed them to assemble entire applications around preexisting structures.
Python seemed, for a time, like something close to the final boss of abstraction. Its syntax was comparatively clean, its high-level data structures were powerful and its design made rapid application development far easier than it had been in lower-level languages. Someone looking at a simple Python program might say that it resembled ordinary written instructions.
But Python was never normal language.
A Python program may be readable, but it remains a formal statement addressed to a machine. A computer does not infer that the programmer “basically meant” something else. The programmer must translate his objective into the exact language the system is prepared to accept.
Large language models introduce a new layer. We are no longer merely using a programming language that vaguely resembles normal language. We are beginning to use normal language itself to build software.
A person can now say: “Add a page that allows users to upload a spreadsheet, identify duplicate entries and download a cleaned version. Preserve the existing visual style and add tests.” A coding agent can inspect the existing project, locate the relevant files, form a plan, write the code, run the tests, observe the failures and revise its work.
The instruction does not specify which files to modify, which libraries to import or how the data should move through memory. It specifies an outcome.
Natural language has therefore become a supervisory layer above source code. The LLM translates an ambiguous statement of intent into a more formal plan, which is translated into source code, which is translated into lower-level instructions, which are ultimately executed by hardware.
Abstraction and Agency
Each level of abstraction has increased the agency of the person operating at that level.
Agency, in this context, is the amount of meaningful change a person can produce through a given amount of effort. A machine-code programmer could exercise extraordinary control over a computer, but relatively little control over the wider world. He might spend a day producing behavior that a modern programmer can request through a single library call.
The economic value created at the lower levels remains immense. We still need electrical engineers, chip designers, compiler engineers, operating-system developers and assembly-language specialists. In some contexts—embedded systems, operating systems, high-performance computing and security—their work is irreplaceable.
But most opportunities for economic value appear at the layers with the greatest agency. Businesses generally do not make money because they moved a value efficiently between two processor registers. They make money because they solved a customer’s problem, reduced a cost, created a useful service or coordinated people more effectively.
Higher abstraction allows the programmer to spend less attention on how the computer works and more attention on what the computer should do.
LLM coding agents expand this agency again. A capable software engineer can supervise several streams of work rather than manually producing every line. A domain expert with limited programming experience can create prototypes that previously required a technical team. A small company can attempt projects that would once have been uneconomical. The scarce resource begins to shift away from the mechanical production of code and toward the selection and definition of worthwhile objectives.
This changes which expertise matters at the margin. Syntax becomes somewhat less valuable. Judgment, system design, domain knowledge, verification and the ability to describe a problem precisely become more valuable.
LLMs as a Normal Technology
Seen through this history, LLM coding looks less like the arrival of an alien intelligence and more like the continuation of a familiar technological process.
The term “normal technology” is used to distinguish from both utopian and apocalyptic conceptions of AI. “Normal” does not mean unimportant. Electricity and the internet are normal technologies in this sense, despite transforming nearly every part of modern life. It means that AI remains a tool whose effects depend on applications, institutions, adoption, complementary investments and human decisions. Improvements in an underlying model do not instantly reorganize the economy. They must first be incorporated into useful products and then diffused through actual organizations.
Coding agents fit this framework exceptionally well. They do not float above society as an independent intelligence.
What Comes After Natural Language?
This brings us to another question: how can our understanding of past abstractions help us to understand what the next level of abstraction look like?
The next rung may move from software specification to outcome specification.
Today, a person might tell an agent to build a claims-processing application. A future system might instead receive the instruction: “Reduce the average time required to process an insurance claim by 30 percent without increasing fraud, violating privacy rules or exceeding this budget.”
The system might interview employees, inspect existing workflows, propose several alternatives, build the necessary applications, connect them to existing databases, run a limited pilot, measure the results and revise the process. Software would become less of a fixed product and more of a continuously changing instrument through which an organization pursues its goals.
This would create extraordinary agency, but also extraordinary opportunities to make mistakes. A poorly written line of machine code might crash one program. A poorly specified institutional objective could redirect thousands of automated decisions. At every new level of abstraction, the unit of instruction becomes more powerful. The consequences of ambiguity increase with it.
The future programmer may therefore look less like a person writing code and more like a combination of architect, product manager, auditor and constitutional lawyer. The task will be to determine what the system should optimize, what it must never do and who remains accountable when the abstraction fails.
The lower layers will not disappear. They never have. More software will likely produce greater demand for the comparatively small number of people capable of repairing compilers, securing operating systems, designing chips and understanding what is actually happening underneath the interface.
But most people will work higher up.
The history of software is the history of expanding the distance between what a human must say and what a machine can do. LLM coding agents are not the end of programming. They are the next rung on the ladder. And, as in every previous generation, the most important question will not be whether the new abstraction can produce more code. It will be what human beings choose to do with the additional agency it gives them.

