@directive-run/knowledge 1.14.0 → 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/README.md +50 -15
- package/ai/ai-adapters.md +7 -0
- package/ai/ai-agents-streaming.md +187 -149
- package/ai/ai-budget-resilience.md +305 -132
- package/ai/ai-communication.md +220 -197
- package/ai/ai-debug-observability.md +259 -173
- package/ai/ai-guardrails-memory.md +191 -153
- package/ai/ai-mcp-rag.md +204 -199
- package/ai/ai-multi-agent.md +254 -153
- package/ai/ai-orchestrator.md +353 -114
- package/ai/ai-security.md +287 -180
- package/ai/ai-tasks.md +8 -1
- package/ai/ai-testing-evals.md +363 -256
- package/core/anti-patterns.md +18 -2
- package/core/constraints.md +13 -2
- package/core/core-patterns.md +12 -0
- package/core/error-boundaries.md +8 -0
- package/core/history.md +7 -0
- package/core/multi-module.md +15 -3
- package/core/naming.md +128 -90
- package/core/plugins.md +7 -0
- package/core/react-adapter.md +256 -174
- package/core/resolvers.md +10 -0
- package/core/schema-types.md +8 -0
- package/core/system-api.md +10 -0
- package/core/testing.md +257 -143
- package/examples/checkers.ts +15 -16
- package/examples/contact-form.ts +2 -2
- package/examples/counter-react.ts +1 -1
- package/examples/counter-svelte.ts +1 -1
- package/examples/counter-vue.ts +1 -1
- package/examples/counter.ts +1 -1
- package/examples/data-triggers.ts +4 -4
- package/examples/feature-flags.ts +2 -2
- package/examples/form-wizard.ts +2 -2
- package/examples/newsletter.ts +2 -2
- package/examples/server.ts +2 -2
- package/examples/shopping-cart.ts +1 -1
- package/examples/topic-guard.ts +1 -1
- package/package.json +3 -3
- package/sitemap.md +17 -11
- package/examples/debounce-constraints.ts +0 -95
- package/examples/multi-module.ts +0 -58
|
@@ -1,215 +1,215 @@
|
|
|
1
|
-
# AI
|
|
1
|
+
# AI guardrails and memory
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Covers `@directive-run/ai/guardrails` and `@directive-run/ai` — input/output/toolCall guardrails (PII, prompt-injection, length, schema, content filter), memory strategies, summarizers.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Guardrails validate and transform input, output, and tool calls. Memory strategies manage conversation history with configurable summarization. Both plug into `createAgentOrchestrator` and `createMultiAgentOrchestrator`.
|
|
6
|
+
|
|
7
|
+
Import guardrail factories from the subpath barrel — the main `@directive-run/ai` re-exports them with `@deprecated` notices for v2.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import {
|
|
11
|
+
createPIIGuardrail,
|
|
12
|
+
createModerationGuardrail,
|
|
13
|
+
createRateLimitGuardrail,
|
|
14
|
+
createToolGuardrail,
|
|
15
|
+
createOutputSchemaGuardrail,
|
|
16
|
+
createOutputTypeGuardrail,
|
|
17
|
+
createLengthGuardrail,
|
|
18
|
+
createContentFilterGuardrail,
|
|
19
|
+
} from "@directive-run/ai/guardrails";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Decision tree
|
|
6
23
|
|
|
7
24
|
```
|
|
8
25
|
What are you guarding against?
|
|
9
|
-
├── PII in input
|
|
26
|
+
├── PII in input → createPIIGuardrail()
|
|
10
27
|
├── Harmful content → createModerationGuardrail()
|
|
11
28
|
├── Rate limits → createRateLimitGuardrail()
|
|
12
|
-
├── Unauthorized tool
|
|
13
|
-
├── Output
|
|
14
|
-
├── Output type
|
|
15
|
-
├── Response length
|
|
16
|
-
└── Banned words/patterns
|
|
29
|
+
├── Unauthorized tool calls → createToolGuardrail()
|
|
30
|
+
├── Output schema mismatch → createOutputSchemaGuardrail()
|
|
31
|
+
├── Output type / shape → createOutputTypeGuardrail()
|
|
32
|
+
├── Response length → createLengthGuardrail()
|
|
33
|
+
└── Banned words/patterns → createContentFilterGuardrail()
|
|
17
34
|
```
|
|
18
35
|
|
|
19
|
-
## GuardrailResult
|
|
36
|
+
## `GuardrailResult` shape
|
|
20
37
|
|
|
21
38
|
Every guardrail returns this shape:
|
|
22
39
|
|
|
23
40
|
```typescript
|
|
24
41
|
interface GuardrailResult {
|
|
25
|
-
// Did the input/output pass?
|
|
26
42
|
passed: boolean;
|
|
27
|
-
|
|
28
|
-
//
|
|
29
|
-
reason?: string;
|
|
30
|
-
|
|
31
|
-
// Modified data – guardrail can transform the input/output
|
|
32
|
-
transformed?: unknown;
|
|
43
|
+
reason?: string; // populated when passed: false
|
|
44
|
+
transformed?: unknown; // when set, replaces the original value downstream
|
|
33
45
|
}
|
|
34
46
|
```
|
|
35
47
|
|
|
36
|
-
When `transformed` is set, the modified value replaces the original for downstream processing.
|
|
48
|
+
When `transformed` is set, the modified value replaces the original for downstream processing — that's how redaction and sanitization work.
|
|
37
49
|
|
|
38
|
-
## Built-
|
|
50
|
+
## Built-in guardrails
|
|
39
51
|
|
|
40
|
-
### PII
|
|
52
|
+
### PII detection + redaction
|
|
41
53
|
|
|
42
54
|
```typescript
|
|
43
|
-
import { createPIIGuardrail } from "@directive-run/ai";
|
|
44
|
-
|
|
45
55
|
const piiGuardrail = createPIIGuardrail({
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
// Redact instead of blocking (default: false)
|
|
50
|
-
redact: true,
|
|
51
|
-
|
|
52
|
-
// Replacement string (default: "[REDACTED]")
|
|
53
|
-
redactReplacement: "***",
|
|
56
|
+
patterns: [/CUSTOM-\d{8}/g], // extra regex patterns beyond defaults (SSN / credit card / email)
|
|
57
|
+
redact: true, // redact in place instead of blocking (default: false)
|
|
58
|
+
redactReplacement: "***", // string to substitute (default: "[REDACTED]")
|
|
54
59
|
});
|
|
55
60
|
```
|
|
56
61
|
|
|
57
|
-
### Content
|
|
62
|
+
### Content moderation (user check function)
|
|
58
63
|
|
|
59
64
|
```typescript
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
checkFn: async (content) => {
|
|
65
|
-
const result = await moderationAPI.check(content);
|
|
66
|
-
|
|
67
|
-
return result.safe;
|
|
65
|
+
const moderation = createModerationGuardrail({
|
|
66
|
+
checkFn: async (text) => {
|
|
67
|
+
const result = await moderationAPI.check(text);
|
|
68
|
+
return result.flagged; // return TRUE when content should be flagged/blocked
|
|
68
69
|
},
|
|
69
|
-
|
|
70
|
-
// Custom rejection message
|
|
71
|
-
message: "Content flagged by moderation",
|
|
70
|
+
message: "Content flagged by moderation", // optional override
|
|
72
71
|
});
|
|
73
72
|
```
|
|
74
73
|
|
|
75
|
-
|
|
74
|
+
The check function may be sync or async. Returning `true` causes the guardrail to block.
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
import { createRateLimitGuardrail } from "@directive-run/ai";
|
|
76
|
+
### Rate limiting (sliding window)
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
```typescript
|
|
79
|
+
const rateLimit = createRateLimitGuardrail({
|
|
80
|
+
maxTokensPerMinute: 50_000, // default 100_000
|
|
81
|
+
maxRequestsPerMinute: 30, // default 60
|
|
83
82
|
});
|
|
83
|
+
|
|
84
|
+
// Test helper — included on the returned guardrail
|
|
85
|
+
rateLimit.reset();
|
|
84
86
|
```
|
|
85
87
|
|
|
86
|
-
### Tool
|
|
88
|
+
### Tool allow/deny lists
|
|
87
89
|
|
|
88
90
|
```typescript
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
// Any tool not in this list is blocked
|
|
91
|
+
const tools = createToolGuardrail({
|
|
92
|
+
allowlist: ["search", "calculator", "readFile"], // only these tools are allowed
|
|
93
|
+
denylist: ["dangerous-tool"], // any of these are blocked
|
|
94
|
+
caseSensitive: false, // default false
|
|
94
95
|
});
|
|
95
96
|
```
|
|
96
97
|
|
|
97
|
-
|
|
98
|
+
Use `allowlist` OR `denylist` (or both). A tool not on the allowlist is blocked; a tool on the denylist is blocked.
|
|
99
|
+
|
|
100
|
+
### Output schema validation
|
|
101
|
+
|
|
102
|
+
The validator is a function — Directive does NOT take a raw JSON schema. Use any validation library that has a `safeParse`-style API; pass an adapter.
|
|
98
103
|
|
|
99
104
|
```typescript
|
|
100
|
-
import {
|
|
105
|
+
import { z } from "zod";
|
|
101
106
|
|
|
102
107
|
const schemaGuardrail = createOutputSchemaGuardrail({
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
properties: {
|
|
106
|
-
title: { type: "string" },
|
|
107
|
-
score: { type: "number", minimum: 0, maximum: 100 },
|
|
108
|
-
},
|
|
109
|
-
required: ["title", "score"],
|
|
110
|
-
},
|
|
108
|
+
validate: (value) => {
|
|
109
|
+
const result = z.object({ title: z.string(), score: z.number() }).safeParse(value);
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
return {
|
|
112
|
+
valid: result.success,
|
|
113
|
+
errors: result.success ? undefined : result.error.issues.map((i) => i.message),
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
errorPrefix: "Output schema validation failed", // default — prepended to error.reason
|
|
114
117
|
});
|
|
115
118
|
```
|
|
116
119
|
|
|
117
|
-
|
|
120
|
+
For automatic schema-retry on the agent's behalf, configure `outputSchema` + `maxSchemaRetries` on the orchestrator instead (see `ai-orchestrator.md` → Structured output).
|
|
118
121
|
|
|
119
|
-
|
|
120
|
-
import { createOutputTypeGuardrail } from "@directive-run/ai";
|
|
122
|
+
### Output type guard (no schema library needed)
|
|
121
123
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
```typescript
|
|
125
|
+
const typeGuard = createOutputTypeGuardrail({
|
|
126
|
+
type: "object", // "string" | "number" | "boolean" | "object" | "array"
|
|
127
|
+
requiredFields: ["id", "name"], // object keys that must exist
|
|
128
|
+
minLength: 1, // for arrays
|
|
129
|
+
maxLength: 100, // for arrays
|
|
130
|
+
minStringLength: 1, // for strings
|
|
131
|
+
maxStringLength: 5000, // for strings
|
|
124
132
|
});
|
|
125
133
|
```
|
|
126
134
|
|
|
127
|
-
### Length
|
|
135
|
+
### Length constraints
|
|
128
136
|
|
|
129
137
|
```typescript
|
|
130
|
-
import { createLengthGuardrail } from "@directive-run/ai";
|
|
131
|
-
|
|
132
138
|
const lengthGuardrail = createLengthGuardrail({
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
maxTokens: 1000,
|
|
139
|
+
maxCharacters: 5000,
|
|
140
|
+
maxTokens: 1200,
|
|
141
|
+
estimateTokens: (text) => Math.ceil(text.length / 4), // default: chars / 4
|
|
137
142
|
});
|
|
138
143
|
```
|
|
139
144
|
|
|
140
|
-
|
|
145
|
+
There is NO `minChars`, `maxChars`, or `minTokens` option — only `maxCharacters` (note the spelling) and `maxTokens`.
|
|
141
146
|
|
|
142
|
-
|
|
143
|
-
import { createContentFilterGuardrail } from "@directive-run/ai";
|
|
147
|
+
### Content filter (banned patterns)
|
|
144
148
|
|
|
149
|
+
```typescript
|
|
145
150
|
const contentFilter = createContentFilterGuardrail({
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
// "block" (default) or "redact"
|
|
149
|
-
action: "redact",
|
|
150
|
-
|
|
151
|
-
// Replacement for redact mode
|
|
152
|
-
replacement: "[FILTERED]",
|
|
151
|
+
blockedPatterns: [/\bpassword\b/i, /\bsecret\b/i, "internal-only"],
|
|
152
|
+
caseSensitive: false,
|
|
153
153
|
});
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
Strings are escaped and compiled to RegExp; RegExp instances pass through. There is NO `action: "redact"` mode — this guardrail blocks only. For redaction, use `createPIIGuardrail({ redact: true, patterns: [...] })`.
|
|
157
|
+
|
|
158
|
+
## Applying guardrails
|
|
157
159
|
|
|
158
160
|
```typescript
|
|
159
161
|
const orchestrator = createAgentOrchestrator({
|
|
160
162
|
runner,
|
|
161
163
|
guardrails: {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// Run after the agent produces output
|
|
166
|
-
output: [lengthGuardrail, schemaGuardrail, contentFilter],
|
|
164
|
+
input: [piiGuardrail, rateLimit],
|
|
165
|
+
output: [lengthGuardrail, schemaGuardrail, contentFilter],
|
|
166
|
+
toolCall: [tools],
|
|
167
167
|
},
|
|
168
168
|
});
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
##
|
|
171
|
+
## Catching `GuardrailError`
|
|
172
172
|
|
|
173
173
|
```typescript
|
|
174
|
-
|
|
175
|
-
try {
|
|
176
|
-
const result = await orchestrator.run(agent, prompt);
|
|
177
|
-
} catch (error) {
|
|
178
|
-
if (error instanceof Error) {
|
|
179
|
-
console.log(error.message); // No guardrail context
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// CORRECT – catch GuardrailError for full context
|
|
184
|
-
import { GuardrailError } from "@directive-run/ai";
|
|
174
|
+
import { GuardrailError, isGuardrailError } from "@directive-run/ai";
|
|
185
175
|
|
|
186
176
|
try {
|
|
187
|
-
|
|
177
|
+
await orchestrator.run(agent, prompt);
|
|
188
178
|
} catch (error) {
|
|
189
|
-
if (error
|
|
190
|
-
console.log(error.
|
|
191
|
-
console.log(error.
|
|
192
|
-
console.log(error.
|
|
179
|
+
if (isGuardrailError(error)) {
|
|
180
|
+
console.log(error.code); // "INPUT_GUARDRAIL_FAILED" | "OUTPUT_GUARDRAIL_FAILED" | "TOOL_CALL_GUARDRAIL_FAILED" | …
|
|
181
|
+
console.log(error.guardrailName); // "pii-detection"
|
|
182
|
+
console.log(error.guardrailType); // "input" | "output" | "toolCall"
|
|
183
|
+
console.log(error.userMessage); // safe-to-show user-facing message
|
|
184
|
+
console.log(error.agentName); // which agent triggered it
|
|
185
|
+
// error.input and error.data are non-enumerable to prevent accidental log leakage
|
|
193
186
|
}
|
|
194
187
|
}
|
|
195
188
|
```
|
|
196
189
|
|
|
197
|
-
|
|
190
|
+
There is no `errorCode` field — it's `code`. There is no `reason` field on `GuardrailError` — the rejection reason from the guardrail's result becomes the error's `message` (or `userMessage` for safe display).
|
|
198
191
|
|
|
199
|
-
|
|
192
|
+
`GuardrailErrorCode` union:
|
|
193
|
+
- `INPUT_GUARDRAIL_FAILED` / `OUTPUT_GUARDRAIL_FAILED` / `TOOL_CALL_GUARDRAIL_FAILED`
|
|
194
|
+
- `APPROVAL_REJECTED`
|
|
195
|
+
- `BUDGET_EXCEEDED`
|
|
196
|
+
- `RATE_LIMIT_EXCEEDED`
|
|
197
|
+
- `AGENT_ERROR`
|
|
200
198
|
|
|
201
|
-
|
|
199
|
+
---
|
|
202
200
|
|
|
203
|
-
##
|
|
201
|
+
## Memory strategies
|
|
202
|
+
|
|
203
|
+
Memory strategies control how conversation history is trimmed as it grows.
|
|
204
204
|
|
|
205
205
|
```
|
|
206
206
|
How should history be trimmed?
|
|
207
207
|
├── Keep N most recent messages → createSlidingWindowStrategy()
|
|
208
208
|
├── Keep within token budget → createTokenBasedStrategy()
|
|
209
|
-
└── Both
|
|
209
|
+
└── Both at once → createHybridStrategy()
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
-
### Sliding
|
|
212
|
+
### Sliding window (message count)
|
|
213
213
|
|
|
214
214
|
```typescript
|
|
215
215
|
import { createAgentMemory, createSlidingWindowStrategy } from "@directive-run/ai";
|
|
@@ -217,17 +217,15 @@ import { createAgentMemory, createSlidingWindowStrategy } from "@directive-run/a
|
|
|
217
217
|
const memory = createAgentMemory({
|
|
218
218
|
strategy: createSlidingWindowStrategy({
|
|
219
219
|
maxMessages: 50,
|
|
220
|
-
|
|
221
|
-
// Always keep the N most recent (default: 5)
|
|
222
|
-
preserveRecentCount: 10,
|
|
220
|
+
preserveRecentCount: 10, // always keep the N most recent (default 5)
|
|
223
221
|
}),
|
|
224
222
|
});
|
|
225
223
|
```
|
|
226
224
|
|
|
227
|
-
### Token-
|
|
225
|
+
### Token-based
|
|
228
226
|
|
|
229
227
|
```typescript
|
|
230
|
-
import {
|
|
228
|
+
import { createTokenBasedStrategy } from "@directive-run/ai";
|
|
231
229
|
|
|
232
230
|
const memory = createAgentMemory({
|
|
233
231
|
strategy: createTokenBasedStrategy({
|
|
@@ -237,57 +235,54 @@ const memory = createAgentMemory({
|
|
|
237
235
|
});
|
|
238
236
|
```
|
|
239
237
|
|
|
240
|
-
### Hybrid (
|
|
238
|
+
### Hybrid (both constraints)
|
|
241
239
|
|
|
242
240
|
```typescript
|
|
243
|
-
import {
|
|
241
|
+
import { createHybridStrategy } from "@directive-run/ai";
|
|
244
242
|
|
|
245
243
|
const memory = createAgentMemory({
|
|
246
244
|
strategy: createHybridStrategy({
|
|
247
245
|
maxMessages: 100,
|
|
248
|
-
maxTokens:
|
|
246
|
+
maxTokens: 16_000,
|
|
249
247
|
}),
|
|
250
248
|
});
|
|
251
249
|
```
|
|
252
250
|
|
|
253
251
|
## Summarizers
|
|
254
252
|
|
|
255
|
-
When messages are evicted, a summarizer condenses them
|
|
253
|
+
When messages are evicted, a summarizer condenses them.
|
|
256
254
|
|
|
257
|
-
### Truncation (
|
|
255
|
+
### Truncation (drop, no summary)
|
|
258
256
|
|
|
259
257
|
```typescript
|
|
260
258
|
import { createTruncationSummarizer } from "@directive-run/ai";
|
|
261
259
|
|
|
262
|
-
// Simply drops old messages – no summary generated
|
|
263
260
|
const summarizer = createTruncationSummarizer();
|
|
264
261
|
```
|
|
265
262
|
|
|
266
|
-
### Key
|
|
263
|
+
### Key-points (rule-based, no LLM call)
|
|
267
264
|
|
|
268
265
|
```typescript
|
|
269
266
|
import { createKeyPointsSummarizer } from "@directive-run/ai";
|
|
270
267
|
|
|
271
|
-
// Extracts bullet points from evicted messages (rule-based, no LLM)
|
|
272
268
|
const summarizer = createKeyPointsSummarizer();
|
|
273
269
|
```
|
|
274
270
|
|
|
275
|
-
### LLM-
|
|
271
|
+
### LLM-based (async)
|
|
276
272
|
|
|
277
273
|
```typescript
|
|
278
274
|
import { createLLMSummarizer } from "@directive-run/ai";
|
|
279
275
|
|
|
280
|
-
// Uses the runner to summarize evicted messages via LLM
|
|
281
276
|
const summarizer = createLLMSummarizer(runner);
|
|
282
277
|
```
|
|
283
278
|
|
|
284
|
-
###
|
|
279
|
+
### Wiring memory to an orchestrator
|
|
285
280
|
|
|
286
281
|
```typescript
|
|
287
282
|
const memory = createAgentMemory({
|
|
288
283
|
strategy: createSlidingWindowStrategy({ maxMessages: 50 }),
|
|
289
284
|
summarizer: createKeyPointsSummarizer(),
|
|
290
|
-
autoManage: true, //
|
|
285
|
+
autoManage: true, // automatically trim + summarize after each run (default: true)
|
|
291
286
|
});
|
|
292
287
|
|
|
293
288
|
const orchestrator = createAgentOrchestrator({
|
|
@@ -296,37 +291,80 @@ const orchestrator = createAgentOrchestrator({
|
|
|
296
291
|
});
|
|
297
292
|
```
|
|
298
293
|
|
|
299
|
-
## Anti-
|
|
294
|
+
## Anti-patterns
|
|
295
|
+
|
|
296
|
+
### Calling guardrails by old field names
|
|
300
297
|
|
|
301
298
|
```typescript
|
|
302
|
-
// WRONG
|
|
303
|
-
|
|
299
|
+
// WRONG — these option names don't exist
|
|
300
|
+
createOutputSchemaGuardrail({ schema: jsonSchema, retries: 2 }) // → use validate + outputSchema on the orchestrator for retry
|
|
301
|
+
createToolGuardrail({ allowedTools: [...] }) // → use allowlist
|
|
302
|
+
createLengthGuardrail({ minChars, maxChars, minTokens, maxTokens })// → only maxCharacters + maxTokens
|
|
303
|
+
createContentFilterGuardrail({ patterns, action: "redact" }) // → blockedPatterns; this guardrail BLOCKS only
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Catching `Error` instead of `GuardrailError`
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
// WRONG — loses code, guardrailName, guardrailType, userMessage
|
|
310
|
+
try { await orch.run(agent, prompt); } catch (e) {
|
|
311
|
+
if (e instanceof Error) console.log(e.message);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// CORRECT — narrow to GuardrailError
|
|
315
|
+
try { await orch.run(agent, prompt); } catch (e) {
|
|
316
|
+
if (e instanceof GuardrailError) {
|
|
317
|
+
console.log(e.code, e.guardrailName, e.userMessage);
|
|
318
|
+
} else {
|
|
319
|
+
throw e;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Reading the wrong error fields
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
// WRONG — these don't exist on GuardrailError
|
|
328
|
+
error.errorCode // → use error.code
|
|
329
|
+
error.reason // → use error.message (or userMessage for user-facing)
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### LLM summarizer with `autoManage: true`
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
// WRONG — autoManage runs synchronously; the async summarizer is never awaited
|
|
336
|
+
createAgentMemory({
|
|
304
337
|
strategy: createSlidingWindowStrategy({ maxMessages: 20 }),
|
|
305
338
|
summarizer: createLLMSummarizer(runner),
|
|
306
|
-
autoManage: true,
|
|
307
|
-
})
|
|
339
|
+
autoManage: true,
|
|
340
|
+
})
|
|
308
341
|
|
|
309
|
-
// CORRECT
|
|
342
|
+
// CORRECT — disable autoManage, call memory.manage() after each run
|
|
310
343
|
const memory = createAgentMemory({
|
|
311
344
|
strategy: createSlidingWindowStrategy({ maxMessages: 20 }),
|
|
312
345
|
summarizer: createLLMSummarizer(runner),
|
|
313
346
|
autoManage: false,
|
|
314
347
|
});
|
|
315
348
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
await memory.manage(); // Awaits the async summarizer
|
|
349
|
+
await orchestrator.run(agent, prompt);
|
|
350
|
+
await memory.manage(); // awaits the async summarizer
|
|
319
351
|
```
|
|
320
352
|
|
|
321
|
-
## Quick
|
|
353
|
+
## Quick reference
|
|
322
354
|
|
|
323
|
-
| Guardrail |
|
|
355
|
+
| Guardrail | Phase | Required options |
|
|
324
356
|
|---|---|---|
|
|
325
|
-
| `createPIIGuardrail` |
|
|
326
|
-
| `createModerationGuardrail` |
|
|
327
|
-
| `createRateLimitGuardrail` |
|
|
328
|
-
| `createToolGuardrail` |
|
|
329
|
-
| `createOutputSchemaGuardrail` |
|
|
330
|
-
| `createOutputTypeGuardrail` |
|
|
331
|
-
| `createLengthGuardrail` |
|
|
332
|
-
| `createContentFilterGuardrail` |
|
|
357
|
+
| `createPIIGuardrail` | input | (none — sensible defaults) |
|
|
358
|
+
| `createModerationGuardrail` | input + output | `checkFn` |
|
|
359
|
+
| `createRateLimitGuardrail` | input | (none — defaults 100K tokens/60 requests per minute) |
|
|
360
|
+
| `createToolGuardrail` | toolCall | `allowlist` or `denylist` |
|
|
361
|
+
| `createOutputSchemaGuardrail` | output | `validate` (`SchemaValidator<T>`) |
|
|
362
|
+
| `createOutputTypeGuardrail` | output | `type` |
|
|
363
|
+
| `createLengthGuardrail` | output | one of `maxCharacters` or `maxTokens` |
|
|
364
|
+
| `createContentFilterGuardrail` | output | `blockedPatterns` |
|
|
365
|
+
|
|
366
|
+
## See also
|
|
367
|
+
|
|
368
|
+
- [`ai-orchestrator.md`](./ai-orchestrator.md) — `guardrails: { input, output, toolCall }` and `memory:` options on `createAgentOrchestrator`
|
|
369
|
+
- [`ai-security.md`](./ai-security.md) — `createPIIGuardrail`, `createPromptInjectionGuardrail`, `createAuditTrail`, `createCompliance` — the security-flavored guardrails
|
|
370
|
+
- [`ai-budget-resilience.md`](./ai-budget-resilience.md) — `createSemanticCache` pairs with `createSemanticCacheGuardrail` for caching-as-guardrail
|