---
title: "Intercept and control agent behavior with hooks Code Agent SDK"
source: https://docs.autohand.ai/agent-sdk/customize/hooks
---

# Intercept and control agent behaviour with hooks

In the SDKs the “hook” surface is the JSON-RPC event stream. You observe what the agent does, log it, and decide whether to allow, deny, or alter the next step. The CLI also exposes filesystem-level hooks for pre and post-prompt scripts.

## Two layers of hooks

-   **SDK-level (event stream)**: subscribe to \`tool\_start\`, \`tool\_update\`, \`tool\_end\`, \`file\_modified\`, \`permission\_request\`, and \`error\`. Use these for logging, metrics, UI rendering, audit trails, and approval gates.
-   **CLI-level (filesystem hooks)**: drop scripts into \`~/.autohand/hooks/\` to run before or after every prompt the CLI handles. Use these for organisation-wide policy, secret scrubbing, or routing every prompt through a logging pipeline.

The Swift SDK additionally exposes a \`HookManager\` that the \`PermissionManager\` consults for in-process approval decisions.

## Hook into the event stream

Wrap a \`streamPrompt\` loop in a small dispatcher. Each branch is a hook: keep them fast, push slow work to a background queue.

## Filesystem hooks

The Autohand CLI looks for executable scripts in \`~/.autohand/hooks/\`. Two slots run on every prompt:

-   **\`pre-prompt\`**: receives the user prompt on stdin. Exit non-zero to block the prompt; print to stdout to rewrite it.
-   **\`post-prompt\`**: receives the final assistant response on stdin. Use it for audit logging, redaction, or downstream notifications.

This is the right layer for org-wide policy that should apply to every SDK consumer, including ad-hoc CLI use.

## Best practices

-   Treat the event stream as your hook surface. It is consistent across SDKs and forward-compatible with new event types.
-   Keep handlers fast. Push slow work (network calls, disk writes) to a background queue.
-   Use filesystem hooks for policy that has to apply to every CLI run, not just SDK code paths.
-   Always handle \`error\` events and \`permission\_request\` in \`interactive\` mode.
-   Avoid mutating the prompt mid-stream. If you need to redirect the agent, call \`abort()\` and start a new run.