More Simplification
#6: In which the agent thinks I won't notice it's lying to me.
At the start of 2025, I often described coding agents as over-eager interns. They would jump on any task with enthusiasm and confidence. Whether they produced anything useful or not was a different question. As their manager, you ask yourself whether they are actually helping you or if you are simply providing them an education — and paying for it. Even when a given highly detailed specification of the task that took nearly as much time and effort as implementing it yourself, there was no guarantee of a good result.
Coming into 2026, I started thinking of them as over-eager junior developers. They had real skill but often lack the discipline of senior developers. There, the relationship has a much clearer ratio of benefit to cost. As a senior member of a team, you know will often spend much, if not most, of your time guiding less experienced colleagues, but they make real contributions that add to the overall velocity of the engineering organization.
One characteristic that both classes of employee share is that — in addition to being willing to grind away at tasks for more hours than you since they don’t yet have that much of a life outside of work — they think they’re smarter than you.
With all the bold declarations that tasks are completed, clean, and production-ready, it is always frustrating to inspect the generated output to find a ball of spaghetti full of duplication and dead code that barely function. For every session devoted to a new feature, there is another devoted to cleanup. To be clear a technical manager, be it of people or AI agents, is ultimately responsible for the output of the team, and we are all still learning the techniques of effective AI agent management. I am lucky to have spent many years managing people at startups. What makes that different from a managing people at a big company is that you never stop being hands-on with the codebase. It is not a transferral of skill to manage AI agents, but there is a ton of overlap.
One principle that I hold as a manager of people is that tech debt is an investment, and it is best paid down constantly. I believe that dedicating sprints exclusively to tech debt is a sign of mismanagement, and it is sure may to bring down morale.
So, it is with a heavy, disappointed heart that I know I will devote a few pull requests to tech debt an cleanup. I attribute the need to a few things:
I wrote many imprecise prompts. To an extent, this has been part of the experience so far. I have been curious to test the limits of how much a model “knows.” The consequences of this approach are becoming clear.
The agents are way too eager to please. This should be fixable through how I define my agents, but I have not gone through that process.
There is a flaw in my view of treating Opencode using Sonnet 4.x as something akin to a single junior developer. Every session is a new developer who is only aware of previous work by reading the code and a few notes left behind. It’s more like I have hired an agency (it’s in the name) of experienced engineers that cannot provide a dedicated developer for my project.
With all this in mind I got started on paying down some tech debt.
I would like to continue with some refactoring to make the code as simple an as clear as possible. Let's looks at it together and strategize changes. I will just ask some questions. First: Do we really need the `Processor` trait. I see that the `MelodyGenerator` and `Oscillator` modules implement it. But it does appear to be used.
It found that the Processor is no longer used and there are other similar structures that, while still in use, could be removed with a little refactoring. The agent said that the reason for some of these pieces remaining in place was because previous instances of the agent noted in the AGENTS.md that these legacy systems need to be preserved. Notably, it described the templated Generator<T> trait as one of the things that could be removed. The fact that it was templated made be realize something: the agents never fully simplified the signal type despite being asked to multiple times. This seemed to be in the name of backwards compatibility. Again, this was after being told not to worry so much about backwards compatibility. It is a message that was lost in the agents’ notes to self.
Hold that thought. Before we do that, let's investigate the signal types. Do we need anything other than `Audio` at this point?
After some back and forth we decided to:
Remove any sort of type aliasing for signal types and just use
f32numeric primitives.Remove the
Generatorinterface altogether.Remove legacy systems.
Rename structures, like
ModularModule, that only had stupid names because the agent was overly concerned with backwards compatibility.
It was another massive refactor with not functional change, but Fugue is better off for it. While I will begin refining my process to reduce the need for these sessions in the future, I know it won’t be the last.
2026.1.29



