ezyang's blog

the arc of software bends towards understanding

Code review as human alignment, in the era of LLMs

I’ve recently been doing a lot of both submitting and reviewing pull requests to PyTorch that were authored with substantial LLM assistance. This is a big difference from earlier this year, where it was clear LLMs worked well for greenfield projects but the code was too hopelessly sloppy for a production codebase. Here are my merged PRs that mention claude code in their description; Jason Ansel has also had a similar experience (Meta only link, here is the list of issues he referenced in his writeup). There already has been increasing discourse (Simon Willison, LLVM) on how code review should adapt to this new era of LLMs. My contribution to this discourse is this: within teams, code review should change to being primarily be a human alignment mechanism.

Here is a simple example: it is well known that LLMs are prone to generating overly defensive code: e.g., they will be constantly sprinkling try...catch everywhere or testing if a variable is some type when system invariants imply that it should always be that type. If someone sends me a PR with these problems, I am not commenting on these problems solely because I want them to be fixed. If that’s all I cared about, I could have just fed my comments directly to claude code. The real problem is that the human who was operating the LLM didn’t agree with me that this defensive code was bad, and the point of the review is to align them with me on what is overly defensive versus not. In the most trivial cases, maybe the engineer didn’t read the LLM output, in which case the remedy is to make them actually read the code. But sometimes real human work has to happen; for example, maybe there is a global system invariant that one has to understand to know if the defensiveness is necessary or not. If we agree about the global system invariants, there’s no reason the code review has to go through me: the original code author can just instruct the LLM to fix problems and keep me out of the loop until they have aligned the LLM output to themselves–at which point we should do the more expensive human to human alignment. The ideal is that I don’t need to ever write review comments about mechanical problems, because they have already been fixed by the original author ahead of time.

Conversely, when I am putting up an LLM generated PR for human review, I am trying to transmit higher level information. How does the new code work? What do I need to know about the existing system to understand this code? This doesn’t even have to be in the PR description: if the LLM proposes a fix that I myself don’t understand, or seems difficult to understand, I will simply instruct it to try it a different way, until the resulting diff is obviously correct. Tokens are cheap: we should expect more out of the author of code, because the cost of generating these PRs has gone way down. Similarly, I am willing to throw out the code and start again; you don’t have to feel bad about wasting my time (I didn’t type it! I spent my time understanding the problem, and none of that is regretted.)

There is a lot of scaremongering about how engineers who don’t pick up AI tools will be left behind. My take on this is that there a number of different skills that make up what it means to be a good software engineer, and it is clear that LLM coding, even today, is clearly reweighting the relative importance of these skills. I care a lot more about your ability to read code, reason about the big picture, communicate clearly and to have good taste, than I care about your ability to mechanically write code. There is an archetype of junior engineer who is not that good at coding but very good at the softer, higher level skills, and I think they will be very valuable in this new world order. Conversely, I think going forward I will have substantially less patience if I have to keep telling you the same things over and over, because I just don’t value raw “ability to code” as much anymore. My ideal state is like that with long time senior teammates: I can trust that they have made good low level decisions, and I can focus on understanding the bigger picture and updating my mental model of how the system works.

Today’s LLMs have no memory: they have to rediscover everything in the system from first principles every time they are run. The purpose of the humans, of the team, is to collectively maintain a shared vision of what, platonically, the system should do. I want code review to reconfigure itself around this purpose.

4 Comments

  1. vieplivee
    I had a friend who drove very defensively. He seemed to be scared of speed, actually. He would drive at 20 mph on a 50 mph limit road. I tried to tell him this didn’t feel right, and his argument was “why is slower safer?"—till one day he got caught by police officers for driving too slowly.
  2. vieplivee

    I doubt those people with only higher level skills would be good at reading codes, not to mention having a taste about codes.

    Taste comes and only comes from scar tissues that those good at higher level skill folks tend not to have the time or patience to spend time accumulating.

  3. parvin121
    It might be helpful to consider using prompts that include language-specific rules when generating code with the LLM tool. This could make the outputs more consistent and reduce the need for repeated tweaks.
  4. David Pereira

    This is an interesting post, thanks for sharing!

    The core idea of human alignment is good, and it will depend on each team. For example, I believe code review can be an effective way of finding and fixing bugs, and also upskill the engineers in your team. You gave more examples on OSS projects, and I guess the upskill part matters way more for teams. The policy around coding standards, “zero bugs” and others is indeed all about human alignment, since some teams might prefer speed, not quality. It’s a cool idea :)

    > Today’s LLMs have no memory

    I mean kinda true, yes. But I also think the instructions.md, memory.md, AGENTS.md and others help in this regard, which you didn’t mention. Copilot is kinda working more on this it seems (https://github.blog/changelog/2025-12-19-copilot-memory-early-access-for-pro-and-pro/). And it will continue to be an improvement area.

    Anyways, great post.