Do We Need a New Programming Language for the AI Era?
Do We Need a New Programming Language for the AI Era? Jul 25, 2026 When I receive a PR written by AI—especially when it comes from a project manager who is not an Android developer—and I feel that the changes have ruine…
Do We Need a New Programming Language for the AI Era? Jul 25, 2026 When I receive a PR written by AI—especially when it comes from a project manager who is not an Android developer—and I feel that the changes have ruined human-crafted, thoughtfully engineered code, I genuinely feel bad. My review comments can fix some small issues, but they cannot fix the entire architecture. I have tried leaving more general comments, but that often results in the whole solution being rewritten, which means I need to review it from the beginning and understand the code all over again. As we rely more on AI-generated code, I feel that our codebases are starting to resemble traditional auto-generated code, such as the Kotlin or Java code produced by tools like Room KSP. However, we never directly modify, review, or even version-control that generated code. That is because it is generated from a well-defined set of annotations and functions, and the output is fully deterministic. We can generate it on different machines at different times and still get the same result. We can clearly see that something is missing from our current AI code-generation workflow. A project manager or even a developer writes a prompt based on their own knowledge and a Jira ticket, and then other developers are assigned to review the generated code and its changes—sometimes without even seeing the original prompt. Because of this, some people suggest spending more time on the initial prompt, storing it in Git, sharing it with the team, and asking developers for input. So, is this prompt becoming a new language? Human language? I have seen people start writing specification .md files using AI. It is easier: they do not need to think through every sentence or type everything themselves. They can simply provide a Jira ticket and use a good AI skill to generate the specification. But are people actually reading those .md files? Usually, no. Even when they need information from them, they ask AI to summarize the files or answer questions based on their contents. It is easy for AI to turn a simple task description into something complicated—to use wordy language, rephrase the same point, and repeat it in several different ways. This is exactly where we are now: nothing feels worth reading, and nothing feels worth watching, because you do not know whether it was created by a person or generated by AI. You do not even know whether the creator bothered to read it before publishing it, or whether they simply trusted the AI and left the rest of us alone with that shit. Producing long texts has become much easier than reading them. What do these .md files contain? They usually include a mixture of context, examples, references, requirements, and design and architecture decisions. If we are going to treat these files as a new language, then we are back in the 1980s, when we were simply happy that we could write something and make it work, without thinking much about structure or architecture. I am not talking about the architecture of the application described inside the .md file. I am talking about the architecture and structure of the .md files themselves. Where should we put them? What should we include in them? How should we name them? How should they reference one another? How should we write them? Human Language Is Too Verbose My first problem is that they are written in human language, and human language is extremely verbose. Let me give you an example. As a programmer, which one would you prefer? The name of this account is Mike. Based on the identity associated with the currently active session, the name of the current user can be confidently identified as Mike. I would say neither. Personally, I would prefer: "name": "Mike" It is easy to understand. I do not need to read a collection of unnecessary words just to extract the only two pieces of information that matter: name and Mike. I feel the same way about entire .md files. They are often verbose, wordy, and phrased in a way that nobody wants to read. In the end, you extract only a small amount of useful context from a large amount of text. You might even need to highlight a few words and sentences so that, when you return later, you can scan only the highlighted parts and quickly restore the context in your mind. Constraints Help Us Build Larger Systems Many programming languages are designed to make certain things easier while intentionally making other things more difficult. They introduce constraints. In the early days of programming, with languages such as BASIC, we could decide where to place data in memory and where to write the code. We had control over almost the entire memory space. Was that a good thing or a bad thing? Over time, we created languages that abstracted those details away. In C, for example, we introduced functions, structs, and other abstractions. When systems became even more complicated, people brought ideas such as object-oriented programming into widespread use. We added even more constraints than before. Now, you need to think about where a function belongs, how classes are supposed to communicate, and which design patterns should be used. These constraints allowed us to design increasingly complicated systems. A Language for Communicating Intent Today, with AI, I believe we are experiencing another version of that early “access to the whole memory” moment. So I want to propose a new language. This time, however, the language would be different. We would not write code primarily to communicate with machines and CPUs. We would write code to communicate with other programmers. That is what programmers are good at. We can scan the implementation of a well-written function and understand what it does—assuming that the function is properly implemented and uses the right abstractions. With AI, we may be able to work with these kinds of abstractions much more than before. We may not need to write every implementation detail ourselves. Complicated functions containing 300 lines of code could be implemented by AI. We would only need to provide the AI with good context. Programming could move towards a form of metaprogramming, perhaps using annotations. @context("This app is a weather app that fetches weather data from an API and displays it to the user") class App @context("This is the main entry point of the application") fun main() { // Functions starting with $ are not real functions. // They can be replaced by a class or even a transitive set of classes. // They are more like pointers. // The idea is to give AI enough context to implement the function. print($get_weather("copenhagen")) } // OPTIONAL: We can provide additional context to the AI. // Here, we tell the AI to generate or use WeatherRepository // and GetWeatherUseCase. The AI is smart enough to understand // how they are related to each other. @context($WeatherRepository, $GetWeatherUseCase) @transitivelyDependsOn("retrofit", "okHttp", "kotlinx-serialization") @file:UseCase // Refers to a text file that the AI reads when implementing this function. fun $get_weather(city): $Weather // OPTIONAL: We can also provide implementation details for the repository. fun &WeatherRepository.get_weather(city): $Weather { val response = weatherService.getWeather(city) return response.$toWeather() } It would be up to the developer to decide how deeply they want to go. They could fully implement a function, partially describe it, or leave it entirely for AI to implement based on the available context. The Reasoner This code would be processed by a Reasoner, which would produce a textual representation of the system’s structure: its modules, classes, functions, and relationships. The functions would be described by name and responsibility, without necessarily including their actual implementations. The reasoning process would be performed by an AI model. The resulting reasoned files would be preserved and committed to Git. Different models might produce different reasoning, so each reasoned file would be tagged with the name and version of the model that produced it. The reasoned file would then be used to generate the actual code using AI. The implementation model could be the same model that performed the reasoning, or it could be a different one. The main purpose of the Reasoner would be to separate the hidden reasoning process from the implementation process. Instead of allowing the model to reason privately every time it generates code, we would preserve the result of that reasoning in a concrete form. These files would be much more specific than our original abstract definitions. As a result, different models could potentially produce similar implementations from the same reasoned file. The reasoned files would not be edited directly. To change them, developers would update the context or abstract code and run the Reasoner again. The reasoned files could be represented as JSON, TOML, or structured human-language text. [reasoning] model = "example-model" version = "1.0" [component.WeatherRepository] responsibility = "Fetch weather data from the remote API" [component.GetWeatherUseCase] depends_on = ["WeatherRepository"] returns = "Weather" There would also be tools designed to provide AI models with the right context during both the reasoning phase and the code-generation phase. I have already chosen a name for this language. I call it Ruz, pronounced “rooz.”