Reliability & Deterministic Enforcement
This module focuses on Agent SDK hooks and structured error contracts that guarantee compliance and normalization even when the model's reasoning deviates from its instructions. Prompts are probabilistic; hooks, gates, and validators are deterministic.
1. Deterministic vs. Probabilistic Enforcement
Prompts can ask the model not to issue a high-risk refund. A PreToolUse hook can block the refund before it executes. This distinction matters for financial, legal, privacy, safety, and irreversible operations.
1a. PreToolUse Interception
Use PreToolUse to intercept outgoing tool calls before execution. This is the only way to guarantee that high-value actions, such as refunds over $500, are blocked and redirected to human escalation regardless of the model's intent.
REFUND_LIMIT = 500
def pre_tool_use(tool_call):
if tool_call["name"] != "issue_refund":
return {"decision": "allow"}
amount = tool_call["arguments"].get("amount_usd", 0)
if amount > REFUND_LIMIT:
return {
"decision": "deny",
"redirectTool": "escalate_to_human",
"reason": "Refunds over $500 require human approval.",
}
return {"decision": "allow"}
1b. Programmatic Prerequisite Gates
tool_choice can force the model to call an identification tool first, but a programmatic gate is what blocks downstream tools until the prerequisite has actually succeeded.
For example, block process_refund until get_customer or identity_verification has returned a verified success status. A model can ignore a prompt; it cannot bypass a runtime gate.
2. Standardized Structured Error Contracts
Uniform prose errors like "Operation failed" are anti-patterns because they prevent the agent from making informed recovery decisions. Every tool should return the same structured fields when it fails.
2a. The errorCategory Enum
TRANSIENT: timeouts or service unavailability; Claude should attempt a retry.VALIDATION: invalid input, such as a bad email format; the agent should clarify with the user.PERMISSION: authorization issues; the agent should inform the user of the access gap.BUSINESS: policy violations, such as refund exceeds limit; the agent should communicate the rule.
2b. Metadata Over Prose
Always return an isRetryable boolean. This prevents the agent from wasting tokens on repeated attempts for non-retryable permission, validation, or business-rule failures.
{
"isError": true,
"errorCategory": "TRANSIENT",
"isRetryable": true,
"message": "Refund system is temporarily offline."
}
{
"isError": true,
"errorCategory": "BUSINESS",
"isRetryable": false,
"message": "Refunds over $500 require human approval."
}
3. PostToolUse Normalization for MCP
Different MCP servers often return inconsistent data formats: Unix timestamps, local date strings, ISO strings, numeric status codes, or provider-specific labels.
Implement PostToolUse hooks to rewrite heterogeneous tool results into a homogeneous shape before they reach the model. This reduces thinking-budget consumption because the model does not have to reconcile formats manually.
from datetime import datetime, timezone
def post_tool_use(tool_name, result):
if tool_name == "crm_database_lookup" and "created_at_unix" in result:
created_at = datetime.fromtimestamp(
result["created_at_unix"],
tz=timezone.utc,
).isoformat()
result["created_at"] = created_at
del result["created_at_unix"]
return result
4. Forced Prerequisite Strategy
Use forced tool selection to implement deterministic multi-step sequences. On the first turn, set:
{
"tool_choice": {
"type": "tool",
"name": "get_customer"
}
}
This makes the identification step mandatory. On subsequent turns, switch back to "auto" or "any" so the agent can reason flexibly after the prerequisite evidence exists.
tool_choiceensures the first step is attempted.PreToolUsegates ensure unsafe downstream tools cannot execute without verified prerequisite state.- Structured errors tell the model whether to retry, clarify, inform, or escalate.
PostToolUsenormalization ensures the model reasons over stable result shapes.
Lab Exercise: The Defense-in-Depth Refund Workflow
Self-driven lab Module9_Self_Driven_Lab.ipynbObjective: combine tool_choice, PreToolUse hooks, structured errors, and PostToolUse normalization to build a safe financial agent.
- Prerequisite forcing: use
tool_choiceto force the agent to call anidentity_verificationtool on its first turn. - Safety hook: implement a PreToolUse hook that blocks
issue_refundwhenamount_usdis over$500, even if the model's reasoning says it is authorized. Redirect the agent toescalate_to_human. - Structured error handling: create a tool handler for a "System Offline" error that returns
isError: true,errorCategory: TRANSIENT, andisRetryable: true; observe the agent attempting a recovery retry. - Normalization: implement a PostToolUse hook that converts a Unix timestamp from an MCP database tool into a human-readable ISO string.
- Validation vs. access: test a "User Not Found" response as
isError: falsebecause it is a valid empty result, then compare it with an actual "Access Denied" error marked asPERMISSION.
Exam tip: errors talk to the model; hooks talk to the runtime. Use structured errors to guide recovery, but use hooks and gates to enforce policy.