@mozaik-ai/core 3.1.1 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +252 -65
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,24 +1,12 @@
1
1
  # Mozaik
2
2
 
3
- **Mozaik** is a TypeScript framework for building controllable multi-step AI agents.
3
+ **Mozaik** is a TypeScript framework for building non-blocking AI agents.
4
4
 
5
- Instead of focusing on agents themselves, Mozaik provides a structured way to **model, manipulate, persist, and restore the context** that drives language model behavior. It implements a clean object model aligned with the **OpenResponses specification**, enabling developers to work with LLM inputs and outputs as composable, typed entities.
6
-
7
- With Mozaik, you can:
8
-
9
- - Structure interactions as ordered **context items** (messages, reasoning steps, function calls, etc.)
10
- - Append and evolve context across multiple model calls
11
- - Persist and reload context from storage
12
- - Manage context size and avoid overflow
13
- - Build complex workflows through **context composition**, not ad-hoc prompt strings
14
-
15
- Mozaik treats context as a **first-class primitive**, making it easier to design scalable, maintainable, and provider-agnostic LLM applications.
16
-
17
- ![mozaik](https://github.com/user-attachments/assets/0fdc15a8-3778-4d0e-bd13-143d04090b9e)
5
+ It provides a structured agent loop, a lifecycle hook system, a typed context model, and an experimental multi-agent runtime — giving you full control over how agents think, act, and collaborate.
18
6
 
19
7
  ---
20
8
 
21
- ## 📦 Installation
9
+ ## Installation
22
10
 
23
11
  ```bash
24
12
  yarn add @mozaik-ai/core
@@ -26,94 +14,293 @@ yarn add @mozaik-ai/core
26
14
 
27
15
  ## API Key Configuration
28
16
 
29
- Make sure to set your API keys in a `.env` file at the root of your project:
30
-
31
17
  ```env
32
- # For OpenAI
18
+ # .env
33
19
  OPENAI_API_KEY=your-openai-key-here
34
20
  ```
35
21
 
36
- ## Context Runtime (Overview)
22
+ ---
23
+
24
+ ## Architecture
25
+
26
+ Mozaik is organized into four layers:
27
+
28
+ ```mermaid
29
+ graph TD
30
+ AgentSociety["AgentSociety (experimental)"] --> Agent
31
+ Agent --> AgentRuntime
32
+ AgentRuntime --> AgentLoop["AgentLoop (FSM + hooks)"]
33
+ AgentLoop --> OpenAIResponses["OpenAIResponses (OpenResponses adapter)"]
34
+ AgentLoop --> Context["Context + ContextItems"]
35
+ ```
36
+
37
+ | Layer | Responsibility |
38
+ | ----------------------- | ------------------------------------------------------ |
39
+ | **AgentSociety** | Runs multiple agents concurrently (experimental) |
40
+ | **Agent** | Lifecycle callbacks, visitor hooks, high-level `run()` |
41
+ | **AgentRuntime** | Drives the loop, dispatches hooks, manages errors |
42
+ | **AgentLoop + Context** | FSM transitions and typed context model |
43
+
44
+ ---
45
+
46
+ ## Core Concepts
47
+
48
+ ### Agent Loop
49
+
50
+ The agent loop is a **finite state machine** that drives a multi-step inference cycle. Each execution moves through states until it reaches a terminal condition.
51
+
52
+ ```mermaid
53
+ stateDiagram-v2
54
+ [*] --> INFERENCE_PENDING
55
+ INFERENCE_PENDING --> FUNCTION_CALL_PENDING: model returned a function call
56
+ INFERENCE_PENDING --> MODEL_MESSAGE_RECEIVED: model returned a message
57
+ FUNCTION_CALL_PENDING --> INFERENCE_PENDING: tool executed, feeding output back
58
+ MODEL_MESSAGE_RECEIVED --> [*]: execution complete
59
+ ```
60
+
61
+ An `Execution` object tracks the current state, step count, transition history, and terminal status (`RUNNING`, `COMPLETED`, `FAILED`).
62
+
63
+ ---
64
+
65
+ ### Hooks (Events)
66
+
67
+ Every state transition exposes **before** and **after** hooks. You register callbacks on an `AgentRuntime` using `.on(hookId, callback)`:
68
+
69
+ ```ts
70
+ import { AgentRuntime, HookId } from "@mozaik-ai/core"
71
+
72
+ const runtime = new AgentRuntime()
73
+
74
+ runtime.on(HookId.BEFORE_INFERENCE, async (context) => {
75
+ console.log("About to call the model...")
76
+ })
77
+
78
+ runtime.on(HookId.AFTER_INFERENCE, async (context) => {
79
+ console.log("Model responded:", context.inferenceResponse)
80
+ })
81
+
82
+ runtime.on(HookId.AFTER_FUNCTION_CALL, async (context) => {
83
+ console.log("Tool executed:", context.functionCallOutput)
84
+ })
85
+
86
+ runtime.on(HookId.ON_ERROR, async (context) => {
87
+ console.error("Agent failed:", context.error)
88
+ })
89
+ ```
90
+
91
+ Available hooks:
92
+
93
+ | Hook | Fires |
94
+ | ---------------------- | ------------------------------------ |
95
+ | `BEFORE_INFERENCE` | Before the model is called |
96
+ | `AFTER_INFERENCE` | After the model responds |
97
+ | `BEFORE_FUNCTION_CALL` | Before a tool is invoked |
98
+ | `AFTER_FUNCTION_CALL` | After a tool returns |
99
+ | `BEFORE_MODEL_MESSAGE` | Before the final message is received |
100
+ | `AFTER_MODEL_MESSAGE` | After the final message is received |
101
+ | `ON_ERROR` | When any state handler throws |
102
+
103
+ ---
104
+
105
+ ### Agent
106
+
107
+ `Agent` wraps an `AgentRuntime` and pre-wires all hooks as overridable methods. Subclass it to customize behavior at any point in the lifecycle:
108
+
109
+ ```ts
110
+ import { Agent, AgentRuntime, RuntimeContext } from "@mozaik-ai/core"
111
+
112
+ class MyAgent extends Agent {
113
+ constructor() {
114
+ super(new AgentRuntime())
115
+ }
116
+
117
+ async afterInference(context: RuntimeContext): Promise<void> {
118
+ console.log("Tokens used:", context.inferenceResponse?.tokenUsage)
119
+ }
120
+
121
+ async onError(context: RuntimeContext): Promise<void> {
122
+ console.error("Something went wrong:", context.error?.message)
123
+ }
124
+ }
125
+
126
+ const agent = new MyAgent()
127
+ await agent.run("Summarize the latest news", model, context)
128
+ ```
129
+
130
+ ---
37
131
 
38
- The **Context Runtime** models the core behavior of a language model:
132
+ ### InferenceVisitor
39
133
 
40
- > Given a structured **context**, produce a **response**.
134
+ `InferenceVisitor` is a **visitor interface** that lets you observe the inference lifecycle without modifying the agent itself. Attach it to any `Agent` instance via `setInferenceVisitor`.
41
135
 
42
- It abstracts away vendor-specific APIs (e.g. OpenAI) and provides a domain-centric interface for working with LLMs.
136
+ ```ts
137
+ import { InferenceVisitor, InferenceResponse, RuntimeContext } from "@mozaik-ai/core"
138
+
139
+ class TelemetryVisitor implements InferenceVisitor {
140
+ async onStart(context: RuntimeContext): Promise<void> {
141
+ console.log("Agent started, execution:", context.execution.executionId)
142
+ }
143
+
144
+ async afterInference(response: InferenceResponse): Promise<void> {
145
+ console.log("Inference complete, tokens:", response.tokenUsage)
146
+ }
147
+ }
148
+
149
+ const agent = new MyAgent()
150
+ agent.setInferenceVisitor(new TelemetryVisitor())
151
+ ```
152
+
153
+ Use `InferenceVisitor` for concerns that should stay separate from agent logic: logging, telemetry, streaming responses to a UI, or recording usage metrics.
43
154
 
44
155
  ---
45
156
 
46
- ## Compatibility
157
+ ### Context Model
47
158
 
48
- This domain model is fully compatible with the **Open Responses** specification for multi-provider LLM interfaces ([openresponses.org](https://www.openresponses.org/)).
159
+ `Context` is the structured input passed to the model. It is composed of ordered **`ContextItem`** objects — each representing a single unit of context.
49
160
 
50
- ![OpenResponses overview](public/openresponses-overview.png)
161
+ **Client-provided items** (you add these):
51
162
 
52
- The core idea of OpenResponses is a **unified specification across LLM providers**: while vendors differ in details, most models follow the same interaction architecture and principles. OpenResponses standardizes that shared shape using **typed context items** (and clarifies that any item type can be streamed).
163
+ - `UserMessage` — the user's turn
164
+ - `DeveloperMessage` — system instructions
165
+ - `FunctionCallOutput` — tool result fed back to the model
53
166
 
54
- - **Input (context)**: client-provided context items such as **user_message**, **developer_message**, and **function_call_output**
55
- - **Output (response)**: model-produced context items such as **reasoning**, **function_call**, and **model_message**
56
- - **Streaming (optional)**: items may be delivered incrementally as **semantic events** (meaningful events at the item level, not just raw token streams)
167
+ **Model-produced items** (appended by the loop):
57
168
 
58
- ## Mozaik Core Concepts
169
+ - `ModelMessage` — the model's final text response
170
+ - `FunctionCall` — a tool invocation requested by the model
171
+ - `Reasoning` — the model's internal reasoning trace
59
172
 
60
- Mozaik turns the OpenResponses specification into a practical **object model** so developers can manipulate LLM context in different ways (compose it, append model outputs, **persist it**, and **restore it** from a database/repository, etc.). This is a starting point—our main goal is to address core **context engineering** problems like **context bloating**, **context window overflow**, and **sequential agent collaboration**.
173
+ ```ts
174
+ import { Context, DeveloperMessage, UserMessage, InMemoryContextRepository } from "@mozaik-ai/core"
175
+
176
+ const context = Context.create("project-id")
177
+ .addItem(DeveloperMessage.create("You are a helpful assistant."))
178
+ .addItem(UserMessage.create("What is the capital of France?"))
61
179
 
62
- ### Context
180
+ const repo = new InMemoryContextRepository()
181
+ await repo.save(context)
63
182
 
64
- Represents everything the model needs to generate a response.
183
+ // later...
184
+ const restored = await repo.getByProjectId("project-id")
185
+ ```
65
186
 
66
- A context is composed of ordered **context items**.
187
+ Context can be persisted and restored via `ContextRepository`. The built-in `InMemoryContextRepository` is suitable for development; implement `ContextRepository` to connect any storage backend.
67
188
 
68
189
  ---
69
190
 
70
- ### ContextItem
191
+ ### OpenResponses
192
+
193
+ `OpenAIResponses` is the framework's inference provider. It implements the **OpenResponses** specification ([openresponses.org](https://www.openresponses.org/)), mapping Mozaik's typed `Context` to the OpenAI Responses API and back.
71
194
 
72
- A single unit of context.
195
+ It is the default provider used by `AgentRuntime` and handles:
73
196
 
74
- Examples:
197
+ - Serializing `ContextItem` objects to API-compatible input
198
+ - Deserializing model output into `ModelMessage`, `FunctionCall`, and `Reasoning` items
199
+ - Extracting token usage from the response
75
200
 
76
- - Client-specific
77
- - User message
78
- - Developer message (System instruction)
79
- - Function call output (added after a model function call and fed back so the model can continue reasoning or finish the job)
80
- - Model-specific
81
- - Function call
82
- - Model message
83
- - Reasoning
201
+ You can use it directly for single-shot inference outside the agent loop:
202
+
203
+ ```ts
204
+ import { OpenAIResponses, InferenceRequest, Gpt54 } from "@mozaik-ai/core"
205
+
206
+ const openaiResponses = new OpenAIResponses()
207
+ const request = new InferenceRequest(new Gpt54(), context)
208
+ const response = await openaiResponses.infer(request)
209
+
210
+ context.applyModelOutput(response.contextItems)
211
+ ```
212
+
213
+ Available models: `Gpt54`, `Gpt54Mini`, `Gpt54Nano`.
84
214
 
85
215
  ---
86
216
 
87
- ## Example (Context + OpenAI Responses)
217
+ ### AgentSociety _(experimental)_
88
218
 
89
- This is a minimal end-to-end example that:
219
+ `AgentSociety` is the framework's answer to one of the core limitations in today's agent systems: **agents that block on each other**. Most multi-agent frameworks run agents sequentially, which creates bottlenecks and prevents true parallelism.
90
220
 
91
- - builds a `Context` from a developer message + user message
92
- - calls a model (OpenAI Responses API)
93
- - stores/restores the context using a repository
221
+ `AgentSociety` runs agents **concurrently and non-blocking**. When `enter()` is called, every agent in the society starts its execution independently — none waits for another to finish.
94
222
 
95
223
  ```ts
96
- const message = UserMessage.create("Tell me a joke about birds")
97
- const developerMessage = DeveloperMessage.create(
98
- "You are a joke teller. You will be given a joke and you will need to tell it to the user.",
99
- )
224
+ import { AgentSociety, AgentRuntime } from "@mozaik-ai/core"
225
+
226
+ const society = new AgentSociety("research-team")
227
+
228
+ society.join(new ResearchAgent())
229
+ society.join(new SummaryAgent())
230
+ society.join(new FactCheckAgent())
231
+
232
+ // Start the society's event loop
233
+ society.start()
100
234
 
101
- const projectId = `pr-${crypto.randomUUID()}`
102
- const contextRepository = new InMemoryContextRepository()
103
- const context = Context.create(projectId).addItem(developerMessage).addItem(message)
235
+ // All three agents run in parallel on the same context
236
+ society.enter("Analyze the impact of AI on software development", model, context)
104
237
 
105
- await contextRepository.save(context)
238
+ // Shut down when done
239
+ society.stop()
240
+ ```
241
+
242
+ All agents receive the same `Context`, enabling **collaborative context building** — each agent's output is visible to others through the shared context as the execution progresses.
243
+
244
+ > **Experimental:** `AgentSociety` is in active development. The API is stable enough to build on, but expect refinements — particularly around context isolation, coordination primitives, and agent-to-agent messaging. Feedback and contributions are welcome.
245
+
246
+ ---
106
247
 
107
- const openresponses = new OpenAIResponses()
108
- const newContextItems = await openresponses.infer(gpt54, context)
109
- context.applyModelOutput(newContextItems)
248
+ ## Full Example
110
249
 
111
- await contextRepository.save(context)
112
- const restoredContexts = await contextRepository.getByProjectId(projectId)
113
- console.log(restoredContexts)
250
+ End-to-end example with a tool-calling agent and hook observability:
251
+
252
+ ```ts
253
+ import {
254
+ Agent,
255
+ AgentRuntime,
256
+ HookId,
257
+ Context,
258
+ DeveloperMessage,
259
+ Gpt54Mini,
260
+ InMemoryContextRepository,
261
+ Tool,
262
+ } from "@mozaik-ai/core"
263
+
264
+ // Define a tool
265
+ const weatherTool = new Tool({
266
+ name: "get_weather",
267
+ description: "Get the current weather for a city",
268
+ parameters: {
269
+ type: "object",
270
+ properties: { city: { type: "string" } },
271
+ required: ["city"],
272
+ },
273
+ invoke: async ({ city }) => ({ temperature: "22°C", condition: "sunny" }),
274
+ })
275
+
276
+ // Create runtime and wire hooks
277
+ const runtime = new AgentRuntime()
278
+
279
+ runtime.on(HookId.BEFORE_INFERENCE, async (ctx) => {
280
+ console.log(`[step ${ctx.execution.stepCount}] calling model...`)
281
+ })
282
+
283
+ runtime.on(HookId.AFTER_FUNCTION_CALL, async (ctx) => {
284
+ console.log("tool result:", ctx.functionCallOutput)
285
+ })
286
+
287
+ // Create agent
288
+ const agent = new Agent(runtime)
289
+
290
+ // Set up model and context
291
+ const model = new Gpt54Mini([weatherTool])
292
+ const context = Context.create("demo").addItem(DeveloperMessage.create("You are a weather assistant."))
293
+
294
+ const repo = new InMemoryContextRepository()
295
+ await repo.save(context)
296
+
297
+ // Run
298
+ await agent.run("What's the weather like in Tokyo?", model, context)
114
299
  ```
115
300
 
301
+ ---
302
+
116
303
  ## Author & License
117
304
 
118
- Created by [JigJoy](https://jigjoy.io) team
305
+ Created by the [JigJoy](https://jigjoy.io) team.
119
306
  Licensed under the MIT License.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mozaik-ai/core",
3
- "version": "3.1.1",
3
+ "version": "3.1.3",
4
4
  "description": "A TypeScript framework for building AI agents",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",