Skip to main content

Natural Language Compiler

An Alternative to Agentic Workflow

Updated 15 min readMarkdown

Introduction

Software engineering has continuously evolved alongside new ways of representing, building, and maintaining computer systems. From the earliest programming languages to modern development tools, each technological advance has introduced new abstractions that make it easier to describe computation at a higher level. The recent evolution of artificial intelligence represents another such shift, enabling agents to understand natural language descriptions and participate in activities that were previously restricted to software developers.

The emergence of these capabilities creates an opportunity to reconsider some of the assumptions underlying software engineering. If language models are already capable of understanding natural language instructions and producing functional implementations, perhaps it is time to question what should be the primary artifact of software development.

Traditionally, source code has fulfilled this role: it is the ultimate representation of software, used for implementation, maintenance, and evolution. However, this model was conceived in a context where skilled developers were indispensable for transforming ideas and requirements into executable programs.

This article proposes a different perspective. It suggests that we may need to reconsider both the importance of source code itself and the role of artificial intelligence in its production. If a system can be defined in sufficient detail using natural language, that description may serve as the goal of the software development process, while its implementation in a programming language becomes the result of a compilation process, much like object code.


The Problem with Code-Centric Development

The widespread adoption of AI agents has transformed software development. Instead of writing code manually, developers describe the desired behavior in natural language, and AI agents generate the corresponding source code.

Developer ──► Instructions ──► AI Agent ──► Code ──► System

Implementation shifts from developers to AI agents, which generate code through large language model inference pipelines. While this accelerates development, code remains the primary artifact: it is versioned, tested, executed, and maintained. AI changes how software is produced, but not the central role of code.

Considering that programming languages were designed to provide mechanisms that facilitate the writing and reading of software by humans, and that the current paradigm changes the implementation agent while keeping code as the central artifact, a natural question emerges: should code continue to occupy the center of the development process?

A reinforcement of this question comes from an important outcome of increased productivity: as our ability to produce code grows, so does the effort required to understand it. Systems grow faster and accumulate more implementations, dependencies, and abstraction layers, making it progressively more challenging to identify where the knowledge that truly matters—the business rules and domain concepts—actually resides.

The centrality of code creates an asymmetry between implementation knowledge and domain knowledge. Although software exists to represent business processes, policies, and user goals, these concepts are scattered across implementation artifacts such as classes, configuration files, database schemas, and infrastructure definitions. As a result, understanding what a system does increasingly requires understanding how it is implemented.

Modern software engineering amplifies this problem. Frameworks, libraries, generated code, and architectural patterns improve modularity and reuse but also increase the cognitive distance between domain concepts and their implementation. Developers spend more effort navigating technical abstractions than reasoning about business logic, making code progressively less effective as a medium for expressing system intent.

AI-generated code further intensifies this imbalance. As the cost of producing code approaches zero, implementation artifacts proliferate while the amount of domain knowledge remains essentially unchanged. The result is a growing volume of executable code containing an increasingly smaller proportion of the conceptual information that developers actually need to understand.

It's difficult for developers, and also for coding agents, which need to analyze code in order to assist with software development. Layers of abstraction and lines of algorithm implementation are not just a cognitive challenge for humans. Debugging is an even greater task than writing code, and that work doesn't disappear—it simply changes hands.

From this perspective, the source of the problem may not lie in the speed at which code is produced, but rather in its centrality and the importance derived from it. The faster code is written while remaining the definitive description of the system, the greater the cost of understanding, maintaining, and transferring the knowledge it is supposed to represent.


Natural Language Source

One way to overcome the centrality of code is to introduce an artifact that sits closer to the specification while still pointing toward the implementation.

Such an artifact would describe the blocks that compose the system, how they relate to one another, the behaviors they must exhibit, and the constraints they must satisfy, while remaining independent of programming languages, frameworks, or infrastructure choices. At the same time, it cannot be so abstract that it loses the information necessary to produce an implementation. It must preserve sufficient structural and behavioral detail to enable multiple implementations to be derived from it consistently.

A component design provides this intermediate artifact. Unlike a specification, which defines a system in terms of its requirements and expected properties, a component design describes the system in terms of the components that fulfill those requirements and the relationships between them. It captures the system's component interfaces, responsibilities, interactions, and behavioral constraints without prescribing implementation details such as programming languages, frameworks, or deployment technologies.

In this sense, the specification answers what the system must achieve, whereas the component design explains how those requirements are realized through an organized set of collaborating components, while remaining sufficiently implementation-independent to support multiple concrete realizations, functioning as a source for the system written in natural language.

Specification ──► Components Design ──► System

Defining the components that make up a system, their behavior, and how they interact captures much of what is traditionally expressed in source code. By describing component design in natural language, we move one step closer to implementation while preserving accessibility and readability through a technology-independent approach.

An essential feature of component design expressed in the source text is that there is a direct correspondence between the implementation code—or, in the case of compiled, unmanaged platforms, the resulting binary artifacts—and the corresponding artifact. Each element of the codebase is the result of the materialization of a unique component defined in the source text base.

Just as root-cause analysis rarely requires inspecting compiled binaries, it should not require examining the object code generated from the source text. Any behavior observed in testing, staging, or production environments can ultimately be traced back to the source text. The source text remains the definitive artifact for understanding, diagnosing, and reasoning about system behavior.

Moving from source expressed as programming language code to source text written in natural language may require additional artifacts alongside the Component Design artifact. However, all such artifacts should preserve the essential property of direct correspondence with implementation elements or support this property through other artifacts.

As a proposal, the Component Design can be regarded as the source of the system, expressed directly in natural language rather than in machine-oriented instructions. The code is moved to a lower level as a compilation artifact of this natural language source, occupying a role analogous to the binary output generated from source code in traditional software development processes.


Natural Language Compiler

Source text artifacts require the use of an actor that is not new but has not been employed in software development processes: the Natural Language Compiler.

Unlike conventional compilers, whose purpose is to translate programs written in one formal language into another executable representation, this compiler receives a source text written in natural language and produces a functional implementation as its output.

The development workflow is redefined as:

Specification ──► Developer ──► Source Text ──► NL Compiler ──► Code ──► System

The compiler uses the source text as the construction plan and automatically synthesizes the code required to implement it. No validation or verification of the functional or non-functional requirements is performed. No analysis of the solution's completeness is carried out, and no architectural decisions are made. At this stage, the source text is taken as-is, and the implementation is generated as faithfully as possible.

Compilers versus AI Agents

At first glance, this process may appear similar to development based on autonomous programming agents. However, the fundamental difference lies in the expectations regarding the role of artificial intelligence.

In the agent-based workflow, the quality and reliability of the result depend primarily on the agent's ability to infer intentions, fill gaps in the specification, and make decisions during code generation. As language models evolve, the expectation is that the process will become increasingly reliable.

The Natural Language Compiler, however, breaks this dependency. Instead of relying on the model's ability to interpret incomplete or ambiguous specifications, it requires a more rigorous, detailed, and precise description. Responsibility for the correctness of the system shifts from the model's inference capabilities to the quality of the source text.

While agents are evaluated by their ability to produce good results from vague or incomplete instructions, natural language development requires discipline in writing the source text and expects the compiler to produce code strictly derived from the provided content, preserving its semantics while minimizing implicit implementation decisions. Consequently, the behaviors, features, and even the defects of the system originate from the source text itself, rather than from decisions made during code generation by an autonomous agent.

A Tool, Not an Assistant

Since its primary input consists of artifacts written in natural language, the compiler—like AI agents—also relies on language models. The key difference is in how it is used. Unlike programming assistants, the developer does not provide task-oriented instructions, contextual resources, and then wait for the model to decide how to solve the problem.

Instead, the compiler follows a predefined compilation pipeline. Its purpose is not to autonomously complete arbitrary tasks, but to deterministically transform a high-level design into a well-defined output.

Because of this, many of the architectural principles that have made programming language compilers reliable for decades can also be applied to natural-language compilation.

  • Dependency Graph — Represent relationships between design documents, requirements, constraints, and generated artifacts as an explicit graph. This enables precise impact analysis, selective recomputation, consistency checking, and deterministic dependency tracking instead of repeatedly reasoning over the entire project.

  • Compiler Passes — Decompose the transformation into a sequence of well-defined stages, each responsible for a single concern. Unlike traditional compilation, these passes may depend on the target platform rather than the input language.

  • Incremental Compilation — Recompile only the artifacts affected by a change rather than executing the entire pipeline. By tracking dependencies between intermediate representations, modifications propagate only to the necessary stages, significantly improving efficiency while preserving consistency.

  • Optimization — Apply deterministic optimization passes to improve the generated artifacts before resorting to language-model reasoning. Many transformations—such as simplification, normalization, dead artifact elimination, caching, deduplication, dependency pruning, and structural rewrites—can be performed algorithmically, reducing cost and improving reproducibility.

A reasonable counterargument is that a sufficiently capable programming assistant could achieve similar results when given the same collection of artifacts as input. In principle, this is true. However, explicitly modeling the compilation process and restricting language models to narrowly defined semantic tasks leads to a substantially more reliable system.

Language models should be treated as specialized reasoning components rather than general-purpose execution engines. Every operation that can be implemented deterministically should be automated through the compiler itself, reserving the language model only for problems that genuinely require interpretation or semantic inference. Repeatedly invoking an intelligent agent to perform work that can instead be expressed as deterministic computation increases cost, reduces reproducibility, and introduces unnecessary sources of variability.


Implications

By placing the source text written in natural language at the center of the development process, the system is not defined by the implementation used at a given moment. This shift has implications across multiple dimensions: architecture, maintenance, evolution, collaboration, and knowledge preservation.

Technological Independence and Portability

The system's source is independent of any specific programming language, framework, or platform. The same source can be recompiled for different technologies, preserving the architecture across changes to the underlying infrastructure or execution environment.

This separation between design and implementation reduces migration costs and enables new technologies to be adopted without rebuilding the overall structure of the system.

Traceability and Maintenance

Because the natural language source serves as the common reference point connecting requirements, architecture, and implementation, modifications are made to it as the software's primary representation, from which the corresponding implementations are then regenerated.

Maintaining a common system representation helps prevent divergence between documentation and implementation, improves decision traceability, and simplifies maintenance by concentrating the evolution of the system in a single source of knowledge.

Organization and Preservation of Knowledge

In traditional systems, much of the knowledge is dispersed across implementation details, spread throughout thousands of lines of code and technical decisions accumulated over time.

With natural language as the central artifact, this knowledge is organized according to domain concepts. The system's representation aligns more closely with the way domain experts describe problems and processes, making it more understandable, reusable, and less dependent on specific technologies.

Progressive Implementations and Incremental Validation

The source text allows implementations to be generated with different levels of completeness, suitable for different stages of the development lifecycle. A simplified implementation can support concept exploration, business rule validation, requirements experimentation, and early testing, while more complete implementations can be targeted toward staging and production.

Experimentation cost is significantly reduced, which in turn enables the system to evolve progressively and incrementally, without requiring the entire production infrastructure from the outset.

For example, a system could initially be compiled into a desktop application executed locally by developers and business analysts. This environment would enable rapid validation of concepts and domain rules. Later, the same source text could be recompiled into a cloud-based implementation intended for staging and production.

In both scenarios, the source text remains unchanged; only the implementation is adapted to the requirements of the execution environment.

Context-Aware Development and Implementation Protection

Because the essential structure of the system is represented in the natural language source, selected portions can be provided to development teams together with the relevant context snippet from the source to support them.

This model allows features to be implemented and tested without requiring access to the complete system or the production implementation. Teams can work on isolated portions of the domain, using compatible environments for validation.

Besides facilitating collaboration and distributed development, this approach protects the operational implementation by avoiding the sharing of production code with external teams. Developers receive only the subset of the source text necessary for their work, together with the resources required to execute it, thereby preserving the confidentiality of the actual implementation.

Optimized use of artificial intelligence

The source is expressed entirely in natural language rather than traditional programming languages, making it highly compatible with AI-driven workflows. Because AI models are predominantly trained on natural language, they can reason about the system with less cognitive overhead, without first translating or interpreting implementation-specific syntax.

This separation also enables technology- and platform-specific models or specialized agents to transform component design descriptions directly into concrete implementations. By working from clear implementation descriptions instead of mixed design and code, these agents can produce outputs that are more predictable, reproducible, and reliable.

Reducing the complexity of the reasoning process required by AI models enables the use of smaller, more efficient models while maintaining high-quality outputs. By providing structured and explicit descriptions of system component behavior, models do not need to infer as much context from low-level implementation details. This makes AI-assisted development more practical on local hardware, where resource constraints favor lightweight models, and enables more private, responsive, and cost-effective execution without relying entirely on large cloud-based systems.


Challenges and Limitations

Natural language is inherently ambiguous, requiring sufficiently structured specifications to enable consistent compilation. Questions related to the reproducibility, verifiability, and explainability of decisions made by artificial intelligence also remain open.

Furthermore, certain domains—such as embedded systems or highly optimized applications—will likely continue to require specialized implementations for a long time, as they involve components intrinsically tied to implementation details and, in many cases, closely coupled to the hardware platform for which they are designed.

The technological challenges are only part of the picture. The adoption of such a paradigm would also depend on the evolution of software engineering methodologies and development processes. Many of the best practices and techniques developed over time for specific programming languages and paradigms may be used as templates for standards governing the writing of natural language sources with comparable objectives.


Conclusion

The adoption of language models makes it possible to envision a shift in how software is represented and maintained. Natural language ceases to be used merely for expressing project requirements and instead assumes the role of the system source text: the canonical artifact that is versioned, maintained, and evolved throughout the system’s lifecycle.

As a consequence, code written in programming languages ceases to be the central artifact of software development and instead assumes a role analogous to that of object code: a representation generated from a source document, intended for execution and capable of being regenerated whenever necessary.

From this perspective, the Natural Language Compiler is not merely a tool for automating program generation, but a mechanism that redefines the boundary between specification and implementation. Through this approach, software engineering can evolve toward a model in which the system’s source is embodied in natural language, while programming languages become primarily a means of materializing the executable software.

No comments yet. Be the first to comment.