What you’ll be able to do
- Distinguish SDK-level lifecycle hooks from prompt-level instructions for enforcement
- Place policy, logging, and guardrail logic at the correct lifecycle point
- Explain why hook-based enforcement survives prompt drift and prompt injection better than instructions
- Separate Agent SDK hooks from Claude Code’s own hooks configuration
What you need to know
A prompt instruction is a request. A hook is a gate.
Telling a model in its system prompt "never call the delete_account tool without explicit user confirmation" is a request the model is expected to honor. Most of the time it will. But a system prompt is data the model reasons over, not a mechanism that physically prevents an action — a sufficiently adversarial input, a long conversation that dilutes the instruction's salience, or a genuine model mistake can all produce the tool call anyway.
An Agent SDK lifecycle hook that intercepts a tool call before it executes and rejects it unless a confirmation flag is present doesn't ask — it blocks. That's the architectural distinction: prompts are advisory, hooks are structural. Anything that must never happen belongs in a hook, not only in the instructions.
Where hooks belong in the lifecycle
An agent's execution has natural interception points, and different responsibilities belong at different ones:
- Before a tool executes — validate the tool call's arguments, enforce a policy (block a disallowed tool, require confirmation for a destructive one), or redact sensitive fields before they reach an external system.
- After a tool executes — log the call and its result for audit, redact sensitive data out of what flows back into context, or trigger a side effect like a notification.
- Around the full turn — enforce a budget (token count, cost, elapsed time) and halt the loop if it's exceeded, independent of what any individual tool call does.
Putting a guardrail at the wrong point undermines it. Logging after execution doesn't stop a bad call from happening — it only tells you it happened. Enforcement has to sit before the action it's meant to prevent.
Why hooks resist what prompts don’t
A hook's logic lives in code the model doesn't see and can't reason its way around. This matters specifically against prompt injection: if a tool result or a piece of retrieved content contains text engineered to convince the model to ignore its instructions, a prompt-level safeguard is exactly the thing being attacked. A hook that categorically blocks a dangerous tool call regardless of what the model was just told isn't vulnerable to that attack in the same way — it doesn't consult the model's current beliefs at all.
Not the same thing as Claude Code’s hooks
Claude Code has its own hooks feature — configuration in settings.json that runs shell commands at points in the CLI's lifecycle, like before a tool runs or when a session starts. That's a product feature of the Claude Code tool itself, configured declaratively, aimed at a developer's local workflow.
Agent SDK lifecycle hooks are a different thing: code-level callbacks inside a custom application you're building with the Agent SDK, aimed at production enforcement for an agent your system deploys. Same word, different layer — the exam tests whether you know which one a scenario is actually describing.
Key concept
Enforcement belongs in a hook, not a prompt. A system prompt instruction is something the model honors; a lifecycle hook is something the system enforces regardless of what the model decides.
When a scenario asks how to guarantee a dangerous action never happens — not "reduce the chance," but guarantee — the answer is a code-level hook, not a stronger instruction.
Practice scenario
Work it through, then open this
The $10,000 limit was enforced only as a prompt instruction, which is advisory and can be overridden by a long conversation or content engineered to distract from it. The fix is a pre-tool-call hook on the transfer tool itself that checks the amount against the limit and blocks or requires explicit second approval before execution — a check the model’s own reasoning can’t route around, because it doesn’t run inside the model’s reasoning at all.
Build exercise — Move an enforcement rule from prompt to hook
Intermediate · 20 min
What you’ll learn
- Identifying a safety rule that currently exists only as a prompt instruction
- Designing a pre-tool-call hook that enforces it structurally
- Choosing the right lifecycle point for a given guardrail
-
Find a rule in an agent’s system prompt that describes something the agent should never do.
- Why: Rules phrased as “never do X” in a prompt are the ones most worth checking for a code-level backstop.
- You should see: A rule that currently has no enforcement mechanism other than the model reading and following it.
-
Design a pre-tool-call hook that would block the disallowed action structurally, independent of the model’s current reasoning.
- Why: This converts an advisory instruction into a guarantee.
- You should see: A check written in code against the tool’s arguments, not a re-statement of the rule in different words.
-
Decide whether the hook belongs before the tool call, after it, or around the whole turn, and justify the choice.
- Why: Placement determines whether the hook prevents the action or only records that it happened.
- You should see: A specific lifecycle point matched to what the guardrail is actually meant to do.
Exam traps
Enforcing a safety rule only in the system prompt with no code-level backstop
Prompts are advisory. Anything that must never happen needs a structural gate, not just an instruction.
Confusing Claude Code’s hooks configuration with Agent SDK lifecycle hooks in a custom application
Same word, two different layers — one is a CLI product feature, the other is application-level code you write.
Logging tool calls after the fact instead of gating them before execution
After-the-fact logging tells you what happened. It doesn’t prevent anything.
Putting guardrail logic in a place the model’s own output can influence or bypass
If the check consults something the model just produced, a sufficiently engineered input can influence the check itself.
Using a hook for something a simple return-value check in the tool itself would handle
Not every validation needs the full hook machinery — reserve it for cross-cutting policy, not per-tool input checking that belongs in the tool.