| name | identity-and-guardrails |
| description | Enable prompt injection detection, PII masking, behavioral contracts, kill switch controls, and audit logging for safe production deployments. |
| compatibility | Reactive Agents TypeScript projects using @reactive-agents/* |
| metadata | {"author":"reactive-agents","version":"2.0","tier":"capability"} |
Identity and Guardrails
Agent objective
Produce a builder with guardrails, behavioral contracts, and safety controls correctly configured so the agent operates within defined bounds and can be stopped when needed.
When to load this skill
- Deploying an agent in a multi-tenant or public-facing context
- Restricting which tools an agent can call or which topics it can address
- Requiring human approval before certain tool calls
- Needing runtime pause/resume/stop controls
- Enforcing token/iteration/output-length budgets at the contract level
Implementation baseline
import { ReactiveAgents } from "@reactive-agents/runtime";
const agent = await ReactiveAgents.create()
.withName("assistant")
.withProvider("anthropic")
.withReasoning({ defaultStrategy: "adaptive" })
.withTools({ allowedTools: ["web-search", "http-get", "file-read", "checkpoint"] })
.withGuardrails({
injection: true,
pii: true,
toxicity: true,
})
.withBehavioralContracts({
deniedTools: ["file-write", "shell-execute"],
maxToolCalls: 30,
maxIterations: 20,
requireDisclosure: true,
})
.withKillSwitch()
.withAudit()
.build();
Key patterns
Guardrails
.withGuardrails()
.withGuardrails({
injection: true,
pii: false,
toxicity: true,
customBlocklist: ["competitor-product", "internal-codename"],
})
Guardrail violations abort the turn and return a structured error — the agent never processes the blocked content.
Behavioral contracts
Full field reference for .withBehavioralContracts(contract):
.withBehavioralContracts({
deniedTools: ["file-delete", "shell-execute"],
allowedTools: ["web-search", "file-read"],
maxToolCalls: 50,
maxIterations: 20,
maxOutputLength: 4000,
deniedTopics: ["competitor names", "legal advice"],
requireDisclosure: true,
})
Contract violations are enforced at runtime — violations halt the current turn with a ContractViolation error.
Kill switch (runtime control)
.withKillSwitch()
const handle = agent.run("Do a long task...");
await handle.pause();
await handle.resume();
await handle.stop("User requested cancellation");
await handle.terminate("Emergency shutdown");
Kill switch controls are no-ops if .withKillSwitch() was not called during build.
Audit
.withAudit()
Audit events flow to the observability stream — pair with .withObservability() to capture them.
GuardrailsOptions reference
| Field | Type | Default | Notes |
|---|
injection | boolean | true | Prompt injection detection |
pii | boolean | true | PII detection and masking |
toxicity | boolean | true | Toxic content detection |
customBlocklist | string[] | [] | Case-insensitive substring blocklist |
BehavioralContract reference
| Field | Type | Notes |
|---|
deniedTools | string[] | Tools that may never be called |
allowedTools | string[] | If set, only these tools are allowed |
maxToolCalls | number | Hard stop after N total tool calls |
maxIterations | number | Hard stop after N reasoning iterations |
maxOutputLength | number | Max output characters before truncation |
deniedTopics | string[] | Topics the agent must refuse |
requireDisclosure | boolean | Agent must disclose AI identity |
Pitfalls
.withGuardrails() with no args enables ALL detectors — disable selectively if your use case legitimately handles PII
deniedTools in a contract and allowedTools in .withTools() are independent — a tool can be in .withTools({ allowedTools }) but still blocked by a contract's deniedTools
- Kill switch controls (
pause, resume, stop, terminate) are no-ops without .withKillSwitch() — no error is thrown, calls are silently ignored
requireDisclosure enforces the agent states it is AI in its first response — this is a prompt-level enforcement, not cryptographic
- Contract violations raise
ContractViolation errors — handle these in your error callback or the agent run will throw
.withAudit() without a log destination writes to the observability stream — add .withObservability() to capture audit events