Stark-Kit / Docs

Guardrails & Hooks

The hooks option lets you inject behavior at three key points in the run loop. This is useful for guardrails, logging, secrets redaction, and policy enforcement.

Defining Hooks

Hooks are provided when defining an Agent. They execute automatically during the loop.

hooks.ts
import "dotenv/config";
import { Agent, ClaudeProvider } from "@mehularora/stark-kit";
const provider = new ClaudeProvider();
const agent = new Agent({
name: "SecureAgent",
provider,
instructions: "Handle user requests.",
hooks: {
// Runs before every LLM call — return a modified history or nothing
beforeChat: async (history) => {
return history.map(msg => ({
...msg,
// Redact API keys from user messages before sending to the LLM
content: typeof msg.content === "string"
? msg.content.replace(/api_key=[\w-]+/gi, "api_key=REDACTED")
: msg.content,
}));
},
// Runs before each tool execution — throw to block, return new args to override
beforeTool: async (toolName, args) => {
if (toolName === "deleteFiles" && (args as any).path.startsWith("/etc")) {
throw new Error("Permission denied: cannot delete system files.");
}
// Returning undefined (or nothing) allows the call to proceed unchanged
},
// Runs after each tool execution — return a modified result string or nothing
afterTool: async (toolName, result, isError) => {
// Mask Social Security numbers in tool responses before the LLM sees them
return result.replace(/\b\d{3}-\d{2}-\d{4}\b/g, "***-**-****");
},
},
});

Hook Signatures

typescript
// AgentHooks interface reference
interface AgentHooks {
// Called with the full message history before every LLM step.
// Return a CanonicalMessage[] to replace the history, or undefined to keep it.
beforeChat?(history: CanonicalMessage[]): Promise<CanonicalMessage[] | void>;
// Called with the tool name and parsed arguments before execution.
// Throw to block the call. Return new args to override them.
beforeTool?(toolName: string, args: unknown): Promise<unknown | void>;
// Called with the tool name, result string, and error flag after execution.
// Return a new string to replace the result the LLM will see.
afterTool?(toolName: string, result: string, isError: boolean): Promise<string | void>;
}
Hook Reference
beforeChat

Receives the full message history. Return a modified history to replace it, or return nothing to leave it unchanged. Good for redacting sensitive data before it reaches the LLM.

beforeTool

Receives the tool name and parsed arguments. Throw an Error to block execution entirely. Return new arguments to override what the model chose. Return nothing to proceed as-is.

afterTool

Receives the tool name, its string result, and a boolean indicating if it errored. Return a new string to replace the result the LLM sees. Useful for masking PII or normalizing output.