@mozaik-ai/core 3.8.1 → 3.8.4

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 +50 -79
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mozaik
2
2
 
3
- **Mozaik** is an open-source TypeScript framework for building reactive AI agents that share an **agentic environment** instead of being orchestrated through rigid workflows.
3
+ **Mozaik** is TypeScript framework for building reactive agents. It provides the easiest way to build collaborative, **event-driven agents** that can work together in parallel.
4
4
 
5
5
  ![npm downloads](https://img.shields.io/npm/dt/@mozaik-ai/core) ![npm downloads weekly](https://img.shields.io/npm/dw/@mozaik-ai/core) ![npm version](https://img.shields.io/npm/v/@mozaik-ai/core)
6
6
 
@@ -25,17 +25,21 @@ OPENAI_API_KEY=your-openai-key-here
25
25
 
26
26
  ## The agentic environment
27
27
 
28
- `AgenticEnvironment` is a broadcast bus for typed events. `Participant`s `join()` it, and anything produced by one participant is delivered to every subscriber through a **dedicated typed callback** — one per event kind, with separate handlers for items the participant emitted itself versus items emitted by someone else:
28
+ `AgenticEnvironment` is where everything happens. `Participant`s `join()` it, and from that moment on they can **listen to messages and events** flowing through the environment by overriding any of the handlers below:
29
29
 
30
- | Producer call | Self handler | External handler |
31
- | ----------------------------------------- | ---------------------- | ----------------------------------------- |
32
- | `deliverFunctionCall(source, item)` | `onFunctionCall` | `onExternalFunctionCall(source, …)` |
33
- | `deliverFunctionCallOutput(source, item)` | `onFunctionCallOutput` | `onExternalFunctionCallOutput(source, …)` |
34
- | `deliverReasoning(source, item)` | `onReasoning` | `onExternalReasoning(source, …)` |
35
- | `deliverModelMessage(source, item)` | `onModelMessage` | `onExternalModelMessage(source, …)` |
36
- | `deliverMessage(source, message)` | _(not delivered)_ | `onMessage(message)` |
30
+ | Handler | Triggered when… |
31
+ | ------------------------------ | ------------------------------------------------------ |
32
+ | `onMessage` | any participant sends a message |
33
+ | `onFunctionCall` | its own inference returns a function call |
34
+ | `onExternalFunctionCall` | another agent's inference returns a function call |
35
+ | `onFunctionCallOutput` | its own function call runner returns a result |
36
+ | `onExternalFunctionCallOutput` | another agent's function call runner returns a result |
37
+ | `onReasoning` | its own inference returns a reasoning item |
38
+ | `onExternalReasoning` | another agent's inference returns a reasoning item |
39
+ | `onModelMessage` | its own inference returns an assistant message |
40
+ | `onExternalModelMessage` | another agent's inference returns an assistant message |
37
41
 
38
- Messages are plain `string`s exchanged between participants. Every other event flows as a typed `ContextItem` (`FunctionCallItem`, `FunctionCallOutputItem`, `ReasoningItem`, `ModelMessageItem`).
42
+ Every handler defaults to a no-op — override only the ones you care about.
39
43
 
40
44
  ```mermaid
41
45
  flowchart LR
@@ -58,48 +62,6 @@ Mozaik ships two ready-to-use participants:
58
62
  | `BaseHumanParticipant` | `InputCapable` | `InputStream` |
59
63
  | `BaseAgentParticipant` | `InputCapable`, `InferenceCapable`, `FunctionCallCapable` | `InputStream`, `InferenceRunner`, `FunctionCallRunner` |
60
64
 
61
- Each capability method is **non-blocking**: it returns `Promise<void>`, and as the underlying generator yields, every yielded value is forwarded into the environment through the matching typed `deliverX` method.
62
-
63
- `streamInput` pulls plain-text messages from an `InputStream` and routes each one to `deliverMessage` — participants exchange raw text on the wire, not `UserMessageItem` / `DeveloperMessageItem` / `SystemMessageItem` envelopes:
64
-
65
- ```ts
66
- async streamInput(environment: AgenticEnvironment): Promise<void> {
67
- if (!this.isJoinedTo(environment)) return
68
-
69
- const stream = this.inputSource.stream()
70
- for await (const message of stream) {
71
- await environment.deliverMessage(this, message)
72
- }
73
- }
74
- ```
75
-
76
- `runInference` does the same for model output, dispatching each yielded item to `deliverReasoning`, `deliverFunctionCall`, or `deliverModelMessage`:
77
-
78
- ```ts
79
- async runInference(
80
- environment: AgenticEnvironment,
81
- context: ModelContext,
82
- model: GenerativeModel,
83
- signal?: AbortSignal,
84
- ): Promise<void> {
85
- if (!this.isJoinedTo(environment)) return
86
-
87
- const stream = this.inferenceRunner.run(context, model, signal)
88
-
89
- for await (const item of stream) {
90
- if (item.type === "reasoning") {
91
- await environment.deliverReasoning(this, item)
92
- } else if (item.type === "function_call") {
93
- await environment.deliverFunctionCall(this, item)
94
- } else if (item.type === "message" && item.role === "assistant") {
95
- await environment.deliverModelMessage(this, item)
96
- }
97
- }
98
- }
99
- ```
100
-
101
- Because each call is a fresh promise that wraps an async iterable, multiple participants can act on the same environment **concurrently**:
102
-
103
65
  ```ts
104
66
  import {
105
67
  AgenticEnvironment,
@@ -131,46 +93,49 @@ The environment fans every item out to every subscriber synchronously and withou
131
93
 
132
94
  ---
133
95
 
134
- ## Intercepting events from other participants
135
-
136
- Instead of a single catch-all callback, `Participant` exposes **one typed handler per event kind**, with a clear split between events the participant emitted itself and events emitted by someone else. A participant can:
96
+ ## Agent Loop Implementation
137
97
 
138
- - **Observe** events from other participants via the `onExternal*` family (telemetry, audit, UI streaming) and `onMessage` for plain-text messages.
139
- - **React** to its own outputs via the self handlers (e.g. execute a `FunctionCallItem` it just produced), or to others' outputs via the external handlers.
140
- - **Ignore** events it doesn't care about — every handler defaults to a no-op in the bundled participants.
141
-
142
- The intercept surface, taken from `Participant`:
98
+ The easiest way to build **and control** an agent loop is to override three handlers on `BaseAgentParticipant`:
143
99
 
144
100
  ```ts
145
- abstract onFunctionCall(item: FunctionCallItem): Promise<void>
146
-
147
- abstract onExternalFunctionCall(source: Participant, item: FunctionCallItem): Promise<void>
148
-
149
- abstract onFunctionCallOutput(item: FunctionCallOutputItem): Promise<void>
150
-
151
- abstract onExternalFunctionCallOutput(source: Participant, item: FunctionCallOutputItem): Promise<void>
152
-
153
- abstract onReasoning(item: ReasoningItem): Promise<void>
154
-
155
- abstract onExternalReasoning(source: Participant, item: ReasoningItem): Promise<void>
101
+ export class CustomAgent extends BaseAgentParticipant {
102
+ constructor(
103
+ inputSource: InputStream,
104
+ inferenceRunner: InferenceRunner,
105
+ functionCallRunner: FunctionCallRunner,
106
+ private readonly environment: AgenticEnvironment,
107
+ private readonly context: ModelContext,
108
+ private readonly model: GenerativeModel,
109
+ ) {
110
+ super(inputSource, inferenceRunner, functionCallRunner)
111
+ }
156
112
 
157
- abstract onModelMessage(item: ModelMessageItem): Promise<void>
113
+ async onMessage(message: string): Promise<void> {
114
+ this.context.addContextItem(UserMessageItem.create(message))
115
+ this.runInference(this.environment, this.context, this.model)
116
+ }
158
117
 
159
- abstract onExternalModelMessage(source: Participant, item: ModelMessageItem): Promise<void>
118
+ async onFunctionCall(item: FunctionCallItem): Promise<void> {
119
+ this.context.addContextItem(item)
120
+ this.executeFunctionCall(this.environment, item)
121
+ }
160
122
 
161
- abstract onMessage(message: string): Promise<void>
123
+ async onFunctionCallOutput(item: FunctionCallOutputItem): Promise<void> {
124
+ this.context.addContextItem(item)
125
+ this.runInference(this.environment, this.context, this.model)
126
+ }
127
+ }
162
128
  ```
163
129
 
164
- The typed `ContextItem`s involved are defined in [src/domain/model-context/context-item](src/domain/model-context/context-item):
130
+ ---
165
131
 
166
- - Client-produced: `FunctionCallOutputItem` (and `UserMessageItem` / `DeveloperMessageItem` / `SystemMessageItem` when building a `ModelContext` directly)
167
- - Model-produced: `ModelMessageItem`, `FunctionCallItem`, `ReasoningItem`
132
+ ## Reacting to external events
168
133
 
169
- Plain conversational input flows as a `string` through `onMessage` — participants exchange messages without committing to a specific `ContextItem` shape on the wire.
134
+ Participants can listen to external events and react by overriding methods like `onMessage`, `onExternalFunctionCall`, `onExternalFunctionCallOutput`, `onExternalReasoning`, and `onExternalModelMessage`.
170
135
 
171
136
  ### Passive observer
172
137
 
173
- A passive observer subclasses `Participant` and overrides only the handlers it cares about:
138
+ You can create observers that don't run inference themselves but watch what's happening in the conversation and take side actions (logging, metrics, persistence, etc.). Subclass `Participant` and override only the handlers you care about:
174
139
 
175
140
  ```ts
176
141
  import { Participant, FunctionCallItem, FunctionCallOutputItem, ReasoningItem, ModelMessageItem } from "@mozaik-ai/core"
@@ -411,6 +376,12 @@ You now own input, inference, and tool execution end-to-end while keeping the sa
411
376
 
412
377
  ---
413
378
 
379
+ ## Made with Mozaik
380
+
381
+ - **[baro](https://github.com/Lotus015/baro)** — a Claude agent orchestrator where ten specialized participants (planner, executors, reviewer, fixer, librarian, auditor, and more) work fully concurrently on the same goal, like a team collaborating in real time instead of a single agent doing everything alone.
382
+
383
+ ---
384
+
414
385
  ## Author & License
415
386
 
416
387
  Created by the [JigJoy](https://jigjoy.io) team.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mozaik-ai/core",
3
- "version": "3.8.1",
3
+ "version": "3.8.4",
4
4
  "description": "A TypeScript framework for building reactive agents",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",