"Don't write frameworks for dummies."
That sentence stuck with me while reading Domain-Driven Design: Tackling Complexity in the Heart of Software. I didn't fully understand it at first - but after building (and then redesigning) an AI orchestration framework, I do now.
When we began building a framework for orchestrating AI agents, one of the first features we introduced was a unified request interface across multiple LLM providers.
At first, it felt like a great design decision.
One interface.
Multiple providers.
Clean abstraction.
Simple.
But that simplicity turned out to be misleading.
Over time, cracks started to show:
By flattening everything into a single interface, we erased the differences between models. Developers stopped thinking about capabilities and limitations - which is exactly what they should be thinking about.
New models come with new capabilities, parameters, and behaviors. A "unified" interface either:
Neither is good design.
The API didn't reflect the domain. It reflected our attempt to simplify it. That meant the language of the library didn't express real model capabilities.
The worst part: the abstraction allowed developers to make mistakes easily - and only discover them at runtime.
For example:
passing reasoning_effort="high" to a model that doesn't support reasoning.The system didn't prevent it. It allowed it.
That's not just a bad developer experience - it's a failure in design. The abstraction wasn't helping developers. It was hiding the truth.
So we changed direction.
Instead of forcing a unified interface, we started modeling each LLM separately, along with its capabilities and constraints.

Power users are no longer limited by a lowest-common-denominator API.
Treating them as identical leads to misuse. Embracing differences leads to better outcomes.
Instead of runtime surprises, errors are surfaced immediately.
Clear APIs, explicit capabilities, fewer hidden assumptions.
The design now reflects reality - not an oversimplified version of it.
We're not done yet.
We haven't fully committed the redesign - but we've started moving in this direction, and the changes will roll out in the next versions of Mozaik.
The goal is simple:
This is still evolving, and we'll likely learn more (and fix more mistakes) along the way.
But one thing is already clear:
We're no longer trying to hide the complexity of LLMs.
We're designing for it.
"Don't write frameworks for dummies. Team divisions that assume some developers are not smart enough to design are likely to fail because they underestimate the difficulty of application development. If those people are not smart enough to design, they shouldn't be assigned to develop software."