Why Agent Frameworks End Up As SDK Wrappers — And How To Overcome It

Today, most frameworks for building AI agents are missing something fundamental. If you look closely at the language they use, you'll notice a pattern: their domain models are anemic. They give you abstractions like "agent", "tool", "step", but they don't actually model the thing that matters most - context. Because of that, developers are left on their own to deal with problems like:

And where does all of that logic end up? In your application layer.

The Hidden Cost: Polluting Your Domain

Instead of focusing on your actual domain (finance, healthcare, internal tooling, etc.), you start writing code like:

This is not your domain. It's not even context engineering. In the absence of the right abstractions, developers are pushed to reimplement core LLM concepts themselves—while mixing them with their own domain logic. And this is where complexity arises. We experienced these issues firsthand. That’s what pushed us to address them—so engineers like us can extract more from LLMs and open up new possibilities.

The goal with Mozaik is simple:

Enable developers to use a rich domain model for handling context in agentic applications.

So instead of letting LLM concerns leak into your domain, you can:

At the same time, this is a space we're actively learning in. LLMs are still evolving, and we want to both learn and share what we discover while working on these problems.

Starting Point: OpenResponses

Mozaik 2.0 compability with OpenResponses

We didn't start from scratch.

Our starting point is the OpenResponses specification, published by companies like OpenAI, OpenRouter, Vercel and others in January this year. Their goal is to standardize how we work with LLM providers. They define a shared structure that reflects how models actually operate.

At its core:

Context is composed of context items.

These include:

Client-created items

  • user message
  • developer message
  • function call output

Model-generated items

  • reasoning
  • function call
  • model message

They also introduce an important idea:

Model-generated items are state machines that can be streamed with semantic events.

Those are the fundamental building blocks of the OpenResponses specification and how major LLM providers implement them. For a deeper dive, you can check: https://www.openresponses.org/

Context as a structured sequence of typed items from client and model

Our Take on This

OpenResponses gives us the source of truth for how LLMs work today. These building blocks should not be ignored. But the specification itself is not enough. Developers still need a way to work with it in practice.

Enter Mozaik

Our approach is to take this specification and turn it into a rich object domain model. The goal is not to abstract everything away, but to:

With our base implementation, developers can:

All without leaking context engineering concerns into their core domain logic.

Where This Leads

We see this as a starting point.

By introducing a richer domain model for context, new opportunities open up:

Basic Example

Here's a minimal example of building and storing context using Mozaik:

1const contextRepository = new InMemoryContextRepository()
2
3const message = UserMessage.create("Tell me a joke about birds")
4const developerMessage = DeveloperMessage.create(
5 "You are a joke teller. You will be given a joke and you will need to tell it to the user.",
6)
7
8const projectId = `pr-${crypto.randomUUID()}`
9
10const context = Context.create(projectId)
11 .addItem(developerMessage)
12 .addItem(message)
13
14await contextRepository.save(context)
15
16const model = new GPT54Model()
17const generatedItems = await model.call(context)
18context.addItems(generatedItems)
19await contextRepository.save(context)
20
21const restoredContexts = await contextRepository.getByProjectId(projectId)
22console.log(restoredContexts)

This uses an in-memory repository, but in real applications you can plug in your own persistence layer.

You can find more working examples in the GitHub repository:

github.com/jigjoy-ai/mozaik-examples

Final Thought

The industry is moving fast. But if we keep ignoring context as a core primitive, we'll keep rebuilding the same fragile systems. Mozaik is our attempt to fix that — by giving context the place it actually deserves. And this is just the beginning. We're excited to see where this journey takes us.

Miodrag Vilotijević

Miodrag Vilotijević

Co-founder @ JigJoy

Building the future of software development

When complexity gets out of hand, the software can no longer be understood well enough to be easily changed or extended. By contrast, a good design can make opportunities out of those complex features.