@directive-run/claude-plugin 1.16.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/.claude-plugin/plugin.json +6 -0
- package/LICENSE +26 -0
- package/README.md +113 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +66 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
- package/skills/README.md +9 -0
- package/skills/building-ai-agents/SKILL.md +414 -0
- package/skills/building-ai-agents/ai-adapters.md +257 -0
- package/skills/building-ai-agents/ai-agents-streaming.md +307 -0
- package/skills/building-ai-agents/ai-communication.md +304 -0
- package/skills/building-ai-agents/api-skeleton.md +5 -0
- package/skills/building-ai-agents/examples.md +849 -0
- package/skills/building-ai-orchestrators/SKILL.md +401 -0
- package/skills/building-ai-orchestrators/ai-multi-agent.md +375 -0
- package/skills/building-ai-orchestrators/ai-orchestrator.md +466 -0
- package/skills/building-ai-orchestrators/ai-tasks.md +268 -0
- package/skills/building-ai-orchestrators/api-skeleton.md +5 -0
- package/skills/building-ai-orchestrators/examples.md +1609 -0
- package/skills/building-directive-systems/SKILL.md +499 -0
- package/skills/building-directive-systems/api-skeleton.md +5 -0
- package/skills/building-directive-systems/examples.md +4149 -0
- package/skills/building-directive-systems/multi-module.md +327 -0
- package/skills/building-directive-systems/plugins.md +361 -0
- package/skills/building-directive-systems/react-adapter.md +376 -0
- package/skills/building-directive-systems/system-api.md +463 -0
- package/skills/getting-started-with-directive/SKILL.md +198 -0
- package/skills/getting-started-with-directive/api-skeleton.md +5 -0
- package/skills/getting-started-with-directive/core-patterns.md +240 -0
- package/skills/getting-started-with-directive/examples.md +87 -0
- package/skills/getting-started-with-directive/sitemap.md +202 -0
- package/skills/hardening-ai-systems/SKILL.md +377 -0
- package/skills/hardening-ai-systems/ai-budget-resilience.md +408 -0
- package/skills/hardening-ai-systems/ai-guardrails-memory.md +370 -0
- package/skills/hardening-ai-systems/ai-security.md +400 -0
- package/skills/hardening-ai-systems/api-skeleton.md +5 -0
- package/skills/hardening-ai-systems/examples.md +628 -0
- package/skills/migrating-to-directive/SKILL.md +249 -0
- package/skills/migrating-to-directive/anti-patterns.md +382 -0
- package/skills/migrating-to-directive/api-skeleton.md +5 -0
- package/skills/migrating-to-directive/core-patterns.md +240 -0
- package/skills/migrating-to-directive/examples.md +511 -0
- package/skills/migrating-to-directive/schema-types.md +273 -0
- package/skills/reviewing-directive-code/SKILL.md +232 -0
- package/skills/reviewing-directive-code/anti-patterns.md +382 -0
- package/skills/reviewing-directive-code/api-skeleton.md +5 -0
- package/skills/reviewing-directive-code/core-patterns.md +240 -0
- package/skills/reviewing-directive-code/examples.md +463 -0
- package/skills/reviewing-directive-code/naming.md +321 -0
- package/skills/scaffolding-directive-modules/SKILL.md +218 -0
- package/skills/scaffolding-directive-modules/api-skeleton.md +5 -0
- package/skills/scaffolding-directive-modules/core-patterns.md +240 -0
- package/skills/scaffolding-directive-modules/examples.md +1386 -0
- package/skills/scaffolding-directive-modules/naming.md +321 -0
- package/skills/scaffolding-directive-modules/schema-types.md +273 -0
- package/skills/testing-ai-systems/SKILL.md +398 -0
- package/skills/testing-ai-systems/ai-debug-observability.md +329 -0
- package/skills/testing-ai-systems/ai-mcp-rag.md +293 -0
- package/skills/testing-ai-systems/ai-testing-evals.md +485 -0
- package/skills/testing-ai-systems/api-skeleton.md +5 -0
- package/skills/testing-ai-systems/examples.md +1261 -0
- package/skills/testing-directive-code/SKILL.md +479 -0
- package/skills/testing-directive-code/api-skeleton.md +5 -0
- package/skills/testing-directive-code/examples.md +156 -0
- package/skills/testing-directive-code/history.md +351 -0
- package/skills/testing-directive-code/testing.md +412 -0
- package/skills/writing-directive-constraints/SKILL.md +486 -0
- package/skills/writing-directive-constraints/api-skeleton.md +5 -0
- package/skills/writing-directive-constraints/constraints.md +274 -0
- package/skills/writing-directive-constraints/error-boundaries.md +330 -0
- package/skills/writing-directive-constraints/examples.md +1361 -0
- package/skills/writing-directive-constraints/resolvers.md +367 -0
- package/skills/writing-directive-modules/SKILL.md +342 -0
- package/skills/writing-directive-modules/anti-patterns.md +382 -0
- package/skills/writing-directive-modules/api-skeleton.md +5 -0
- package/skills/writing-directive-modules/core-patterns.md +240 -0
- package/skills/writing-directive-modules/examples.md +1639 -0
- package/skills/writing-directive-modules/naming.md +321 -0
- package/skills/writing-directive-modules/schema-types.md +273 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: building-ai-orchestrators
|
|
3
|
+
description: "Create AI orchestration systems using createAgentOrchestrator (single agent) and createMultiAgentOrchestrator (multi-agent). Define factsSchema with t.*() builders, init state, constraints for trigger conditions, and resolvers for LLM execution. Use when building LLM-powered workflows, agent pipelines, task runners, or multi-agent coordination systems."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Building AI Orchestrators
|
|
7
|
+
|
|
8
|
+
## Prerequisites
|
|
9
|
+
|
|
10
|
+
This skill applies when the project uses `@directive-run/ai`. If not found in `package.json`, suggest installing it: `npm install @directive-run/ai`.
|
|
11
|
+
|
|
12
|
+
## When Claude Should Use This Skill
|
|
13
|
+
|
|
14
|
+
## Auto-Invoke Triggers
|
|
15
|
+
- User asks to "build an AI agent", "create an orchestrator", "set up an LLM workflow"
|
|
16
|
+
- User wants agents to coordinate, handoff, or collaborate
|
|
17
|
+
- User needs structured AI task execution with constraints and state
|
|
18
|
+
- User mentions `createAgentOrchestrator` or `createMultiAgentOrchestrator`
|
|
19
|
+
- User asks about `orchestrator.run()` or `orchestrator.runStream()`
|
|
20
|
+
|
|
21
|
+
## Exclusions
|
|
22
|
+
- Do NOT invoke for general Directive (non-AI) patterns – use core Directive docs instead
|
|
23
|
+
- Do NOT invoke for testing orchestrators – use `testing-ai-systems` skill
|
|
24
|
+
- Do NOT invoke for guardrails, budgets, or security – use `hardening-ai-systems` skill
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick Reference
|
|
29
|
+
|
|
30
|
+
## Decision Tree: Which Orchestrator?
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
Need AI orchestration?
|
|
34
|
+
├── Single agent doing one job → createAgentOrchestrator
|
|
35
|
+
│ ├── Simple: runner + factsSchema + init + resolvers
|
|
36
|
+
│ └── Complex: add constraints, retry, plugins
|
|
37
|
+
└── Multiple agents coordinating → createMultiAgentOrchestrator
|
|
38
|
+
├── Agents run in sequence → default sequential
|
|
39
|
+
├── Agents run in parallel → parallel: true on agents
|
|
40
|
+
└── Dynamic routing → coordinator constraints
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## createAgentOrchestrator – Core Pattern
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { createAgentOrchestrator } from "@directive-run/ai";
|
|
47
|
+
import { createAnthropicRunner } from "@directive-run/ai/anthropic";
|
|
48
|
+
import { t } from "@directive-run/core";
|
|
49
|
+
|
|
50
|
+
const orchestrator = createAgentOrchestrator({
|
|
51
|
+
runner: createAnthropicRunner({
|
|
52
|
+
model: "claude-opus-4-6",
|
|
53
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
54
|
+
}),
|
|
55
|
+
|
|
56
|
+
// ALWAYS use t.*() builders – never TypeScript type annotations
|
|
57
|
+
factsSchema: {
|
|
58
|
+
input: t.string(),
|
|
59
|
+
output: t.string().optional(),
|
|
60
|
+
status: t.string<"idle" | "running" | "done" | "error">(),
|
|
61
|
+
attempt: t.number(),
|
|
62
|
+
error: t.string().optional(),
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
// init() is required – sets starting state
|
|
66
|
+
init: (facts) => {
|
|
67
|
+
facts.status = "idle";
|
|
68
|
+
facts.attempt = 0;
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
constraints: {
|
|
72
|
+
startProcessing: {
|
|
73
|
+
when: (facts) => facts.status === "idle" && facts.input.length > 0,
|
|
74
|
+
require: { type: "PROCESS_INPUT" },
|
|
75
|
+
},
|
|
76
|
+
retryOnError: {
|
|
77
|
+
priority: 10,
|
|
78
|
+
when: (facts) => facts.status === "error" && facts.attempt < 3,
|
|
79
|
+
require: { type: "PROCESS_INPUT" },
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
resolvers: {
|
|
84
|
+
processInput: {
|
|
85
|
+
requirement: "PROCESS_INPUT",
|
|
86
|
+
resolve: async (req, context) => {
|
|
87
|
+
context.facts.status = "running";
|
|
88
|
+
context.facts.attempt += 1;
|
|
89
|
+
|
|
90
|
+
const result = await context.runner.run({
|
|
91
|
+
prompt: context.facts.input,
|
|
92
|
+
system: "You are a helpful assistant.",
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
context.facts.output = result.text;
|
|
96
|
+
context.facts.status = "done";
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Execute
|
|
103
|
+
const result = await orchestrator.run({ input: "Summarize this text..." });
|
|
104
|
+
console.log(result.facts.output);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## createMultiAgentOrchestrator – Core Pattern
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { createMultiAgentOrchestrator } from "@directive-run/ai";
|
|
111
|
+
import { createAnthropicRunner } from "@directive-run/ai/anthropic";
|
|
112
|
+
import { t } from "@directive-run/core";
|
|
113
|
+
|
|
114
|
+
const orchestrator = createMultiAgentOrchestrator({
|
|
115
|
+
// Coordinator defines shared state across all agents
|
|
116
|
+
coordinator: {
|
|
117
|
+
factsSchema: {
|
|
118
|
+
topic: t.string(),
|
|
119
|
+
phase: t.string<"research" | "draft" | "review" | "done">(),
|
|
120
|
+
researchNotes: t.string().optional(),
|
|
121
|
+
draft: t.string().optional(),
|
|
122
|
+
finalOutput: t.string().optional(),
|
|
123
|
+
},
|
|
124
|
+
init: (facts) => {
|
|
125
|
+
facts.phase = "research";
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
agents: {
|
|
130
|
+
researcher: {
|
|
131
|
+
runner: createAnthropicRunner({ model: "claude-haiku-4-5" }),
|
|
132
|
+
// Per-agent schema – merged with coordinator facts
|
|
133
|
+
factsSchema: {
|
|
134
|
+
searchDepth: t.number(),
|
|
135
|
+
},
|
|
136
|
+
init: (facts) => {
|
|
137
|
+
facts.searchDepth = 3;
|
|
138
|
+
},
|
|
139
|
+
constraints: {
|
|
140
|
+
doResearch: {
|
|
141
|
+
when: (facts) => facts.phase === "research",
|
|
142
|
+
require: { type: "RESEARCH" },
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
resolvers: {
|
|
146
|
+
research: {
|
|
147
|
+
requirement: "RESEARCH",
|
|
148
|
+
resolve: async (req, context) => {
|
|
149
|
+
const result = await context.runner.run({
|
|
150
|
+
prompt: `Research this topic: ${context.facts.topic}`,
|
|
151
|
+
});
|
|
152
|
+
context.facts.researchNotes = result.text;
|
|
153
|
+
context.facts.phase = "draft";
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
writer: {
|
|
160
|
+
runner: createAnthropicRunner({ model: "claude-opus-4-6" }),
|
|
161
|
+
factsSchema: {
|
|
162
|
+
style: t.string(),
|
|
163
|
+
},
|
|
164
|
+
init: (facts) => {
|
|
165
|
+
facts.style = "professional";
|
|
166
|
+
},
|
|
167
|
+
constraints: {
|
|
168
|
+
writeDraft: {
|
|
169
|
+
when: (facts) => facts.phase === "draft" && !!facts.researchNotes,
|
|
170
|
+
require: { type: "WRITE" },
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
resolvers: {
|
|
174
|
+
write: {
|
|
175
|
+
requirement: "WRITE",
|
|
176
|
+
resolve: async (req, context) => {
|
|
177
|
+
const result = await context.runner.run({
|
|
178
|
+
prompt: `Write a ${context.facts.style} article based on: ${context.facts.researchNotes}`,
|
|
179
|
+
});
|
|
180
|
+
context.facts.draft = result.text;
|
|
181
|
+
context.facts.phase = "done";
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const result = await orchestrator.run({ topic: "Quantum computing" });
|
|
190
|
+
console.log(result.facts.finalOutput);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Streaming Execution
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// runStream() returns AsyncIterable<OrchestratorEvent>
|
|
197
|
+
const stream = orchestrator.runStream({ input: "Analyze this..." });
|
|
198
|
+
|
|
199
|
+
for await (const event of stream) {
|
|
200
|
+
switch (event.type) {
|
|
201
|
+
case "token": {
|
|
202
|
+
process.stdout.write(event.text);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case "requirement_met": {
|
|
206
|
+
console.log(`Resolved: ${event.requirementType}`);
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case "done": {
|
|
210
|
+
console.log("Final:", event.facts);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case "error": {
|
|
214
|
+
console.error("Failed:", event.error);
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## createTask – Structured Work Units
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { createTask } from "@directive-run/ai";
|
|
225
|
+
|
|
226
|
+
const summarizeTask = createTask({
|
|
227
|
+
name: "summarize",
|
|
228
|
+
description: "Summarize text to a target length",
|
|
229
|
+
input: {
|
|
230
|
+
text: t.string(),
|
|
231
|
+
maxWords: t.number(),
|
|
232
|
+
},
|
|
233
|
+
output: {
|
|
234
|
+
summary: t.string(),
|
|
235
|
+
wordCount: t.number(),
|
|
236
|
+
},
|
|
237
|
+
// Tasks integrate into orchestrator resolvers
|
|
238
|
+
resolve: async (input, context) => {
|
|
239
|
+
const result = await context.runner.run({
|
|
240
|
+
prompt: `Summarize in ${input.maxWords} words: ${input.text}`,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
summary: result.text,
|
|
245
|
+
wordCount: result.text.split(" ").length,
|
|
246
|
+
};
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Use task inside a resolver
|
|
251
|
+
resolvers: {
|
|
252
|
+
summarize: {
|
|
253
|
+
requirement: "SUMMARIZE",
|
|
254
|
+
resolve: async (req, context) => {
|
|
255
|
+
const output = await summarizeTask.run(
|
|
256
|
+
{ text: context.facts.input, maxWords: 100 },
|
|
257
|
+
context
|
|
258
|
+
);
|
|
259
|
+
context.facts.summary = output.summary;
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Resolver Context API
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
resolve: async (req, context) => {
|
|
269
|
+
context.facts // Read/write orchestrator facts
|
|
270
|
+
context.runner // Execute LLM calls
|
|
271
|
+
context.signal // AbortSignal for cancellation
|
|
272
|
+
context.emit(event) // Emit custom events to stream
|
|
273
|
+
context.plugins // Access plugin instances
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## factsSchema Type Builders Reference
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
// Primitives
|
|
281
|
+
t.string() // string
|
|
282
|
+
t.number() // number
|
|
283
|
+
t.boolean() // boolean
|
|
284
|
+
|
|
285
|
+
// Optional / nullable
|
|
286
|
+
t.string().optional() // string | undefined
|
|
287
|
+
t.string().nullable() // string | null
|
|
288
|
+
|
|
289
|
+
// Union literal types
|
|
290
|
+
t.string<"idle" | "running">() // typed string union
|
|
291
|
+
t.number<1 | 2 | 3>() // typed number union
|
|
292
|
+
|
|
293
|
+
// Objects and arrays
|
|
294
|
+
t.object<MyInterface>() // typed object
|
|
295
|
+
t.array(t.string()) // string[]
|
|
296
|
+
t.array(t.object<Item>()) // Item[]
|
|
297
|
+
|
|
298
|
+
// Record / map
|
|
299
|
+
t.record(t.string(), t.number()) // Record<string, number>
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Common Constraint Patterns
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
constraints: {
|
|
306
|
+
// Trigger on status transition
|
|
307
|
+
onIdle: {
|
|
308
|
+
when: (facts) => facts.status === "idle" && !!facts.input,
|
|
309
|
+
require: { type: "START" },
|
|
310
|
+
},
|
|
311
|
+
|
|
312
|
+
// Priority for conflict resolution (higher = wins)
|
|
313
|
+
emergency: {
|
|
314
|
+
priority: 100,
|
|
315
|
+
when: (facts) => facts.errorCount > 5,
|
|
316
|
+
require: { type: "ABORT" },
|
|
317
|
+
},
|
|
318
|
+
|
|
319
|
+
// Pass data in requirement
|
|
320
|
+
withPayload: {
|
|
321
|
+
when: (facts) => facts.ready,
|
|
322
|
+
require: (facts) => ({ type: "PROCESS", model: facts.preferredModel }),
|
|
323
|
+
},
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Critical Anti-Patterns
|
|
330
|
+
|
|
331
|
+
## Using TypeScript types instead of t.*() in factsSchema
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
// WRONG – TypeScript type annotations, not schema builders
|
|
335
|
+
factsSchema: {
|
|
336
|
+
status: "idle" | "running" | "done", // type annotation, not runtime schema
|
|
337
|
+
count: number,
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// CORRECT – t.*() builders provide runtime validation + TypeScript inference
|
|
341
|
+
factsSchema: {
|
|
342
|
+
status: t.string<"idle" | "running" | "done">(),
|
|
343
|
+
count: t.number(),
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Forgetting init()
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
// WRONG – facts start undefined, constraints fail immediately
|
|
351
|
+
const orchestrator = createAgentOrchestrator({
|
|
352
|
+
factsSchema: { status: t.string() },
|
|
353
|
+
// missing init: facts.status is undefined
|
|
354
|
+
constraints: {
|
|
355
|
+
start: { when: (facts) => facts.status === "idle", ... },
|
|
356
|
+
},
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
// CORRECT
|
|
360
|
+
init: (facts) => {
|
|
361
|
+
facts.status = "idle";
|
|
362
|
+
},
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Resolver parameter naming
|
|
366
|
+
Always use `(req, context)` – never `(req, ctx)` or `(request, context)`.
|
|
367
|
+
|
|
368
|
+
## Single-line returns without braces
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
// WRONG
|
|
372
|
+
when: (facts) => facts.status === "idle" ? true : false,
|
|
373
|
+
|
|
374
|
+
// CORRECT – always use multi-line blocks when branching
|
|
375
|
+
when: (facts) => {
|
|
376
|
+
return facts.status === "idle";
|
|
377
|
+
},
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Mutating facts outside resolvers
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
// WRONG – direct mutation bypasses reactivity
|
|
384
|
+
orchestrator.facts.status = "done";
|
|
385
|
+
|
|
386
|
+
// CORRECT – always via context.facts inside resolvers
|
|
387
|
+
resolve: async (req, context) => {
|
|
388
|
+
context.facts.status = "done";
|
|
389
|
+
},
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## Reference Files
|
|
395
|
+
|
|
396
|
+
- `ai-orchestrator.md` – Full createAgentOrchestrator API, options, lifecycle
|
|
397
|
+
- `ai-multi-agent.md` – createMultiAgentOrchestrator, coordinator pattern, agent communication
|
|
398
|
+
- `ai-tasks.md` – createTask API, task composition, input/output validation
|
|
399
|
+
- `examples/ai-orchestrator.ts` – Complete single-agent example
|
|
400
|
+
- `examples/ai-checkpoint.ts` – Checkpoint/resume pattern
|
|
401
|
+
- `examples/fraud-analysis.ts` – Multi-agent fraud detection example
|