Hooks
Intercept agent operations without modifying tools. Use tool.before, tool.after, and status hooks for validation, transformation, and observability.
Add validation, transform inputs and outputs, or observe status updates from a single hooks configuration on the agent. Hooks run for all tools — built-in and custom.
Tool Hooks
Two hooks run around every tool execution: tool.before and tool.after. They apply to all tools—built-in and custom.
tool.before
Called before any tool executes. You can modify the input or throw to block execution.
import { agent } from "experimental-agent";
const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
hooks: {
"tool.before": async ({ name, input, context }) => {
if (name === "Bash" && (input as { command: string }).command.includes("rm -rf")) {
throw new Error("Destructive commands are not allowed");
}
return { input: { ...(input as Record<string, unknown>), command: `cd /safe && ${(input as { command: string }).command}` } };
},
},
});- Return
{ input }— Replace or modify the input before the tool runs. - Throw — Block execution. The tool never runs.
- Return
undefined— Pass through unchanged.
tool.after
Called after any tool executes. You can modify the result before it returns to the model.
hooks: {
"tool.after": async ({ name, input, result, context }) => {
if (name === "Bash") {
const r = result as { stdout: string };
return { result: { ...r, stdout: redactSecrets(r.stdout) } };
}
},
}- Return
{ result }— Replace or modify the result. - Return
undefined— Pass through unchanged.
ToolContext
Both tool hooks receive context: ToolContext:
type ToolContext = {
session: Session;
sandbox: Sandbox;
storage: Storage;
context: TContext; // Per-request data from contextSchema
};Use it to access the session, sandbox, storage, or per-request context (e.g. auth tokens) inside your hooks.
Status Hook
The status hook is called when the agent emits status updates during long operations. Use it for logging, analytics, or custom UI.
const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
hooks: {
status: (status) => {
console.log(`Agent status: ${status.type}`, status);
},
},
});Status types include: sandbox-setup, sandbox-setup-cold, loading-skills, processing-approvals, needs-approval, thinking, and custom. See Streaming for how status flows through the stream.
Scope
Hooks run for all tools—the 8 built-in tools (Read, Write, Edit, Grep, List, Bash, Skill, JavaScript) and any custom tools you add. There is no per-tool hook configuration; use the name parameter inside the hook to branch logic.
Next Steps
- Extending Built-in Tools — Wrap or augment built-in tools with custom behavior
- Tools — Built-in and custom tools
- Streaming — How status updates flow through the stream