@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.
- package/README.md +50 -79
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Mozaik
|
|
2
2
|
|
|
3
|
-
**Mozaik** is
|
|
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
|
  
|
|
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
|
|
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
|
-
|
|
|
31
|
-
|
|
|
32
|
-
| `
|
|
33
|
-
| `
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
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
|
-
|
|
118
|
+
async onFunctionCall(item: FunctionCallItem): Promise<void> {
|
|
119
|
+
this.context.addContextItem(item)
|
|
120
|
+
this.executeFunctionCall(this.environment, item)
|
|
121
|
+
}
|
|
160
122
|
|
|
161
|
-
|
|
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
|
-
|
|
130
|
+
---
|
|
165
131
|
|
|
166
|
-
|
|
167
|
-
- Model-produced: `ModelMessageItem`, `FunctionCallItem`, `ReasoningItem`
|
|
132
|
+
## Reacting to external events
|
|
168
133
|
|
|
169
|
-
|
|
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
|
-
|
|
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.
|