| name | hardening-ai-systems |
| description | Add guardrails (input/output validation), memory strategies, token budgets, PII detection, prompt injection prevention, and circuit breakers to AI orchestrators. Use when enforcing content policies, managing costs, preventing security vulnerabilities, adding resilience, or implementing agent memory across turns. |
Hardening AI Systems
Prerequisites
This skill applies when the project uses @directive-run/ai. If not found in package.json, suggest installing it: npm install @directive-run/ai.
When Claude Should Use This Skill
Auto-Invoke Triggers
- User asks about input/output validation for LLM calls
- User wants to prevent harmful content or prompt injection
- User needs to control token spending or set cost limits
- User asks about agent memory, conversation history, or context management
- User mentions
createGuardrail, GuardrailError, createAgentMemory
- User wants retry logic, circuit breakers, or failure resilience
Exclusions
- Do NOT invoke for basic orchestrator/agent setup – use
building-ai-orchestrators
- Do NOT invoke for streaming or provider setup – use
building-ai-agents
- Do NOT invoke for test mocking – use
testing-ai-systems
Quick Reference
Decision Tree: Which Hardening Feature?
What do you need?
├── Block bad inputs before LLM call → Input guardrail
├── Validate/filter LLM output → Output guardrail
├── Remember context across turns → createAgentMemory
├── Limit cost / token spend → maxTokenBudget
├── Detect PII in prompts → PII guardrail
├── Prevent prompt injection → Injection guardrail
└── Handle provider failures gracefully → Circuit breaker + retry
Guardrails
Guardrails are pure validators. They check content and throw GuardrailError on violation. They must NOT modify the content they check.
Input + Output Guardrails
import { createGuardrail, GuardrailError } from "@directive-run/ai";
const lengthGuardrail = createGuardrail({
name: "input-length",
type: "input",
check: async (input) => {
if (input.prompt.length > 10_000) {
throw new GuardrailError({
code: "INPUT_TOO_LONG",
message: `Input exceeds 10,000 characters (got ${input.prompt.length})`,
guardrail: "input-length",
});
}
},
});
const toxicityGuardrail = createGuardrail({
name: "toxicity-check",
type: "output",
check: async (output) => {
const score = await getToxicityScore(output.text);
if (score > 0.8) {
throw new GuardrailError({
code: "TOXIC_OUTPUT",
message: `Toxicity score ${score} exceeds threshold`,
guardrail: "toxicity-check",
});
}
},
});
const orchestrator = createAgentOrchestrator({
runner: createAnthropicRunner({ model: "claude-opus-4-6", apiKey: process.env.ANTHROPIC_API_KEY }),
guardrails: [lengthGuardrail, toxicityGuardrail],
factsSchema: {
input: t.string(),
output: t.string().optional(),
status: t.string<"idle" | "done" | "blocked">(),
violationCode: t.string().optional(),
},
init: (facts) => {
facts.status = "idle";
},
resolvers: {
process: {
requirement: "PROCESS",
resolve: async (req, context) => {
try {
const result = await context.runner.run({ prompt: context.facts.input });
context.facts.output = result.text;
context.facts.status = "done";
} catch (error) {
if (error instanceof GuardrailError) {
context.facts.status = "blocked";
context.facts.violationCode = error.code;
} else {
throw error;
}
}
},
},
},
});
Security Guardrails
PII Detection
const piiGuardrail = createGuardrail({
name: "pii-check",
type: "input",
check: async (input) => {
const patterns: Record<string, RegExp> = {
ssn: /\b\d{3}-\d{2}-\d{4}\b/,
creditCard: /\b\d{4}[\s-]\d{4}[\s-]\d{4}[\s-]\d{4}\b/,
email: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/,
};
const detected = Object.entries(patterns)
.filter(([, re]) => re.test(input.prompt))
.map(([type]) => type);
if (detected.length > 0) {
throw new GuardrailError({
code: "PII_DETECTED",
message: `Input contains PII: ${detected.join(", ")}`,
guardrail: "pii-check",
metadata: { piiTypes: detected },
});
}
},
});
Prompt Injection Prevention
const injectionGuardrail = createGuardrail({
name: "injection-prevention",
type: "input",
check: async (input) => {
const patterns = [
/ignore\s+(all\s+)?previous\s+instructions/i,
/you\s+are\s+now\s+(?:in\s+)?(?:developer|admin|god)\s+mode/i,
/disregard\s+(?:your\s+)?(?:system\s+)?instructions/i,
/<\|im_start\|>/i,
];
const matched = patterns.some((re) => re.test(input.prompt));
if (matched) {
throw new GuardrailError({
code: "PROMPT_INJECTION",
message: "Potential prompt injection detected",
guardrail: "injection-prevention",
});
}
},
});
Agent Memory
import { createAgentMemory } from "@directive-run/ai";
const memory = createAgentMemory({
strategy: "sliding-window",
maxMessages: 20,
maxTokens: 8000,
});
const summaryMemory = createAgentMemory({
strategy: "summary",
maxMessages: 50,
summarizeAfter: 30,
summaryRunner: createAnthropicRunner({ model: "claude-haiku-4-5", apiKey: process.env.ANTHROPIC_API_KEY }),
});
const semanticMemory = createAgentMemory({
strategy: "semantic",
maxRetrieved: 5,
embedder: myEmbeddingFunction,
});
resolvers: {
respond: {
requirement: "RESPOND",
resolve: async (req, context) => {
const result = await context.runner.run({
prompt: context.facts.userMessage,
messages: context.memory.getMessages(),
});
context.facts.response = result.text;
},
},
},
Token Budget Management
const orchestrator = createAgentOrchestrator({
runner: createAnthropicRunner({ model: "claude-opus-4-6", apiKey: process.env.ANTHROPIC_API_KEY }),
budget: {
maxTokenBudget: 100_000,
budgetWarningThreshold: 0.8,
onBudgetWarning: (used, max) => {
console.warn(`Budget at ${Math.round((used / max) * 100)}%`);
},
},
factsSchema: {
input: t.string(),
output: t.string().optional(),
tokensUsed: t.number(),
},
init: (facts) => {
facts.tokensUsed = 0;
},
resolvers: {
process: {
requirement: "PROCESS",
resolve: async (req, context) => {
if (!context.budget.canAfford(estimateTokens(context.facts.input))) {
throw new Error("Insufficient token budget");
}
const result = await context.runner.run({ prompt: context.facts.input });
context.facts.output = result.text;
context.facts.tokensUsed += result.usage.totalTokens;
},
},
},
});
function estimateTokens(text: string): number {
return Math.ceil(text.length / 4);
}
Resilience: Circuit Breaker + Retry
import { createCircuitBreaker } from "@directive-run/ai";
const breaker = createCircuitBreaker({
failureThreshold: 5,
recoveryTimeout: 30_000,
halfOpenRequests: 2,
onStateChange: (from, to) => console.log(`Circuit: ${from} → ${to}`),
});
resolvers: {
callLLM: {
requirement: "CALL_LLM",
retry: {
attempts: 3,
backoff: "exponential",
initialDelay: 500,
maxDelay: 10_000,
retryOn: (error) => {
return error.message.includes("rate_limit") ||
error.message.includes("overloaded");
},
},
resolve: async (req, context) => {
const result = await context.runner.run({ prompt: context.facts.input });
context.facts.output = result.text;
},
},
},
Critical Anti-Patterns
Guardrails that modify content
const bad = createGuardrail({
name: "sanitizer",
type: "input",
check: async (input) => {
input.prompt = input.prompt.replace(/badword/g, "***");
return input;
},
});
const good = createGuardrail({
name: "content-check",
type: "input",
check: async (input) => {
if (input.prompt.includes("badword")) {
throw new GuardrailError({ code: "PROHIBITED", message: "Prohibited content", guardrail: "content-check" });
}
},
});
Not setting token budgets in production
const orchestrator = createAgentOrchestrator({ runner, });
const orchestrator = createAgentOrchestrator({
runner,
budget: { maxTokenBudget: 50_000, budgetWarningThreshold: 0.8 },
});
Catching GuardrailError silently
} catch (e) { }
} catch (error) {
if (error instanceof GuardrailError) {
context.facts.status = "blocked";
context.facts.violationCode = error.code;
} else {
throw error;
}
}
Resolver parameter naming
Always use (req, context) – never (req, ctx) or (request, context).
Reference Files
ai-guardrails-memory.md – Full guardrail API, all memory strategies, configuration options
ai-budget-resilience.md – Budget configuration, circuit breaker, retry policies, estimateTokens
ai-security.md – PII patterns, injection detection, security best practices
examples/auth-flow.ts – Auth-gated orchestrator with security guardrails
examples/fraud-analysis.ts – Budget-aware multi-agent fraud detection