@mozaik-ai/core 3.10.0 → 3.10.1
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/README.md +58 -62
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,13 +56,15 @@ OPENAI_API_KEY=your-openai-key-here
|
|
|
56
56
|
| `onExternalReasoning` | another agent's inference returns a reasoning item |
|
|
57
57
|
| `onModelMessage` | its own inference returns an assistant message |
|
|
58
58
|
| `onExternalModelMessage` | another agent's inference returns an assistant message |
|
|
59
|
+
| `onInternalEvent` | its own inference emits a semantic stream event |
|
|
60
|
+
| `onExternalEvent` | another participant emits a semantic stream event |
|
|
59
61
|
|
|
60
62
|
Every handler defaults to a no-op — override only the ones you care about.
|
|
61
63
|
|
|
62
64
|
```mermaid
|
|
63
65
|
flowchart LR
|
|
64
|
-
Human[
|
|
65
|
-
Agent[
|
|
66
|
+
Human[BaseHuman] -->|sendMessage| Env(("AgenticEnvironment"))
|
|
67
|
+
Agent[BaseAgent] -->|"runInference / executeFunctionCall"| Env
|
|
66
68
|
Observer[Custom Participant] -->|join| Env
|
|
67
69
|
Env -->|"onMessage / onExternal*"| Human
|
|
68
70
|
Env -->|"onFunctionCall / onReasoning / …"| Agent
|
|
@@ -74,26 +76,29 @@ flowchart LR
|
|
|
74
76
|
|
|
75
77
|
## Non-blocking participants
|
|
76
78
|
|
|
77
|
-
Mozaik ships
|
|
79
|
+
Mozaik ships three ready-to-use participants:
|
|
78
80
|
|
|
79
|
-
| Participant
|
|
80
|
-
|
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
81
|
+
| Participant | Role |
|
|
82
|
+
| --------------- | ---- |
|
|
83
|
+
| `BaseHuman` | Sends messages with `sendMessage(environment, text)` |
|
|
84
|
+
| `BaseAgent` | Runs inference and function calls via `InferenceRunner` and `FunctionCallRunner` |
|
|
85
|
+
| `BaseObserver` | Listens only; no inference |
|
|
83
86
|
|
|
84
87
|
```ts
|
|
85
88
|
import {
|
|
86
89
|
AgenticEnvironment,
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
BaseAgent,
|
|
91
|
+
BaseHuman,
|
|
92
|
+
OpenAIInferenceRunner,
|
|
93
|
+
DefaultFunctionCallRunner,
|
|
89
94
|
Gpt54Mini,
|
|
90
95
|
ModelContext,
|
|
91
96
|
} from "@mozaik-ai/core"
|
|
92
97
|
|
|
93
98
|
const environment = new AgenticEnvironment()
|
|
94
99
|
|
|
95
|
-
const human = new
|
|
96
|
-
const agent = new
|
|
100
|
+
const human = new BaseHuman()
|
|
101
|
+
const agent = new BaseAgent(new OpenAIInferenceRunner(), new DefaultFunctionCallRunner())
|
|
97
102
|
|
|
98
103
|
human.join(environment)
|
|
99
104
|
agent.join(environment)
|
|
@@ -104,7 +109,7 @@ const context = ModelContext.create("demo")
|
|
|
104
109
|
const model = new Gpt54Mini()
|
|
105
110
|
|
|
106
111
|
// Both participants produce items in parallel — neither awaits the other.
|
|
107
|
-
human.
|
|
112
|
+
human.sendMessage(environment, "Hello")
|
|
108
113
|
agent.runInference(environment, context, model)
|
|
109
114
|
```
|
|
110
115
|
|
|
@@ -114,32 +119,33 @@ The environment fans every item out to every subscriber synchronously and withou
|
|
|
114
119
|
|
|
115
120
|
## Reactive agent
|
|
116
121
|
|
|
117
|
-
A reactive agent extends `
|
|
122
|
+
A reactive agent extends `BaseAgent` 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:
|
|
118
123
|
|
|
119
124
|
```ts
|
|
120
125
|
import {
|
|
121
|
-
|
|
126
|
+
BaseAgent,
|
|
122
127
|
Participant,
|
|
123
128
|
UserMessageItem,
|
|
124
129
|
FunctionCallItem,
|
|
130
|
+
FunctionCallOutputItem,
|
|
131
|
+
ReasoningItem,
|
|
132
|
+
ModelMessageItem,
|
|
125
133
|
AgenticEnvironment,
|
|
126
134
|
ModelContext,
|
|
127
135
|
GenerativeModel,
|
|
128
|
-
InputStream,
|
|
129
136
|
InferenceRunner,
|
|
130
137
|
FunctionCallRunner,
|
|
131
138
|
} from "@mozaik-ai/core"
|
|
132
139
|
|
|
133
|
-
export class ReactiveAgent extends
|
|
140
|
+
export class ReactiveAgent extends BaseAgent {
|
|
134
141
|
constructor(
|
|
135
|
-
inputSource: InputStream,
|
|
136
142
|
inferenceRunner: InferenceRunner,
|
|
137
143
|
functionCallRunner: FunctionCallRunner,
|
|
138
144
|
private readonly environment: AgenticEnvironment,
|
|
139
145
|
private readonly context: ModelContext,
|
|
140
146
|
private readonly model: GenerativeModel,
|
|
141
147
|
) {
|
|
142
|
-
super(
|
|
148
|
+
super(inferenceRunner, functionCallRunner)
|
|
143
149
|
}
|
|
144
150
|
|
|
145
151
|
// A message from a human (or any other participant) → record it and think.
|
|
@@ -179,12 +185,29 @@ Three things to note:
|
|
|
179
185
|
|
|
180
186
|
---
|
|
181
187
|
|
|
188
|
+
## Streaming and semantic events
|
|
189
|
+
|
|
190
|
+
Enable streaming on a model that supports it, then run inference as usual:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
const model = new Gpt54Mini()
|
|
194
|
+
model.setStreaming(true)
|
|
195
|
+
|
|
196
|
+
await agent.runInference(environment, context, model)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
With streaming enabled, `OpenAIInferenceRunner` emits **`SemanticEvent`** chunks (provider `type` + `data`) into the environment. The producing agent receives `onInternalEvent`; everyone else receives `onExternalEvent(source, event)`. Use these handlers to drive a live UI—for example, print text deltas from `response.output_text.delta` events.
|
|
200
|
+
|
|
201
|
+
`setStreaming(true)` on a model without `supportStreaming` throws before the API is called.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
182
205
|
## Lifecycle hooks
|
|
183
206
|
|
|
184
207
|
Every participant receives lifecycle notifications when it or others join/leave an environment:
|
|
185
208
|
|
|
186
209
|
```ts
|
|
187
|
-
export class TeamAgent extends
|
|
210
|
+
export class TeamAgent extends BaseAgent {
|
|
188
211
|
// Called when this participant joins an environment.
|
|
189
212
|
onJoined(environment: AgenticEnvironment): void {
|
|
190
213
|
console.log("I joined the environment")
|
|
@@ -270,64 +293,41 @@ await repo.save(context)
|
|
|
270
293
|
|
|
271
294
|
Implement `ModelContextRepository` to plug in any storage backend.
|
|
272
295
|
|
|
273
|
-
The default
|
|
296
|
+
The default inference path is `OpenAIInferenceRunner`, which maps `ModelContext` to the OpenAI Responses API and back into typed `ContextItem`s (and `SemanticEvent`s when streaming). Bundled models: `Gpt54`, `Gpt54Mini`, `Gpt54Nano`, `Gpt55`.
|
|
274
297
|
|
|
275
298
|
```ts
|
|
276
|
-
import {
|
|
299
|
+
import { OpenAIInferenceRunner, DefaultFunctionCallRunner, Gpt54, ModelContext } from "@mozaik-ai/core"
|
|
300
|
+
|
|
301
|
+
const runner = new OpenAIInferenceRunner()
|
|
302
|
+
const context = ModelContext.create("demo")
|
|
277
303
|
|
|
278
|
-
const
|
|
279
|
-
|
|
304
|
+
for await (const item of runner.run(context, new Gpt54())) {
|
|
305
|
+
// ReasoningItem | FunctionCallItem | ModelMessageItem | SemanticEvent
|
|
306
|
+
}
|
|
280
307
|
```
|
|
281
308
|
|
|
282
309
|
---
|
|
283
310
|
|
|
284
311
|
## Overriding Generators
|
|
285
312
|
|
|
286
|
-
Mozaik uses generators for inference
|
|
287
|
-
|
|
288
|
-
### Custom `InputStream`
|
|
289
|
-
|
|
290
|
-
```ts
|
|
291
|
-
import { InputStream } from "@mozaik-ai/core"
|
|
292
|
-
|
|
293
|
-
export class HelloInputStream implements InputStream {
|
|
294
|
-
async *stream(): AsyncIterable<string> {
|
|
295
|
-
yield "Hello"
|
|
296
|
-
yield "World"
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
```
|
|
313
|
+
Mozaik uses async generators for inference and function calls — that's what lets the system emit events incrementally so participants can react to them as they arrive. Swap any runner to change _how_ events are produced.
|
|
300
314
|
|
|
301
|
-
|
|
315
|
+
Humans send text with `sendMessage(environment, message)`; other participants receive it via `onMessage`.
|
|
302
316
|
|
|
303
317
|
### Custom `InferenceRunner`
|
|
304
318
|
|
|
305
|
-
An `InferenceRunner` can yield `ReasoningItem`, `FunctionCallItem`, and `
|
|
319
|
+
An `InferenceRunner` can yield `ReasoningItem`, `FunctionCallItem`, `ModelMessageItem`, and `SemanticEvent` (when streaming).
|
|
306
320
|
|
|
307
321
|
```ts
|
|
308
322
|
import {
|
|
309
323
|
InferenceRunner,
|
|
310
|
-
InferenceRequest,
|
|
311
324
|
ModelContext,
|
|
312
325
|
GenerativeModel,
|
|
313
|
-
|
|
314
|
-
ReasoningItem,
|
|
315
|
-
FunctionCallItem,
|
|
316
|
-
ModelMessageItem,
|
|
326
|
+
OpenAIInferenceRunner,
|
|
317
327
|
} from "@mozaik-ai/core"
|
|
318
328
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
export class OpenAIInferenceRunner implements InferenceRunner {
|
|
322
|
-
private readonly runtime = new OpenAIResponses()
|
|
323
|
-
|
|
324
|
-
async *run(context: ModelContext, model: GenerativeModel, signal?: AbortSignal): AsyncIterable<InferenceItem> {
|
|
325
|
-
const response = await this.runtime.infer(new InferenceRequest(model, context))
|
|
326
|
-
for (const item of response.contextItems) {
|
|
327
|
-
yield item as InferenceItem
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
329
|
+
// Use the bundled runner, or implement InferenceRunner for another provider.
|
|
330
|
+
const runner: InferenceRunner = new OpenAIInferenceRunner()
|
|
331
331
|
```
|
|
332
332
|
|
|
333
333
|
### Custom `FunctionCallRunner`
|
|
@@ -353,13 +353,9 @@ export class ToolRegistryFunctionCallRunner implements FunctionCallRunner {
|
|
|
353
353
|
### Wiring it together
|
|
354
354
|
|
|
355
355
|
```ts
|
|
356
|
-
import {
|
|
356
|
+
import { BaseAgent, AgenticEnvironment, OpenAIInferenceRunner } from "@mozaik-ai/core"
|
|
357
357
|
|
|
358
|
-
const agent = new
|
|
359
|
-
new HelloInputStream(),
|
|
360
|
-
new OpenAIInferenceRunner(),
|
|
361
|
-
new ToolRegistryFunctionCallRunner(tools),
|
|
362
|
-
)
|
|
358
|
+
const agent = new BaseAgent(new OpenAIInferenceRunner(), new ToolRegistryFunctionCallRunner(tools))
|
|
363
359
|
|
|
364
360
|
agent.join(new AgenticEnvironment())
|
|
365
361
|
```
|