@mozaik-ai/core 3.6.6 → 3.8.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 JigJoy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # Mozaik
2
2
 
3
- **Mozaik** is an open-source TypeScript framework for building AI agents that share an **agentic environment** instead of being orchestrated through rigid pipelines.
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.
4
4
 
5
- In Mozaik, humans, agents, observers, and tools are all `Participant`s of the same `AgenticEnvironment`. Each participant runs **non-blocking** and streams typed `ContextItem`s into the environment. Every other participant sees those items in real time and can react, intercept, or stay silent — without any central scheduler.
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
+
7
+ In Mozaik, humans, agents, observers, and tools are all `Participant`s of the same `AgenticEnvironment`. Each participant runs **non-blocking** and produces typed events — function calls, function call outputs, reasoning, model messages, and plain-text messages — into the environment. Every other participant sees those events in real time and can react, intercept, or stay silent — without any central scheduler.
6
8
 
7
9
  ---
8
10
 
@@ -23,16 +25,26 @@ OPENAI_API_KEY=your-openai-key-here
23
25
 
24
26
  ## The agentic environment
25
27
 
26
- `AgenticEnvironment` is a broadcast bus for typed context items. `Participant`s `join()` it, and any item produced by one participant is delivered to every subscriber's `onContextItem(source, item)` callback.
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:
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)` |
37
+
38
+ Messages are plain `string`s exchanged between participants. Every other event flows as a typed `ContextItem` (`FunctionCallItem`, `FunctionCallOutputItem`, `ReasoningItem`, `ModelMessageItem`).
27
39
 
28
40
  ```mermaid
29
41
  flowchart LR
30
42
  Human[BaseHumanParticipant] -->|streamInput| Env(("AgenticEnvironment"))
31
43
  Agent[BaseAgentParticipant] -->|"runInference / executeFunctionCall"| Env
32
44
  Observer[Custom Participant] -->|join| Env
33
- Env -->|onContextItem| Human
34
- Env -->|onContextItem| Agent
35
- Env -->|onContextItem| Observer
45
+ Env -->|"onMessage / onExternal*"| Human
46
+ Env -->|"onFunctionCall / onReasoning / …"| Agent
47
+ Env -->|"onExternal*"| Observer
36
48
  ```
37
49
 
38
50
  ---
@@ -41,35 +53,45 @@ flowchart LR
41
53
 
42
54
  Mozaik ships two ready-to-use participants:
43
55
 
44
- | Participant | Capabilities | Pulls from |
45
- | --- | --- | --- |
46
- | `BaseHumanParticipant` | `InputCapable` | `InputItemSource` |
47
- | `BaseAgentParticipant` | `InputCapable`, `InferenceCapable`, `FunctionCallCapable` | `InputItemSource`, `InferenceRunner`, `FunctionCallRunner` |
48
-
49
- Each capability method is **non-blocking**: it returns `Promise<void>`, and as the underlying generator yields items they are streamed into the environment one-by-one through the `deliverStream` helper:
50
-
51
- ```5:14:src/application/deliver-stream.ts
52
- export async function deliverStream<T extends ContextItem>(
53
- environment: AgenticEnvironment,
54
- initiator: Participant,
55
- stream: AsyncIterable<T>,
56
- ): Promise<void> {
57
-
58
- for await (const item of stream) {
59
- await environment.deliverContextItem(initiator, item);
60
- }
61
- }
56
+ | Participant | Capabilities | Pulls from |
57
+ | ---------------------- | --------------------------------------------------------- | ----------------------------------------------------- |
58
+ | `BaseHumanParticipant` | `InputCapable` | `InputStream` |
59
+ | `BaseAgentParticipant` | `InputCapable`, `InferenceCapable`, `FunctionCallCapable` | `InputStream`, `InferenceRunner`, `FunctionCallRunner`|
60
+
61
+ Each capability method is **non-blocking**: it returns `Promise<void>`, and as the underlying generator yields, items are streamed into the environment one-by-one through the matching typed `deliverX` method. For example, `runInference` dispatches each yielded item to `deliverReasoning`, `deliverFunctionCall`, or `deliverModelMessage`:
62
+
63
+ ```81:100:src/application/agent.ts
64
+ async runInference(
65
+ environment: AgenticEnvironment,
66
+ context: ModelContext,
67
+ model: GenerativeModel,
68
+ signal?: AbortSignal,
69
+ ): Promise<void> {
70
+ if (!this.isJoinedTo(environment)) return
71
+
72
+ const stream = this.inferenceRunner.run(context, model, signal)
73
+
74
+ for await (const item of stream) {
75
+ if (item.type === "reasoning") {
76
+ await environment.deliverReasoning(this, item)
77
+ } else if (item.type === "function_call") {
78
+ await environment.deliverFunctionCall(this, item)
79
+ } else if (item.type === "message" && item.role === "assistant") {
80
+ await environment.deliverModelMessage(this, item)
81
+ }
82
+ }
83
+ }
62
84
  ```
63
85
 
64
86
  Because each call is a fresh promise that wraps an async iterable, multiple participants can act on the same environment **concurrently**:
65
87
 
66
88
  ```ts
67
89
  import {
68
- AgenticEnvironment,
69
- BaseAgentParticipant,
70
- BaseHumanParticipant,
71
- Gpt54Mini,
72
- ModelContext,
90
+ AgenticEnvironment,
91
+ BaseAgentParticipant,
92
+ BaseHumanParticipant,
93
+ Gpt54Mini,
94
+ ModelContext,
73
95
  } from "@mozaik-ai/core"
74
96
 
75
97
  const environment = new AgenticEnvironment()
@@ -94,84 +116,149 @@ The environment fans every item out to every subscriber synchronously and withou
94
116
 
95
117
  ---
96
118
 
97
- ## Intercepting items from other participants
119
+ ## Intercepting events from other participants
120
+
121
+ 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:
122
+
123
+ - **Observe** events from other participants via the `onExternal*` family (telemetry, audit, UI streaming) and `onMessage` for plain-text messages.
124
+ - **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.
125
+ - **Ignore** events it doesn't care about — every handler defaults to a no-op in the bundled participants.
126
+
127
+ The intercept surface, taken from `Participant`:
128
+
129
+ ```38:54:src/domain/agentic-environment/participant.ts
130
+ abstract onFunctionCall(item: FunctionCallItem): Promise<void>
131
+
132
+ abstract onExternalFunctionCall(source: Participant, item: FunctionCallItem): Promise<void>
133
+
134
+ abstract onFunctionCallOutput(item: FunctionCallOutputItem): Promise<void>
135
+
136
+ abstract onExternalFunctionCallOutput(source: Participant, item: FunctionCallOutputItem): Promise<void>
137
+
138
+ abstract onReasoning(item: ReasoningItem): Promise<void>
139
+
140
+ abstract onExternalReasoning(source: Participant, item: ReasoningItem): Promise<void>
98
141
 
99
- `onContextItem(source, item)` is the single intercept point. A participant can:
142
+ abstract onModelMessage(item: ModelMessageItem): Promise<void>
100
143
 
101
- - **Observe** items from other participants (telemetry, audit, UI streaming).
102
- - **React** to items by triggering its own capabilities (turn a `UserMessageItem` into an inference run, turn a `FunctionCallItem` into a tool execution).
103
- - **Ignore** items it doesn't care about — it is just a method call.
144
+ abstract onExternalModelMessage(source: Participant, item: ModelMessageItem): Promise<void>
104
145
 
105
- Items are discriminated by the `ContextItem` subclass and, for messages, the `role` field. The full taxonomy is in [src/domain/model-context/context-item](src/domain/model-context/context-item):
146
+ abstract onMessage(message: string): Promise<void>
147
+ ```
148
+
149
+ The typed `ContextItem`s involved are defined in [src/domain/model-context/context-item](src/domain/model-context/context-item):
106
150
 
107
- - Client-produced: `UserMessageItem`, `DeveloperMessageItem`, `SystemMessageItem`, `FunctionCallOutputItem`
151
+ - Client-produced: `FunctionCallOutputItem` (and `UserMessageItem` / `DeveloperMessageItem` / `SystemMessageItem` when building a `ModelContext` directly)
108
152
  - Model-produced: `ModelMessageItem`, `FunctionCallItem`, `ReasoningItem`
109
153
 
154
+ Plain conversational input flows as a `string` through `onMessage` — participants exchange messages without committing to a specific `ContextItem` shape on the wire.
155
+
110
156
  ### Passive observer
111
157
 
158
+ A passive observer subclasses `Participant` and overrides only the handlers it cares about:
159
+
112
160
  ```ts
113
- import { Participant, ContextItem } from "@mozaik-ai/core"
161
+ import {
162
+ Participant,
163
+ FunctionCallItem,
164
+ FunctionCallOutputItem,
165
+ ReasoningItem,
166
+ ModelMessageItem,
167
+ } from "@mozaik-ai/core"
114
168
 
115
169
  export class TranscriptLogger extends Participant {
116
- async onContextItem(source: Participant, item: ContextItem): Promise<void> {
117
- console.log(`[${source.constructor.name}]`, item.toJSON())
118
- }
170
+ async onMessage(message: string): Promise<void> {
171
+ console.log("[message]", message)
172
+ }
173
+
174
+ async onExternalFunctionCall(source: Participant, item: FunctionCallItem): Promise<void> {
175
+ console.log(`[${source.constructor.name}] function_call`, item.toJSON())
176
+ }
177
+
178
+ async onExternalFunctionCallOutput(source: Participant, item: FunctionCallOutputItem): Promise<void> {
179
+ console.log(`[${source.constructor.name}] function_call_output`, item.toJSON())
180
+ }
181
+
182
+ async onExternalReasoning(source: Participant, item: ReasoningItem): Promise<void> {
183
+ console.log(`[${source.constructor.name}] reasoning`, item.toJSON())
184
+ }
185
+
186
+ async onExternalModelMessage(source: Participant, item: ModelMessageItem): Promise<void> {
187
+ console.log(`[${source.constructor.name}] model_message`, item.toJSON())
188
+ }
189
+
190
+ // Self-emitted handlers (onFunctionCall, onReasoning, …) can be no-ops for a pure observer.
191
+ async onFunctionCall(): Promise<void> {}
192
+ async onFunctionCallOutput(): Promise<void> {}
193
+ async onReasoning(): Promise<void> {}
194
+ async onModelMessage(): Promise<void> {}
119
195
  }
120
196
  ```
121
197
 
122
198
  ### Reactive agent
123
199
 
124
- A reactive agent extends `BaseAgentParticipant` and uses incoming items from *other* participants to decide when to run inference or execute a tool call:
200
+ A reactive agent extends `BaseAgentParticipant` and overrides the handlers it wants to react on. Each handler is already a no-op in the base class, so only the relevant ones need bodies:
125
201
 
126
202
  ```ts
127
203
  import {
128
- BaseAgentParticipant,
129
- Participant,
130
- ContextItem,
131
- UserMessageItem,
132
- FunctionCallItem,
133
- AgenticEnvironment,
134
- ModelContext,
135
- GenerativeModel,
136
- InputItemSource,
137
- InferenceRunner,
138
- FunctionCallRunner,
204
+ BaseAgentParticipant,
205
+ Participant,
206
+ UserMessageItem,
207
+ FunctionCallItem,
208
+ AgenticEnvironment,
209
+ ModelContext,
210
+ GenerativeModel,
211
+ InputStream,
212
+ InferenceRunner,
213
+ FunctionCallRunner,
139
214
  } from "@mozaik-ai/core"
140
215
 
141
216
  export class ReactiveAgent extends BaseAgentParticipant {
142
- constructor(
143
- inputSource: InputItemSource,
144
- inferenceRunner: InferenceRunner,
145
- functionCallRunner: FunctionCallRunner,
146
- private readonly environment: AgenticEnvironment,
147
- private readonly context: ModelContext,
148
- private readonly model: GenerativeModel,
149
- ) {
150
- super(inputSource, inferenceRunner, functionCallRunner)
151
- }
152
-
153
- async onContextItem(source: Participant, item: ContextItem): Promise<void> {
154
- if (source === this) return
155
-
156
- this.context.addContextItem(item)
157
-
158
- if (item instanceof UserMessageItem) {
159
- this.runInference(this.environment, this.context, this.model)
160
- return
161
- }
162
-
163
- if (item instanceof FunctionCallItem) {
164
- this.executeFunctionCall(this.environment, item)
165
- return
166
- }
167
- }
217
+ constructor(
218
+ inputSource: InputStream,
219
+ inferenceRunner: InferenceRunner,
220
+ functionCallRunner: FunctionCallRunner,
221
+ private readonly environment: AgenticEnvironment,
222
+ private readonly context: ModelContext,
223
+ private readonly model: GenerativeModel,
224
+ ) {
225
+ super(inputSource, inferenceRunner, functionCallRunner)
226
+ }
227
+
228
+ // A message from a human (or any other participant) → record it and think.
229
+ async onMessage(message: string): Promise<void> {
230
+ this.context.addContextItem(UserMessageItem.create(message))
231
+ this.runInference(this.environment, this.context, this.model)
232
+ }
233
+
234
+ // The agent just produced a function call → execute it.
235
+ async onFunctionCall(item: FunctionCallItem): Promise<void> {
236
+ this.context.addContextItem(item)
237
+ this.executeFunctionCall(this.environment, item)
238
+ }
239
+
240
+ // The tool just produced an output → feed it back and run inference again.
241
+ async onFunctionCallOutput(item: FunctionCallOutputItem): Promise<void> {
242
+ this.context.addContextItem(item)
243
+ this.runInference(this.environment, this.context, this.model)
244
+ }
245
+
246
+ // Keep the local context in sync with model-emitted reasoning and replies.
247
+ async onReasoning(item: ReasoningItem): Promise<void> {
248
+ this.context.addContextItem(item)
249
+ }
250
+
251
+ async onModelMessage(item: ModelMessageItem): Promise<void> {
252
+ this.context.addContextItem(item)
253
+ }
168
254
  }
169
255
  ```
170
256
 
171
- Two things to note:
257
+ Three things to note:
172
258
 
173
- 1. The agent never `await`s its own capability calls inside `onContextItem` — the methods are non-blocking, so the environment keeps delivering items while inference and tool execution run in the background.
174
- 2. Behaviors compose by **reaction**, not orchestration. Add a second agent that listens for `ModelMessageItem`s and you get a critique loop. Add a `TranscriptLogger` and you get a UI stream. Neither change touches the existing participants.
259
+ 1. The split between self handlers and `onExternal*` handlers means a participant can encode "act on my own outputs" separately from "observe others", without inspecting `source` by hand.
260
+ 2. The agent never `await`s its own capability calls inside the handlers — those methods are non-blocking, so the environment keeps delivering events while inference and tool execution run in the background.
261
+ 3. Behaviors compose by **reaction**, not orchestration. Add a second agent that overrides `onExternalModelMessage` and you get a critique loop. Add a `TranscriptLogger` and you get a UI stream. Neither change touches the existing participants.
175
262
 
176
263
  ---
177
264
 
@@ -180,16 +267,11 @@ Two things to note:
180
267
  `ModelContext` is the ordered list of `ContextItem`s a `GenerativeModel` is asked to reason over. It is constructed and mutated explicitly — typically inside a participant in response to delivered items.
181
268
 
182
269
  ```ts
183
- import {
184
- ModelContext,
185
- DeveloperMessageItem,
186
- UserMessageItem,
187
- InMemoryModelContextRepository,
188
- } from "@mozaik-ai/core"
270
+ import { ModelContext, DeveloperMessageItem, UserMessageItem, InMemoryModelContextRepository } from "@mozaik-ai/core"
189
271
 
190
272
  const context = ModelContext.create("project-id")
191
- .addContextItem(DeveloperMessageItem.create("You are a helpful assistant."))
192
- .addContextItem(UserMessageItem.create("What is the capital of France?"))
273
+ .addContextItem(DeveloperMessageItem.create("You are a helpful assistant."))
274
+ .addContextItem(UserMessageItem.create("What is the capital of France?"))
193
275
 
194
276
  const repo = new InMemoryModelContextRepository()
195
277
  await repo.save(context)
@@ -197,7 +279,7 @@ await repo.save(context)
197
279
 
198
280
  Implement `ModelContextRepository` to plug in any storage backend.
199
281
 
200
- The default OpenAI provider is `OpenAIResponses`, implementing the [OpenResponses](https://www.openresponses.org/) spec. It maps `ModelContext` to the OpenAI Responses API and back into typed `ContextItem`s. Bundled models: `Gpt54`, `Gpt54Mini`, `Gpt54Nano`.
282
+ The default OpenAI provider is `OpenAIResponses`, implementing the [OpenResponses](https://www.openresponses.org/) spec. It maps `ModelContext` to the OpenAI Responses API and back into typed `ContextItem`s. Bundled models: `Gpt54`, `Gpt54Mini`, `Gpt54Nano`, `Gpt55`.
201
283
 
202
284
  ```ts
203
285
  import { OpenAIResponses, InferenceRequest, Gpt54 } from "@mozaik-ai/core"
@@ -210,42 +292,37 @@ const response = await runtime.infer(new InferenceRequest(new Gpt54(), context))
210
292
 
211
293
  ## Advanced: overriding generators
212
294
 
213
- `BaseAgentParticipant` and `BaseHumanParticipant` are deliberately thin shells around three generator interfaces. Swap any of them to change *how* items are produced without touching the environment, the participants, or any consumers.
295
+ `BaseAgentParticipant` and `BaseHumanParticipant` are deliberately thin shells around three generator interfaces. Swap any of them to change _how_ events are produced without touching the environment, the participants, or any consumers.
214
296
 
215
- ### Custom `InputItemSource`
297
+ ### Custom `InputStream`
216
298
 
217
- ```ts
218
- import {
219
- InputItemSource,
220
- UserMessageItem,
221
- DeveloperMessageItem,
222
- SystemMessageItem,
223
- } from "@mozaik-ai/core"
299
+ An `InputStream` yields plain `string` messages, which are then broadcast to every other participant through `onMessage`:
224
300
 
225
- type InputItem = UserMessageItem | DeveloperMessageItem | SystemMessageItem
226
-
227
- export class QueueInputSource implements InputItemSource {
228
- private readonly queue: InputItem[] = []
229
- private resolveNext?: () => void
230
-
231
- push(item: InputItem) {
232
- this.queue.push(item)
233
- this.resolveNext?.()
234
- this.resolveNext = undefined
235
- }
236
-
237
- async *stream(signal?: AbortSignal): AsyncIterable<InputItem> {
238
- while (!signal?.aborted) {
239
- while (this.queue.length > 0) {
240
- yield this.queue.shift()!
241
- }
242
- await new Promise<void>((resolve) => (this.resolveNext = resolve))
243
- }
244
- }
301
+ ```ts
302
+ import { InputStream } from "@mozaik-ai/core"
303
+
304
+ export class QueueInputStream implements InputStream {
305
+ private readonly queue: string[] = []
306
+ private resolveNext?: () => void
307
+
308
+ push(message: string) {
309
+ this.queue.push(message)
310
+ this.resolveNext?.()
311
+ this.resolveNext = undefined
312
+ }
313
+
314
+ async *stream(signal?: AbortSignal): AsyncIterable<string> {
315
+ while (!signal?.aborted) {
316
+ while (this.queue.length > 0) {
317
+ yield this.queue.shift()!
318
+ }
319
+ await new Promise<void>((resolve) => (this.resolveNext = resolve))
320
+ }
321
+ }
245
322
  }
246
323
  ```
247
324
 
248
- Use it for stdin, websockets, an HTTP queue, or anything that produces user/developer/system messages over time.
325
+ Use it for stdin, websockets, an HTTP queue, or anything that produces messages over time. Participants decide for themselves what to do with the string — e.g. wrap it in a `UserMessageItem` before adding it to a `ModelContext`.
249
326
 
250
327
  ### Custom `InferenceRunner`
251
328
 
@@ -253,31 +330,27 @@ Wrap any model runtime — including `OpenAIResponses` — and decide how its ou
253
330
 
254
331
  ```ts
255
332
  import {
256
- InferenceRunner,
257
- InferenceRequest,
258
- ModelContext,
259
- GenerativeModel,
260
- OpenAIResponses,
261
- ReasoningItem,
262
- FunctionCallItem,
263
- ModelMessageItem,
333
+ InferenceRunner,
334
+ InferenceRequest,
335
+ ModelContext,
336
+ GenerativeModel,
337
+ OpenAIResponses,
338
+ ReasoningItem,
339
+ FunctionCallItem,
340
+ ModelMessageItem,
264
341
  } from "@mozaik-ai/core"
265
342
 
266
343
  type InferenceItem = ReasoningItem | FunctionCallItem | ModelMessageItem
267
344
 
268
345
  export class OpenAIInferenceRunner implements InferenceRunner {
269
- private readonly runtime = new OpenAIResponses()
270
-
271
- async *run(
272
- context: ModelContext,
273
- model: GenerativeModel,
274
- signal?: AbortSignal,
275
- ): AsyncIterable<InferenceItem> {
276
- const response = await this.runtime.infer(new InferenceRequest(model, context))
277
- for (const item of response.contextItems) {
278
- yield item as InferenceItem
279
- }
280
- }
346
+ private readonly runtime = new OpenAIResponses()
347
+
348
+ async *run(context: ModelContext, model: GenerativeModel, signal?: AbortSignal): AsyncIterable<InferenceItem> {
349
+ const response = await this.runtime.infer(new InferenceRequest(model, context))
350
+ for (const item of response.contextItems) {
351
+ yield item as InferenceItem
352
+ }
353
+ }
281
354
  }
282
355
  ```
283
356
 
@@ -288,26 +361,18 @@ Replace the body with a streaming runtime and items will flow into the environme
288
361
  Resolve a `FunctionCallItem` against a tool registry and yield its output:
289
362
 
290
363
  ```ts
291
- import {
292
- FunctionCallRunner,
293
- FunctionCallItem,
294
- FunctionCallOutputItem,
295
- Tool,
296
- } from "@mozaik-ai/core"
364
+ import { FunctionCallRunner, FunctionCallItem, FunctionCallOutputItem, Tool } from "@mozaik-ai/core"
297
365
 
298
366
  export class ToolRegistryFunctionCallRunner implements FunctionCallRunner {
299
- constructor(private readonly tools: Tool[]) {}
300
-
301
- async *run(
302
- call: FunctionCallItem,
303
- signal?: AbortSignal,
304
- ): AsyncIterable<FunctionCallOutputItem> {
305
- const tool = this.tools.find((t) => t.name === call.name)
306
- if (!tool) throw new Error(`Unknown tool: ${call.name}`)
307
-
308
- const result = await tool.invoke(JSON.parse(call.args))
309
- yield FunctionCallOutputItem.create(call.callId, JSON.stringify(result))
310
- }
367
+ constructor(private readonly tools: Tool[]) {}
368
+
369
+ async *run(call: FunctionCallItem, signal?: AbortSignal): AsyncIterable<FunctionCallOutputItem> {
370
+ const tool = this.tools.find((t) => t.name === call.name)
371
+ if (!tool) throw new Error(`Unknown tool: ${call.name}`)
372
+
373
+ const result = await tool.invoke(JSON.parse(call.args))
374
+ yield FunctionCallOutputItem.create(call.callId, JSON.stringify(result))
375
+ }
311
376
  }
312
377
  ```
313
378
 
@@ -317,9 +382,9 @@ export class ToolRegistryFunctionCallRunner implements FunctionCallRunner {
317
382
  import { BaseAgentParticipant, AgenticEnvironment } from "@mozaik-ai/core"
318
383
 
319
384
  const agent = new BaseAgentParticipant(
320
- new QueueInputSource(),
321
- new OpenAIInferenceRunner(),
322
- new ToolRegistryFunctionCallRunner(tools),
385
+ new QueueInputStream(),
386
+ new OpenAIInferenceRunner(),
387
+ new ToolRegistryFunctionCallRunner(tools),
323
388
  )
324
389
 
325
390
  agent.join(new AgenticEnvironment())
package/dist/index.d.mts CHANGED
@@ -298,7 +298,11 @@ declare class AgenticEnvironment {
298
298
  private isActive;
299
299
  subscribe(subscriber: Participant): void;
300
300
  unsubscribe(user: Participant): void;
301
- deliverContextItem(source: Participant, item: ContextItem): void;
301
+ deliverFunctionCall(source: Participant, item: FunctionCallItem): void;
302
+ deliverModelMessage(source: Participant, item: ModelMessageItem): void;
303
+ deliverReasoning(source: Participant, item: ReasoningItem): void;
304
+ deliverFunctionCallOutput(source: Participant, item: FunctionCallOutputItem): void;
305
+ deliverMessage(source: Participant, message: string): void;
302
306
  start(): Promise<void>;
303
307
  stop(): void;
304
308
  }
@@ -309,7 +313,15 @@ declare abstract class Participant {
309
313
  leave(environment: AgenticEnvironment): void;
310
314
  protected isJoinedTo(environment: AgenticEnvironment): boolean;
311
315
  getEnvironments(): AgenticEnvironment[];
312
- abstract onContextItem(source: Participant, item: ContextItem): Promise<void>;
316
+ abstract onFunctionCall(item: FunctionCallItem): Promise<void>;
317
+ abstract onExternalFunctionCall(source: Participant, item: FunctionCallItem): Promise<void>;
318
+ abstract onFunctionCallOutput(item: FunctionCallOutputItem): Promise<void>;
319
+ abstract onExternalFunctionCallOutput(source: Participant, item: FunctionCallOutputItem): Promise<void>;
320
+ abstract onReasoning(item: ReasoningItem): Promise<void>;
321
+ abstract onExternalReasoning(source: Participant, item: ReasoningItem): Promise<void>;
322
+ abstract onModelMessage(item: ModelMessageItem): Promise<void>;
323
+ abstract onExternalModelMessage(source: Participant, item: ModelMessageItem): Promise<void>;
324
+ abstract onMessage(message: string): Promise<void>;
313
325
  }
314
326
 
315
327
  interface InputCapable {
@@ -330,16 +342,25 @@ interface FunctionCallRunner {
330
342
  run(functionCallItem: FunctionCallItem, signal?: AbortSignal): AsyncIterable<FunctionCallOutputItem>;
331
343
  }
332
344
 
333
- interface InputItemSource {
334
- stream(signal?: AbortSignal): AsyncIterable<UserMessageItem | DeveloperMessageItem | SystemMessageItem>;
345
+ interface InputStream {
346
+ stream(signal?: AbortSignal): AsyncIterable<string>;
335
347
  }
336
348
 
337
349
  declare class BaseAgentParticipant extends Participant implements InputCapable, InferenceCapable, FunctionCallCapable {
338
350
  private inputSource;
339
351
  private inferenceRunner;
340
352
  private functionCallRunner;
341
- constructor(inputSource: InputItemSource, inferenceRunner: InferenceRunner, functionCallRunner: FunctionCallRunner);
342
- onContextItem(source: Participant, item: ContextItem): Promise<void>;
353
+ constructor(inputSource: InputStream, inferenceRunner: InferenceRunner, functionCallRunner: FunctionCallRunner);
354
+ onInternalContextItem(item: ContextItem): Promise<void>;
355
+ onFunctionCall(item: FunctionCallItem): Promise<void>;
356
+ onExternalFunctionCall(source: Participant, item: FunctionCallItem): Promise<void>;
357
+ onFunctionCallOutput(item: FunctionCallOutputItem): Promise<void>;
358
+ onExternalFunctionCallOutput(source: Participant, item: FunctionCallOutputItem): Promise<void>;
359
+ onReasoning(item: ReasoningItem): Promise<void>;
360
+ onExternalReasoning(source: Participant, item: ReasoningItem): Promise<void>;
361
+ onModelMessage(item: ModelMessageItem): Promise<void>;
362
+ onExternalModelMessage(source: Participant, item: ModelMessageItem): Promise<void>;
363
+ onMessage(message: string): Promise<void>;
343
364
  executeFunctionCall(environment: AgenticEnvironment, functionCallItem: FunctionCallItem, signal?: AbortSignal): Promise<void>;
344
365
  runInference(environment: AgenticEnvironment, context: ModelContext, model: GenerativeModel, signal?: AbortSignal): Promise<void>;
345
366
  streamInput(environment: AgenticEnvironment): Promise<void>;
@@ -347,8 +368,17 @@ declare class BaseAgentParticipant extends Participant implements InputCapable,
347
368
 
348
369
  declare class BaseHumanParticipant extends Participant implements InputCapable {
349
370
  private inputSource;
350
- constructor(inputSource: InputItemSource);
371
+ constructor(inputSource: InputStream);
372
+ onFunctionCall(item: FunctionCallItem): Promise<void>;
373
+ onExternalFunctionCall(source: Participant, item: FunctionCallItem): Promise<void>;
351
374
  onContextItem(source: Participant, item: ContextItem): Promise<void>;
375
+ onFunctionCallOutput(item: FunctionCallOutputItem): Promise<void>;
376
+ onExternalFunctionCallOutput(source: Participant, item: FunctionCallOutputItem): Promise<void>;
377
+ onReasoning(item: ReasoningItem): Promise<void>;
378
+ onExternalReasoning(source: Participant, item: ReasoningItem): Promise<void>;
379
+ onModelMessage(item: ModelMessageItem): Promise<void>;
380
+ onExternalModelMessage(source: Participant, item: ModelMessageItem): Promise<void>;
381
+ onMessage(message: string): Promise<void>;
352
382
  streamInput(environment: AgenticEnvironment): Promise<void>;
353
383
  }
354
384
 
@@ -364,4 +394,22 @@ declare class DefaultFunctionCallRunner implements FunctionCallRunner {
364
394
  run(call: FunctionCallItem, signal?: AbortSignal): AsyncIterable<FunctionCallOutputItem>;
365
395
  }
366
396
 
367
- export { AgenticEnvironment, BaseAgentParticipant, BaseHumanParticipant, ContextItem, DefaultFunctionCallRunner, DeveloperMessageItem, FunctionCallItem, FunctionCallOutputItem, type FunctionCallRunner, type GenerativeModel, Gpt54, Gpt54Mini, Gpt54Nano, InMemoryModelContextRepository, InferenceRequest, InferenceResponse, type InferenceRunner, type InputItemSource, InputTokenDetails, ModelContext, type ModelContextRepository, ModelMessageItem, OpenAIInferenceRunner, OpenAIResponses, OutputTokenDetails, Participant, ReasoningItem, SystemMessageItem, TokenUsage, type Tool, UserMessageItem };
397
+ declare class Gpt55 implements GenerativeModel, ReasoningEffort<OpenAIReasoningEffortType>, ToolCallingCapability {
398
+ readonly specification: {
399
+ name: string;
400
+ supportReasoningEffort: boolean;
401
+ defaultReasoningEffort: OpenAIReasoningEffortType;
402
+ supportStreaming: boolean;
403
+ contextWindowSize: number;
404
+ maxOutputTokens: number;
405
+ supportFunctionCalling: boolean;
406
+ };
407
+ private tools;
408
+ setTools(tools: Tool[]): void;
409
+ getTools(): Tool[];
410
+ private readonly effort;
411
+ setReasoningEffort(effort: OpenAIReasoningEffortType): void;
412
+ getReasoningEffort(): OpenAIReasoningEffortType;
413
+ }
414
+
415
+ export { AgenticEnvironment, BaseAgentParticipant, BaseHumanParticipant, ContextItem, DefaultFunctionCallRunner, DeveloperMessageItem, FunctionCallItem, FunctionCallOutputItem, type FunctionCallRunner, type GenerativeModel, Gpt54, Gpt54Mini, Gpt54Nano, Gpt55, InMemoryModelContextRepository, InferenceRequest, InferenceResponse, type InferenceRunner, type InputStream, InputTokenDetails, ModelContext, type ModelContextRepository, ModelMessageItem, OpenAIInferenceRunner, OpenAIResponses, OutputTokenDetails, Participant, ReasoningItem, SystemMessageItem, TokenUsage, type Tool, UserMessageItem };