Key Facts
Good Engineering Is Good Engineering
A few minutes' read on why the fundamentals never really change.
Intelligence ... is the faculty of making artificial objects, especially tools to make tools.
— Henri Bergson, L'Évolution créatrice (Creative Evolution), 1907
(quoted by McIlroy, Pinson, and Tague as the epigraph to their Unix foreword, 1978)
Software has a pattern that repeats every decade or so. A new technology arrives, brings its own vocabulary, and gets presented as something entirely without precedent. Conferences get held. Blog posts proliferate. Consultants appear. And if you look carefully underneath the new terminology, you'll find the same ideas that were already there — just wearing different clothes.
We're in one of those moments now with AI agents, MCP, tool calling, and agentic workflows. It's worth pausing to notice that almost none of it is new.
The Unix Insight
In 1978, McIlroy, Pinson, and Tague published a foreword to the Bell System Technical Journal's Unix issue. Under the heading Style, they laid out the maxims that had grown up among Unix's builders:
(i) Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new "features."
(ii) Expect the output of every program to become the input to another, as yet unknown, program. Don't clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don't insist on interactive input.
— M. D. McIlroy, E. N. Pinson, and B. A. Tague, UNIX Time-Sharing System: Foreword, The Bell System Technical Journal, Vol. 57, No. 6, July–August 1978.
That's the whole thing. A small tool, a clear contract, a composable interface.
The Unix pipe operator — | — is the original tool-chaining mechanism. Take the output of one program and feed it as input to the next. Neither program needs to know what came before it or what comes after. Each does its job. The shell decides how to connect them.
cat orders.csv | grep "overdue" | sort | head -10
Four programs, none of them written to work together, all of them composable because they share a universal interface: text on stdout.
Stallman, Kernighan, Pike — they weren't writing about AI. They were writing about awk, grep, and sed. But the principle they articulated is precisely what makes modern AI tool-calling work.
What AI Agents Actually Are
Strip away the terminology, and an AI agent is a process that calls functions in a loop until it meets a goal. The model receives a description of available tools, decides which to call, receives the result, and decides what to do next. It stops when the goal is satisfied or it runs out of options.
Expert systems did this in the 1980s. Rule engines did it in the 1990s. Workflow orchestrators did it in the 2000s. The difference today is that the orchestration intelligence — the part that decides which function to call and when — is no longer hand-written. The model infers it from natural language intent.
That's the genuine delta. Not the architecture. Not the composability. Not the tool contracts. Just the fuzzy input handling: the ability to map "show me overdue deliveries" onto a precise, structured function call without a hand-written parser.
Everything else is plumbing we've built before.
The Names Change. The Problems Don't.
Consider how many times we've reinvented the callable interface with a schema:
- CORBA (1991) — remote objects with typed interfaces
- WSDL/SOAP (1998) — web services with machine-readable contracts
- REST + OpenAPI (2000s) — HTTP resources with schema descriptions
- GraphQL (2015) — a typed query interface over a data graph
- MCP (2024) — tools with JSON Schema descriptions, callable by an LLM
Each generation looked at the one before it and said "too complex, too coupled, too verbose," then built something simpler that solved the same problem. MCP is a clean, minimal take on the callable interface. It's good work. It's just not a new idea.
The same pattern shows up everywhere:
| What we call it now | What we called it before |
|---|---|
| AI Agent | Expert system / rule engine |
| Tool calling | RPC / function dispatch |
| RAG | Information retrieval + summarization |
| Agentic workflow | Orchestration / BPM |
| UI-driven agent | RPA / Selenium / macros |
| Prompt engineering | Query formulation / information architecture |
None of this is cynicism. The new implementations are genuinely better — more capable models, cleaner interfaces, more accessible tooling. But the underlying engineering problems haven't changed: schema design, versioning, transport, authentication, observability, error handling.
We Know This. We Just Don't Do It.
Here's the uncomfortable part. These principles aren't obscure or new. They've been written down, taught, and repeated for nearly fifty years. And the commercial software industry has spent most of that time cheerfully ignoring them.
We write functions that do twelve things. We build classes that know about the database, the UI, the business logic, and the email system all at once. We couple modules so tightly that changing one line means understanding ten files. We skip tests because the code's too tangled to test, then make it more tangled because there are no tests to catch us. We bolt features onto things that already do too much, because that's faster than building something new and composing it in.
Spaghetti code isn't an accident or a failure of intelligence. It's the natural result of optimizing for short-term delivery over long-term maintainability — which is what commercial pressure almost always demands. The monolith grows because adding to it is faster than decomposing it. The function gets longer because the deadline is tomorrow. The coupling deepens because the right abstraction would take a week to design properly, and nobody has a week.
This isn't a new problem, either. Brooks wrote about it in The Mythical Man-Month in 1975. McIlroy was writing his maxims partly in reaction to the bloated, incoherent software already surrounding Unix. Every generation of developers inherits a codebase that violates these principles and spends half its time fighting the consequences.
The honest version of this argument admits that knowing the right thing and doing the right thing are very different problems. The principles are simple. The discipline to apply them under real commercial conditions is not.
The Standard We Owe Our Clients
So here's the question that actually matters: if we've known these principles for fifty years and keep failing to apply them, what changes now?
Not the technology. The AI wave won't fix a poorly designed system — it'll expose it faster. An LLM calling a tangled, side-effect-laden, undocumented API won't just fail; it'll fail in ways far harder to debug than a human clicking the wrong button. The coupling that made your codebase painful to extend will make it painful to integrate with an agent. The missing contracts that made your API awkward for a frontend developer will make it opaque to a model with zero tolerance for ambiguity.
MCP is still an API. It speaks a different language and uses different semantics, but it's a callable interface with a schema, and all the same rules apply. A well-designed MCP tool is well-designed for exactly the same reasons a well-designed REST endpoint is well-designed: clear inputs, clear outputs, one responsibility, no surprises. The LLM on the other end is just another client. It deserves the same quality of interface your frontend developer deserves. So does your frontend developer, for that matter.
For those of us building applications — not language models, not AI infrastructure, but the software businesses actually run on — the AI moment isn't a reason to learn new tricks. It's a reason to finally take the old ones seriously. The clients who trust us with their businesses deserve software built to last, built to change, and built to compose. Not patch jobs held together with good intentions and deadline pressure. Not monoliths only the original author can navigate. Not systems so tightly coupled that adding a feature requires a week of archaeology.
The hype will pass. The software will remain. And when the next wave arrives with its new vocabulary and new protocols, systems built on solid foundations will integrate cleanly — and the rest will be rewritten again from scratch.
The Fundamentals Don't Expire
We've known what good engineering looks like since 1978. The only question worth asking is whether we have the discipline — and the honesty — to actually deliver it.