I was deep in the theKrew MVP. Multi-agent architecture, complex workflows, tight security requirements baked into every layer. The kind of project where you're moving fast, making decisions on the fly, and leaning heavily on an AI coding agent to keep pace.
Then I noticed it. The codebase was getting messy. Shared helper functions being called from multiple places. Logic bleeding between layers. It was starting to look like spaghetti.
Old instinct kicked in immediately. Stop. Refactor. Clean this up.
Then I caught myself. Wait. Should I?
What happened next changed how I think about building software.
The Rules We Inherited
Every developer, and every technical lead who has managed developers, learned the same principles. Don't Repeat Yourself. Abstract your code into clean layers. Build inheritance trees so child classes reuse parent logic. Handle errors gracefully with structured exception handling. Keep files small and modular.
These weren't arbitrary rules. They were hard-won lessons built over decades. They reduced maintenance costs, prevented bugs from spreading, and made codebases navigable by human teams over long periods of time.
The key phrase: human teams, over long periods of time.
That's not always the context we're building in anymore.
Where the Agent Breaks the Rules
Take abstraction: building clean, layered architecture where each part of your system has a defined role and boundary. For theKrew, I built exactly that. Clean interfaces, separation of concerns, each layer responsible for its own job.
The agent dismantled it within a week. Not maliciously. It just didn't respect the boundaries. When I asked it to add a new feature, it bypassed the interface entirely and wrote the logic wherever was most convenient. When I asked it to fix something in one layer, it changed the wrong layer. The abstraction I built to protect the codebase became the exact thing that made agent edits unpredictable.
The same thing happened with inheritance. I had a base workflow class that several other workflows inherited from. The agent kept editing the parent directly and breaking all the children simultaneously, without realising the relationship existed. With a human engineer, you think about what else inherits from a class before you touch it. Agents don't think that way. They solve the immediate problem and move on.
Polymorphism ran into a similar wall. I built interchangeable components that all shared the same interface so the workflow layer didn't need to care which type it was dealing with. The agent didn't trust the interface. It wrote around it, added type checks, created separate code paths for every case. The flexible design became a tangle of conditionals. It worked. But the architecture was gone.
Exception handling got the same treatment. I'd built structured error hierarchies so the system would fail gracefully and tell you exactly what went wrong. It got flattened to a generic "catch everything and log it" within days. The agent defaults to the safest, broadest option. Your carefully designed error signals disappear, and you only find out something went wrong when a client calls.
Duplication Is Now a Feature
The hardest one to accept was DRY: Don't Repeat Yourself.
The shared utility functions in theKrew were the source of my worst debugging sessions. Every time the agent touched one of them, something else broke somewhere else in the system. The code was too shared, too central, too connected.
So I did something that felt deeply wrong: I duplicated them. Each module got its own copy of what it needed. No shared dependencies. No ripple effects.
And it worked. Perfectly.
Here's why the math has changed: the whole point of DRY was to reduce maintenance burden on human engineers. One place to fix means one place to update. But agents don't maintain, they edit. And when they edit shared code, they don't ask "what else depends on this?" They just make the change.
Duplication removes that risk. Each piece of code lives in one place, serves one purpose, and can be edited in isolation. If you need consistency across duplicates, you run an agent job to apply the same change everywhere. What used to take a careful engineer an afternoon of fearful editing now takes a few minutes.
The overhead that made duplication a bad practice has collapsed. The risk that made it dangerous is now manageable.
Where You Still Need to Be Human
This doesn't mean you stop thinking. You just think differently about where to apply rigor.
Anything that touches production data, business logic, security — anything where a bug would be catastrophic — I review every single line. Short leash, explicit instructions, manual sign-off.
The React dashboard component that renders a summary and works when you click through it? I test the output. I don't read every line of code. There might be imperfections in there. It works. That's enough.
You develop intuition for this over time. The real senior engineering skill right now is knowing where to trust the agent and where to keep it on a very short leash.
The Part That Surprised Me Most
This MVP isn't meant to last five years. In twelve months, I'll point a better, cheaper agent at it and say: clean this up, make it production-grade.
We spent decades writing code that had to survive — maintainable, extensible, documented for whoever inherited it next — because the cost of rewriting was enormous. That cost is collapsing. You're not writing for the ages. Write it to work today, ship it, learn, and let a future agent handle the refactor.
The principles we inherited were never handed down from on high. They were engineering responses to specific constraints: expensive human time, slow iteration, long maintenance cycles. Those constraints are changing faster than most of us are updating our mental models.
Spaghetti code used to be a sign of a lazy developer.
In the agent era, it might be a sign of a smart one.
Tuple Technologies is a New Jersey-based managed service provider helping businesses build smarter, leaner, and more efficient technology systems. As AI becomes core infrastructure, we help our clients engineer it right — from the architecture layer up.
Ready to build smarter systems with AI agents on your team? Get in touch with our team.