PostToolUse Hook

Agent SDK

Definition

An Agent SDK lifecycle hook that intercepts tool results before the agent processes them. Can normalize, enrich, or transform results from multiple tools into a consistent format. Works with both custom and third-party MCP tools without modifying their source code.

Example Usage

Use PostToolUse to normalize Unix timestamps, ISO dates, and status codes from different tools into human-readable formats before the agent sees them.

Why It Matters for the CCA-F Exam

Exam scenarios for PostToolUse often involve multi-tool pipelines where results from different tools need to be reconciled. If a question describes an agent struggling with inconsistent formats across tool outputs, PostToolUse normalization is the correct architectural lever. Distinguish it from PreToolUse (input-side) and Stop hook (end-of-turn quality gate).

In Depth

PostToolUse fires after a tool has executed and returned its result, but before the agent processes that result in its next reasoning step. This timing gives the hook a unique property: it cannot undo the tool's side effects, but it has full visibility into what the tool actually returned and can reshape that data before the model ever sees it.

The canonical use case is result normalization across heterogeneous tools. In a real-world agentic system you might call a billing API (returns Unix timestamps), a CRM tool (returns ISO 8601 strings), and a custom database tool (returns epoch milliseconds). Your agent's reasoning quality degrades when it must mentally reconcile three date formats. A PostToolUse hook attached to all three normalizes every timestamp to a single human-readable ISO format, so the model always sees consistent data regardless of which tool produced it.

PostToolUse is also ideal for:

  • Enrichment: Append metadata the tool itself cannot provide — e.g., add a fetched_at timestamp, or tag the source tool name onto each result
  • Redaction: Strip sensitive fields (API keys, PII) from tool results before they enter the context window
  • Validation: Confirm a tool returned a result matching an expected schema; if not, return a structured error to the agent prompting a retry
  • Logging: Persist both the raw result and the normalized form for debugging and compliance

Because PostToolUse runs after the tool executes, it cannot prevent the tool's side effects — a file already written stays written. Do not use PostToolUse as a security gate; that job belongs to PreToolUse. Instead, think of PostToolUse as a *translation layer* that isolates the agent's reasoning from the idiosyncrasies of individual tools.

This separation matters especially when integrating MCP servers you do not control. Third-party MCP tools may return results in any format. PostToolUse lets you wrap them without forking the server's source code. The hook runs in your process, under your control, and can even call out to a schema validation library before passing results to the model.

In practice, PostToolUse hooks are registered per tool name (or a wildcard matcher) and receive the tool name, original input, and the result. See Agent SDK Hooks: PostToolUse & Interception for deeper implementation guidance.

How It Compares

ConcernPreToolUsePostToolUse
Fires whenBefore tool executesAfter tool returns
Can prevent tool executionYesNo
Sees tool inputYesYes (original input available)
Sees tool resultNoYes
Primary purposeGating / parameter controlNormalization / enrichment
Typical triggerSecurity policy, rate limitFormat inconsistency, redaction

Example

A PostToolUse callback that normalizes Unix timestamps to ISO 8601 across any tool result — applied once, affects all tool integrations without modifying their source.

python
def post_tool_use_handler(event):
    # Normalize all date fields in any tool result
    result = event.result
    if isinstance(result, dict):
        for key in ("created_at", "updated_at", "timestamp"):
            if key in result and isinstance(result[key], (int, float)):
                from datetime import datetime, timezone
                result[key] = datetime.fromtimestamp(
                    result[key], tz=timezone.utc
                ).isoformat()
    return result

Frequently Asked Questions

If PostToolUse transforms a result, does the agent ever see the original raw output?

No. The transformed result replaces the raw output in the agent's context. The original is only visible to the hook itself (and any logging you write inside it). The agent reasons solely from whatever the hook returns.

Can PostToolUse be used to retry a failed tool call?

PostToolUse can detect a failure result and return a structured error that prompts the agent to retry, but it cannot itself re-invoke the tool. The retry decision belongs to the agent's reasoning loop. For automatic retry logic independent of the agent, consider a wrapper tool that handles retries internally before PostToolUse ever fires.