A refund must never run before identity is verified. The prompt says so, yet logs show it happened on 1 in 300 conversations. What do you change?
Why B is the answer
Block process_refund with a hook until verification has returned a customer ID
A rule that must always hold needs deterministic enforcement. Better prompting lowers the failure rate but never removes it.
In detail
- A prompt asks and a hook enforces. Instructions shape behavior, but they are probabilistic, so a failure rate of 1 in 300 is what "mostly works" looks like.
- A PreToolUse hook runs in code before the tool. The Claude Code docs say to use one to block an action regardless of what Claude decides.
- Here the check is simple: if the conversation has no verified customer ID, deny process_refund and return a reason. Claude can then go and verify the customer.
- One detail worth knowing: a hook that exits 0 with no output has no decision to report, and staying silent does not approve the call. A block needs a deny decision or exit code 2.
- Keep the prompt rule too, because it guides normal behavior. The hook is what guarantees the order.
Use case
An illustrative scenario, not a real incident.
A retailer's agent is told to verify identity first. Most of the time it does, but in a long conversation it skips the step and refunds the wrong account. A hook on process_refund then blocks the call until get_customer has returned an ID.
See it in different ways
flowchart LR
A["Claude requests a tool"] --> B{"PreToolUse hook"}
B -->|"Deny"| C["Blocked, reason returned"]
B -->|"Allow"| D["Tool runs"]stateDiagram-v2 [*] --> Unverified Unverified --> Unverified: process_refund denied Unverified --> Verified: verification returns a customer ID Verified --> Refunded: process_refund allowed Refunded --> [*]
flowchart LR A["Rule in the prompt"] --> B["Model usually follows it"] C["Rule in a hook"] --> D["Code always checks it"]
sequenceDiagram participant P0 as Agent participant P1 as Hook participant P2 as Refund tool P0->>P1: process_refund, no customer ID yet P1-->>P0: Denied, verify the customer first P0->>P1: process_refund, with customer ID P1->>P2: Allowed P2-->>P0: Refund complete
Key point: If a rule must always hold, enforce it in code.
Why the other options are wrong
- A. Move to a larger model that follows long instructions more reliably
- A larger model is still a model. Reliability that depends on model behavior stays probabilistic.
- C. Repeat the rule in capitals at the top and the bottom of the system prompt
- Emphasis may reduce failures but cannot remove them, and this rule must always hold.
- D. Add more few-shot examples showing verification always happening first
- Examples also improve the odds without guaranteeing anything. The incident rate would drop, but not reach zero.

