Guardrails
Guardrails run before and after each agent step to validate messages, detect unsafe content, and enforce policies. The framework ships a GuardrailValidator with composable rules that you pass to createAgent().
Quick start
ts
import { createAgent } from 'personaforge';
import { GuardrailValidator, createPiiDetectionRule, createPromptInjectionRule } from 'personaforge';
const guardrails = new GuardrailValidator({
rules: [
createPromptInjectionRule({ threshold: 0.7 }),
createPiiDetectionRule({ redact: true }),
],
});
const agent = createAgent({
name: 'safe-agent',
instructions: 'You are a helpful assistant.',
model: 'gpt-4o-mini',
apiKey: process.env.OPENAI_API_KEY!,
guardrails,
});Pass guardrails: false to disable all guardrails.
GuardrailValidator
The core engine. Compose any combination of built-in and custom rules.
ts
import { GuardrailValidator } from 'personaforge';
const guardrails = new GuardrailValidator({
rules: [rule1, rule2, rule3],
onViolation: (violation, ctx) => {
// called when any rule fires
console.warn('Guardrail violation:', violation.rule, violation.message);
// return 'block' | 'warn' | 'redact' | 'continue'
},
});PII detection
Detect and optionally redact personally identifiable information:
ts
import { createPiiDetectionRule } from 'personaforge';
const piiRule = createPiiDetectionRule({
redact: true, // replace PII with [REDACTED]
// redact: false // just flag without modifying
// PII types to detect (all enabled by default):
types: ['email', 'phone', 'ssn', 'credit_card', 'jwt', 'aws_key', 'api_key'],
});Detected PII types: email · phone · ssn · credit_card · national_insurance · passport · aws_key · api_key · jwt · and more from PII_PATTERNS.
ts
import { detectPii, PII_PATTERNS } from 'personaforge';
// Use standalone (no agent required) — detectPii is synchronous
const result = detectPii('Contact me at alice@example.com or 555-123-4567', { extract: true });
console.log(result.found); // true
console.log(result.types); // ['email', 'phone']
console.log(result.matches); // { email: ['alice@example.com'], phone: ['555-123-4567'] }Prompt injection detection
Block attempts to hijack the agent via crafted input:
ts
import { createPromptInjectionRule, detectPromptInjection } from 'personaforge';
const injectionRule = createPromptInjectionRule({
threshold: 0.7, // 0.0–1.0; higher = stricter. Default: 0.7
});
// Standalone usage — detectPromptInjection is synchronous:
const detection = detectPromptInjection('Ignore all previous instructions and...');
console.log(detection.isInjection); // true
console.log(detection.score); // 0.95
console.log(detection.signals); // [{ pattern: 'instruction-override', description, weight, match }, ...]LLM-based injection classifier (higher accuracy)
ts
import { createLlmInjectionClassifier } from 'personaforge';
import { OpenAIProvider } from 'personaforge';
const injectionRule = createLlmInjectionClassifier({
llm: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY! }),
model: 'gpt-4o-mini',
threshold: 0.8,
});Content moderation
OpenAI Moderation API
ts
import { createOpenAiModerationRule } from 'personaforge';
const moderationRule = createOpenAiModerationRule({
apiKey: process.env.OPENAI_API_KEY!,
// Block if any category score exceeds threshold:
thresholds: {
hate: 0.7,
'hate/threatening': 0.5,
harassment: 0.7,
'self-harm': 0.5,
sexual: 0.8,
violence: 0.7,
},
});Forbidden topics
ts
import { createForbiddenTopicsRule } from 'personaforge';
const topicsRule = createForbiddenTopicsRule({
topics: ['competitor pricing', 'internal salary data', 'acquisition plans'],
action: 'block', // 'block' | 'warn'
});Content and length rules
ts
import {
createContentRule,
createMaxLengthRule,
createAllowlistRule,
createSensitiveDataRule,
createUrlValidationRule,
} from 'personaforge';
const rules = [
// Block responses that contain specific patterns.
// Signature: createContentRule(name, description, pattern, severity?)
createContentRule(
'no-credentials',
'Blocks responses containing credential patterns.',
/\b(password|secret|token)\s*[:=]/i,
'error',
),
// Limit output length.
// Signature: createMaxLengthRule(name, maxLength, severity?)
createMaxLengthRule('max-length', 10_000, 'error'),
// Enforce an allowlist over tools, hosts, paths, outputs, and blocked patterns.
createAllowlistRule({
allowedTools: ['search', 'get_order'],
allowedHosts: ['api.company.com', 'docs.company.com'],
blockedPatterns: [/\b(password|secret)\b/i],
}),
// Flag built-in sensitive data patterns (credit cards, SSNs, API keys). No args.
createSensitiveDataRule(),
// Restrict URLs to allowed protocols (and optionally hosts).
// Signature: createUrlValidationRule(allowedProtocols, allowedHosts?)
createUrlValidationRule(['https:'], ['api.company.com', 'docs.company.com']),
];Tool allowlist
Restrict which tools the agent can call from within a guardrail rule:
ts
import { createToolAllowlistRule } from 'personaforge';
// Signature: createToolAllowlistRule(allowedTools). Any tool not in the list
// is blocked before execution.
const toolRule = createToolAllowlistRule(['search_orders', 'get_product_info']);Custom rules
ts
import type { GuardrailRule, GuardrailContext, GuardrailResult } from 'personaforge';
const noProfanityRule: GuardrailRule = {
name: 'no-profanity',
description: 'Blocks prohibited language in agent output.',
severity: 'error', // 'error' | 'warning'
check: (ctx: GuardrailContext): GuardrailResult => {
const text = typeof ctx.output === 'string' ? ctx.output : '';
const hasProfanity = /\b(badword1|badword2)\b/i.test(text);
if (hasProfanity) {
return {
passed: false,
rule: 'no-profanity',
message: 'Response contains prohibited language.',
};
}
return { passed: true, rule: 'no-profanity' };
},
};
const guardrails = new GuardrailValidator({ rules: [noProfanityRule] });Full example: production guardrail stack
ts
import { createAgent } from 'personaforge';
import {
GuardrailValidator,
createPromptInjectionRule,
createPiiDetectionRule,
createOpenAiModerationRule,
createForbiddenTopicsRule,
createMaxLengthRule,
createToolAllowlistRule,
} from 'personaforge';
const guardrails = new GuardrailValidator({
rules: [
createPromptInjectionRule({ threshold: 0.75 }),
createPiiDetectionRule({ redact: true }),
createOpenAiModerationRule({ apiKey: process.env.OPENAI_API_KEY! }),
createForbiddenTopicsRule({ topics: ['competitor pricing', 'legal strategy'] }),
createMaxLengthRule('max-length', 8_000, 'error'),
createToolAllowlistRule(['search', 'get_order', 'send_email']),
],
onViolation: (violation) => {
// Send to your audit log
auditLogger.warn({ rule: violation.rule, action: violation.action, score: violation.score });
},
});
const agent = createAgent({
name: 'customer-service',
instructions: 'You are a customer service agent for Acme Corp.',
model: 'gpt-4o-mini',
apiKey: process.env.OPENAI_API_KEY!,
guardrails,
tools: [searchTool, orderTool, emailTool],
});Where to go next
- HITL — escalate violations to a human instead of auto-blocking.
- Production — rate limiting, circuit breakers, and audit logging.
- Agents — how guardrails fit into the full
createAgent()config.