Coding agents are no silver bullet
Frederick Brooks’ classic paper, No Silver Bullet, is an interesting read on the complexity involved in developing software. Central to the paper is whether there is one silver bullet that can be used to manage and solve that complexity.
Essential and Accidental Complexity
In the paper, Brooks categorizes software complexity into two: essential and accidental complexity. Essential complexity is the complexity that is inherent in the problem domain itself while accidental complexity is that which comes from the process and tooling we choose to solve the problem.
Take, for example, building a restaurant delivery app. Here the essential complexity at the heart of the problem includes order flow, dispatch timing, and edge cases like cancellations or delayed riders. Accidental complexity here can be the constraints and challenges that arise when trying to implement the system, such as deployment configs, database migrations, and UI state bugs. These could be due to the programming language used, development environment, software tooling, among other factors.
In his opinion, much progress had been made in tackling accidental complexity such as advances in higher-level programming languages, concurrency and parallelism tooling, compiler tooling and so on. However, he also maintained that the essential complexity of software remained unsolved, and there is no silver bullet to solve it.
Historical Context
Moving on from Brooks’ times, software development has become accessible to more and more people partly because of the advances made in solving the accidental complexity involved. Today we have highly sophisticated IDEs integrated with formatters, linters, type checkers and such tooling that won’t hesitate to yell at you for a misplaced semicolon.
For example, in the early 2000s, enterprise web development particularly in the Java ecosystem was largely a complex mishmash which required fiddling with mountains of XML, SOAP/WSDL plumbing and the like.
The rise of web frameworks such as Rails (2004) and Django (2005) helped clear part of this accidental complexity by introducing strong conventions and abstracting away most of the boilerplate and setup ceremony involved. You no longer had to hand-roll authentication, session handling, or CRUD scaffolding or implement ad hoc MVC patterns. No. The selling point of these frameworks was freeing developers from these accidents to focus on the essence of the problem they were trying to solve. To a large extent these frameworks have lived up to their promise, as can be attested by their longevity (Lindy Effect).
Single Page Application (SPA) frameworks deserve credit but their early ecosystem carried significant accidental complexity. In the early to mid-2010s thereabout, it seemed as though what distinguished you as an SPA craftsperson was how skilled you were at solving the associated accidental complexity. You had to first tinker with bundlers, runners, transpilers, etc., and once you were done with that you had to imbibe the tribal and often opinionated knowledge of whatever SPA framework you chose. One had to jump those hurdles first before they could even get to the start line of whatever they wanted to solve.
Things have immensely improved today and front-end web development can be successfully decoupled from a lot of the underlying accidental complexity. Vite was such a welcome break from Webpack complexity that it inspired a documentary - pun intended.
Coding agents and accidental complexity
When reading the paper, I was struck by how relevant Brooks’ arguments still are today with the rise of agentic coding, where coding agents powered by LLMs are now generating code at scale.
It is undeniable that coding agents have made programming accessible to more people now and some argue this has completely eliminated the accidental complexity. Anyone can vibe code now. People are showcasing tools and projects they made over the weekend while at the same time they are completely ignorant of whatever underlying technology was used. A prompt went in and a tool solving a real-life problem came out. Who cares about dependency conflicts or programming language factions?
One thing that should not escape us here is that coding agents create new forms of accidental complexity too. Whatever coding agent or agentic workflow you choose, you still need to learn how to work with it to get the best out of it. However, this is the accidental complexity that can be justified due to the benefits one gets. It thus pays to spend time fiddling with these agents, knowing what agent or model is best for what, and various tips and tricks required to work with them. Given that this is also a space that is changing at a rapid pace, staying informed with what the latest agents can offer is important even if you are not a heavy user at the moment.
Coding agents and essential complexity
Brooks’ central argument still fits in today’s age of coding agents: we keep reducing accidental complexity, while essential complexity remains harder.
Essential complexity persists because software depends on tacit domain knowledge and what Peter Naur called ‘programming as theory building.’ The crucial understanding of a system lives partly in people’s heads—in mental models, trade-offs, and context—not fully in code or documentation (except in very small systems). This challenge grows when we factor in unpredictable human behavior, business rule conflicts, and systems that must evolve over time.
Despite this, we can still use coding agents to help us tackle the essential complexity of software systems. They will not remove it, but they can help us see it earlier and reason about it better. They can help us reason about architecture choices, disambiguate requirements, and quickly build prototypes to prove or disprove a point. They can also surface hidden assumptions earlier, which is essential in tackling it.
In the end, whether these agents become fully autonomous will depend more on how well they handle essential complexity than on code generation.