Coding agents have changed what I expect from software.
I used to accept frameworks as the price of moving fast. They supplied routing, conventions, integrations, and answers to decisions I had not made yet. The bargain looked sensible because writing those pieces myself cost too much time.
That cost has fallen. Codex, Claude Code, and Gemini CLI can help me read unfamiliar code, build a focused abstraction, test it, and replace it later. I no longer need to adopt someone else’s entire mental model to avoid writing a few hundred lines.
This does not make every framework obsolete. It raises the standard a framework must meet.
Abstractions Have Owners
Every framework carries decisions about control flow, I/O, deployment, error handling, and upgrades. Those decisions spread through an application. Once they do, replacing the framework means rewriting the assumptions around it.
Alain Dichiappari argues that coding agents let developers remove much of this adaptation layer:
We can finally get rid of all that middle work. That adapting layer of garbage we blindly accepted during these years. A huge amount of frameworks and libraries and tooling that has completely polluted software engineering, especially in web, mobile and desktop development. Layers upon layers of abstractions that abstract nothing meaningful, that solve problems we shouldn’t have had in the first place, that create ten new problems for every one they claim to fix.
I would put it less broadly. Some abstractions earn their place. The mistake is treating adoption as free.
A package imports an API, assumptions, a release schedule, transitive dependencies, and security exposure. I add one when it solves a defined problem better than code I can reasonably own. I do not want a pile of packages to be the starting price of an API server.
Why I Start With the Standard Library
This is a major reason I use Zig and Go.
Zig 0.16 introduced std.Io, which lets an application decide how I/O runs without forcing the rest of the code into separate synchronous and asynchronous versions. The application owns that policy.
Go takes a different route. Its standard library includes net/http, encoding/json, os, net, testing, and sync. Goroutines and channels provide concurrency at the language level. I can build and operate a useful API server before choosing a framework.
The designs differ, but both let me begin with the language. Third-party dependencies remain decisions instead of prerequisites.
Python, JavaScript, and TypeScript often invert that relationship. Their standard libraries can handle I/O, but their server ecosystems encourage an early stack choice. In Python, that may mean choosing between requests and aiohttp, then adding FastAPI and Uvicorn. In JavaScript or TypeScript, it may mean adopting Express, separate type definitions, middleware, and the conventions that connect them.
The application inherits a dependency graph before it has business logic.
What Two Package Decisions Cost
I measured clean package resolutions on August 5, 2026. requests 2.34.2 installed five distributions in total, while aiohttp 3.14.3 installed nine. FastAPI 0.141.1 with Uvicorn 0.52.1 resolved to 13 distributions: the two packages I selected and 11 selected on my behalf.
Package counts understate the source I inherit. Using cloc and excluding blank lines and comments, I measured 3,597 lines of Python in requests and about 31,400 in its dependencies. aiohttp contained 19,157 lines, with another 26,731 in its dependencies. FastAPI and Uvicorn contained 17,563 lines together; their dependencies added 76,098. A two-package choice placed 93,661 lines of installed Python behind the application.
The JavaScript result was different but pointed in the same direction. Express 5.2.1 declared 28 direct runtime dependencies and resolved to 67 installed packages. Express contained 1,140 lines of JavaScript; its dependencies added 17,870. Adding @types/express 5.0.6 introduced three direct type-package dependencies and 19,895 lines of TypeScript declarations across the resolved package set.
These figures estimate installed source, not the lines executed on each request. They count .py, .js, and .d.ts files, exclude blanks and comments, and omit native code already compiled into binary wheels. Versions and platforms will change the totals. That volatility is part of the cost.
Agents Change the Tradeoff
Andrej Karpathy described neural networks as ‘Software 2.0’ in 2017. His argument concerned learned programs rather than coding agents, but the phrase points toward the change I now feel in daily engineering: more software is produced through model behavior, not only handwritten instructions.
A recent conversation with Boris Cherny sharpened that point for me. He described removing most of a coding harness system prompt as the underlying model improved. Better model capability made part of the surrounding scaffold unnecessary.
I see the same pressure on application frameworks. If an agent makes focused code cheaper to create and maintain, a broad abstraction has to justify the constraints it adds. The relevant question is no longer whether a framework saves keystrokes. It is whether I want its decisions embedded in the system.
For API servers, I avoid dependencies when the standard library gives me enough to write the implementation myself. A convenient package can pull in tens of thousands of lines that either I or my agent must understand when the system breaks. I would rather own a small implementation than inherit dependency hell.
For my next server, I will start with the language and add abstractions only when the code proves it needs them. Coding agents did not remove engineering judgment. They made that judgment more valuable.