Back to Blog

Controlling Claude Agent Execution With Hooks in the Agent SDK

March 20, 20268 min readMichael Ridland

One of the things that separates a demo AI agent from a production AI agent is control. In a demo, the agent does its thing and you hope for the best. In production, you need to intercept the agent at specific points, validate what it's about to do, log what it did, and sometimes stop it from doing something stupid.

That's what hooks are for in the Claude Agent SDK. They give you defined interception points in the agent's execution loop where you can run your own code. Think of them as middleware for AI agents - if you've ever worked with Express.js middleware or ASP.NET action filters, the concept is similar.

We build a lot of AI agent systems for Australian businesses, and hooks are one of the first things we configure in any production deployment. Let me walk through how they work and where they matter.

What Hooks Are

Hooks are shell commands or scripts that execute in response to specific events during a Claude agent's execution. When the agent is about to call a tool, a hook can run first. When the agent finishes a tool call, another hook can run. When the agent starts or stops a session, hooks can fire then too.

The key thing is that hooks run outside the agent's context. They're not part of the conversation, they're not consuming tokens, and they're not influenced by the agent's reasoning. They're your code, running at your discretion, with full access to the system. This separation matters because it means the agent can't talk its way past a hook the way it might talk its way past a system prompt instruction.

Anthropic's official hooks documentation covers the full configuration syntax.

Types of Hooks

The Agent SDK provides several hook points. The ones I find most useful in practice:

Pre-tool-call hooks. These run before the agent executes a tool. The hook receives information about which tool is being called and with what parameters. Your hook can approve the call, modify the parameters, or block the call entirely. This is your primary safety mechanism.

Post-tool-call hooks. These run after a tool call completes. You get the tool name, parameters, and the result. Useful for logging, auditing, and triggering downstream actions based on what the agent just did.

Session start hooks. These fire when an agent session begins. Good for initialisation - loading user context, setting up logging, checking prerequisites.

Session end hooks. These fire when a session wraps up. Clean up resources, finalise logs, trigger notifications.

Prompt submission hooks. These run when user input is received, before the agent processes it. Useful for input validation and content filtering.

Why This Matters for Production Agents

Let me give you some concrete scenarios from our client work to explain why hooks earn their complexity.

Preventing unintended file operations. We built an agent for a client that helps their development team with code reviews and refactoring suggestions. The agent has access to file system tools - it can read code, suggest changes, even write files. Without hooks, there's nothing stopping the agent from modifying files outside the project directory, or deleting files it shouldn't touch. A pre-tool-call hook that checks the file path before any write or delete operation is the kind of guardrail you don't want to rely on system prompt instructions for.

Audit logging for compliance. Several of our clients in financial services and healthcare need a complete audit trail of everything an AI agent does. Not just the conversation transcript - the actual tool calls, parameters, results, and timestamps. Post-tool-call hooks that write structured log entries to an audit system give you this without bloating the agent's context window.

Cost control. AI agents can be expensive if they go off on tangents. We've had situations where an agent gets stuck in a loop, repeatedly calling the same tool, burning through API credits. A hook that tracks tool call frequency and blocks excessive calls has saved clients real money. One client's agent racked up $400 in API costs in a single afternoon before we added rate limiting hooks. That was an expensive lesson that we now prevent by default.

Dynamic permission management. Different users should be able to do different things through the same agent. A pre-tool-call hook that checks the user's role against a permissions table before allowing database writes, external API calls, or file modifications is much more reliable than trying to explain permissions in the system prompt.

Practical Implementation Patterns

Here are the patterns we use most frequently.

The Allowlist Pattern

The simplest and most common hook. Before any tool call, check whether the tool and its parameters match an allowlist. If not, block it.

This works well when you have a clearly defined set of operations the agent should be able to perform. A customer service agent that can look up orders, check delivery status, and process simple returns gets an allowlist with exactly those three tool types. Anything else - database modifications, file system access, external API calls - gets blocked automatically.

The beauty of an allowlist is that it's secure by default. New tools or capabilities don't accidentally become available just because someone updated the agent's system prompt. You have to explicitly add them to the allowlist.

The Logging Pipeline Pattern

Every tool call - before and after - gets logged to a structured data store. We typically send these to Azure Application Insights or a similar monitoring platform. The log includes the tool name, parameters, result summary, execution time, and any errors.

This gives you visibility into what your agent is actually doing across all sessions. You can spot patterns - which tools are used most, which ones fail frequently, where agents get stuck. This data is gold for improving agent performance over time.

The Escalation Pattern

Pre-tool-call hooks that detect when an agent is about to do something that should involve a human. Maybe it's a refund above a certain dollar amount, a data deletion request, or a response to a complaint. The hook blocks the tool call and instead triggers a notification to a human operator who can review and approve or deny the action.

This is the pattern that makes business stakeholders comfortable with AI agents. They're not worried about the 95% of interactions that are routine. They're worried about the 5% where the agent might do something wrong that has real consequences. Hooks let you put humans in the loop for exactly those high-stakes moments.

The Transformation Pattern

Sometimes you want to modify what the agent sends to a tool before it actually executes. A pre-tool-call hook can sanitise inputs, add default parameters, enforce formatting standards, or inject additional context. For example, if your agent is sending database queries, a hook can add a row limit to prevent accidentally pulling millions of records.

Setting Up Hooks

The configuration lives in your Claude Agent SDK settings. Hooks are defined as shell commands or script paths that receive event data via standard input and return responses via standard output.

A typical setup looks like defining your hook scripts, pointing the SDK configuration at those scripts for each event type, and handling the input/output contract. The scripts can be written in any language - Python, Node.js, Bash, whatever fits your stack. We usually write ours in Python because most of our agent infrastructure is already Python-based, but for .NET shops we've also built hooks in C#.

The important thing is reliability. A hook that crashes or hangs will block your agent's execution. Keep hooks simple, fast, and well-tested. A hook that takes 5 seconds to execute adds 5 seconds of latency to every tool call it intercepts. For pre-tool-call hooks that run on every single operation, you want sub-100ms execution times.

Mistakes We've Made So You Don't Have To

Over-hooking. Early on, we put hooks on everything. Every tool call, every message, every session event. The agent became noticeably slower and the log volume was overwhelming. Now we're more selective - hooks go where there's a specific risk to mitigate or a specific requirement to meet.

Fragile hooks that break silently. We had a logging hook that depended on an external API endpoint. When that endpoint went down, the hook failed silently and we lost three days of audit logs. Now all our hooks have local fallback logging and alerting when the primary destination is unreachable.

Not testing hooks against the agent. Hooks that work in unit tests sometimes behave differently when they're processing real agent output. The data format, the timing, the edge cases - you need to test hooks with actual agent sessions, not just synthetic data.

Where Hooks Fit in the Bigger Picture

Hooks are one piece of a responsible AI agent deployment. They work alongside system prompts (for guiding agent behaviour), tool definitions (for defining what the agent can do), and monitoring systems (for tracking how the agent performs over time).

If you're building AI agents using the Claude Agent SDK - or any agent framework - spend time on your hook infrastructure early. It's less exciting than building the agent's capabilities, but it's what lets you deploy with confidence and sleep at night.

We work with Australian businesses on AI agent development across multiple frameworks including the Claude Agent SDK. If you're building agents that need production-grade controls, or if you're looking at agentic automation for your business processes, we can help you design the right architecture from the start.

The agents themselves are getting smarter every month. Hooks make sure that intelligence stays pointed in the right direction.