@evolvingmachines/evolve 0.0.55-project-sable.20260916.db0bc0bb → 0.0.56
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/dist/cli/index.cjs +32 -32
- package/dist/cli/index.js +27 -27
- package/package.json +4 -6
- package/skills/evolve/SKILL.md +4 -3
- package/skills/evolve-evals/SKILL.md +112 -0
- package/{docs-evals → skills/evolve-evals/references}/cli-reference/run.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/cli-reference/skills.mdx +4 -4
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/agents.mdx +2 -2
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/analyze.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/jobs.mdx +3 -3
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/models.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/sandboxes.mdx +2 -2
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/secrets.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/trial-outputs.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/getting-started/quick-start.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/index.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/sdk/python.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/sdk/typescript.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/sdk-reference/errors.mdx +2 -2
- package/{docs-evals → skills/evolve-evals/references}/sdk-reference/jobs.mdx +2 -2
- package/docs-agents/SKILL.md +0 -138
- package/docs-agents/index.md +0 -81
- package/docs-agents/python/01-getting-started.md +0 -511
- package/docs-agents/python/02-configuration.md +0 -855
- package/docs-agents/python/03-runtime.md +0 -899
- package/docs-agents/python/04-streaming.md +0 -451
- package/docs-agents/python/05-swarm-pipeline.md +0 -953
- package/docs-agents/python/index.md +0 -122
- package/docs-agents/typescript/01-getting-started.md +0 -494
- package/docs-agents/typescript/02-configuration.md +0 -841
- package/docs-agents/typescript/03-runtime.md +0 -864
- package/docs-agents/typescript/04-streaming.md +0 -478
- package/docs-agents/typescript/05-swarm-pipeline.md +0 -957
- package/docs-agents/typescript/index.md +0 -121
- package/docs-evals/SKILL.md +0 -112
- package/docs-evals/docs.json +0 -180
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/agent.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/analysis.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/analyze.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/auth.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/check.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/dataset.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/index.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/job.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/secrets.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/skill.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/trial.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/upload.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/check.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/datasets.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/index.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/skills.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/tasks.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/trials.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/upload.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/checks.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/datasets.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/jobs.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/traces.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/trial-viewer.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/getting-started/installation.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/agents.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/analyses.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/auth.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/checks.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/datasets.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/index.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/meta.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/skills.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/trials.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/types.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/snippets/global-options.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/snippets/list-flags.mdx +0 -0
|
@@ -1,957 +0,0 @@
|
|
|
1
|
-
# Swarm & Pipeline
|
|
2
|
-
|
|
3
|
-
Functional programming for AI agents: `map`, `filter`, `reduce`, `bestOf`, `verify`.
|
|
4
|
-
|
|
5
|
-
```ts
|
|
6
|
-
import { Swarm } from "@evolvingmachines/evolve";
|
|
7
|
-
import { z } from "zod"; // Or use plain JSON Schema objects instead
|
|
8
|
-
|
|
9
|
-
const swarm = new Swarm({
|
|
10
|
-
agent: { type: "claude" }, // Default agent for all operations
|
|
11
|
-
skills: ["anthropics/skills"], // Default skills (skills.sh / git / local references)
|
|
12
|
-
integrations: { // Default Integrations config for all workers
|
|
13
|
-
userId: "root",
|
|
14
|
-
apps: ["github", "linear"],
|
|
15
|
-
},
|
|
16
|
-
mcpServers: {...}, // Default MCP servers for all workers
|
|
17
|
-
concurrency: 4, // Max parallel sandboxes (default: 4)
|
|
18
|
-
timeoutMs: 3_600_000, // Default timeout per worker (default: 1 hour)
|
|
19
|
-
tag: "my-pipeline", // Tag prefix for observability
|
|
20
|
-
retry: { // Default retry config for all operations
|
|
21
|
-
maxAttempts: 3,
|
|
22
|
-
backoffMs: 1000,
|
|
23
|
-
backoffMultiplier: 2,
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
> **Defaults**: `agent`, `skills`, `integrations`, `mcpServers`, `timeoutMs`, and `retry` set here are inherited by all operations (`map`, `filter`, `reduce`, `bestOf`). Pass these options to individual operations to override.
|
|
29
|
-
|
|
30
|
-
**SwarmConfig** — configuration for Swarm instance:
|
|
31
|
-
```ts
|
|
32
|
-
{
|
|
33
|
-
agent?: AgentConfig,
|
|
34
|
-
sandbox?: SandboxProvider,
|
|
35
|
-
skills?: string[],
|
|
36
|
-
integrations?: IntegrationsSetup,
|
|
37
|
-
mcpServers?: Record<string, McpServerConfig>,
|
|
38
|
-
concurrency?: number,
|
|
39
|
-
timeoutMs?: number,
|
|
40
|
-
workspaceMode?: "knowledge" | "swe",
|
|
41
|
-
tag?: string,
|
|
42
|
-
retry?: RetryConfig,
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
| Option | Default | Notes |
|
|
47
|
-
|--------|---------|-------|
|
|
48
|
-
| `agent.type` | `'claude'` | Auto-resolved from env |
|
|
49
|
-
| `agent.model` | per type | `'opus'` (claude), `'gpt-5.6-sol'` (codex), etc. |
|
|
50
|
-
| `sandbox` | auto-resolved | Provider for every worker; falls back to env (`E2B_API_KEY`, `DAYTONA_API_KEY`, `MODAL_TOKEN_*`, `EVOLVE_API_KEY`) |
|
|
51
|
-
| `skills` | `undefined` | Set here or per-operation |
|
|
52
|
-
| `integrations` | `undefined` | Set here or per-operation |
|
|
53
|
-
| `mcpServers` | `undefined` | Set here or per-operation |
|
|
54
|
-
| `concurrency` | `4` | Max parallel sandboxes |
|
|
55
|
-
| `timeoutMs` | `3_600_000` | 1 hour per worker |
|
|
56
|
-
| `workspaceMode` | `'knowledge'` | `'knowledge'` or `'swe'`; `'task'` is not a Swarm mode (the type excludes it) |
|
|
57
|
-
| `tag` | `'swarm'` | Observability prefix |
|
|
58
|
-
| `retry` | `undefined` | Set here or per-operation |
|
|
59
|
-
|
|
60
|
-
The `agent` here is the full `AgentConfig` — the same shape `.withAgent()` takes, so `apiKey`, `providerApiKey`, `oauthToken` and `maxContextSize` all belong on it. The narrower `AgentOverride` (type, model, reasoningEffort) is what individual operations take when they override this default; see [AgentOverride](#agentoverride).
|
|
61
|
-
|
|
62
|
-
**Minimal setup** — with `EVOLVE_API_KEY` set (see [Authentication](./01-getting-started.md#authentication)):
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
import "dotenv/config"; // If using .env file
|
|
66
|
-
import { Swarm } from "@evolvingmachines/evolve";
|
|
67
|
-
|
|
68
|
-
const swarm = new Swarm(); // Auto-resolves agent (claude) and sandbox from env
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
**RetryConfig** — auto-retry on error with exponential backoff:
|
|
72
|
-
```ts
|
|
73
|
-
{
|
|
74
|
-
maxAttempts?: number,
|
|
75
|
-
backoffMs?: number,
|
|
76
|
-
backoffMultiplier?: number,
|
|
77
|
-
retryOn?: (result) => boolean,
|
|
78
|
-
onItemRetry?: (idx, attempt, error) => void,
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Input Types
|
|
83
|
-
|
|
84
|
-
Swarm runs in **knowledge mode** by default—files are uploaded to `context/` in the sandbox.
|
|
85
|
-
|
|
86
|
-
**FileMap structure:**
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
// FileMap: Record<path, content>
|
|
90
|
-
// - path: string → file path in context/ folder
|
|
91
|
-
// - content: string | Uint8Array → file content
|
|
92
|
-
|
|
93
|
-
type FileMap = Record<string, string | Uint8Array>;
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
**Case 1: One file per worker**
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
// 3 workers, each gets 1 file
|
|
102
|
-
const items: FileMap[] = [
|
|
103
|
-
{ "report.txt": "Q1 revenue..." }, // → Worker 0: context/report.txt
|
|
104
|
-
{ "report.txt": "Q2 revenue..." }, // → Worker 1: context/report.txt
|
|
105
|
-
{ "report.txt": "Q3 revenue..." }, // → Worker 2: context/report.txt
|
|
106
|
-
];
|
|
107
|
-
|
|
108
|
-
const results = await swarm.map({
|
|
109
|
-
items,
|
|
110
|
-
prompt: "Summarize this report",
|
|
111
|
-
});
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
---
|
|
115
|
-
|
|
116
|
-
**Case 2: Multiple files per worker**
|
|
117
|
-
|
|
118
|
-
```ts
|
|
119
|
-
// 3 workers, each gets 2 files
|
|
120
|
-
const items: FileMap[] = [
|
|
121
|
-
{ // → Worker 0:
|
|
122
|
-
"doc1.pdf": fs.readFileSync("./doc1.pdf"), // context/doc1.pdf
|
|
123
|
-
"doc2.pdf": fs.readFileSync("./doc2.pdf"), // context/doc2.pdf
|
|
124
|
-
},
|
|
125
|
-
{ // → Worker 1:
|
|
126
|
-
"doc3.pdf": fs.readFileSync("./doc3.pdf"), // context/doc3.pdf
|
|
127
|
-
"doc4.pdf": fs.readFileSync("./doc4.pdf"), // context/doc4.pdf
|
|
128
|
-
},
|
|
129
|
-
{ // → Worker 2:
|
|
130
|
-
"doc5.pdf": fs.readFileSync("./doc5.pdf"), // context/doc5.pdf
|
|
131
|
-
"doc6.pdf": fs.readFileSync("./doc6.pdf"), // context/doc6.pdf
|
|
132
|
-
},
|
|
133
|
-
];
|
|
134
|
-
|
|
135
|
-
const results = await swarm.map({
|
|
136
|
-
items,
|
|
137
|
-
prompt: "Compare these two documents",
|
|
138
|
-
});
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
**Case 3: Entire folder per worker**
|
|
144
|
-
|
|
145
|
-
```ts
|
|
146
|
-
import { readLocalDir } from "@evolvingmachines/evolve";
|
|
147
|
-
|
|
148
|
-
// readLocalDir(path, recursive) → returns FileMap with all files
|
|
149
|
-
const items: FileMap[] = [
|
|
150
|
-
readLocalDir("./project-a", true), // → Worker 0: all files from project-a (recursive)
|
|
151
|
-
readLocalDir("./project-b", true), // → Worker 1: all files from project-b (recursive)
|
|
152
|
-
readLocalDir("./project-c", true), // → Worker 2: all files from project-c (recursive)
|
|
153
|
-
];
|
|
154
|
-
|
|
155
|
-
const results = await swarm.map({
|
|
156
|
-
items,
|
|
157
|
-
prompt: "Review this codebase",
|
|
158
|
-
});
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
## Abstractions
|
|
162
|
-
|
|
163
|
-
Two types of operations:
|
|
164
|
-
|
|
165
|
-
| Operation | Type | Description | Passes On |
|
|
166
|
-
|-----------|------|-------------|-----------|
|
|
167
|
-
| `bestOf` | transform + select | `input` → `output` (best of N candidates) | winner output |
|
|
168
|
-
| `map` | transform | `input` → `output` (agent produces new data) | agent output |
|
|
169
|
-
| `filter` | gate | `input` → `input` (agent evaluates, condition decides) | original input + status (`success` \| `filtered`) |
|
|
170
|
-
| `reduce` | transform | `inputs` → `output` (agent synthesizes) | agent output |
|
|
171
|
-
|
|
172
|
-
**Transforms** produce new output files. **Filter** passes through original input files unchanged.
|
|
173
|
-
|
|
174
|
-
**BestOfConfig** — run N candidates in parallel, judge picks the best:
|
|
175
|
-
```ts
|
|
176
|
-
{
|
|
177
|
-
n?: number,
|
|
178
|
-
judgeCriteria: string,
|
|
179
|
-
taskAgents?: AgentOverride[],
|
|
180
|
-
judgeAgent?: AgentOverride,
|
|
181
|
-
skills?: string[],
|
|
182
|
-
judgeSkills?: string[],
|
|
183
|
-
integrations?: IntegrationsSetup,
|
|
184
|
-
judgeIntegrations?: IntegrationsSetup,
|
|
185
|
-
mcpServers?: Record<string, McpServerConfig>,
|
|
186
|
-
judgeMcpServers?: Record<string, McpServerConfig>,
|
|
187
|
-
onCandidateComplete?: (idx, candIdx, status) => void,
|
|
188
|
-
onJudgeComplete?: (idx, winnerIdx, reasoning) => void,
|
|
189
|
-
}
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
**VerifyConfig** — LLM-as-judge verifies output, retries with feedback if failed:
|
|
193
|
-
```ts
|
|
194
|
-
{
|
|
195
|
-
criteria: string,
|
|
196
|
-
maxAttempts?: number,
|
|
197
|
-
verifierAgent?: AgentOverride,
|
|
198
|
-
verifierSkills?: string[],
|
|
199
|
-
verifierIntegrations?: IntegrationsSetup,
|
|
200
|
-
verifierMcpServers?: Record<string, McpServerConfig>,
|
|
201
|
-
onWorkerComplete?: (idx, attempt, status) => void,
|
|
202
|
-
onVerifierComplete?: (idx, attempt, passed, feedback?) => void,
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### bestOf
|
|
207
|
-
|
|
208
|
-
Run N agents on the same `item` in parallel, then a judge picks the best. `Agent[i]` outputs `candidates[i]`, judge selects `winner`.
|
|
209
|
-
|
|
210
|
-
```
|
|
211
|
-
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
212
|
-
│ Sandbox 0 │ │ Sandbox 1 │ │ Sandbox 2 │
|
|
213
|
-
│ Agent 0 │ │ Agent 1 │ │ Agent 2 │
|
|
214
|
-
│ │ │ │ │ │
|
|
215
|
-
│ context/ │ │ context/ │ │ context/ │
|
|
216
|
-
│ item │ │ item │ │ item │
|
|
217
|
-
│ output/ │ │ output/ │ │ output/ │
|
|
218
|
-
│ candidates[0]│ │ candidates[1]│ │ candidates[2]│
|
|
219
|
-
└───────┬─────────┘ └───────┬─────────┘ └───────┬─────────┘
|
|
220
|
-
│ │ │
|
|
221
|
-
└───────────────────┼───────────────────┘
|
|
222
|
-
▼
|
|
223
|
-
┌───────────────┐
|
|
224
|
-
│ Judge │
|
|
225
|
-
└───────┬───────┘
|
|
226
|
-
│
|
|
227
|
-
▼
|
|
228
|
-
winner
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
```ts
|
|
232
|
-
// Signature
|
|
233
|
-
swarm.bestOf<T>({
|
|
234
|
-
item: FileMap | SwarmResult,
|
|
235
|
-
prompt: string,
|
|
236
|
-
config: BestOfConfig, // { n?, judgeCriteria, taskAgents?, judgeAgent?, mcpServers?, judgeMcpServers?, skills?, judgeSkills?, integrations?, judgeIntegrations?, ... }
|
|
237
|
-
name?: string, // Operation name for observability (appears in meta.operationName)
|
|
238
|
-
schema?: z.ZodType<T> | JsonSchema,
|
|
239
|
-
systemPrompt?: string,
|
|
240
|
-
retry?: RetryConfig, // Per-candidate retry (judge uses default)
|
|
241
|
-
timeoutMs?: number,
|
|
242
|
-
}): Promise<BestOfResult<T>>
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
```ts
|
|
246
|
-
const input = { "task.txt": "Complex problem..." };
|
|
247
|
-
|
|
248
|
-
const result = await swarm.bestOf({
|
|
249
|
-
item: input,
|
|
250
|
-
prompt: "Solve this problem",
|
|
251
|
-
config: {
|
|
252
|
-
n: 3,
|
|
253
|
-
judgeCriteria: "Most accurate and well-explained solution",
|
|
254
|
-
onCandidateComplete: (idx, candIdx, status) => console.log(`Candidate ${candIdx}: ${status}`),
|
|
255
|
-
onJudgeComplete: (idx, winnerIdx, reasoning) => console.log(`Winner: ${winnerIdx}`),
|
|
256
|
-
},
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
console.log(result.winner); // Best SwarmResult
|
|
260
|
-
console.log(result.winnerIndex); // 0, 1, or 2
|
|
261
|
-
console.log(result.judgeReasoning); // Why this was chosen
|
|
262
|
-
console.log(result.candidates); // All candidate results
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
Use different agents per candidate:
|
|
266
|
-
|
|
267
|
-
```ts
|
|
268
|
-
const claudeAgent = { type: "claude", model: "opus" };
|
|
269
|
-
const codexAgent = { type: "codex", model: "gpt-5.3-codex" };
|
|
270
|
-
const geminiAgent = { type: "gemini", model: "gemini-3.5-flash" };
|
|
271
|
-
|
|
272
|
-
const result = await swarm.bestOf({
|
|
273
|
-
item: input,
|
|
274
|
-
prompt: "Solve this",
|
|
275
|
-
config: {
|
|
276
|
-
taskAgents: [claudeAgent, codexAgent, geminiAgent],
|
|
277
|
-
judgeCriteria: "Best solution quality",
|
|
278
|
-
judgeAgent: claudeAgent,
|
|
279
|
-
mcpServers: {...}, // (optional) MCP servers for candidates
|
|
280
|
-
judgeMcpServers: {...}, // (optional) MCP servers for judge
|
|
281
|
-
skills: ["anthropics/skills"], // (optional) Skills for candidates
|
|
282
|
-
judgeSkills: ["anthropics/skills"], // (optional) Skills for judge
|
|
283
|
-
integrations: {...}, // (optional) Integrations config for candidates
|
|
284
|
-
judgeIntegrations: {...}, // (optional) Integrations config for judge
|
|
285
|
-
},
|
|
286
|
-
});
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
### map
|
|
290
|
-
|
|
291
|
-
Process items in parallel. `Agent[i]` sees `items[i]` and outputs `results[i]` (which includes `result.json` if `schema` provided).
|
|
292
|
-
|
|
293
|
-
```
|
|
294
|
-
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
295
|
-
│ Sandbox 0 │ │ Sandbox 1 │ │ Sandbox 2 │
|
|
296
|
-
│ Agent 0 │ │ Agent 1 │ │ Agent 2 │
|
|
297
|
-
│ │ │ │ │ │
|
|
298
|
-
│ context/ │ │ context/ │ │ context/ │
|
|
299
|
-
│ items[0] │ │ items[1] │ │ items[2] │
|
|
300
|
-
│ output/ │ │ output/ │ │ output/ │
|
|
301
|
-
│ results[0] │ │ results[1] │ │ results[2] │
|
|
302
|
-
└───────┬─────────┘ └───────┬─────────┘ └───────┬─────────┘
|
|
303
|
-
│ │ │
|
|
304
|
-
└───────────────────┼───────────────────┘
|
|
305
|
-
▼
|
|
306
|
-
[results[0], results[1], results[2]]
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
```ts
|
|
310
|
-
// Signature (schema accepts Zod or JSON Schema object)
|
|
311
|
-
swarm.map<T>({
|
|
312
|
-
items: FileMap[] | SwarmResult[],
|
|
313
|
-
prompt: string | ((files: FileMap, index: number) => string),
|
|
314
|
-
name?: string, // Operation name for observability (appears in meta.operationName)
|
|
315
|
-
schema?: z.ZodType<T> | JsonSchema,
|
|
316
|
-
systemPrompt?: string,
|
|
317
|
-
agent?: AgentOverride,
|
|
318
|
-
bestOf?: BestOfConfig, // N candidates + judge (mutually exclusive with verify)
|
|
319
|
-
verify?: VerifyConfig, // LLM-as-judge quality check with retry loop
|
|
320
|
-
retry?: RetryConfig, // Auto-retry on error with backoff
|
|
321
|
-
mcpServers?: Record<string, McpServerConfig>,
|
|
322
|
-
skills?: string[], // e.g. ["anthropics/skills"]
|
|
323
|
-
integrations?: IntegrationsSetup, // managed integrations config
|
|
324
|
-
timeoutMs?: number,
|
|
325
|
-
}): Promise<SwarmResultList<T>>
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
```ts
|
|
329
|
-
// Basic
|
|
330
|
-
const results = await swarm.map({
|
|
331
|
-
items: documents,
|
|
332
|
-
prompt: "Summarize this document",
|
|
333
|
-
});
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
When `schema` is provided, a structured output prompt is automatically embedded—instructing the agent to write `output/result.json` matching the schema.
|
|
337
|
-
|
|
338
|
-
```ts
|
|
339
|
-
// With Zod schema
|
|
340
|
-
const SummarySchema = z.object({
|
|
341
|
-
title: z.string(),
|
|
342
|
-
keyPoints: z.array(z.string()),
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
const results = await swarm.map({
|
|
346
|
-
items: documents,
|
|
347
|
-
prompt: "Extract summary",
|
|
348
|
-
schema: SummarySchema,
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
// Or with JSON Schema
|
|
352
|
-
const SummaryJsonSchema = {
|
|
353
|
-
type: "object",
|
|
354
|
-
properties: {
|
|
355
|
-
title: { type: "string" },
|
|
356
|
-
keyPoints: { type: "array", items: { type: "string" } },
|
|
357
|
-
},
|
|
358
|
-
required: ["title", "keyPoints"],
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
const results = await swarm.map({
|
|
362
|
-
items: documents,
|
|
363
|
-
prompt: "Extract summary",
|
|
364
|
-
schema: SummaryJsonSchema,
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
// With dynamic prompt
|
|
368
|
-
const results = await swarm.map({
|
|
369
|
-
items: documents,
|
|
370
|
-
prompt: (files, index) => `Analyze document ${index + 1}: focus on revenue`,
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
// Access results
|
|
374
|
-
for (const r of results) {
|
|
375
|
-
if (r.status === "success") {
|
|
376
|
-
console.log(r.data); // Parsed schema or FileMap
|
|
377
|
-
console.log(r.files); // Output files from agent
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
### map + bestOf
|
|
383
|
-
|
|
384
|
-
Combine map parallelism with bestOf quality:
|
|
385
|
-
|
|
386
|
-
```ts
|
|
387
|
-
const AnalysisSchema = z.object({
|
|
388
|
-
findings: z.array(z.string()),
|
|
389
|
-
confidence: z.number(),
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
// Each item gets N candidates, judge picks best per item
|
|
393
|
-
const results = await swarm.map({
|
|
394
|
-
items: documents,
|
|
395
|
-
prompt: "Analyze thoroughly",
|
|
396
|
-
schema: AnalysisSchema,
|
|
397
|
-
bestOf: {
|
|
398
|
-
n: 3,
|
|
399
|
-
judgeCriteria: "Most comprehensive analysis",
|
|
400
|
-
// taskAgents?: AgentOverride[], // Different agent per candidate
|
|
401
|
-
// judgeAgent?: AgentOverride, // Override judge agent
|
|
402
|
-
// mcpServers?: {...}, // MCP servers for candidates
|
|
403
|
-
// judgeMcpServers?: {...}, // MCP servers for judge
|
|
404
|
-
// skills?: [...], // Skills for candidates
|
|
405
|
-
// judgeSkills?: [...], // Skills for judge
|
|
406
|
-
// integrations?: {...}, // Integrations for candidates
|
|
407
|
-
// judgeIntegrations?: {...}, // Integrations for judge
|
|
408
|
-
},
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
// Results contain only winners (one per input item)
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
### filter
|
|
415
|
-
|
|
416
|
-
Two-step evaluation (`schema` and `condition` are required):
|
|
417
|
-
1. `Agent[i]` sees `items[i]`, assesses it, outputs `result.json` matching `schema`
|
|
418
|
-
2. SDK parses `result.json` → `data`, your `condition(data)` applies the threshold
|
|
419
|
-
3. Passing items forward their original input files, not agent output
|
|
420
|
-
|
|
421
|
-
```
|
|
422
|
-
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
423
|
-
│ Sandbox 0 │ │ Sandbox 1 │ │ Sandbox 2 │
|
|
424
|
-
│ Agent 0 │ │ Agent 1 │ │ Agent 2 │
|
|
425
|
-
│ │ │ │ │ │
|
|
426
|
-
│ context/ │ │ context/ │ │ context/ │
|
|
427
|
-
│ items[0] │ │ items[1] │ │ items[2] │
|
|
428
|
-
│ output/ │ │ output/ │ │ output/ │
|
|
429
|
-
│ result.json │ │ result.json │ │ result.json │
|
|
430
|
-
└───────┬─────────┘ └───────┬─────────┘ └───────┬─────────┘
|
|
431
|
-
│ │ │
|
|
432
|
-
└───────────────────┼───────────────────┘
|
|
433
|
-
▼
|
|
434
|
-
condition(data)
|
|
435
|
-
✓ ✗ ✓
|
|
436
|
-
│ │
|
|
437
|
-
▼ ▼
|
|
438
|
-
[items[0], items[2]]
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
```ts
|
|
442
|
-
// Signature (schema accepts Zod or JSON Schema object)
|
|
443
|
-
swarm.filter<T>({
|
|
444
|
-
items: FileMap[] | SwarmResult[],
|
|
445
|
-
prompt: string, // Describe what to assess (agent outputs result.json)
|
|
446
|
-
name?: string, // Operation name for observability (appears in meta.operationName)
|
|
447
|
-
schema: z.ZodType<T> | JsonSchema, // Required - defines evaluation output structure
|
|
448
|
-
condition: (data: T) => boolean, // Local function applies threshold
|
|
449
|
-
systemPrompt?: string,
|
|
450
|
-
agent?: AgentOverride,
|
|
451
|
-
verify?: VerifyConfig, // LLM-as-judge quality check with retry loop
|
|
452
|
-
retry?: RetryConfig, // Auto-retry on error with backoff
|
|
453
|
-
mcpServers?: Record<string, McpServerConfig>,
|
|
454
|
-
skills?: string[], // e.g. ["anthropics/skills"]
|
|
455
|
-
integrations?: IntegrationsSetup, // managed integrations config
|
|
456
|
-
timeoutMs?: number,
|
|
457
|
-
}): Promise<SwarmResultList<T>>
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
```ts
|
|
461
|
-
const EvalSchema = z.object({
|
|
462
|
-
severity: z.enum(["critical", "warning", "info"]),
|
|
463
|
-
score: z.number(),
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
const results = await swarm.filter({
|
|
467
|
-
items: documents,
|
|
468
|
-
prompt: "Assess the severity of issues in this document", // Agent evaluates
|
|
469
|
-
schema: EvalSchema,
|
|
470
|
-
condition: (data) => data.severity === "critical", // Code applies threshold
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
// Three possible statuses:
|
|
474
|
-
results.success; // Passed condition
|
|
475
|
-
results.filtered; // Evaluated but didn't pass
|
|
476
|
-
results.error; // Agent error
|
|
477
|
-
|
|
478
|
-
// Chain to next step
|
|
479
|
-
await swarm.reduce({
|
|
480
|
-
items: results.success,
|
|
481
|
-
prompt: "Summarize critical issues",
|
|
482
|
-
});
|
|
483
|
-
```
|
|
484
|
-
|
|
485
|
-
### reduce
|
|
486
|
-
|
|
487
|
-
Synthesize many items into one. A single agent sees all `items` as `item_0/`, `item_1/`, etc. and outputs a unified `result` (which includes `result.json` if `schema` provided).
|
|
488
|
-
|
|
489
|
-
```
|
|
490
|
-
┌─────────────────────────┐
|
|
491
|
-
│ Sandbox │
|
|
492
|
-
│ Agent │
|
|
493
|
-
│ │
|
|
494
|
-
│ context/ │
|
|
495
|
-
│ item_0/items[0] │
|
|
496
|
-
│ item_1/items[1] │
|
|
497
|
-
│ item_2/items[2] │
|
|
498
|
-
│ output/ │
|
|
499
|
-
│ result │
|
|
500
|
-
└────────────┬────────────┘
|
|
501
|
-
│
|
|
502
|
-
▼
|
|
503
|
-
result
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
```ts
|
|
507
|
-
// Signature (schema accepts Zod or JSON Schema object)
|
|
508
|
-
swarm.reduce<T>({
|
|
509
|
-
items: FileMap[] | SwarmResult[],
|
|
510
|
-
prompt: string,
|
|
511
|
-
name?: string, // Operation name for observability (appears in meta.operationName)
|
|
512
|
-
schema?: z.ZodType<T> | JsonSchema,
|
|
513
|
-
systemPrompt?: string,
|
|
514
|
-
agent?: AgentOverride,
|
|
515
|
-
verify?: VerifyConfig, // LLM-as-judge quality check with retry loop
|
|
516
|
-
retry?: RetryConfig, // Auto-retry on error with backoff
|
|
517
|
-
mcpServers?: Record<string, McpServerConfig>,
|
|
518
|
-
skills?: string[], // e.g. ["anthropics/skills"]
|
|
519
|
-
integrations?: IntegrationsSetup, // managed integrations config
|
|
520
|
-
timeoutMs?: number,
|
|
521
|
-
}): Promise<ReduceResult<T>>
|
|
522
|
-
```
|
|
523
|
-
|
|
524
|
-
```ts
|
|
525
|
-
// Agent sees: item_0/, item_1/, item_2/, etc.
|
|
526
|
-
const report = await swarm.reduce({
|
|
527
|
-
items: results.success,
|
|
528
|
-
prompt: "Create a unified report from all analyses",
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
if (report.status === "success") {
|
|
532
|
-
console.log(report.files); // Final output files
|
|
533
|
-
console.log(report.data); // Parsed schema if provided
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// With schema
|
|
537
|
-
const ReportSchema = z.object({
|
|
538
|
-
summary: z.string(),
|
|
539
|
-
recommendations: z.array(z.string()),
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
const report = await swarm.reduce({
|
|
543
|
-
items,
|
|
544
|
-
prompt: "Create report",
|
|
545
|
-
schema: ReportSchema,
|
|
546
|
-
});
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
### verify (quality gate)
|
|
550
|
-
|
|
551
|
-
Add a verification loop to any operation (`map`, `filter`, `reduce`). A separate verifier agent checks if the worker's output meets your criteria. On failure, the worker retries with the verifier's feedback — up to `maxAttempts` times.
|
|
552
|
-
|
|
553
|
-
```
|
|
554
|
-
┌───────────────┐ ┌──────────────┐
|
|
555
|
-
│ Worker │─────▶│ Verifier │
|
|
556
|
-
│ (attempt 1) │ │ │
|
|
557
|
-
└───────────────┘ └──────┬───────┘
|
|
558
|
-
│
|
|
559
|
-
pass? │ fail + feedback
|
|
560
|
-
│ │ │
|
|
561
|
-
▼ │ ▼
|
|
562
|
-
output │ ┌───────────────┐
|
|
563
|
-
└─▶│ Worker │──▶ Verifier ──▶ ...
|
|
564
|
-
│ (attempt 2) │ (up to maxAttempts)
|
|
565
|
-
└───────────────┘
|
|
566
|
-
```
|
|
567
|
-
|
|
568
|
-
```ts
|
|
569
|
-
const results = await swarm.map({
|
|
570
|
-
items: documents,
|
|
571
|
-
prompt: "Write a detailed analysis",
|
|
572
|
-
schema: AnalysisSchema,
|
|
573
|
-
verify: {
|
|
574
|
-
criteria: "Analysis must include specific data points and cite sources",
|
|
575
|
-
maxAttempts: 3, // Default: 3
|
|
576
|
-
// verifierAgent: { type: "claude", model: "opus" }, // Override verifier agent
|
|
577
|
-
// verifierSkills: ["anthropics/skills"], // Skills for verifier
|
|
578
|
-
onWorkerComplete: (idx, attempt, status) => {
|
|
579
|
-
console.log(`Item ${idx}, attempt ${attempt}: ${status}`);
|
|
580
|
-
},
|
|
581
|
-
onVerifierComplete: (idx, attempt, passed, feedback) => {
|
|
582
|
-
console.log(`Verify item ${idx}: ${passed ? "PASS" : feedback}`);
|
|
583
|
-
},
|
|
584
|
-
},
|
|
585
|
-
});
|
|
586
|
-
|
|
587
|
-
// Check verification outcome
|
|
588
|
-
for (const r of results) {
|
|
589
|
-
if (r.verify) {
|
|
590
|
-
console.log(`Passed: ${r.verify.passed}, attempts: ${r.verify.attempts}`);
|
|
591
|
-
console.log(`Reasoning: ${r.verify.reasoning}`);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
On each failed attempt, the verifier's feedback is appended to the worker's prompt so it can address specific issues. The final result includes `verify: VerifyInfo` with the outcome.
|
|
597
|
-
|
|
598
|
-
> **Note:** `verify` and `bestOf` are mutually exclusive on `map`. Use one or the other per operation.
|
|
599
|
-
|
|
600
|
-
---
|
|
601
|
-
|
|
602
|
-
## Result Types
|
|
603
|
-
|
|
604
|
-
```ts
|
|
605
|
-
// SwarmResult<T> - from map, filter, bestOf candidates
|
|
606
|
-
interface SwarmResult<T> {
|
|
607
|
-
status: "success" | "filtered" | "error";
|
|
608
|
-
data: T | null; // Parsed schema, or null on error
|
|
609
|
-
files: FileMap; // Output files (map/bestOf) or input files (filter)
|
|
610
|
-
meta: IndexedMeta; // { operationId, operation, tag, sandboxId, itemIndex }
|
|
611
|
-
error?: string; // Error message if status === "error"
|
|
612
|
-
rawData?: string; // Raw result.json when parse/validation failed (for debugging)
|
|
613
|
-
bestOf?: { // Present when map used bestOf option
|
|
614
|
-
winnerIndex: number;
|
|
615
|
-
judgeReasoning: string;
|
|
616
|
-
judgeMeta: JudgeMeta; // { operationId, operation, tag, sandboxId, candidateCount }
|
|
617
|
-
candidates: SwarmResult<T>[];
|
|
618
|
-
};
|
|
619
|
-
verify?: VerifyInfo; // Present when verify option was used
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
// SwarmResultList<T> - from map, filter (extends Array)
|
|
623
|
-
results.success; // SwarmResult[] with status "success"
|
|
624
|
-
results.filtered; // SwarmResult[] with status "filtered"
|
|
625
|
-
results.error; // SwarmResult[] with status "error"
|
|
626
|
-
|
|
627
|
-
// ReduceResult<T> - from reduce
|
|
628
|
-
interface ReduceResult<T> {
|
|
629
|
-
status: "success" | "error";
|
|
630
|
-
data: T | null;
|
|
631
|
-
files: FileMap;
|
|
632
|
-
meta: ReduceMeta; // { operationId, operation, tag, sandboxId, inputCount, inputIndices }
|
|
633
|
-
error?: string;
|
|
634
|
-
rawData?: string; // Raw result.json when parse/validation failed (for debugging)
|
|
635
|
-
verify?: VerifyInfo; // Present when verify option was used
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
// VerifyInfo - verification outcome
|
|
639
|
-
interface VerifyInfo {
|
|
640
|
-
passed: boolean; // Final verification status
|
|
641
|
-
reasoning: string; // Verifier's reasoning
|
|
642
|
-
verifyMeta: VerifyMeta; // { operationId, operation, tag, sandboxId, attempts }
|
|
643
|
-
attempts: number; // Total attempts made
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
// BestOfResult<T> - from bestOf
|
|
647
|
-
interface BestOfResult<T> {
|
|
648
|
-
winner: SwarmResult<T>;
|
|
649
|
-
winnerIndex: number;
|
|
650
|
-
judgeReasoning: string;
|
|
651
|
-
judgeMeta: JudgeMeta; // { operationId, operation, tag, sandboxId, candidateCount }
|
|
652
|
-
candidates: SwarmResult<T>[];
|
|
653
|
-
}
|
|
654
|
-
```
|
|
655
|
-
|
|
656
|
-
## Chaining Operations
|
|
657
|
-
|
|
658
|
-
When chaining Swarm operations, `result.json` from a previous step is automatically renamed to `data.json`. This avoids confusion when the downstream agent writes its own `result.json`. This also applies to [Pipeline](#pipeline).
|
|
659
|
-
|
|
660
|
-
**Example: map → reduce chain**
|
|
661
|
-
|
|
662
|
-
```
|
|
663
|
-
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
664
|
-
│ MAP (parallel) │
|
|
665
|
-
│ │
|
|
666
|
-
│ item_0 agent writes: item_1 agent writes: │
|
|
667
|
-
│ output/ output/ │
|
|
668
|
-
│ result.json ← schema result.json ← schema │
|
|
669
|
-
│ │
|
|
670
|
-
└─────────────────────────────────────────────────────────────────────────────┘
|
|
671
|
-
│
|
|
672
|
-
▼
|
|
673
|
-
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
674
|
-
│ REDUCE (single agent) │
|
|
675
|
-
│ │
|
|
676
|
-
│ context/ │
|
|
677
|
-
│ item_0/ │
|
|
678
|
-
│ data.json ← renamed from result.json │
|
|
679
|
-
│ item_1/ │
|
|
680
|
-
│ data.json ← renamed from result.json │
|
|
681
|
-
│ output/ │
|
|
682
|
-
│ result.json ← reduce agent writes its own │
|
|
683
|
-
│ │
|
|
684
|
-
└─────────────────────────────────────────────────────────────────────────────┘
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
```ts
|
|
688
|
-
const AnalysisSchema = z.object({ summary: z.string() });
|
|
689
|
-
const SeveritySchema = z.object({ severity: z.enum(["critical", "warning", "info"]) });
|
|
690
|
-
|
|
691
|
-
// Full pipeline: map → filter → reduce
|
|
692
|
-
const analyzed = await swarm.map({
|
|
693
|
-
items: documents,
|
|
694
|
-
prompt: "Analyze",
|
|
695
|
-
schema: AnalysisSchema,
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
const critical = await swarm.filter({
|
|
699
|
-
items: analyzed.success,
|
|
700
|
-
prompt: "Evaluate severity",
|
|
701
|
-
schema: SeveritySchema,
|
|
702
|
-
condition: (d) => d.severity === "critical",
|
|
703
|
-
});
|
|
704
|
-
|
|
705
|
-
const report = await swarm.reduce({
|
|
706
|
-
items: critical.success,
|
|
707
|
-
prompt: "Create summary report",
|
|
708
|
-
});
|
|
709
|
-
|
|
710
|
-
// Combine success and filtered
|
|
711
|
-
const allEvaluated = [...critical.success, ...critical.filtered];
|
|
712
|
-
await swarm.reduce({
|
|
713
|
-
items: allEvaluated,
|
|
714
|
-
prompt: "Summarize all evaluated items",
|
|
715
|
-
});
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
## AgentOverride
|
|
719
|
-
|
|
720
|
-
Override the default agent for any operation (apiKey inherited from Swarm config):
|
|
721
|
-
|
|
722
|
-
```ts
|
|
723
|
-
interface AgentOverride {
|
|
724
|
-
type: "claude" | "codex" | "gemini" | "qwen" | "kimi" | "opencode" | "droid";
|
|
725
|
-
model?: string;
|
|
726
|
-
reasoningEffort?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | "thinking" | "no-thinking";
|
|
727
|
-
}
|
|
728
|
-
```
|
|
729
|
-
|
|
730
|
-
```ts
|
|
731
|
-
const codexAgent: AgentOverride = {
|
|
732
|
-
type: "codex",
|
|
733
|
-
reasoningEffort: "high",
|
|
734
|
-
};
|
|
735
|
-
|
|
736
|
-
const results = await swarm.map({
|
|
737
|
-
items,
|
|
738
|
-
prompt: "Analyze",
|
|
739
|
-
agent: codexAgent,
|
|
740
|
-
});
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
## Concurrency
|
|
744
|
-
|
|
745
|
-
Global semaphore limits parallel sandboxes across all operations.
|
|
746
|
-
|
|
747
|
-
```ts
|
|
748
|
-
const swarm = new Swarm({
|
|
749
|
-
agent,
|
|
750
|
-
sandbox,
|
|
751
|
-
concurrency: 4, // Max 4 sandboxes at once (default: 4)
|
|
752
|
-
});
|
|
753
|
-
|
|
754
|
-
// map(10) with bestOf(5) = 60 agent calls, but only 4 run at any time
|
|
755
|
-
```
|
|
756
|
-
|
|
757
|
-
**Ordering guarantees:**
|
|
758
|
-
- `bestOf`: Judge runs only after all candidates complete
|
|
759
|
-
- `map` → `filter` → `reduce`: Each phase completes before next starts
|
|
760
|
-
- Within a phase: Items run in parallel (up to concurrency limit)
|
|
761
|
-
|
|
762
|
-
---
|
|
763
|
-
|
|
764
|
-
## Pipeline
|
|
765
|
-
|
|
766
|
-
Fluent wrapper over Swarm for chaining operations. **All Swarm features work in Pipeline steps** — `schema`, `bestOf`, `verify`, `retry`, `agent`, `mcpServers`, `skills`, `integrations`, dynamic prompts.
|
|
767
|
-
|
|
768
|
-
```ts
|
|
769
|
-
import "dotenv/config";
|
|
770
|
-
import { Swarm, Pipeline } from "@evolvingmachines/evolve";
|
|
771
|
-
|
|
772
|
-
const swarm = new Swarm(); // See Swarm Abstractions for full config
|
|
773
|
-
|
|
774
|
-
const pipeline = new Pipeline(swarm)
|
|
775
|
-
.map({
|
|
776
|
-
name: "analyze",
|
|
777
|
-
prompt: "Analyze...",
|
|
778
|
-
schema: AnalysisSchema,
|
|
779
|
-
})
|
|
780
|
-
.filter({
|
|
781
|
-
name: "critical",
|
|
782
|
-
prompt: "Rate...",
|
|
783
|
-
schema: SeveritySchema,
|
|
784
|
-
condition: d => d.severity === "critical",
|
|
785
|
-
})
|
|
786
|
-
.reduce({
|
|
787
|
-
name: "report",
|
|
788
|
-
prompt: "Summarize...",
|
|
789
|
-
});
|
|
790
|
-
|
|
791
|
-
// Reusable — run with different data
|
|
792
|
-
const result1 = await pipeline.run(batch1);
|
|
793
|
-
const result2 = await pipeline.run(batch2);
|
|
794
|
-
```
|
|
795
|
-
|
|
796
|
-
### Step Configurations
|
|
797
|
-
|
|
798
|
-
Each step accepts the same options as the corresponding Swarm method, plus `name` for observability:
|
|
799
|
-
|
|
800
|
-
```ts
|
|
801
|
-
// Map step — same as swarm.map() + name
|
|
802
|
-
.map<T>({
|
|
803
|
-
name?: string, // Step name (appears in events)
|
|
804
|
-
prompt: string | ((files, idx) => string),
|
|
805
|
-
schema?: z.ZodType<T> | JsonSchema,
|
|
806
|
-
bestOf?: BestOfConfig, // N candidates + judge
|
|
807
|
-
verify?: VerifyConfig, // LLM-as-judge quality check
|
|
808
|
-
retry?: RetryConfig, // Auto-retry on error
|
|
809
|
-
agent?: AgentOverride,
|
|
810
|
-
mcpServers?: Record<string, McpServerConfig>,
|
|
811
|
-
skills?: string[], // Skills for workers
|
|
812
|
-
integrations?: IntegrationsSetup, // managed integrations config
|
|
813
|
-
systemPrompt?: string,
|
|
814
|
-
timeoutMs?: number,
|
|
815
|
-
})
|
|
816
|
-
|
|
817
|
-
// Filter step — same as swarm.filter() + name + emit
|
|
818
|
-
.filter<T>({
|
|
819
|
-
name?: string,
|
|
820
|
-
prompt: string,
|
|
821
|
-
schema: z.ZodType<T> | JsonSchema, // Required
|
|
822
|
-
condition: (data: T) => boolean, // Required
|
|
823
|
-
emit?: "success" | "filtered" | "all", // What passes to next step: "success" (default), "filtered", or "all"
|
|
824
|
-
verify?: VerifyConfig,
|
|
825
|
-
retry?: RetryConfig,
|
|
826
|
-
agent?: AgentOverride,
|
|
827
|
-
mcpServers?: Record<string, McpServerConfig>,
|
|
828
|
-
skills?: string[], // Skills for workers
|
|
829
|
-
integrations?: IntegrationsSetup, // managed integrations config
|
|
830
|
-
systemPrompt?: string,
|
|
831
|
-
timeoutMs?: number,
|
|
832
|
-
})
|
|
833
|
-
|
|
834
|
-
// Reduce step — same as swarm.reduce() + name (terminal: no steps after)
|
|
835
|
-
.reduce<T>({
|
|
836
|
-
name?: string,
|
|
837
|
-
prompt: string,
|
|
838
|
-
schema?: z.ZodType<T> | JsonSchema,
|
|
839
|
-
verify?: VerifyConfig,
|
|
840
|
-
retry?: RetryConfig,
|
|
841
|
-
agent?: AgentOverride,
|
|
842
|
-
mcpServers?: Record<string, McpServerConfig>,
|
|
843
|
-
skills?: string[], // Skills for workers
|
|
844
|
-
integrations?: IntegrationsSetup, // managed integrations config
|
|
845
|
-
systemPrompt?: string,
|
|
846
|
-
timeoutMs?: number,
|
|
847
|
-
})
|
|
848
|
-
```
|
|
849
|
-
|
|
850
|
-
### Full Example
|
|
851
|
-
|
|
852
|
-
```ts
|
|
853
|
-
const pipeline = new Pipeline(swarm)
|
|
854
|
-
|
|
855
|
-
.map({
|
|
856
|
-
name: "analyze",
|
|
857
|
-
prompt: (files, idx) => `Analyze document ${idx + 1}`,
|
|
858
|
-
schema: AnalysisSchema,
|
|
859
|
-
bestOf: {
|
|
860
|
-
n: 3,
|
|
861
|
-
judgeCriteria: "Most thorough analysis",
|
|
862
|
-
},
|
|
863
|
-
retry: { maxAttempts: 2 },
|
|
864
|
-
agent: { type: "claude", model: "opus" },
|
|
865
|
-
})
|
|
866
|
-
|
|
867
|
-
.filter({
|
|
868
|
-
name: "quality-gate",
|
|
869
|
-
prompt: "Rate the analysis quality",
|
|
870
|
-
schema: z.object({
|
|
871
|
-
score: z.number(),
|
|
872
|
-
reasoning: z.string(),
|
|
873
|
-
}),
|
|
874
|
-
condition: d => d.score >= 8,
|
|
875
|
-
emit: "success", // Only high-quality pass through
|
|
876
|
-
verify: {
|
|
877
|
-
criteria: "Rating must be justified with specific examples",
|
|
878
|
-
},
|
|
879
|
-
})
|
|
880
|
-
|
|
881
|
-
.reduce({
|
|
882
|
-
name: "synthesize",
|
|
883
|
-
prompt: "Create executive summary from all analyses",
|
|
884
|
-
schema: ReportSchema,
|
|
885
|
-
verify: {
|
|
886
|
-
criteria: "Summary must cover all key findings",
|
|
887
|
-
},
|
|
888
|
-
})
|
|
889
|
-
|
|
890
|
-
.on("stepComplete", e => {
|
|
891
|
-
console.log(`${e.name}: ${e.successCount}/${e.successCount + e.errorCount}`);
|
|
892
|
-
});
|
|
893
|
-
|
|
894
|
-
const result = await pipeline.run(documents);
|
|
895
|
-
```
|
|
896
|
-
|
|
897
|
-
### Events
|
|
898
|
-
|
|
899
|
-
Pipeline unifies all Swarm callbacks at the pipeline level, adding `stepIndex` and `stepName`:
|
|
900
|
-
|
|
901
|
-
```ts
|
|
902
|
-
pipeline
|
|
903
|
-
.on("stepStart", e => {
|
|
904
|
-
console.log(`Step ${e.index} started with ${e.itemCount} items`);
|
|
905
|
-
})
|
|
906
|
-
.on("stepComplete", e => {
|
|
907
|
-
console.log(`Step ${e.index} done in ${e.durationMs}ms`);
|
|
908
|
-
})
|
|
909
|
-
.on("stepError", e => {
|
|
910
|
-
console.error(`Step ${e.index} failed:`, e.error);
|
|
911
|
-
});
|
|
912
|
-
|
|
913
|
-
// Or object style
|
|
914
|
-
pipeline.on({
|
|
915
|
-
onStepComplete: e => console.log(`${e.name}: ${e.successCount} success`),
|
|
916
|
-
onItemRetry: e => console.log(`Retry: step ${e.stepIndex}, item ${e.itemIndex}`),
|
|
917
|
-
onVerifierComplete: e => console.log(`Verify: ${e.passed ? "PASS" : e.feedback}`),
|
|
918
|
-
});
|
|
919
|
-
```
|
|
920
|
-
|
|
921
|
-
| Event | Fields |
|
|
922
|
-
|-------|--------|
|
|
923
|
-
| `stepStart` | `type`, `index`, `name?`, `itemCount` |
|
|
924
|
-
| `stepComplete` | `type`, `index`, `name?`, `durationMs`, `successCount`, `errorCount`, `filteredCount` |
|
|
925
|
-
| `stepError` | `type`, `index`, `name?`, `error` |
|
|
926
|
-
| `itemRetry` | `stepIndex`, `stepName?`, `itemIndex`, `attempt`, `error` |
|
|
927
|
-
| `workerComplete` | `stepIndex`, `stepName?`, `itemIndex`, `attempt`, `status` |
|
|
928
|
-
| `verifierComplete` | `stepIndex`, `stepName?`, `itemIndex`, `attempt`, `passed`, `feedback?` |
|
|
929
|
-
| `candidateComplete` | `stepIndex`, `stepName?`, `itemIndex`, `candidateIndex`, `status` |
|
|
930
|
-
| `judgeComplete` | `stepIndex`, `stepName?`, `itemIndex`, `winnerIndex`, `reasoning` |
|
|
931
|
-
|
|
932
|
-
### Result
|
|
933
|
-
|
|
934
|
-
```ts
|
|
935
|
-
interface PipelineResult<T> {
|
|
936
|
-
pipelineRunId: string;
|
|
937
|
-
steps: StepResult[]; // { type, index, durationMs, results }
|
|
938
|
-
output: SwarmResult<T>[] | ReduceResult<T>;
|
|
939
|
-
totalDurationMs: number;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
// Access step results
|
|
943
|
-
for (const step of result.steps) {
|
|
944
|
-
console.log(`${step.type} took ${step.durationMs}ms`);
|
|
945
|
-
}
|
|
946
|
-
```
|
|
947
|
-
|
|
948
|
-
### Terminal Pipeline
|
|
949
|
-
|
|
950
|
-
After `.reduce()`, no more steps can be added (returns `TerminalPipeline`):
|
|
951
|
-
|
|
952
|
-
```ts
|
|
953
|
-
const terminal = pipeline.reduce({ prompt: "..." });
|
|
954
|
-
terminal.map({ prompt: "..." }); // Throws: "Cannot add steps after reduce"
|
|
955
|
-
```
|
|
956
|
-
|
|
957
|
-
---
|