@agentick/guardrails
Guardrail middleware for Agentick — gate tool execution with rules and classifiers.
Install
pnpm add @agentick/guardrails
Quick Start
import { toolGuardrail, deny, allow } from "@agentick/guardrails";
const guardrail = toolGuardrail({
rules: [deny("file_delete", "exec_*"), allow("file_read", "file_write")],
});
app.use(guardrail);
API
toolGuardrail(config)
Create middleware that gates tool execution.
toolGuardrail({
rules?: GuardrailRule[],
classify?: GuardrailClassifier,
onDeny?: (toolName: string, reason: string) => void,
})
Only intercepts procedures with operationName === "tool:run". Other procedures pass through.
deny(...patterns)
Create a deny rule.
deny("file_delete", "exec_*");
allow(...patterns)
Create an allow rule.
allow("file_read", "search");
Rule Patterns
Patterns support * wildcard matching:
"search" | Exact match only |
"file_*" | file_read, file_write, ... |
"*_admin" | read_admin, write_admin, ... |
"*" | Everything |
Evaluation Order
- Static rules — first-match-wins
deny → throw GuardrailDenied
allow → skip classifier, proceed
- Classifier — only runs if no rule matched
- Return
{ action: "deny", reason } to block
- Return
null / undefined / { action: "allow" } to proceed
- Default — allow
Classifier
const guardrail = toolGuardrail({
classify: async (call, envelope) => {
if (call.input?.dangerous) {
return { action: "deny", reason: "Dangerous input detected" };
}
return null;
},
});
Error Handling
Denied tools throw GuardrailDenied (extends GuardError):
import { isGuardError } from "@agentick/shared";
try {
await tool.run(input);
} catch (error) {
if (isGuardError(error)) {
}
}
The model sees a tool error result with the denial reason, allowing it to try a different approach.
Future
inputGuardrail — gate based on user input content
outputGuardrail — gate based on model output content