tool

Mozaik

created 2026-05-28 ai · agents · reactive · swarms · typescript · streaming · framework

Mozaik

A TypeScript framework for building reactive agents — collaborative, event-driven agents that work together in parallel. Built by JigJoy (Miodrag Vilotijević). Package: @mozaik-ai/core, MIT licensed.

npm install @mozaik-ai/core

Core Idea

Humans, agents, tools, and observers are all Participants in a shared AgenticEnvironment (an event bus). Each participant emits typed events that every other participant can consume in real time — no central orchestrator. Streaming is treated as part of the runtime, not a UI concern (see streaming-as-runtime). Behavior is composed from independent reactive participants rather than orchestrated by a controller (see reactive-agents, agent-swarms).

API Surface

Participant types

ClassRole
ParticipantBase class for any entity; all handlers default to no-op
BaseAgent / BaseAgentParticipantReactive agent with inference + function-calling
BaseHumanSends text messages into the environment
BaseObserverListen-only participant

AgenticEnvironment is the event bus participants join(); call environment.start() to run.

Typed event handlers

The framework replaced a single generic onContextItem(source, item) intercept with dedicated, default-no-op handlers, so an agent overrides only what it needs and reads as a flat “when X → do Y” list with no branching dispatch:

  • onMessage — plain string messages (conversational lane)
  • onFunctionCall / onFunctionCallOutput
  • onReasoning
  • onModelMessage
  • lifecycle: onJoined, onLeft, onParticipantJoined, onParticipantLeft

Self vs. external split — each handler has an external twin fired when a peer emits:

  • onFunctionCall (mine) vs onExternalFunctionCall(source, item) (a peer’s)
  • likewise onExternalFunctionCallOutput, onExternalReasoning, onExternalModelMessage
  • streaming-level: onInternalEvent() / onExternalEvent()

This eliminates manual source-checking and cleanly separates “act on my own outputs” from “observe others.” A passive logger is just a participant overriding only the onExternal* handlers.

Two communication lanes

  • Messages — plain strings via onMessage(message: string).
  • ContextItems — typed model internals (function calls, reasoning, model messages), each with .toJSON(). InputItemSource was replaced by InputStream (async iterable of strings).

Runners, context, providers

  • InferenceRunner (OpenAIInferenceRunner) — produces reasoning, function calls, model messages, and semantic events.
  • FunctionCallRunner (DefaultFunctionCallRunner) — executes tools, yields results.
  • ModelContext — ordered list of ContextItems passed to the model; ModelContextRepository is the persistence abstraction.
  • OpenAI provider models (framework’s own names): Gpt54, Gpt54Mini, Gpt54Nano, Gpt55, on the OpenAIResponses runtime.

Quickstart

import {
  AgenticEnvironment,
  BaseAgent,
  BaseHuman,
  OpenAIInferenceRunner,
  DefaultFunctionCallRunner,
  Gpt54Mini,
} from "@mozaik-ai/core"

const environment = new AgenticEnvironment()

const human = new BaseHuman()
const agent = new BaseAgent(new OpenAIInferenceRunner(), new DefaultFunctionCallRunner())

human.join(environment)
agent.join(environment)

environment.start()

human.sendMessage(environment, "Hello")

Design Notes

  • Non-blocking by design: semantic streaming events are delivered synchronously to all subscribers, so a slow listener never blocks producers — a deliberate producer-priority stance on back-pressure (the framework favors not stalling generation over guaranteeing every listener keeps up).
  • Composability: adding a new role to a swarm = writing one more reactive agent and join()-ing it, not editing a central controller.

How It Differs From LangGraph

LangGraphMozaik
StructureGraph/DAG of nodesConcurrent participants in one environment
ControlSupervisor / explicit edges / Command routingNo controller; reaction-driven
Turn modelSequential (mostly)Concurrent, event-reactive
LanguagePython-firstTypeScript-native
Add a capabilityEdit graph / add nodeWrite + join() a participant

Not a drop-in replacement — a different paradigm. See ai-agent-architectures for where each fits.

See also