Volodymyr Dvernytskyi
Personal blog about Navision & Dynamics 365 Business Central
results count:
post cover

Do humans still need to read AI-generated code?

Almost no one doubts anymore that AI agents are very useful for generating code. But what about reading the generated code? Most developers, when asked whether AI-generated code still needs to be read, will answer unambiguously: yes, code needs to be read. But the answer will come quickly, and the reasoning behind it probably won’t be nearly as confident. There are a few experienced developers who believe that AI-generated code no longer needs to be read. And they back this up with arguments that aren’t so easy to dispute. For example, that we stopped reading the assembly produced by compilers, and software didn’t get any worse because of it. I propose we break down the arguments of both sides of the discussion and turn this debate into more concrete, precise reasoning. This is necessary to understand the place of the software engineer in the AI era.

Agenda

  1. The day it goes wrong
  2. Three positions
  3. Where we agree
  4. Is code the new assembly?
  5. What verification cannot see
  6. What is reading actually for?
  7. Who will read the code in ten years?
  8. How much reading is enough?
  9. What I am not saying
  10. Who can answer?

The day it goes wrong

Imagine a situation where company X generated an application for client Y that recalculates discounts on sales invoices according to a required business rule. Lots of tests were generated too, and they confirmed that everything was fine. At the first meeting, client Y's accountant had told company X's consultant that the invoice discount is calculated on the total after line discounts and rounded once, not on every line. It seemed so obvious that nobody wrote it into the prompt. At the end of the year, an auditor finds a rounding issue, and thousands of invoices contain an error. The auditor will most likely ask a simple question: "Who reviewed the discount calculation?" And the answer will be: "The agents did." The next question could be: "And how does it round when a line discount and an invoice discount both apply?"

One cent per invoice: rounding the 5% invoice discount on each line gives 3.06, rounding once on the total gives 3.05, and in the AL code the mistake is one Round inside the loop

Nobody at company X knows what actually happened, none of them had read the code. Nobody wrote the necessary test, even the agent missed it. The responsibility, of course, lies with company X, and nobody will argue with that. But what can company X do with that responsibility, when nobody who carries it can explain why the code rounds this way, because none of them ever decided that it should? Here I would like to quote Søren:

Accountability without comprehension is just liability wearing a blindfold.

I think this quote describes the problem very well. This isn’t an argument against agents in general, I use them every day. But this situation could show us the broader picture.

Reading code has never been just about the code. In reality, reading and writing code is what allows a person to build a predictive model of a system. That model is what would have answered the auditor’s second question before release, while nobody had tried that case yet. AI agents can produce code, tests, and documentation, but they can’t put that model into a human brain. Usually we build it by writing the code ourselves. When we no longer write the code, reading it is the only route left to build that model. And when an agent fills a gap in the task, reading is also the moment its guess becomes someone’s decision.

I think the question is not whether to read all of the code or none of it. For me the question is who should still be able to read the code, which code and how much of it.

But what would the people who believe code no longer needs to be read say in response? I think this is where you need to read Vjekoslav Babić. He has decades in software engineering, agents have written every line of his code for more than ten months, and he says so in public.

Three positions

Vjekoslav claims that he hasn’t read a single line of the code he ships for months. Many years of writing every line of code himself, and now he doesn’t even read it. When he does look at the output, out of curiosity rather than to review it, every glance tells him everything is fine.

Let’s look at a few of his statements before reasoning about them.

But reading code was never the point. Understanding the system was.

The code stops being the single source of truth and becomes what assembly output was yesterday: an intermediate artifact that somebody could inspect, but nobody did.

Code used to be the complete description of a system, because a compiler translates exactly what you wrote. Now a product can be generated from a conversation, a technical specification, and a set of tests.

The person who knows what to ask for and can reliably tell whether they received it.

And none of this moves accountability an inch.

Also, he has an answer to the obvious objection that code nobody has read is code nobody has reviewed. Every line of code he ships is now read even more than before, but it’s read by agents, not humans. And as Søren relays his question, if you trust agents to write code, why not trust agents to review it too?

Søren takes a middle position. He agrees that we will all be reading less and less of the code we ship. And he has an example: he recently released a free website for searching Business Central apps, and its code was written and reviewed by agents. He defends shipping it unread because the stakes are low, and the only person exposed is him. But he also makes an observation that I haven’t seen Vjekoslav address:

The freedom to stop writing and reading code was bought with a lifetime of writing and reading code.

And the people most able to skip the work, he adds, are exactly the ones who already did it.

My position in a few sentences:

  • Reading code and understanding how it works is an additional quality gate on top of tests, logs and traces. By dropping reading, we make software worse, not better.
  • The value a specialist brings to the chain from agent to customer is that they, as an expert in the domain, understand, verify and evaluate the final result.
  • Reading and writing code is a necessary stage in becoming a software engineer. It is how judgment develops, and judgment skill is important for any expert.

And although at first glance our positions seem so different, in reality they have a lot in common.

Where we agree

I think there are claims most of us will agree with, regardless of our position:

Accountability is still on the people who ship the code.

People will read a smaller percentage of the code than before, though in my view not necessarily a smaller amount.

Code ownership doesn’t change because the code was generated by an agent. Vjekoslav uses the analogy of Gaudí and Michelangelo: neither of them laid a single brick, and they still built their cathedrals. I agree with this, almost nobody lays the bricks of their own house, yet they still own it, although someone who can tell a bad brick usually checks the work. But the analogy answers "must I write?", while the question is "must I be able to read?".

1280px-Sagrada_Familia_towers_and_construction_cranes_(18603572979).jpg

Gaudí left the Sagrada Família 15–25% built, and his plans and models were partly destroyed in 1936. Today’s design is based on reconstructed plans and modern adaptations. Photo: Eric Fischer, CC BY 2.0, via Wikimedia Commons.

I think that judgment is the scarce skill, and in July Vjekoslav and I nearly wrote the same sentence. His version is "the person who knows what to ask for and can reliably tell whether they received it". Mine is a domain expert who understands, verifies and evaluates the output. But in October he went further. His /judge skill now makes probably more than 90% of the decisions that would otherwise stop his agents and records why, and he reviews those records. In his words:

What I actually bring is ownership.

So for him, owning a decision no longer means making it, and here our positions really part.

We still agree that the human’s job is to know what should happen and whether it did. The difference is in how we assess the need to read code for that. And even more importantly, will we still be able to do it in 5-10 years?

Is code the new assembly?

One of Vjekoslav's weightiest arguments is the examples from the history of IT. As the story goes, von Neumann was angry at his assistant who created an assembler. FORTRAN was laughed at and considered stupid. Dijkstra declared that students who had learned BASIC had suffered irreparable mental damage. In 1983, the satirical essay "Real Programmers Don't Use Pascal" was published. Every new level of abstraction felt like a trick, like cheating, and every "we will always need..." had an expiration date. So why is generated code not simply the next level?

Because each previous level had two properties that agent generation lacks.

  1. Each level added a complete artifact at the new level, and people kept reading it. They stopped reading the assembly, but nobody stopped reading the FORTRAN, the C, the Java, the SQL. What you stopped reading was always below a complete artifact that you kept reading. FORTRAN's own authors expected even more: their 1954 report promised that FORTRAN "should virtually eliminate coding and debugging". Backus later admitted they had been "hopelessly optimistic" about debugging FORTRAN programs. Debugging did not disappear. It moved up to the FORTRAN, together with the complete record.
  2. The translator was trusted once, for everyone. That is, the authors had already defined correctness at some point: the meaning must match the source code. And since then, every compiled program has automatically inherited that trust. This is the real reason why nobody audits the assembly. The compiler earned the trust once, and the source above it says everything the assembly says. When either of those is in doubt, people do read the assembly! Kernel developers, cryptographers, anyone chasing a compiler bug does it.

1280px-IBM_Electronic_Data_Processing_Machine_-_GPN-2000-001881.jpg

The IBM 704 at NACA in 1957. FORTRAN was designed for this machine. Photo: NASA, public domain, via Wikimedia Commons.

I can understand his reasoning behind it, for seventy years code was the only complete record of what a system actually does. Because the compiler did exactly what you wrote. He thinks the translator now takes part in working out what you meant. In his words:

It fills gaps, it proposes, it asks back, it iterates.

In his view, code becomes an intermediate artifact.

Let's take his description literally. A record with gaps the machine filled is not a complete record. Anything the agent decided on its own is not included in the specification, and it gets into the tests only where someone thought to test it. All of it is in exactly one place: the code. The compiler moved the complete record up, from assembly to source. But the agent step didn't move it up to the prompt, because the prompt is incomplete by design. The complete record stayed in the code he stopped reading. The property he uses to retire reading is the property that makes it necessary. The decision-making translator already generates the output that needs to be read, since the decisions it makes are not necessarily recorded anywhere else.

Where the complete record lives: before agents, people read the source code; with agents, the prompt has gaps and the complete record is the generated code

Let's look at the most common objection to the compiler analogy: "a compiler is deterministic, a model is not". This is actually true, and it's worth checking twice: first in practice, and then in principle. Give a compiler the same source code several times and you will get the same result. But with an agent the situation is different: make the same request each time and you may get a different result.

One could object that we can control repeatability with the generation temperature. What if we simply set the temperature to zero? In theory, a temperature set to zero should make every generation predictable. But in practice it isn't so. In September 2025, Thinking Machines asked the Qwen3-235B model the same question 1,000 times at a temperature of zero and got 80 different answers, with the first divergence appearing as early as the 103rd token. The cause lies not in the specific model, but in how the server computes it. The result of the computation changes slightly depending on how many other requests ended up in the same batch as yours, and the server load changes unpredictably. That's why, according to the authors, "nearly all LLM inference endpoints are nondeterministic". They fixed this problem by rewriting the low-level GPU code so that the result doesn't depend on the batch size. After that all answers became identical, but generation slowed down, roughly 1.5-2x in their test. So on the endpoints people actually use, even at temperature zero, the same prompt doesn't give the same output.

Besides, lowering the temperature isn't free even when it works. The companies building LLMs today write about this in their documentation. They give clear recommendations not to lower the temperature too much. Google no longer lets you change it. From Gemini 3.6 Flash on, the temperature is "deprecated and ignored", and in later generations sending it will return an error. Anthropic already does that. On its latest models any temperature other than the default returns an error, and since API version 2026-10-21 every model rejects a request that sets a temperature at all. Its migration guide says to drop the parameter and "use prompting to guide the model’s behavior instead". OpenAI’s GPT-5 reasoning models reject low temperature as well, the API answers "Only the default (1) value is supported". Same for open models. The Qwen team’s card for Qwen3 says, in capitals: "DO NOT use greedy decoding, as it can lead to performance degradation and endless repetitions". The April 2026 card for Qwen3.6 recommends 1.0 for thinking and 0.6 for coding. Moonshot’s January 2026 card for Kimi K2.5 recommends 1.0 for thinking mode. As you can see zero temperature is not recommended at all.

The reasons are laid out in a paper accepted at ICML 2026, "Wait, Wait, Wait... Why Do Reasoning Models Loop?". The paper measured the behavior of open models reasoning about math at zero temperature. Every model tested got stuck repeating the same steps on a certain share of problems. And the frequency of looping decreased as the temperature went up. The authors also note that most providers now recommend running models "hot", which helps reduce this problem. In essence, randomness hides flaws in the model. That's why vendors tell you to keep the temperature up. A compiler is deterministic because it has to be. A model is run with randomness because it works better that way.

Now let's suppose that all these problems do get solved in the future. Should we trust code without reading it? Still no. It would be reproducible, but not one iota more likely to be correct. Because the model still does the same thing: it fills the gaps in your request with its best guesses about what you meant. There are two uncertainties here: which guess the model picks, and what you meant by the request. Determinism removes the first and leaves the second untouched. A model that makes wrong assumptions deterministically makes them wrong the same way every time.

Therefore, the real problem is not repeatability, which agents lack. It is what each of them is allowed to decide. A compiler makes decisions too, which registers to use, in which order to run the instructions. But the rules of the language do not allow any of those decisions to change what the program does. The agent’s decisions are exactly about what the program does. What it does in every other case that neither the prompt nor the tests specified. A compiler decides how to do what you wrote. An agent decides what to do where you wrote nothing. This is why the prompt cannot be the specification. So, the only place where the behavior is fully decided is the code. When a developer fills a gap in the specification, the decision belongs to someone. When an agent fills it and nobody reads the result, a decision was made by nobody. Vjekoslav’s /judge records hold the decisions the agent knew it was making. The rounding in my example was not one of them: to the agent it wasn’t a decision, just the obvious way to write the code. The only record of the decisions nobody noticed is the code.

The second property breaks too, and it is about cost. A compiler is trusted once, by everyone. Each AI generation is a fresh translation from an informal input, by a translator that may choose differently tomorrow. Its trust has to be earned per output, by whoever ships it. That is not the same job done more often. It is a different job.

Someone will object that specs and tests will one day be complete enough to be the source. When that day comes, the spec is the source and you read the spec. The argument moves up one level. It does not disappear.

So the analogy fails on both properties, and the first one is decisive. Assembly was safe to skip because a complete record sat above it, and people read that record. Nothing complete sits above generated code. Generated code is in the position source was in, not the position assembly was in. And the prompt is in the position of the design meeting: the place where intent is discussed, not the place where it is finally decided, down to the last branch. Nobody ever skipped reading the source because the design meeting went well.

Generated code is not the new assembly. It is the new source. The prompt is the new design meeting.

What verification cannot see

Vjekoslav's second argument is that he never stopped checking his code, he only stopped reading it. And in his view, checking and reading code are different things. I agree with this, but the question is different. How can we know that the agent didn't make a mistake? Well, his answer is that he verifies the result with tests, logs, traces, reproduction and runtime behavior.

And of course I agree that verification tools are very important in the SDLC. But they were important before the rise of AI agents! Their importance couldn't be denied before, and it can't be denied now. But there is something more important here: reading and verifying code were never two different ways of doing the same thing. They catch different things, and the easiest way to see this is to look at what reading and verification can or cannot see.

Let's think about tests. Tests check the implementation created by the author against the way the author himself framed the task. And it doesn't matter whether the test was written before or after the code. But tests have never been able to detect situations where the developer himself misinterpreted the task. In such situations, the tests, or their absence, may reflect the same mistaken understanding as the code. And such mistakes were usually found by someone else: code review, QA, the customer. But when the same agent writes both the code and the tests from the same prompt, we get a single interpretation of the task, recorded twice. Writing the tests first does help: it catches code that drifts away from the tests. At the same time, if the agent misunderstood the business rule, the test and the code will match each other. The tests will be green, and the business rule itself will remain unchecked by anyone. In case of a discrepancy between the test and the code, the agent itself will decide which one is wrong, after all, we aren't looking at the code. But it will do so based on the very same interpretation of the original task.

Now about logs and traces. They have an important property: they record what has already happened. In the example from the beginning of the article, this means that thousands of invoices have already been posted in the system. It's a reactive tool that tracks down the cause after the fact. Of course, it really works, I do it myself. But sometimes it's just too late. Before the release, logs, traces and reproduction can only show the scenarios someone chose to run. And there is also a difficult category of defects that nobody has discovered yet, nobody even knows the problem is already there.

Essentially, all verification methods share the same limit. Tests only check situations that someone has anticipated in advance, regardless of who writes them. Logs and traces let you figure out situations where something has already gone wrong. Property-based tests, fuzzers and static analyzers go further and find cases nobody thought of, but they still check them only against rules someone wrote down. And for the rules nobody wrote down, only analysis and reading of the code is a barrier that works before the code is released. The code can be correct with respect to the original task, but wrong with respect to the client's needs. And the one who can spot this mismatch is precisely a person who has the necessary knowledge and can match it against the program code. Such a person doesn't have to think of the case in advance, the way the author of a test does, it's enough to recognize it. If the consultant from the beginning of the article had read the discount code, they would have seen the invoice discount rounded on every line and remembered what the accountant said.

What each check can see: only a domain expert reading the code finds cases nobody thought of, knows rules nobody wrote down, and works before release

Someone will say the consultant should simply have written the rule into the prompt. Of course they should have. But nobody writes down everything they know, and this rule was left out of the prompt precisely because it seemed too obvious. A meeting transcript would have helped here, since the accountant happened to say the rule aloud, but many rules are never said at all. A specification depends on someone remembering every rule. Reading the code only depends on recognizing a wrong one.

And for one type of defect there are some very interesting statistics. The 2025 Veracode research report notes that in roughly 45% of cases, AI models chose the insecure way to complete code. More than 100 models took part, and even the large models consistently produced this class of defects. This is something I observe very often when I run into agent-generated code. Code that works but is insecure is exactly the case that can't be caught with tests: they are all green. And notice how Veracode found these flaws. Not with tests, but with a static analyzer. A machine that reads the code looking for patterns it already knows. For known security weaknesses, that could be a good gate. But no analyzer knows your business rules, and for that kind of defect the only reader is a person who knows the rule.

But what if we ask the agent to read the code? In that case the code is read, just not by humans. If you trust the agent to write the code, why not trust it to check the code too?

Because the value of a second reviewer lies in their independence, not in the mere fact that there is one more participant. In 1986 Knight and Leveson tested the assumption behind multi-version programming. If different teams work from the same specification, should they make the same mistakes independently of each other? In practice, their versions failed on the same inputs far more often than would happen by chance. A later analysis found that some parts of the problem were simply harder than others. In some cases different programmers made exactly the same logical error there. In June 2026, researchers repeated the experiment with coding agents, 48 versions from 5 tools and 23 models. They failed together too, and most failures were in the same two conditions, where many agents computed the circle through three points instead of the smallest circle that contains them. Mixing different agents and programming languages did not make the correlation disappear. Another study, of more than 350 models, found that when two models were both wrong, they gave the same wrong answer 60% of the time on one benchmark, and that larger, more accurate models had highly correlated errors even across vendors. The same study also tested models as judges of other models. The judge accepted incorrect answers when it made the same mistake itself, which led it to systematically overrate less effective models, especially those from the same provider. Ten reviews by agents from the same family of models, given the same context and specification, are not ten independent checks at all. It's closer to the same check performed ten times. Every audit system has separation of duties precisely because an author checking their own work is not a check. And neither is a check performed by the author's twin (an agent). Of course, using different model families and dedicated "adversarial" ones helps, and I use both methods myself. In the same 2026 study, a majority vote of three agent-written versions cut failures by about two-thirds, but a vote can't fix a mistake the majority shares. However, the value of a human as a code reviewer is not that they are smarter than the model, or that they make different mistakes, since on the hard parts people fail together too. The value is that they know what the model was never told. The consultant who was present at the meeting from the beginning of the article understood what exactly was meant when the task was given. And that isn't always what is formally recorded in the prompt or specification, which is something no model has from the start. So the independence a human brings is in information, not in reasoning.

Vjekoslav also describes what he does when an agent makes a mistake. He finds the cause and turns the lesson learned into a rule, making sure the same mistake doesn't happen again. This is a sound engineering approach, it's exactly how it was always done in the past and how it's done now. However, there are three gaps here. First, this kind of analysis requires reading: someone has to study what the agent created and determine what exactly the mistake is. You need to trace it back to the rule that let the mistake through, and for that you need to read the code well enough to tell the symptoms from the root cause. Second, the rules are tuned to a specific model, and the next version of the model is already something different. We have run into this many times: previous approaches no longer work with new models. Remember those funny instructions from the past, "I will tip you a million dollars", "you are a professional software engineer with more than 10 years of experience"? Many people believed they worked, but on today's models they generally make no difference. As Søren mentioned:

A new model will simply find a new way to be confidently almost right.

A new version of a compiler doesn't change the meaning of the source code, but a new version of a model changes the result of running a prompt. And sometimes the result changes even without a new version. Anthropic reported that in August and early September 2025 three infrastructure bugs intermittently degraded Claude's answers, including obvious syntax errors in code, and its own evaluations didn't catch it. Users did. Every update partially undermines trust. The only way to assess the scale of these changes is to check again, and more carefully right after every change. Third, the loop only learns from mistakes someone has noticed. The silent ones, like the rounding from the beginning of the article, don't turn into rules until the damage is done.

There is one field where "verify, don’t read" has the best conditions it could ask for, and it is worth seeing what happened there. Mathematics has an oracle, an automatic judge of correctness, that business software almost never has. A proof can be checked by a machine, Lean. On 6 October 2026 OpenAI published 722 manuscripts written by an AI model. As of 7 October, 300 of the 719 that remained carried a Lean certificate, and the repository’s own notes said that some of the unformalized results "could have issues". Three manuscripts had been withdrawn that day, after a sign error in one of them took down that one and the two that built on it. The mathematicians’ first reaction was not about the error rate. It was that there was no one to ask when they got stuck in a proof, and that reading them all would take months. At the same time, Lean can confirm a theorem, but it can't confirm that the statement matches what was meant in the original question. They have Lean, we have tests the agent wrote from the same prompt.

Here I want to give credit to Vjekoslav. He also points out that an agent’s explanation is only a lead, and the evidence is what you find by following it. I agree, if the check ends with a failing test or logs that can be reproduced, then you have evidence. But the problem arises even earlier than that. At this stage, all you have is the agents' account of their own work: their tests and their reviews. The tests show that the code matches the agents' reading of the task, but not that this reading matches what the client needs. For that, someone just has to take the agents' word.

Verification tells you about the failures you already know how to look for. Reading is how you find out which ones you don’t.

What is reading actually for?

So far I have argued that reading catches a class of defect nothing else catches. I believe that, and it is still not the main reason to read code.

In 2013 Bacchelli and Bird studied the code review process at Microsoft. Most developers said that they do code review to find bugs. But in reality it was something more: understanding changes, knowledge spread across the team, awareness of what is happening to the system. Of course, bugs were found, but their importance and number were less than the developers expected. So reading code is not only a filter for bugs.

As I noted earlier, reading code is what allows you to form a model of the system in your mind. I would even say that far from every way of studying code leads to such a model. In my view, we can speak about several levels:

  • Level 1: the code passes the tests
  • Level 2: we can describe what the code does
  • Level 3: we can predict how the code behaves on inputs that nobody has tried
  • Level 4: we can explain why the code is built this way and what the alternatives were

Tests and traces get you to level 1 and level 2. A brief walkthrough of the code from an agent will give you level 2. But before the release, when an answer could still have prevented the damage, the auditor's question from the beginning of the article was a level 3 question, and that's exactly why nobody could answer it. Level 3 can only be reached by studying the code yourself. An explanation of what already happened can be checked with evidence. But if you don't read the code, an explanation of what would happen on inputs nobody thought to try has to be taken on faith, so that's no longer about understanding, it's about faith. Mathematicians came to a similar conclusion about machine-checked proofs. They can give almost complete confidence that a theorem is true, but at the same time give almost no understanding of why it is so.

Someone will say that documentation and the agents' brief summaries contain this information. But like the /judge records, they hold only what the agent noticed. A description answers only the questions its author expected, and that's why it stays at the second level.

I think there is a great term that describes the accumulation of code nobody reads: comprehension debt. That's what I call code running in production that no accountable person has read. Just like technical debt, it's acceptable in small doses. It goes unnoticed until it becomes an obvious problem. And the "interest" on this debt has to be paid with every subsequent change to the code. And we see a similar problem even with humans. A few months after making changes, the author no longer remembers what they did, and the discussion is either forgotten or was never finished. Only the code itself remains, as an artifact of reality. The next change is made by a different person, relying on their own context, the one that's current for them. But that context isn't the "memory" of the whole organization. The new developer has no way to tell whether their changes contradict what was written before, unless they read the code. An agent making the next change reads the code too, but what it learns leaves with its context window. Nothing accumulates in the organization. So code that nobody has read still has an owner, but it has no author.

This debt can be measured directly: count the modules in production that no accountable person has read. And there is an early sign that the "interest" on it is already being paid. According to a repository analysis conducted by GitClear in 2025, over the course of 2024 the number of duplicated code blocks grew eightfold. Between 2021 and 2024, the share of changed lines that were moved or refactored dropped from 25% to less than 10%. Of course, this is only observational data pointing to a correlation. However, the picture matches exactly what you would expect if code is being added by some entity that "doesn't remember" what already exists in the system.

Understanding isn't stored in the repository, it's stored in people. And reading, in this case, is also a write operation.

Who will read the code in ten years?

If understanding is concentrated in people, then the question arises: which people exactly, and where they get it. Recall that when Vjekoslav glances at the code out of curiosity, every glance tells him that everything is fine. I don't doubt that's what Vjekoslav sees. But why does it work? I think the reason is that behind him are many years of writing and reading code, debugging and studying it. As Søren rightly noted, the system of agents Vjekoslav built is essentially his own knowledge converted into rules for the machine. And I agree with this. Someone could say: then just copy his rules. But rules only cover the mistakes already seen, they need re-tuning after every model change, and knowing when a rule no longer fits is exactly the judgment that rules can't hold. And this is an important point in the discussion: those who will do best without reading code are the ones who read it for decades before. Hence the question: what happens if, ten years from now, the engineers who come to replace them never learn to read what the agents create?

We only see what we look at, and our sense of how useful AI agents are is very subjective. In early 2025, the organization METR ran a study with 16 experienced open-source software developers. They performed various tasks in their own repositories, both with AI and without. Paradoxically, with AI tools they worked 19% slower, although they themselves were sure they had sped up by about 20%. It’s a small study, and the tools have improved since 2025, so we shouldn’t jump to conclusions about productivity. But if experienced developers can misjudge their own speed, which a stopwatch can check, then a quick glance’s verdict that the code is fine deserves at least as much caution.

What happens to a skill that isn’t used? Obviously, that skill degrades over time. Lisanne Bainbridge described it in a short paper with a great title, “Ironies of Automation”. The irony was that automation takes over the routine work while leaving the hardest part to the human. Specifically, intervening in the process when the system fails. And that intervention requires more skill, not less. And at some point, maximum professionalism is demanded from the human.

Reasoning about accountability, Vjekoslav gives the example of a car’s autopilot. If a car on autopilot gets into an accident, the responsibility is still on the driver. I agree with this, of course. But let’s look at aviation, the field this term came from and where the autopilot has been evolving for many years. Airlines noticed that pilots had begun to lose their manual flying skills. In 1997 American Airlines ran a training session for its pilots dedicated to the “children of the magenta line”. That’s what they called crews that had become overly dependent on automation. In 2009, Air France flight 447 crashed over the Atlantic because after the autopilot disconnected, the crew lost control of an airworthy aircraft. The investigation named insufficient training in manual handling at high altitude as one of the causes and recommended making such training regular and mandatory. So the aviation industry’s reaction to the arrival of the autopilot did not come down to the logic that if the machine does it better, there’s no need to practice anymore. On the contrary, in 2013 the FAA urged airlines to make sure all pilots get manual flying practice, both on regular flights and in training, even for pilots who may never need it. As you can see in this example, an entire industry deliberately preserves human skills.

But who will pay for acquiring the skills? Previously, beginners were trained directly on the job. A junior developer writes simple code, and a senior checks it. As a result, companies got a working software product and a more qualified engineer. Now an agent creates simple code faster and cheaper. It turns out that a beginner’s work is worth almost nothing to the company, and training stops being a by-product of work and turns into a pure cost. And it’s not profitable for any individual company to bear these costs, since they fall on the shoulders of that specific company, even if the industry as a whole benefits. Similar problems arose in medicine, aviation and the trades, and there they were solved with strict rules: mandatory residency, apprenticeship systems, minimum flight-hour requirements. I suspect our industry will come to the same thing. Søren sums up the problem in one sentence:

The junior you do not hire today is the gatekeeper you do not have in ten years.

Remember that recent OpenAI release of a whole set of mathematical theorems? Well, in the blog post "Proofs and Prompts", Alice Kerr asked whether there will even be a future generation of mathematicians at all. Alain Valette noted that what worries him most is the fate of future mathematicians. After all, mathematicians are formed by working through proofs on their own, just as software engineers are formed by writing and reading code. In both cases, that work can be done by an AI agent.

For developers, this is already more than a worry. In January 2026, two Anthropic researchers published a randomized study in which 52 programmers, most of them professionals, learned a new Python library. The group that used an AI assistant scored 17% lower on the quiz afterwards, with the largest gap in debugging, and on average it wasn't significantly faster. Those who handed the whole task to the AI finished fastest, but at the cost of learning the library. The authors conclude that humans "may not possess the necessary skills to validate and debug AI-written code if their skill formation was inhibited by using AI in the first place". What hurt was not the AI as such, but handing it the thinking: participants who asked it conceptual questions or asked it to explain the code kept their learning.

So what advice can be given to beginner developers? I suppose that at the start of a career nothing can replace working through the code yourself, that's exactly how the basic professional skills are formed. Later, as your level rises, you will hand more and more of your work over to AI agents. And to keep your level up, I can suggest two methods:

  1. Reviewing code with deliberately injected defects, or solving a task like in my project tryal.dev
  2. Mandatory explanation: before merging the code, the person who ships it must explain to the reviewer what exactly this code does and why it is needed.

Someone may object that the models will become so perfect that all of this will lose its meaning. Models will certainly get better, but even a much better model still has to guess what you didn't write, and someone has to be able to check those guesses. Also, let’s take a sober look at the risks. A profession loses a skill slowly, but recovers it even more slowly. Under such uncertain conditions it's impossible to predict what will happen, so I recommend choosing the safest strategy. Perhaps the reading skill won't always be needed. But so far nobody has shown how the next generation of engineers can acquire the same level of professional judgment without going through the same experience as their predecessors.

You can delegate some reading. You cannot delegate learning.

How much reading is enough?

In manufacturing, nobody inspects every bolt coming off the line. But nobody leaves the product completely without control either. The frequency of inspections is determined by the defect rate and by the consequences a defect would have. I think reading code works in a similar way, except that you choose what to check by risk, and check again after every model change.

When we read code, we can actually do it for different purposes:

  1. Reading to make changes
  2. Reading for quality control
  3. Reading for debugging
  4. Reading for learning

In fact, it's fairly easy to delegate the first type of reading, and even the second type partially, through the same kind of sampling inspections as in manufacturing. The third type can only be delegated until the moment the one doing it makes a mistake. And the fourth type can't be delegated at all. Perhaps most arguments about reading code arise because people are talking about different kinds of reading from the list.

Also, the amount of code you need to read depends on two things. The first is the oracle, the mechanism that can automatically assess the correctness of the code without human involvement. This could be type checking, property-based testing, differential testing, etc. The stronger it is, the less you need to read. But what do you do when correctness means matching the customer's intent? Here only a person can help, one who knows what the customer actually wanted and who has studied the code itself. Most business logic lies exactly in this plane, and this fully applies to the Business Central ERP system. The second is how bad a defect would be. Søren draws the line between reading and not reading "where someone else starts paying you to be sure", and below it he puts code that you don't charge for and where the risk is low. I would draw it by the risk alone, because importance isn't always measured by payment: take OpenSSL or log4j, free software, yet critical for the entire industry. At the same time, there is plenty of paid software that is essentially trivial.

And even the strongest oracle only checks what was written down for it. A Lean certificate checks the theorem the AI wrote down. A passing test checks the behavior the agent wrote down. Neither checks what you meant.

So here is my position on reading code:

  • Read 100% of the code related to financial operations and accounting: VAT, discounts, payments. Check all permission sets and security filters, data deletion and retention mechanisms, migrations. Review everything the agent itself flagged as "uncertain".
  • Read all the tests, they are essentially very close to a specification, but remember that not all tests may have been written, so think about the missing scenarios.
  • The rest of the code can be read selectively, the frequency of sampling checks should depend on how often defects are found and on how important the code is, and it should go up after every model change.

Read by risk: read all the code where checks are weak and a defect is costly, sample the rest, and read all the tests everywhere

And I often hear the argument that AI agents produce too much code and it's simply impossible to read all of it. That's true, and nobody should read all of it. But that's no reason to read none of it. The amount of generated code is a parameter that you control yourself. Generate code at the same speed at which you are able to check it, as carefully as the stakes demand. You drive a car the same way: at the speed at which you are able to brake in time. And if you generate more code than you can read, it doesn't mean the need to read it has disappeared. That duty simply falls on the shoulders of those who will work with this code later.

Someone will object that this parameter is set by the market: a competitor who ships without reading can ask a lower price. Vjekoslav expects that too, a market where "price will be fought tooth and nail". But he also sees an opportunity there for those who have always been accountable for their products, and I agree with him. A competitor who doesn't read isn't selling the same product for less. Tests and reading catch different defects, so the defects only reading would catch stay in their code until a client or an auditor finds them. In my example, that means correcting thousands of posted invoices, which costs far more than reading the discount code would have. Søren described this well: if nobody can answer for what you sell on the day it breaks, "you are selling a promise you cannot keep and calling the difference productivity".

What I am not saying

In discussions like this it's very easy to argue against a position that nobody actually holds. So I'd like to clarify a few points. I am not claiming that:

  • Every line of code needs to be read. Does anyone know the entire Base Application of Business Central by heart? Or have access to the code of an app from AppSource? Boilerplate code, glue code, one-off scripts, prototypes, as well as any code that can be reliably checked automatically, don't need to be read.
  • Tests, logs, traces are less important than reading code. They reveal different problems, so both are needed. And agents will help you with this, here is an example of an agent that writes property-based tests and found real bugs in popular Python packages, including NumPy. Meta uses LLMs for mutation testing, where the agent deliberately introduces a bug that the existing tests miss, and then writes new tests capable of catching it.
  • Humans are better at finding bugs than agents. Not at all, humans miss bugs too, and they can write bad code as well. However, a human and an agent may miss different things, because the human knows what the agent was never told. Two imperfect verification methods that fail in different places are far better than the same method applied ten times.
  • The output of agents is mostly wrong. That's certainly not the case, I see this in my own work. Also, many mathematicians who reacted to the OpenAI release noted that long-standing problems in their fields had been solved. Some of them, including Terence Tao, said that many of the proofs appear to introduce clever new ideas. The problem is code that nobody has read: if there is a mistake in it, we find out too late, from the client or the auditor, and if it is correct, nobody even knows why. I'm not claiming at all that Vjekoslav is wrong about his own work. His experience makes this approach far safer in his hands than in anyone else's. However, rules that suit one engineer with decades of experience and rules applicable to the profession as a whole are different things. Vjekoslav himself noted that modern agents make it possible to build a product long before the developer realizes what it means to be accountable for it. That gap is exactly what this article is about.

I'm not asking anyone to go back to writing all code by hand. I'm asking that someone in the building can still read it.

Who can answer?

Let's return to the auditor from the beginning of the article. To the question of who checked the discount calculation, the answer was: "the agents did". To the second question, how exactly the discount rounding works, nobody present knew the answer.

Of course, company X can turn to an agent right there on the spot, which will figure out the causes and give an explanation. But this is the moment when thousands of invoices have already been posted. The agent can tell them what the code does, but not who decided that it should round this way. Nobody at company X did: the agent filled a gap in the business rule, and nobody read the result. So there is no decision to explain, only a guess that nobody looked at. The only person who could give a precise answer, the one who studied the code, simply doesn't exist.

Also, legislation is moving in the direction of formalizing responsibility for software. The new EU Product Liability Directive, which applies to products placed on the market after 9 December 2026, explicitly includes software in its definition of a product. Although this responsibility applies to individuals and their data, this document does not apply to incorrect amounts on invoices. But where it does apply, a court can order the manufacturer to disclose relevant evidence in an easily understandable form, and can presume the product was defective when technical complexity makes it excessively hard for the injured person to prove, and a defect looks likely. Both are hard to answer if nobody can explain the code.

At the beginning I asked the key questions: who exactly should be able to read the code, and how much of it. Here is my answer: the code should be read by those who will have to explain how it works on the day it fails. The code should be studied in those critical places where automated checks can't tell a correct solution from a wrong one. You should also get familiar with the rest of the system's code, to the extent that is enough to understand how much the AI agents can be trusted. And the job of our profession is to make sure such people exist.

So the answer to the auditor should not be "the agents did", but a pointer to a specific human expert. And that person should be able to answer the question, not just own the result. Otherwise, the presence of a human in this chain comes down to nothing more than taking the blame for the actions of AI agents.

LLMs are for people, not people for LLMs.

Back to top