AI Engineer Code 2025
Developer Experience in the Age of AI Coding Agents
Read the talk
Developer Experience in the Age of AI Coding Agents
Coding agents make development environments, testability, written context and code review more consequential—and give teams a reason to invest in foundations that also help humans.
From a talk by Max Kanat-Alexander
Before you start: Familiarity with automated tests, continuous integration and pull-request review will help you follow the examples.
What will still be worth the investment?
Every few weeks, a developer arrives with another tool they want to use. The developer-experience team has barely evaluated the last release before someone asks about the next one. Refusing a tool that appeared yesterday used to feel straightforward; with coding agents, the answer increasingly becomes: perhaps we should try it.
That creates a practical investment question: what can an engineering organization improve now that it will still be glad it improved at the end of 2026? Buying access to coding agents is one answer, but it cannot repair every surrounding problem in a company.
Max Kanat-Alexander approaches the uncertainty through two questions. Which developer-experience principles remain valuable regardless of how agents change? And what must improve outside the agents to make both agents and developers as effective as possible? The durable investments are in the inputs and working conditions around the agent, where improvements can benefit humans as well.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Use tools the way the industry uses them
Start with the development environment: build tools, package managers and linters. Kanat-Alexander recommends industry-standard tools used in conventional ways. His rationale is that those conventions are represented in model training data, giving agents familiar patterns to work from.
An instruction file can explain a heavily modified toolchain, but it also asks the agent to override familiar behavior. A bespoke package manager makes that problem concrete: instead of continually teaching the agent your replacement, consider returning to the standard tool. The recommendation is about reducing the amount of unusual behavior an agent must learn before it can do useful work.
Kanat-Alexander applies the same reasoning to programming languages. Although he enjoys exploring languages, he says he no longer uses obscure ones in his everyday agentic development work. That does not mean new tools must stop emerging; enthusiasts can still explore them.
The tension between experimentation and operational responsibility predates agents. His hypothetical request is to put an unvetted technology released last week underneath a service handling 100,000 queries per second and serving a billion users. Familiarity to a model adds another reason for caution, but the underlying enterprise judgment was already necessary.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Give agents direct actions and useful failures
Once the environment is familiar, the agent needs a way to act. A CLI or API exposes operations directly. Computer use and browser orchestration with Playwright are alternatives, but when a direct interface is available, Kanat-Alexander favors the text interaction agents already use naturally. Each action must work accurately for the larger workflow to succeed; unnecessary interaction complexity makes that harder.
The next requirement is objective, deterministic validation. Tests and linters tell an agent whether a change satisfies a rule, and clear failure messages help it decide what to repair. Whether a human or an agent wrote the validator matters less than the quality of that feedback. A bare 500 Internal Server Error tells the agent something failed without explaining the cause or the next useful action.
Asking the agent to write tests does not automatically solve this. On an untestable system, it may produce a test that establishes only that a button was pressed successfully. The test passes while saying little about the behavior the button was supposed to trigger. Legacy systems with only broad end-to-end tests often lack the focused unit tests that an agent can run repeatedly and use to diagnose a specific failure.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Make behavior possible to inspect
Useful validation depends on system structure. Some legacy codebases are difficult to reason about because the necessary information is missing, or because their organization hides how behavior fits together. An agent can investigate by running the system and seeing what breaks, just as a human can. But that trial-and-error process is a substantial handicap compared with being able to understand the code directly.
The button example exposes the connection between structure and testability. If a test can observe the button press but cannot observe the explosion behind it, generating more tests against the same narrow interface will not reveal the hidden outcome. A human or agent may first need to refactor the code so the relevant behavior becomes observable.
For a concrete illustration, suppose a button reserves stock. Separating the reservation logic from the click handler makes it possible to test the state change and the failure condition directly:
javascript
import assert from 'node:assert/strict';
import test from 'node:test';
function reserveStock(stock, quantity) {
if (!Number.isInteger(quantity) || quantity <= 0) {
throw new Error('Quantity must be a positive integer');
}
if (quantity > stock.available) {
throw new Error(
`Insufficient stock: requested ${quantity}, available ${stock.available}`
);
}
return { ...stock, available: stock.available - quantity };
}
test('reservation reduces available stock and preserves the SKU', () => {
const stock = { sku: 'book', available: 3 };
assert.deepEqual(reserveStock(stock, 2), {
sku: 'book',
available: 1,
});
});
test('reservation rejects insufficient stock', () => {
assert.throws(
() => reserveStock({ sku: 'book', available: 3 }, 4),
{ message: 'Insufficient stock: requested 4, available 3' }
);
});
The important change is what the test can know: it checks the reservation result rather than merely confirming that a handler ran. That is the structural prerequisite behind the recommendation to improve tests.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Document what the code cannot tell you
Documentation debates often focus on whether engineers should write more of it. The agent makes a narrower question unavoidable: where can it find the information it needs? It did not attend an untranscribed meeting. Requirements, specifications and reasons for building a system cannot remain solely in the memories of the people who discussed them.
That does not imply duplicating everything already expressed in code. If the code is comprehensible, an agent can explain its structure. The distinction is between information recoverable from the implementation and information that must come from elsewhere:
| Information | Where the agent can find it |
|---|---|
| Existing code structure | Comprehensible implementation |
| Why the system was built | Written intentions and decisions |
| Accepted URL-parameter shape | An existing validator, if present |
| Expected external input before implementation | An accessible specification |
An existing validator can describe accepted input. Before that validator exists, the agent cannot infer the outside world's contract simply by reading code that has not yet been written. Write down what is absent from the code, somewhere the agent can access.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Make each review response faster
Engineers have long spent more time reading code than writing it. With agents, even producing code increasingly means reading proposed changes. As Kanat-Alexander puts it, “writing code has become reading code.” Engineers become reviewers throughout development, while increased pull-request volume creates another review bottleneck downstream.
Both loops need attention: the formal review of a pull request and the developer's immediate response to an agent. Optimize the time to each useful response, while retaining the iterations needed for a correct result. A review is a quality process. An arbitrary five-minute cutoff is no reason to accept broken code. Faster agent execution helps only part of the loop; humans also need to recognize problems and decide the next step quickly.
At the team level, asking a Slack channel whether any of ten people can review a PR leaves responsibility ambiguous. The most responsive person tends to pick up the work. Kanat-Alexander illustrates the imbalance with one reviewer doing 50 reviews while others do three, two, five or seven. That informal arrangement becomes harder to sustain as agents generate more PRs.
A more deliberate review process needs three things:
- Assign each review to a specific person through a system that distributes work.
- Set response service-level objectives, or SLOs, with a mechanism for enforcing them.
- Make it clear whose turn it is to act.
The third requirement concerns handoffs, not just assignment. After a reviewer leaves comments, an author might reply to one, push a change, then answer the rest. Which event means the PR is ready for another review? Kanat-Alexander's criticism of GitHub concerns that ambiguity, not the absence of a re-review request feature. Relying on an extra Slack message to announce readiness leaves people manually coordinating the workflow.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Keep experienced reviewers in the work
Speed is useful only alongside review quality, both when a developer evaluates agent output and when a teammate reviews the resulting PR. Software design does not require perfection: the goal is good enough and better than before. But the expected lifetime of a system determines how demanding “good enough” must be. A long-lived system may need a substantially higher bar than a short-lived one.
A review process must be capable of rejecting changes that should not enter the system. Otherwise, each accepted change can make later work harder for both humans and agents, eroding the productivity benefit of generating code quickly.
Maintaining that judgment requires apprenticeship. Yet the strongest reviewers are often occupied with meetings, strategy and high-level reviews, leaving little time to teach through ordinary code review. Kanat-Alexander says that in more than 20 years he has found no substitute for doing good reviews with people who are learning. Developing reviewers therefore requires giving experienced engineers time to review actual code alongside less experienced colleagues.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
The next change inherits the last one
These conditions interact. Start with a confusing environment and a difficult codebase. The agent produces poor changes, the developer becomes frustrated, and eventually a PR goes out because the developer thinks it probably works. An overwhelmed reviewer cannot establish whether it is sound and approves it anyway. The next task now begins in a worse codebase.
Kanat-Alexander predicts that organizations caught in this cycle will see agent productivity decrease through the year. The mechanism is cumulative: weak review admits changes that make the next round of generation, understanding and validation harder.
The positive cycle begins with improving those working conditions. More effective agents can help developers make further improvements, which in turn support more effective work. Foundational changes can be expensive, but Kanat-Alexander sees this period as an opportunity for organizations able to make them to distinguish themselves through software engineering velocity.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Put feedback inside the development loop
There is a final operational requirement behind the tooling recommendations: CLIs and APIs must work during development, not only in CI. A capability that becomes available only after submitting a change is poorly positioned for repeated local correction.
Kanat-Alexander characterizes agents as more persistent and patient than humans, but also more error-prone, making repeated validation especially consequential. His illustrative scenario has CI taking 15–20 minutes and an agent repeating the run-and-test cycle five times; he contrasts 20-minute feedback with 30-second feedback. Patience does not remove the delay from the developer's workflow. Making each check fast changes how usable that repeated correction process is.
That development-time condition completes the investments already described: familiar environments and executable interfaces need useful validation; validation needs code that can be tested and understood; the agent needs accessible intentions and external context; and the resulting changes need prompt, discerning review. These are connected improvements, not an exhaustive list of everything an organization could do.
Their lasting value comes from the people who also use them. Clearer code, faster feedback and better review help developers even if a particular investment delivers less benefit to an agent than expected. The closing principle is that what is good for humans is good for AI—and the human benefit remains even when the agent benefit falls short.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
From the talk
Install Playwright and run browser tests locally or in CI, with terminal output and HTML reports.
Further reading
Max Kanat-Alexander explains iteration time, focus, cognitive load and the organizational work behind effective developer tools.
- Speed of Code ReviewsDocumentation
Google's guidance on prompt review responses, protecting focused work and maintaining code quality.
Updates since the talk
Current instructions for distributing review requests among team members using round-robin or load-balancing rules.
Read the transcript and explore slides
Loading transcript and slides…