DEV Community

Cover image for Mozaik in Plain English: A Gentle Introduction to Concurrent AI Agents
jamilxt
jamilxt

Posted on

Mozaik in Plain English: A Gentle Introduction to Concurrent AI Agents

Most AI agent tutorials show you a pipeline. Agent A extracts data, hands it to Agent B, B hands it to C. It works, but it works like an assembly line: if A is slow, everyone waits. If B fails, the line stops. And if you want to add a new specialist to the line, you have to rewire the whole thing.

Mozaik, an open-source runtime built by the JigJoy team, starts from a different idea: what if agents worked like people in a room instead of stations on a line?

I spent last weekend building OpsRoom on Mozaik v4 for the JigJoy hackathon: a live incident war room where AI agents diagnose a production outage together in real time. This post is the plain-English introduction to Mozaik I wish I had before I started, with what I learned along the way.

The room, not the pipeline

In Mozaik, everyone is a Participant. Humans, AI agents, even telemetry feeds. They all join one shared runtime, like people walking into a meeting room.

When something happens (a message, a tool call, someone joining or leaving), it becomes an event published on a shared bus. Every participant can see the events and decide for themselves whether to react. There is no boss. No scheduler. No script that says "first do this, then that".

Think of a group chat where your teammates are all AI. You drop a message, and anyone who cares about it just... acts. That is the mental model.

The three words that explain Mozaik

The docs describe Mozaik with three attributes, and they are worth unpacking:

Concurrency. Agents work at the same time without blocking each other. When an agent starts "thinking" (calling the LLM, running tools), it does not freeze the room. Everyone else keeps going. In my war room, one agent was digging through log files while another was still writing its first proposal. Neither waited for the other.

Awareness. Agents know who else is in the room and what has been said. When someone joins, the others can greet them or hand them context. When someone leaves, others notice. In OpsRoom, two specialists join mid-incident, and the room reacts to their arrival automatically, because joining is itself an event everyone can see.

Adaptivity. Agents can change their behavior based on what is happening. Mozaik calls these situation handlers: "when X happens, then do Y". They read like rules a person would follow: "if a teammate publishes new evidence and I have a pending proposal, re-check my proposal against that evidence."

A tiny example

Here is the essence of the quickstart, simplified:

const agent = createAgent({
  name: 'Assistant',
  instruction: 'You are a helpful teammate.',
  handlers: [thinkOnMessage],   // when someone sends a message, think
});

const human = createHuman({ name: 'User' });

join(human);
join(agent);

sendMessage('Hello', human.getId());
Enter fullscreen mode Exit fullscreen mode

That is the whole setup. The human sends a message, the event hits the bus, the agent's handler matches it, and the agent starts thinking. You never wrote "wait for user input, call the model, return the answer". You declared who is in the room and what each of them reacts to.

What I built, and what it taught me

OpsRoom has 12 participants on one bus: 8 AI agents plus 4 telemetry feeds replaying a fake production incident. The agents are not a pipeline. Triage proposes fixes, LogSleuth digs through raw logs in parallel, RiskCommander challenges anything risky, and a Scribe writes the whole story down as it happens. When a proposal is risky and unevidenced, an interceptor blocks it, and when things get serious, the room pauses until a human approves or rejects.

Three lessons from the weekend that the docs will not tell you:

1. Writing reactions feels weird at first, then clicks. I kept looking for the "orchestration file" that did not exist. The shift is: instead of asking "what is the sequence of steps?", you ask "what does each participant observe, and what does it do about it?" Once you flip that switch, adding a new agent is genuinely just adding a new listener, without touching anything else.

2. LLMs paraphrase, so put contract tokens in your protocol. My RiskCommander needs to catch risky proposals, but the same plan arrives phrased a dozen different ways. The fix: every proposal must start with a literal token like PROPOSAL:. Mozaik's structured output support (JSON schema) lets you enforce this at the model level, so the gate never depends on prose matching.

3. The interception hook is the hidden gem. Mozaik v4 lets you pass an interception handler to the agent loop, which can inspect and rewrite what the model is about to do before it happens. I used it to block any state-changing action (restarts, rollbacks) that had no confirmed evidence behind it. Watching the room block its own unsafe suggestion in real time was the best demo moment of the whole project. If you build agents that touch real systems, build this layer first.

When would you actually use Mozaik?

You have a real multi-agent problem when specialists need each other's output but nobody can predict the exact order. Research teams, incident response, code review crews, data pipelines with judgment calls in the middle. If your agents never need to react to each other, a plain pipeline is simpler, and that is fine. But the moment you find yourself writing a scheduler that mostly routes messages and handles "what if B finishes before A", that is the moment a runtime like Mozaik starts paying for itself.

Where to go next

If you have built agents before, I would love to hear how you handled the coordination problem. Pipeline, graph, or room?

Top comments (3)

Collapse
 
mijura profile image
Miodrag Vilotijević

Thank you so much for spreading the word! This is an amazing article - we couldn’t have written it better ourselves. 🙌

Collapse
 
jamilxt profile image
jamilxt

Pleasure is mine, @mijura

Collapse
 
reidmarlow profile image
Reid Marlow

The event bus model solves the pipeline rigidity problem, but the main trap I ran into with shared room architectures was race conditions on intermediate state. If two agents react to the same telemetry alert concurrently, one starts drafting a rollback while the other is still parsing the stack trace. Without causal ordering or monotonic epochs on the bus, you get split-brain decisions where an agent acts on an assumption that was disproved a second earlier.

The interception hook is where this actually stays sane in production. Pairing that hook with deterministic evidence checks, like requiring an agent tool call to reference a valid error log hash before touching a service restart, stops concurrent agents from running away with each other's half-formed hypotheses.