A security incident went up on a company's forum last week. The config change shipped by mistake. The auto-generated social preview rendered the company's tagline right next to it: Ship without friction. Armin Ronacher — the guy who wrote Flask — used that screenshot to open a conference talk, and the joke landed because everybody in the room had made the same mistake recently.
The uncomfortable argument Armin and his co-founder Christina Poncela Cubeiro made: the friction engineers have spent a decade trying to remove is the friction that was doing the thinking. Remove it and you don't get speed. You get a codebase nobody can steer.
The psychological trap
The first few months of coding with Claude Code or Cursor feel like cheating. You prompt, the machine writes, you ship. Then everyone on your team is using it. Then your team's baseline expectation resets. Then the ambient pressure becomes: more output, faster cycles, shorter PRs. The gift becomes the tax. You no longer have the quiet moments to stop and ask whether this is the best way to implement the thing — because you're one prompt away from shipping it.
Armin calls this the gambler's loop. You don't know if the next prompt is the one that makes the product work, or the one last drop of slop that tips the whole thing into an outage. You keep pulling the lever.
The more interesting part is the illusion underneath it. Because you're producing a lot of output very fast, you feel more efficient. You're not. You've just stopped doing the part of the work where you design.
The team composition shift nobody warns you about
Before agents, engineering teams were supply-constrained on the creation side. The balance between writing code and reviewing code was roughly okay. Now every engineer has 5–10× the production power, and nobody got 5–10× the review power.
Two downstream effects:
1. Pull requests pile up. The ones that aren't reviewed carefully get rubber-stamped.
2. The set of people shipping code expands. Marketing people ship code. Former-engineer CEOs ship code again. The number of entities — humans and machines — participating in code creation now vastly outnumbers the ones that can carry responsibility for it. And the machine can't carry responsibility.
The engineering team is still on the hook. But the production volume hitting them is no longer something they authored.
Why agents rot products faster than libraries
The single most useful technical observation in the talk: agents are excellent at libraries and mediocre at products.
Libraries have a tightly defined problem, a clear API surface, and a simple core. The agent can fit the whole thing in its context window, reason about it globally, and add features cleanly. That's why open-source maintainers are getting real leverage from these tools.
Products are the opposite. UI, API responses, permissions, feature flags, billing, background jobs — every change touches three other concerns. The agent cannot fit the global structure in its context. Locally it looks reasonable. Globally it's incoherent.
And the agent's failure mode is specific: it's been trained to write code that runs. That reward function is exactly what you don't want in a product. A human engineer writing a config loader feels bad when they write if config missing, silently load defaults. The agent feels nothing. So the agent ships it. Two hours later you have database records written against the default config, and you don't know it yet.
Humans build up revulsion toward bad code. Agents don't. The codebase accumulates entropy until the agent itself can no longer navigate it — it starts missing files, writing duplicates, forgetting what already exists. You've built a system neither you nor the agent can reason about.
The agent-legible codebase
Armin's prescription: your codebase is now infrastructure. Design it for the agent the way you'd design infrastructure for operators.
Concrete rules Earendil is enforcing through lint:
- Modularize the code flow, not just the components. The agent does its worst damage between the clearly defined steps — parsing types it shouldn't, stuffing things into state. Name the steps.
- Don't fight the RL. If there's a canonical way to do a thing in this language, use it. The agent is trained on the canonical version.
- No hidden magic. Raw SQL hides intent. An ORM shows it. If the agent can't see it, it can't respect it.
- No bare catch-alls. Silent failure is how products rot.
- One query interface for SQL. Don't make the agent grep the codebase to find where queries live.
- Unique function names. Not for readability. For token efficiency — when the agent greps, it wants one hit, not twelve.
- One UI primitives library, no raw inputs. Consistent styling, consistent behavior.
- No dynamic imports. Source of truth should be static.
- Erasable-syntax-only TypeScript. No transpile step. One source of truth between your code and the compiler.
Every one of these is friction. Every one of them is the point.
The part where your judgment gets woken up
The piece that made the whole talk click for me: Earendil built a PR extension that separates the review inputs. Mechanical bugs and style violations go straight back to the agent — those don't need a human. But a database migration, a permissioning change, a new dependency — those explicitly route to a human call-out that says "your brain should be on now."
Because if you miss them, you will regret them. And you will miss them. The machine's job, in this model, is to notice the moments your judgment is actually required, and to make sure you don't sleep through them.
Why "friction is bad" is the wrong slogan
Large engineering organizations have long used SLOs — service-level objectives — as deliberately inserted friction. The point of an SLO is to force the team to stop and ask: Do I actually need this reliability? Do I have the headcount to run this? Should I ship this service at all?
The AI-coding era has encouraged us to treat all friction as waste. In physical systems, friction is what lets you steer. Without it, you don't go faster. You just stop being the one driving.
The single line to take from Armin and Christina: the friction is where your judgment lives. The shift isn't to stop using agents — it's to stop pretending the remaining ten percent of the work, the slow part, is the disposable part. It's the only part that's still yours.
Source: The Friction is Your Judgment — Armin Ronacher & Cristina Poncela Cubeiro, Earendil
No comments:
Post a Comment