@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.
Files changed (83) hide show
  1. package/.claude-plugin/plugin.json +6 -0
  2. package/LICENSE +26 -0
  3. package/README.md +113 -0
  4. package/dist/index.cjs +2 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.cts +66 -0
  7. package/dist/index.d.ts +66 -0
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.map +1 -0
  10. package/package.json +64 -0
  11. package/skills/README.md +9 -0
  12. package/skills/building-ai-agents/SKILL.md +414 -0
  13. package/skills/building-ai-agents/ai-adapters.md +257 -0
  14. package/skills/building-ai-agents/ai-agents-streaming.md +307 -0
  15. package/skills/building-ai-agents/ai-communication.md +304 -0
  16. package/skills/building-ai-agents/api-skeleton.md +5 -0
  17. package/skills/building-ai-agents/examples.md +849 -0
  18. package/skills/building-ai-orchestrators/SKILL.md +401 -0
  19. package/skills/building-ai-orchestrators/ai-multi-agent.md +375 -0
  20. package/skills/building-ai-orchestrators/ai-orchestrator.md +466 -0
  21. package/skills/building-ai-orchestrators/ai-tasks.md +268 -0
  22. package/skills/building-ai-orchestrators/api-skeleton.md +5 -0
  23. package/skills/building-ai-orchestrators/examples.md +1609 -0
  24. package/skills/building-directive-systems/SKILL.md +499 -0
  25. package/skills/building-directive-systems/api-skeleton.md +5 -0
  26. package/skills/building-directive-systems/examples.md +4149 -0
  27. package/skills/building-directive-systems/multi-module.md +327 -0
  28. package/skills/building-directive-systems/plugins.md +361 -0
  29. package/skills/building-directive-systems/react-adapter.md +376 -0
  30. package/skills/building-directive-systems/system-api.md +463 -0
  31. package/skills/getting-started-with-directive/SKILL.md +198 -0
  32. package/skills/getting-started-with-directive/api-skeleton.md +5 -0
  33. package/skills/getting-started-with-directive/core-patterns.md +240 -0
  34. package/skills/getting-started-with-directive/examples.md +87 -0
  35. package/skills/getting-started-with-directive/sitemap.md +202 -0
  36. package/skills/hardening-ai-systems/SKILL.md +377 -0
  37. package/skills/hardening-ai-systems/ai-budget-resilience.md +408 -0
  38. package/skills/hardening-ai-systems/ai-guardrails-memory.md +370 -0
  39. package/skills/hardening-ai-systems/ai-security.md +400 -0
  40. package/skills/hardening-ai-systems/api-skeleton.md +5 -0
  41. package/skills/hardening-ai-systems/examples.md +628 -0
  42. package/skills/migrating-to-directive/SKILL.md +249 -0
  43. package/skills/migrating-to-directive/anti-patterns.md +382 -0
  44. package/skills/migrating-to-directive/api-skeleton.md +5 -0
  45. package/skills/migrating-to-directive/core-patterns.md +240 -0
  46. package/skills/migrating-to-directive/examples.md +511 -0
  47. package/skills/migrating-to-directive/schema-types.md +273 -0
  48. package/skills/reviewing-directive-code/SKILL.md +232 -0
  49. package/skills/reviewing-directive-code/anti-patterns.md +382 -0
  50. package/skills/reviewing-directive-code/api-skeleton.md +5 -0
  51. package/skills/reviewing-directive-code/core-patterns.md +240 -0
  52. package/skills/reviewing-directive-code/examples.md +463 -0
  53. package/skills/reviewing-directive-code/naming.md +321 -0
  54. package/skills/scaffolding-directive-modules/SKILL.md +218 -0
  55. package/skills/scaffolding-directive-modules/api-skeleton.md +5 -0
  56. package/skills/scaffolding-directive-modules/core-patterns.md +240 -0
  57. package/skills/scaffolding-directive-modules/examples.md +1386 -0
  58. package/skills/scaffolding-directive-modules/naming.md +321 -0
  59. package/skills/scaffolding-directive-modules/schema-types.md +273 -0
  60. package/skills/testing-ai-systems/SKILL.md +398 -0
  61. package/skills/testing-ai-systems/ai-debug-observability.md +329 -0
  62. package/skills/testing-ai-systems/ai-mcp-rag.md +293 -0
  63. package/skills/testing-ai-systems/ai-testing-evals.md +485 -0
  64. package/skills/testing-ai-systems/api-skeleton.md +5 -0
  65. package/skills/testing-ai-systems/examples.md +1261 -0
  66. package/skills/testing-directive-code/SKILL.md +479 -0
  67. package/skills/testing-directive-code/api-skeleton.md +5 -0
  68. package/skills/testing-directive-code/examples.md +156 -0
  69. package/skills/testing-directive-code/history.md +351 -0
  70. package/skills/testing-directive-code/testing.md +412 -0
  71. package/skills/writing-directive-constraints/SKILL.md +486 -0
  72. package/skills/writing-directive-constraints/api-skeleton.md +5 -0
  73. package/skills/writing-directive-constraints/constraints.md +274 -0
  74. package/skills/writing-directive-constraints/error-boundaries.md +330 -0
  75. package/skills/writing-directive-constraints/examples.md +1361 -0
  76. package/skills/writing-directive-constraints/resolvers.md +367 -0
  77. package/skills/writing-directive-modules/SKILL.md +342 -0
  78. package/skills/writing-directive-modules/anti-patterns.md +382 -0
  79. package/skills/writing-directive-modules/api-skeleton.md +5 -0
  80. package/skills/writing-directive-modules/core-patterns.md +240 -0
  81. package/skills/writing-directive-modules/examples.md +1639 -0
  82. package/skills/writing-directive-modules/naming.md +321 -0
  83. package/skills/writing-directive-modules/schema-types.md +273 -0
@@ -0,0 +1,375 @@
1
+ # AI multi-agent orchestrator
2
+
3
+ > Covers `@directive-run/ai/multi-agent` — `createMultiAgentOrchestrator` + 8 composition patterns (parallel / sequential / supervisor / dag / reflect / race / debate / goal).
4
+
5
+ `createMultiAgentOrchestrator` coordinates multiple agents using 8 composition patterns. Each agent becomes a namespaced Directive module with a shared coordinator. Patterns are pure config objects you assemble with factory functions and pass via the `patterns:` option.
6
+
7
+ For a single agent, see `ai-orchestrator.md`.
8
+
9
+ ## Decision tree
10
+
11
+ ```
12
+ How should agents interact?
13
+ ├── Independent, combine results → parallel()
14
+ ├── One feeds the next → sequential()
15
+ ├── One agent delegates work → supervisor()
16
+ ├── Complex dependency graph → dag()
17
+ ├── Producer + evaluator loop → reflect()
18
+ ├── First to finish wins → race()
19
+ ├── Multiple positions debated → debate()
20
+ └── Iterate until goal met → goal()
21
+ ```
22
+
23
+ ## Basic setup
24
+
25
+ Import from the subpath barrel — the main `@directive-run/ai` barrel re-exports these with `@deprecated` notices for v2 removal.
26
+
27
+ ```typescript
28
+ import {
29
+ createMultiAgentOrchestrator,
30
+ parallel,
31
+ sequential,
32
+ supervisor,
33
+ dag,
34
+ reflect,
35
+ race,
36
+ debate,
37
+ goal,
38
+ } from "@directive-run/ai/multi-agent";
39
+ import { createAnthropicRunner } from "@directive-run/ai/anthropic";
40
+
41
+ const runner = createAnthropicRunner({
42
+ apiKey: process.env.ANTHROPIC_API_KEY!,
43
+ });
44
+
45
+ const orchestrator = createMultiAgentOrchestrator({
46
+ agents: {
47
+ researcher: { name: "researcher", instructions: "Research the topic thoroughly.", model: "claude-sonnet-4-5" },
48
+ writer: { name: "writer", instructions: "Write clear, engaging content.", model: "claude-sonnet-4-5" },
49
+ editor: { name: "editor", instructions: "Edit for clarity and correctness.", model: "claude-haiku-4-5" },
50
+ },
51
+ patterns: {
52
+ pipeline: sequential(["researcher", "writer", "editor"]),
53
+ brainstorm: parallel(["researcher", "writer"], (results) => results.map((r) => String(r.output)).join("\n\n")),
54
+ managed: supervisor("editor", ["researcher", "writer"]),
55
+ workflow: dag({
56
+ research: { handler: "researcher" },
57
+ write: { handler: "writer", deps: ["research"] },
58
+ edit: { handler: "editor", deps: ["write"] },
59
+ }),
60
+ },
61
+ runner,
62
+ });
63
+
64
+ // REQUIRED — call start() before runPattern. Single-agent createAgentOrchestrator does NOT need this.
65
+ orchestrator.start();
66
+
67
+ const result = await orchestrator.runPattern("pipeline", "Write about AI");
68
+ ```
69
+
70
+ ## Patterns in depth
71
+
72
+ ### `parallel(handlers, merge, options?)`
73
+
74
+ Runs handlers concurrently and combines their results. **`merge` is REQUIRED as positional argument 2** — without it the call fails at registration. `options?` accepts `minSuccess` and `timeout`.
75
+
76
+ ```typescript
77
+ const brainstorm = parallel(
78
+ ["researcher", "writer"],
79
+ (results) => results.map((r) => String(r.output)).join("\n\n"),
80
+ { minSuccess: 1, timeout: 30_000 },
81
+ );
82
+ ```
83
+
84
+ The `results` arg is `RunResult<unknown>[]` — array, in handler order.
85
+
86
+ ### `sequential(handlers, options?)`
87
+
88
+ Each handler's output feeds as input to the next. `options.transform(output, handlerId, index)` adapts the hand-off; `options.extract(finalOutput)` shapes the return.
89
+
90
+ ```typescript
91
+ const pipeline = sequential(["researcher", "writer", "editor"]);
92
+
93
+ const writeReview = sequential(["writer", "reviewer"], {
94
+ transform: (output) => `Review this draft:\n${output}`,
95
+ });
96
+ ```
97
+
98
+ ### `supervisor(supervisorAgent, workers, options?)`
99
+
100
+ The supervisor runs first and delegates to workers based on its output. Repeats up to `maxRounds` until the supervisor signals completion.
101
+
102
+ ```typescript
103
+ const managed = supervisor("manager", ["worker1", "worker2"], { maxRounds: 3 });
104
+ ```
105
+
106
+ ### `dag(nodes, merge?, options?)`
107
+
108
+ **Nodes are a `Record<string, DagNode>`, NOT an array.** Each node's edges are listed in `deps` (not `dependencies`). The runtime validates the graph is acyclic and that all `deps` refer to declared nodes.
109
+
110
+ ```typescript
111
+ import type { DagNode, DagExecutionContext } from "@directive-run/ai/multi-agent";
112
+
113
+ const workflow = dag(
114
+ {
115
+ research: { handler: "researcher" },
116
+ analyze: { handler: "analyzer", deps: ["research"] },
117
+ summarize: { handler: "summarizer", deps: ["analyze"] },
118
+ },
119
+ // optional merge — receives the execution context with .outputs Record
120
+ (context: DagExecutionContext) => context.outputs.summarize,
121
+ // optional config
122
+ {
123
+ timeout: 60_000,
124
+ maxConcurrent: 4,
125
+ onNodeError: "skip-downstream", // "fail" (default) | "skip-downstream" | "continue"
126
+ },
127
+ );
128
+ ```
129
+
130
+ ### `reflect(handler, evaluator, options?)`
131
+
132
+ Producer + evaluator loop. The producer generates output, the evaluator scores it; if the score is below `threshold` the producer retries with feedback, up to `maxIterations`. **`evaluator` is REQUIRED as positional argument 2.**
133
+
134
+ ```typescript
135
+ const selfImprove = reflect("writer", "reviewer", {
136
+ maxIterations: 3,
137
+ threshold: 0.8,
138
+ onExhausted: "accept-best", // "accept-last" | "accept-best" | "throw"
139
+ onIteration: (record) => console.log(`iter ${record.iteration}: ${record.score}`),
140
+ });
141
+ ```
142
+
143
+ ### `race(handlers, options?)`
144
+
145
+ All handlers start simultaneously; the first to complete successfully wins. Use `minSuccess` to wait for N before picking.
146
+
147
+ ```typescript
148
+ const fastest = race(["fast-model", "smart-model"], {
149
+ timeout: 5000,
150
+ minSuccess: 1, // must be ≤ handlers.length
151
+ });
152
+ ```
153
+
154
+ ### `debate(config)`
155
+
156
+ **Takes a single `DebateConfig` object.** The discriminator agents argue from different positions; the `evaluator` agent judges. There is no `judge` field — it's `evaluator`.
157
+
158
+ ```typescript
159
+ const consensus = debate({
160
+ handlers: ["optimist", "pessimist"],
161
+ evaluator: "judge",
162
+ maxRounds: 2,
163
+ });
164
+ ```
165
+
166
+ ### `goal(nodes, when, options?)`
167
+
168
+ Goal-driven execution. Each node declares what it `produces` and `requires`; the runtime infers the execution graph and runs agents until `when(facts)` returns true. There is no single-agent string form.
169
+
170
+ ```typescript
171
+ import type { GoalNode } from "@directive-run/ai/multi-agent";
172
+
173
+ const pipeline = goal(
174
+ {
175
+ researcher: {
176
+ handler: "researcher",
177
+ produces: ["research.findings"],
178
+ requires: ["research.topic"],
179
+ extractOutput: (r) => ({ "research.findings": r.output }),
180
+ },
181
+ writer: {
182
+ handler: "writer",
183
+ produces: ["article.draft"],
184
+ requires: ["research.findings"],
185
+ extractOutput: (r) => ({ "article.draft": r.output }),
186
+ },
187
+ },
188
+ (facts) => facts["article.draft"] != null,
189
+ {
190
+ maxSteps: 10,
191
+ extract: (facts) => facts["article.draft"],
192
+ satisfaction: (facts) => (facts["article.draft"] ? 1.0 : 0.0),
193
+ },
194
+ );
195
+ ```
196
+
197
+ ## Fact propagation
198
+
199
+ Each agent has its own namespaced facts module. A coordinator module (`__coord`) tracks shared orchestration state.
200
+
201
+ ```typescript
202
+ // Per-agent state — module is named after the agent's key in `agents:`
203
+ orchestrator.system.facts.researcher.status;
204
+ orchestrator.system.facts.writer.output;
205
+
206
+ // Coordinator state
207
+ orchestrator.system.facts.__coord.activePattern;
208
+ orchestrator.system.facts.__coord.completedAgents;
209
+ ```
210
+
211
+ ## Checkpoints
212
+
213
+ Multi-agent uses the same checkpoint shape as single-agent. **`checkpoint()` is async** — returns a `Promise<Checkpoint>`. Restore on an existing instance via `orch.restore(cp)`. There is no `createMultiAgentOrchestrator({ checkpoint })` constructor option.
214
+
215
+ ```typescript
216
+ const cp = await orchestrator.checkpoint({ label: "after-pipeline" });
217
+ const serialized = JSON.stringify(cp);
218
+
219
+ // On a fresh orchestrator with the same agents/patterns/runner:
220
+ const restored = createMultiAgentOrchestrator({ agents, patterns, runner });
221
+ restored.restore(JSON.parse(serialized));
222
+ restored.start();
223
+ ```
224
+
225
+ ## Tasks alongside agents
226
+
227
+ Tasks (registered via `tasks:`) share the handler namespace with agents — a `dag` or `sequential` can refer to either by ID. See `ai-tasks.md` for the full task surface.
228
+
229
+ ```typescript
230
+ const workflow = dag({
231
+ research: { handler: "researcher" },
232
+ format: { handler: "formatter-task" }, // a task, not an agent
233
+ edit: { handler: "editor", deps: ["research", "format"] },
234
+ });
235
+ ```
236
+
237
+ ## Anti-patterns
238
+
239
+ ### Forgetting `start()` on multi-agent
240
+
241
+ ```typescript
242
+ // WRONG — multi-agent orchestrators require explicit start()
243
+ const orch = createMultiAgentOrchestrator({ agents, patterns, runner });
244
+ await orch.runPattern("pipeline", "prompt"); // throws — not started
245
+
246
+ // CORRECT
247
+ const orch = createMultiAgentOrchestrator({ agents, patterns, runner });
248
+ orch.start();
249
+ await orch.runPattern("pipeline", "prompt");
250
+ ```
251
+
252
+ Single-agent `createAgentOrchestrator` does NOT require `start()`. Only multi-agent does.
253
+
254
+ ### Array-form `dag` and `dependencies` key
255
+
256
+ ```typescript
257
+ // WRONG — dag takes Record<string, DagNode>, not an array; and the edge key is `deps`
258
+ dag([
259
+ { id: "research", handler: "researcher" },
260
+ { id: "write", handler: "writer", dependencies: ["research"] },
261
+ ])
262
+
263
+ // CORRECT
264
+ dag({
265
+ research: { handler: "researcher" },
266
+ write: { handler: "writer", deps: ["research"] },
267
+ })
268
+ ```
269
+
270
+ ### `parallel` without the merge arg
271
+
272
+ ```typescript
273
+ // WRONG — merge is a REQUIRED positional argument, not in options
274
+ parallel(["researcher", "writer"], { minSuccess: 1 })
275
+
276
+ // CORRECT — merge first, options second
277
+ parallel(
278
+ ["researcher", "writer"],
279
+ (results) => results.map((r) => String(r.output)).join("\n"),
280
+ { minSuccess: 1 },
281
+ )
282
+ ```
283
+
284
+ ### `reflect` with a single agent
285
+
286
+ ```typescript
287
+ // WRONG — reflect needs a SEPARATE evaluator handler; stopWhen is not an option
288
+ reflect("writer", { maxIterations: 3, stopWhen: (out) => out.includes("FINAL") })
289
+
290
+ // CORRECT — handler + evaluator + threshold (the evaluator decides when to stop)
291
+ reflect("writer", "reviewer", { maxIterations: 3, threshold: 0.8 })
292
+ ```
293
+
294
+ ### `debate` with `judge:` option
295
+
296
+ ```typescript
297
+ // WRONG — debate uses `evaluator`, not `judge`; and it's a single config arg
298
+ debate(["researcher", "writer"], { maxRounds: 5, judge: "editor" })
299
+
300
+ // CORRECT — single config object, evaluator key
301
+ debate({ handlers: ["researcher", "writer"], evaluator: "editor", maxRounds: 5 })
302
+ ```
303
+
304
+ ### `goal` with a single agent string
305
+
306
+ ```typescript
307
+ // WRONG — goal does not take a single agent + goalCheck; it takes a node map + when()
308
+ goal("researcher", { maxIterations: 10, goalCheck: (out, facts) => facts.confidence > 0.9 })
309
+
310
+ // CORRECT — declarative node map + a when() predicate
311
+ goal(
312
+ {
313
+ researcher: {
314
+ handler: "researcher",
315
+ produces: ["confidence"],
316
+ requires: ["topic"],
317
+ extractOutput: (r) => ({ confidence: (r.output as { confidence: number }).confidence }),
318
+ },
319
+ },
320
+ (facts) => (facts.confidence as number) > 0.9,
321
+ { maxSteps: 10 },
322
+ )
323
+ ```
324
+
325
+ ### Handler IDs that don't match `agents:` keys
326
+
327
+ ```typescript
328
+ // WRONG — handler refs must match the keys in agents/tasks
329
+ createMultiAgentOrchestrator({
330
+ agents: { researcher: {...}, writer: {...} },
331
+ patterns: { pipeline: sequential(["research-agent", "write-agent"]) }, // wrong names
332
+ });
333
+
334
+ // CORRECT
335
+ patterns: { pipeline: sequential(["researcher", "writer"]) }
336
+ ```
337
+
338
+ ### `race` with `minSuccess` greater than the handler count
339
+
340
+ ```typescript
341
+ // WRONG — minSuccess can never exceed handlers.length
342
+ race(["researcher", "writer"], { minSuccess: 3 }) // 2 handlers, impossible
343
+ ```
344
+
345
+ ### Restoring via a constructor option
346
+
347
+ ```typescript
348
+ // WRONG — there is no `checkpoint` option on createMultiAgentOrchestrator
349
+ createMultiAgentOrchestrator({ agents, patterns, runner, checkpoint: cp })
350
+
351
+ // CORRECT — restore on an existing instance, then start()
352
+ const orch = createMultiAgentOrchestrator({ agents, patterns, runner });
353
+ orch.restore(cp);
354
+ orch.start();
355
+ ```
356
+
357
+ ## Quick reference
358
+
359
+ | Pattern | Signature | Required arg 2 |
360
+ |---|---|---|
361
+ | `parallel(handlers, merge, options?)` | `string[], (results) => T, { minSuccess?, timeout? }` | merge |
362
+ | `sequential(handlers, options?)` | `string[], { transform?, extract?, continueOnError? }` | — |
363
+ | `supervisor(supervisorAgent, workers, options?)` | `string, string[], { maxRounds?, extract? }` | workers |
364
+ | `dag(nodes, merge?, options?)` | `Record<string, DagNode>, (ctx) => T, { timeout?, maxConcurrent?, onNodeError? }` | — |
365
+ | `reflect(handler, evaluator, options?)` | `string, string, { maxIterations?, threshold?, onExhausted?, onIteration? }` | evaluator |
366
+ | `race(handlers, options?)` | `string[], { timeout?, minSuccess?, extract? }` | — |
367
+ | `debate(config)` | `{ handlers, evaluator, maxRounds?, extract?, parseJudgement? }` | — (single arg) |
368
+ | `goal(nodes, when, options?)` | `Record<string, GoalNode>, (facts) => boolean, { maxSteps?, extract?, satisfaction? }` | when |
369
+
370
+ ## See also
371
+
372
+ - [`ai-orchestrator.md`](./ai-orchestrator.md) — the single-agent flavor; covers options and lifecycle this file builds on
373
+ - [`ai-communication.md`](./ai-communication.md) — `createMessageBus` / `createAgentNetwork` for inter-agent messaging within a pattern
374
+ - [`ai-tasks.md`](./ai-tasks.md) — deterministic task handlers that compose with agents inside `dag` / `sequential` patterns
375
+ - [`ai-testing-evals.md`](./ai-testing-evals.md) — `createTestMultiAgentOrchestrator` and pattern-shape assertions