Mozaik

Quickstart

Initialize a runtime, join a human and an agent, and let the agent think when someone else sends a message.

This walkthrough matches the example in the Mozaik README: define a runtime, register a situation handler, join a human and an agent, then sendMessage. The agent does not need a separate "start inference" call — it reacts through a specification that matches message.sent.

Full example

import {
  defineRuntime,
  RuntimeState,
  createAgent,
  createHuman,
  SituationSpecification,
  Agent,
  type SituationHandler,
  type SituationContext,
} from '@mozaik-ai/core';

class AppState extends RuntimeState {}

const { initializeRuntime, join, sendMessage, runLoop } = defineRuntime<AppState>();

initializeRuntime({ state: new AppState() });

class WhenOthersSendAMessage extends SituationSpecification {
  isSatisfiedBy({ event, participant }: SituationContext): boolean {
    return event.type === 'message.sent' && event.producerId !== participant.getId();
  }
}

const thinkOnMessage: SituationHandler = {
  specification: new WhenOthersSendAMessage(),
  processor: {
    apply({ event, participant }) {
      if (!(participant instanceof Agent)) return;
      const { message } = event.payload as { message: string };
      runLoop(participant.getId(), message, {
        model: 'gpt-5.5',
        context: participant.getMemory().getContext(),
        tools: participant.getTools(),
      });
    },
  },
};

const agent = createAgent({
  name: 'Assistant',
  capabilities: ['inference'],
  instruction: 'You are a helpful teammate.',
  tools: [],
  handlers: [thinkOnMessage],
});

const human = createHuman({ name: 'User', capabilities: [], handlers: [] });

join(human);
join(agent);

sendMessage('Hello', human.getId());

defineRuntime returns the functions for this session. They are not top-level package exports — keep them in module scope (or re-export them yourself). Call initializeRuntime once before join, sendMessage, or runLoop.

What this is doing

  1. defineRuntime<AppState>() — Creates the session API typed to your RuntimeState subclass.
  2. initializeRuntime({ state }) — Instantiates the runtime. Calling it twice throws "Runtime already initialized".
  3. WhenOthersSendAMessage — A SituationSpecification that matches message.sent from someone other than this participant.
  4. runLoop — Starts one agent turn (context update, inference, tools, answer). It returns void and keeps running in the background.
  5. sendMessage('Hello', human.getId()) — Publishes message.sent. The agent's handler matches and starts the loop.

Do not await runLoop or sendMessage inside a processor. Both return immediately while the runtime keeps delivering events.

What you'll need

  • A provider API key — see Installation.
  • A model name on InferenceInput (for example 'gpt-5.5'). The provider is resolved from that name — see Models.
  • For human input, call sendMessage from your UI or I/O layer when the user acts.

On this page