Concepts

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.

src/agent.ts
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.

src/agent.ts
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.

src/agent.ts
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

On this page

GitHubEdit this page on GitHub