DEV Community

Cover image for Why a Single Interface for Multiple LLM Providers Is a Bad Design Decision
Miodrag Vilotijević for JigJoy

Posted on • Originally published at jigjoy.ai

Why a Single Interface for Multiple LLM Providers Is a Bad Design Decision

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.

Where We Started

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.

The Problem with "Unified" Abstractions

Over time, cracks started to show:

All models looked the same to developers

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.

Adding new models became harder, not easier

New models come with new capabilities, parameters, and behaviors. A "unified" interface either ignores those features, or becomes bloated trying to support everything. Neither is good design.

The ubiquitous language was wrong

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.

We enabled misuse by design

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.

The Redesign

So we changed direction.

Instead of forcing a unified interface, we started modeling each LLM separately, along with its capabilities and constraints.

Why This Is the Right Move

Advanced users can extract more value

Power users are no longer limited by a lowest-common-denominator API.

Models are not the same - and that matters

Treating them as identical leads to misuse. Embracing differences leads to better outcomes.

Invalid configurations are caught early

Instead of runtime surprises, errors are surfaced immediately.

Better developer experience (DX)

Clear APIs, explicit capabilities, fewer hidden assumptions.

Most importantly: the library expresses domain knowledge correctly
The design now reflects reality - not an oversimplified version of it.

Looking Forward

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:

  • make model capabilities explicit

  • prevent invalid usage early

  • and let developers actually use the power of each model instead of hiding it

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.

Source:

Why a Single Interface for Multiple LLM Providers Is a Bad Design Decision

Why unified LLM abstractions fail and how modeling each LLM separately improves developer experience. A lesson in Domain-Driven Design.

jigjoy.ai

Top comments (0)