@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,466 @@
|
|
|
1
|
+
# AI Orchestrator (single-agent)
|
|
2
|
+
|
|
3
|
+
> Covers `@directive-run/ai` — `createAgentOrchestrator` for single-agent runs with constraints, resolvers, guardrails, memory, budgets, approval, breakpoints, retry, structured output, circuit breakers, checkpoints.
|
|
4
|
+
|
|
5
|
+
`createAgentOrchestrator` builds a Directive-backed runtime for ONE AI agent with constraints, resolvers, guardrails, memory, budgets, approval, breakpoints, retry, structured output, circuit breakers, checkpoints, and observability hooks.
|
|
6
|
+
|
|
7
|
+
For multiple agents (pipelines, debates, DAGs), see `ai-multi-agent.md`.
|
|
8
|
+
|
|
9
|
+
## Decision tree
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Setting up createAgentOrchestrator…
|
|
13
|
+
├── Custom orchestrator state? → factsSchema with t.*() builders (NOT TS types)
|
|
14
|
+
├── Need input/output guardrails? → guardrails: { input: [...], output: [...] }
|
|
15
|
+
├── Need conversation memory? → memory: createAgentMemory({ strategy })
|
|
16
|
+
├── Need token budget? → maxTokenBudget + onBudgetWarning (TOP-LEVEL — not in hooks)
|
|
17
|
+
├── Need streaming? → orchestrator.runStream(agent, input) returns { stream, result, abort }
|
|
18
|
+
├── Need approval before tool calls? → onApprovalRequest + orchestrator.approve()/reject()
|
|
19
|
+
├── Need human-in-the-loop pauses? → breakpoints: [...] + onBreakpoint callback
|
|
20
|
+
├── Need observability? → hooks.onAgentStart / onAgentComplete / onAgentError / onAgentRetry / onGuardrailCheck
|
|
21
|
+
├── Need automatic retry on failure? → agentRetry: { maxRetries, baseDelayMs }
|
|
22
|
+
├── Need structured output? → outputSchema: zodSchema (with maxSchemaRetries)
|
|
23
|
+
├── Need failure isolation? → circuitBreaker: createCircuitBreaker(...)
|
|
24
|
+
└── Need save/restore? → checkpointStore + orchestrator.checkpoint()/restore()
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Basic setup
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { createAgentOrchestrator } from "@directive-run/ai";
|
|
31
|
+
import { createAnthropicRunner } from "@directive-run/ai/anthropic";
|
|
32
|
+
import { t } from "@directive-run/core";
|
|
33
|
+
|
|
34
|
+
const runner = createAnthropicRunner({
|
|
35
|
+
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const orchestrator = createAgentOrchestrator({
|
|
39
|
+
runner,
|
|
40
|
+
factsSchema: {
|
|
41
|
+
confidence: t.number(),
|
|
42
|
+
analysis: t.string(),
|
|
43
|
+
},
|
|
44
|
+
init: (facts) => {
|
|
45
|
+
facts.confidence = 0;
|
|
46
|
+
facts.analysis = "";
|
|
47
|
+
},
|
|
48
|
+
constraints: {
|
|
49
|
+
lowConfidence: {
|
|
50
|
+
when: (facts) => facts.confidence < 0.5,
|
|
51
|
+
require: { type: "RE_ANALYZE" },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
resolvers: {
|
|
55
|
+
reAnalyze: {
|
|
56
|
+
requirement: (req): req is { type: "RE_ANALYZE" } => req.type === "RE_ANALYZE",
|
|
57
|
+
resolve: async (req, context) => {
|
|
58
|
+
context.facts.confidence = 1;
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const result = await orchestrator.run(
|
|
65
|
+
{ name: "analyst", instructions: "You are a data analyst.", model: "claude-sonnet-4-5" },
|
|
66
|
+
"Analyze this dataset",
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
console.log(result.output, result.tokenUsage);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Running an agent
|
|
73
|
+
|
|
74
|
+
`run(agent, input, options?)` resolves to `RunResult<T>`.
|
|
75
|
+
`runStream(agent, input, options?)` returns `{ stream, result, abort }` — `stream` is the async iterator, `result` is a promise for the final result, `abort` cancels the in-flight run.
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
// Standard run
|
|
79
|
+
const result = await orchestrator.run(agent, "Analyze this dataset");
|
|
80
|
+
console.log(result.output, result.tokenUsage);
|
|
81
|
+
|
|
82
|
+
// Streaming run — destructure the three handles
|
|
83
|
+
const { stream, result, abort } = orchestrator.runStream(agent, "Summarize findings");
|
|
84
|
+
|
|
85
|
+
for await (const chunk of stream) {
|
|
86
|
+
if (chunk.type === "token") {
|
|
87
|
+
process.stdout.write(chunk.data);
|
|
88
|
+
}
|
|
89
|
+
if (chunk.type === "approval_required") {
|
|
90
|
+
// Show your approval UI; resolve with orchestrator.approve(chunk.requestId)
|
|
91
|
+
}
|
|
92
|
+
if (chunk.type === "guardrail_triggered") {
|
|
93
|
+
console.warn("guardrail:", chunk.guardrail);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const final = await result;
|
|
98
|
+
|
|
99
|
+
// Wait for any in-flight resolvers to drain
|
|
100
|
+
await orchestrator.waitForIdle();
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Reading orchestrator state
|
|
104
|
+
|
|
105
|
+
State lives on `orchestrator.facts.agent` — the `AgentState` is nested under `agent` because the orchestrator's facts shape is `OrchestratorState & F` (your custom facts merged with the orchestrator's built-ins).
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// Built-in agent state
|
|
109
|
+
orchestrator.facts.agent.status; // "idle" | "running" | "paused" | "completed" | "error"
|
|
110
|
+
orchestrator.facts.agent.currentAgent; // string | null — the agent name when running
|
|
111
|
+
orchestrator.facts.agent.input; // string | null — current prompt
|
|
112
|
+
orchestrator.facts.agent.output; // unknown | null — last output
|
|
113
|
+
orchestrator.facts.agent.error; // string | null — last error message
|
|
114
|
+
orchestrator.facts.agent.tokenUsage; // number — cumulative tokens used
|
|
115
|
+
orchestrator.facts.agent.turnCount; // number — completed turns
|
|
116
|
+
orchestrator.facts.agent.startedAt; // number | null — ms timestamp
|
|
117
|
+
orchestrator.facts.agent.completedAt; // number | null
|
|
118
|
+
|
|
119
|
+
// Cumulative tokens (also exposed at the top of the orchestrator)
|
|
120
|
+
orchestrator.totalTokens;
|
|
121
|
+
|
|
122
|
+
// Approval queue (when autoApproveToolCalls: false)
|
|
123
|
+
orchestrator.facts.approval.pending; // ApprovalRequest[]
|
|
124
|
+
orchestrator.facts.approval.approved; // string[]
|
|
125
|
+
orchestrator.facts.approval.rejected; // RejectedRequest[]
|
|
126
|
+
|
|
127
|
+
// Conversation + tool call history
|
|
128
|
+
orchestrator.facts.conversation; // Message[]
|
|
129
|
+
orchestrator.facts.toolCalls; // ToolCall[]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Token budget
|
|
133
|
+
|
|
134
|
+
`maxTokenBudget` is the cap. When usage crosses it the orchestrator pauses (sets `facts.agent.status = "paused"`). `budgetWarningThreshold` (0–1, default 0.8) fires `onBudgetWarning` BEFORE the cap. **Both options are top-level — NOT inside `hooks:`**.
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const orchestrator = createAgentOrchestrator({
|
|
138
|
+
runner,
|
|
139
|
+
maxTokenBudget: 100_000,
|
|
140
|
+
budgetWarningThreshold: 0.8,
|
|
141
|
+
onBudgetWarning: ({ currentTokens, maxBudget, percentage }) => {
|
|
142
|
+
console.warn(`Token usage at ${Math.round(percentage * 100)}% (${currentTokens}/${maxBudget})`);
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Memory
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { createAgentMemory, createSlidingWindowStrategy, createKeyPointsSummarizer } from "@directive-run/ai";
|
|
151
|
+
|
|
152
|
+
const orchestrator = createAgentOrchestrator({
|
|
153
|
+
runner,
|
|
154
|
+
memory: createAgentMemory({
|
|
155
|
+
strategy: createSlidingWindowStrategy({ maxMessages: 50 }),
|
|
156
|
+
summarizer: createKeyPointsSummarizer(),
|
|
157
|
+
}),
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
When `memory` is configured, prior conversation context is auto-injected into each agent run, and the agent's response is auto-stored. See `ai-guardrails-memory.md` for memory strategies in depth.
|
|
162
|
+
|
|
163
|
+
## Guardrails
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import {
|
|
167
|
+
createPIIGuardrail,
|
|
168
|
+
createLengthGuardrail,
|
|
169
|
+
createPromptInjectionGuardrail,
|
|
170
|
+
} from "@directive-run/ai/guardrails";
|
|
171
|
+
|
|
172
|
+
const orchestrator = createAgentOrchestrator({
|
|
173
|
+
runner,
|
|
174
|
+
guardrails: {
|
|
175
|
+
input: [
|
|
176
|
+
createPIIGuardrail({ redact: true }),
|
|
177
|
+
createPromptInjectionGuardrail({ strictMode: true }),
|
|
178
|
+
],
|
|
179
|
+
output: [
|
|
180
|
+
createLengthGuardrail({ maxCharacters: 5000 }),
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
See `ai-guardrails-memory.md` for the full list of guardrail factories and their actual option shapes.
|
|
187
|
+
|
|
188
|
+
## Lifecycle hooks (observability)
|
|
189
|
+
|
|
190
|
+
These hooks fire purely for observability — they cannot block, deny, or modify runs. To block a run before it executes, use `breakpoints` (next section) or guardrails.
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
const orchestrator = createAgentOrchestrator({
|
|
194
|
+
runner,
|
|
195
|
+
hooks: {
|
|
196
|
+
onAgentStart: (e) => console.log(`▶ ${e.agentName} @ ${e.timestamp}`),
|
|
197
|
+
onAgentComplete: (e) => console.log(`✓ ${e.agentName} — ${e.tokenUsage} tokens in ${e.durationMs}ms`),
|
|
198
|
+
onAgentError: (e) => console.error(`✗ ${e.agentName}:`, e.error),
|
|
199
|
+
onAgentRetry: (e) => console.warn(`↻ ${e.agentName} attempt ${e.attempt}`),
|
|
200
|
+
onGuardrailCheck: (e) => console.log(`${e.passed ? "✓" : "✗"} ${e.guardrailName}`),
|
|
201
|
+
onBreakpoint: (req) => console.log(`⏸ breakpoint ${req.id}`),
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The full event payload shapes live in `@directive-run/ai`'s `OrchestratorLifecycleHooks` interface.
|
|
207
|
+
|
|
208
|
+
## Human-in-the-loop: breakpoints + approval
|
|
209
|
+
|
|
210
|
+
For approval workflows (pause before a sensitive tool call), Directive offers two layered mechanisms:
|
|
211
|
+
|
|
212
|
+
### Tool-call approval (`autoApproveToolCalls: false`)
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
const orchestrator = createAgentOrchestrator({
|
|
216
|
+
runner,
|
|
217
|
+
autoApproveToolCalls: false,
|
|
218
|
+
onApprovalRequest: (request) => {
|
|
219
|
+
showApprovalDialog(request); // your UI
|
|
220
|
+
},
|
|
221
|
+
approvalTimeoutMs: 5 * 60 * 1000,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// In your UI handler:
|
|
225
|
+
orchestrator.approve(request.id);
|
|
226
|
+
// or
|
|
227
|
+
orchestrator.reject(request.id, "policy violation");
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Breakpoints (arbitrary pause points)
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
import type { BreakpointConfig } from "@directive-run/ai";
|
|
234
|
+
|
|
235
|
+
const orchestrator = createAgentOrchestrator({
|
|
236
|
+
runner,
|
|
237
|
+
breakpoints: [
|
|
238
|
+
{ id: "review-prompt", before: "agent_start" },
|
|
239
|
+
{ id: "review-output", after: "agent_complete" },
|
|
240
|
+
],
|
|
241
|
+
onBreakpoint: (request) => {
|
|
242
|
+
showReviewUI(request);
|
|
243
|
+
},
|
|
244
|
+
breakpointTimeoutMs: 5 * 60 * 1000,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Resume (optionally with input modifications)
|
|
248
|
+
orchestrator.resumeBreakpoint("review-prompt");
|
|
249
|
+
|
|
250
|
+
// Or cancel
|
|
251
|
+
orchestrator.cancelBreakpoint("review-prompt", "user aborted");
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Retry + circuit breaker + self-healing
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { createCircuitBreaker } from "@directive-run/ai";
|
|
258
|
+
|
|
259
|
+
const orchestrator = createAgentOrchestrator({
|
|
260
|
+
runner,
|
|
261
|
+
agentRetry: {
|
|
262
|
+
maxRetries: 3,
|
|
263
|
+
baseDelayMs: 500,
|
|
264
|
+
maxDelayMs: 5000,
|
|
265
|
+
isRetryable: (err) => err.message.includes("rate_limit"),
|
|
266
|
+
onRetry: ({ attempt, error, delayMs }) => console.warn(`retry ${attempt} in ${delayMs}ms:`, error.message),
|
|
267
|
+
},
|
|
268
|
+
circuitBreaker: createCircuitBreaker({
|
|
269
|
+
failureThreshold: 5,
|
|
270
|
+
recoveryTimeMs: 60_000,
|
|
271
|
+
halfOpenMaxRequests: 1,
|
|
272
|
+
}),
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
See `ai-budget-resilience.md` for the resilience surface in depth (retry, fallback, circuit breaker, health monitor, self-healing).
|
|
277
|
+
|
|
278
|
+
## Structured output
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
import { z } from "zod";
|
|
282
|
+
|
|
283
|
+
const orchestrator = createAgentOrchestrator({
|
|
284
|
+
runner,
|
|
285
|
+
outputSchema: z.object({
|
|
286
|
+
summary: z.string(),
|
|
287
|
+
confidence: z.number().min(0).max(1),
|
|
288
|
+
}),
|
|
289
|
+
maxSchemaRetries: 2,
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
const result = await orchestrator.run(agent, "Summarize this article");
|
|
293
|
+
// result.output is typed and parsed by the Zod schema; up to 2 retries on validation failure
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
`outputSchema` accepts anything with a `safeParse(value)` method — Zod, Valibot, or your own validator.
|
|
297
|
+
|
|
298
|
+
## Pause / resume
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
orchestrator.pause(); // in-flight runs complete; new ones queue
|
|
302
|
+
orchestrator.resume(); // queued work begins executing
|
|
303
|
+
orchestrator.reset(); // clears conversation, approval, and tool-call state
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Checkpoints (save / restore)
|
|
307
|
+
|
|
308
|
+
`checkpoint()` is **async** — it returns a Promise. Restore on an EXISTING orchestrator instance with `restore()`; there is no constructor option that takes a checkpoint.
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { createInMemoryCheckpointStore } from "@directive-run/ai";
|
|
312
|
+
|
|
313
|
+
const orchestrator = createAgentOrchestrator({
|
|
314
|
+
runner,
|
|
315
|
+
checkpointStore: createInMemoryCheckpointStore(),
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// Save
|
|
319
|
+
const cp = await orchestrator.checkpoint({ label: "after-analysis" });
|
|
320
|
+
const serialized = JSON.stringify(cp);
|
|
321
|
+
|
|
322
|
+
// Restore — on the same instance, or a fresh one with the same config shape
|
|
323
|
+
const newOrchestrator = createAgentOrchestrator({ runner, /* same options */ });
|
|
324
|
+
newOrchestrator.restore(JSON.parse(serialized));
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## Anti-patterns
|
|
328
|
+
|
|
329
|
+
### TS types instead of `t.*()` for `factsSchema`
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
// WRONG — TS types are erased at runtime; no schema validation, no defaults
|
|
333
|
+
factsSchema: {} as { confidence: number; analysis: string }
|
|
334
|
+
|
|
335
|
+
// CORRECT — t.*() builders provide runtime shape + types
|
|
336
|
+
factsSchema: { confidence: t.number(), analysis: t.string() }
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### In-place array/object mutation
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
// WRONG — the proxy can't detect in-place mutations
|
|
343
|
+
context.facts.cache.push("new-item");
|
|
344
|
+
|
|
345
|
+
// CORRECT — replace the value
|
|
346
|
+
context.facts.cache = [...context.facts.cache, "new-item"];
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Returning data from `resolve`
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
// WRONG — resolvers return void; return value is ignored
|
|
353
|
+
resolve: async (req, context) => {
|
|
354
|
+
return await analyzeData(req.input);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// CORRECT — mutate facts to store results
|
|
358
|
+
resolve: async (req, context) => {
|
|
359
|
+
context.facts.analysis = await analyzeData(req.input);
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Confusing single-agent with multi-agent lifecycle
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
// Single-agent orchestrator — NO start() needed
|
|
367
|
+
const orch = createAgentOrchestrator({ runner });
|
|
368
|
+
await orch.run(agent, "prompt"); // ✓ ready
|
|
369
|
+
|
|
370
|
+
// Multi-agent orchestrator — start() IS required before runPattern
|
|
371
|
+
const multi = createMultiAgentOrchestrator({ agents, runner });
|
|
372
|
+
multi.start();
|
|
373
|
+
await multi.runPattern("pipeline", "prompt");
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Hook names from a guess instead of the type
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
// WRONG — onStart / onBeforeRun / onAfterRun / onError do not exist on OrchestratorLifecycleHooks
|
|
380
|
+
hooks: {
|
|
381
|
+
onStart: () => {},
|
|
382
|
+
onBeforeRun: () => ({ approved: true }),
|
|
383
|
+
onAfterRun: () => {},
|
|
384
|
+
onError: () => {},
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// CORRECT — actual names are onAgent*
|
|
388
|
+
hooks: {
|
|
389
|
+
onAgentStart: (e) => {},
|
|
390
|
+
onAgentComplete: (e) => {},
|
|
391
|
+
onAgentError: (e) => {},
|
|
392
|
+
onAgentRetry: (e) => {},
|
|
393
|
+
onGuardrailCheck: (e) => {},
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Putting `onBudgetWarning` inside `hooks`
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
// WRONG — onBudgetWarning is a TOP-LEVEL option
|
|
401
|
+
{ hooks: { onBudgetWarning: () => {} } }
|
|
402
|
+
|
|
403
|
+
// CORRECT
|
|
404
|
+
{ onBudgetWarning: (event) => {}, maxTokenBudget: 100_000 }
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Treating `checkpoint()` as sync
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
// WRONG — checkpoint() returns a Promise
|
|
411
|
+
const cp = orchestrator.checkpoint();
|
|
412
|
+
const json = JSON.stringify(cp); // serializes "[object Promise]"
|
|
413
|
+
|
|
414
|
+
// CORRECT — await it
|
|
415
|
+
const cp = await orchestrator.checkpoint({ label: "snapshot-1" });
|
|
416
|
+
const json = JSON.stringify(cp);
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Restoring via constructor option
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
// WRONG — there is no `checkpoint` option on createAgentOrchestrator
|
|
423
|
+
const orch = createAgentOrchestrator({ runner, checkpoint: savedCheckpoint });
|
|
424
|
+
|
|
425
|
+
// CORRECT — restore on an existing instance
|
|
426
|
+
const orch = createAgentOrchestrator({ runner });
|
|
427
|
+
orch.restore(savedCheckpoint);
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Iterating `runStream`'s return value directly
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
// WRONG — runStream returns { stream, result, abort }, not an AsyncIterable
|
|
434
|
+
const stream = orchestrator.runStream(agent, "prompt");
|
|
435
|
+
for await (const chunk of stream) { /* never iterates the right thing */ }
|
|
436
|
+
|
|
437
|
+
// CORRECT — destructure
|
|
438
|
+
const { stream, result, abort } = orchestrator.runStream(agent, "prompt");
|
|
439
|
+
for await (const chunk of stream) { /* … */ }
|
|
440
|
+
const final = await result;
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Quick reference
|
|
444
|
+
|
|
445
|
+
| Method | Purpose |
|
|
446
|
+
|---|---|
|
|
447
|
+
| `orch.run(agent, input, opts?)` | Run agent → `Promise<RunResult<T>>` |
|
|
448
|
+
| `orch.runStream(agent, input, opts?)` | Run agent → `{ stream, result, abort }` |
|
|
449
|
+
| `orch.approve(id)` / `orch.reject(id, reason?)` | Resolve a pending approval request |
|
|
450
|
+
| `orch.pause()` / `orch.resume()` / `orch.reset()` | Lifecycle control |
|
|
451
|
+
| `orch.waitForIdle(timeoutMs?)` | Resolves when orchestrator is back at idle |
|
|
452
|
+
| `orch.checkpoint(opts?)` | Async — `Promise<Checkpoint>` |
|
|
453
|
+
| `orch.restore(cp, opts?)` | Restore state on an existing instance |
|
|
454
|
+
| `orch.resumeBreakpoint(id, mods?)` / `orch.cancelBreakpoint(id, reason?)` | Resume/cancel a paused breakpoint |
|
|
455
|
+
| `orch.facts.agent.*` | Read built-in agent state |
|
|
456
|
+
| `orch.totalTokens` | Cumulative token count |
|
|
457
|
+
| `orch.timeline` | DebugTimeline (when `debug: true`); `null` otherwise |
|
|
458
|
+
|
|
459
|
+
## See also
|
|
460
|
+
|
|
461
|
+
- [`ai-multi-agent.md`](./ai-multi-agent.md) — the multi-agent flavor; 8 composition patterns and pattern factories
|
|
462
|
+
- [`ai-adapters.md`](./ai-adapters.md) — provider runners that produce the `runner` this orchestrator wraps
|
|
463
|
+
- [`ai-guardrails-memory.md`](./ai-guardrails-memory.md) — full surface of the `guardrails:` and `memory:` options on this orchestrator
|
|
464
|
+
- [`ai-budget-resilience.md`](./ai-budget-resilience.md) — full surface of the `circuitBreaker:`, `selfHealing:`, `agentRetry:`, `maxTokenBudget:` options
|
|
465
|
+
- [`ai-debug-observability.md`](./ai-debug-observability.md) — full surface of the `debug:`, `breakpoints:`, `onBreakpoint:` options + `orchestrator.timeline`
|
|
466
|
+
- [`ai-testing-evals.md`](./ai-testing-evals.md) — `createTestOrchestrator` for unit testing this surface
|