claudio.cool
CCAR-FLessons

CCAR-F · Agentic Architecture

Agent SDK hooks: intercepting calls and normalizing results

⏱ 3 min readDraft

A hook is your own code that the Agent SDK runs at a fixed point in the agent’s cycle. Because the SDK runs it, not the model, it gives a deterministic guarantee: it always happens, whatever Claude decides. The key for the exam is when each one runs.

Before or after the tool

PreToolUse PostToolUse
When it runs Before the tool executes After the tool executes and before the model sees the result
What it can do Block the call or modify its input Transform, trim or mask the result
What it’s for Policies: “this never runs without…” Data: “the model always receives this clean”

PreToolUse: intercepting the call

The PreToolUse hook looks at the tool name and its parameters and decides. It is the tool for tool call interception:

  • Block: a refund over $500 does not run and the case is redirected to a human. In the SDK, the hook returns a deny decision together with a reason.
  • Explain the block: the reason goes back to the agent. If it says why the call was denied and what to do instead (“run aml_check first” or “escalate to a supervisor”), the agent changes course. A silent block makes it repeat the same call until the limit.
  • Modify the input: if search_orders arrives with no date range, the hook adds a 90-day default before it runs. The full table scan never happens, and if the agent did give a range, it stays as it was.

PostToolUse: normalizing the result

The PostToolUse hook is the last point before the result enters the context. It is the place for data normalization:

  • three MCP servers return dates as a Unix timestamp, ISO 8601 and “03/04/26”: the hook converts them all to ISO 8601 and the model stops mixing up day and month;
  • numeric status codes are translated to text;
  • full card numbers are masked, so they never reach the context or the logs, without touching a tool you can’t change;
  • a 40 KB response is trimmed to the three fields that matter.

A control doesn’t trust the model

To know whether aml_check passed before allowing transfer_funds, the PreToolUse hook can’t look at a parameter the model wrote or search the conversation for a phrase: that is believing what the model says about itself. The reliable design is a PostToolUse hook on aml_check that records the real result in application state, and a PreToolUse hook on transfer_funds that checks that state.

The usual traps

  • Blocking with PostToolUse: by the time it runs, the transfer is gone. To prevent, use PreToolUse.
  • Normalizing with PreToolUse: the messy dates come in the result, not in the call.
  • Asking the model to ignore or not repeat something: the data still enters the context, and it’s still probabilistic.
  • Improving the prompt to go from 95% to 100%: no prompt reaches 100%; a hook does.
  • Removing tools to avoid the problem: it cuts functionality instead of fixing it.

In the exam

Ask yourself two things: is a guarantee needed, or is guidance enough? If a guarantee is needed, is the problem in the call (PreToolUse) or in the result (PostToolUse)? With those two answers, there is almost always only one option left.

Quick question

A practice exam question on this domain. It counts towards your progress.

An online furniture store has a customer support agent that handles delivery questions, returns and refunds up to a policy limit. In its first month in production, the team has seen both unnecessary escalations, which clog the human queue, and cases that should have reached a person but did not.

The team is now defining exactly when the agent should hand a conversation over to a human. Several proposals have been put forward by different team members, and the product owner wants triggers that are clear and reliable. The human support team has eight people and works office hours only.

Which is the most appropriate escalation trigger?

Practise this domain in a practice exam →