Agent SDK hooks intercept events at five points in the session lifecycle. Each fires at a specific moment, which determines what it can do. Using the wrong hook type for a need is a common mistake — PreToolUse can’t transform outputs (they don’t exist yet), and SessionStart can’t validate per-tool inputs (it fires once).
The five hook types
SessionStart
Fires once when the session begins. Use for: loading configuration, initializing context, setting up environment.
Example: load repo-specific CI configuration from .pipeline.yml into agent context at session start.
UserPromptSubmit
Fires when a user submits a message, before the agent processes it. Use for: input sanitization, context injection, language detection, per-message metadata.
Example: inject the customer’s account tier (gold/silver/bronze) into every prompt so the agent applies the correct policies.
Diagnostic: if context injection fails only for API requests (not chat interface), the hook may be registered only on the chat path. Ensure all request paths go through the hook pipeline.
PreToolUse
Fires before a tool executes. Can inspect parameters, block execution, or modify inputs. Use for: blocking unauthorized actions, enforcing prerequisites, parameter validation, input modification (sandbox redirection).
Example: block process_refund when amount > $500. Block delete_file until backup_file completes.
Cannot do: transform tool outputs (they don’t exist yet), load one-time config (fires per tool call, not once).
PostToolUse
Fires after a tool executes, before the agent sees the result. Can inspect and transform the output. Use for: data normalization, PII masking, output enrichment, secret redaction, audit logging of results.
Example: convert all timestamp formats to ISO 8601 before the agent processes tool results.
Cannot do: prevent tool execution (already happened), session-level initialization.
SessionEnd
Fires when the session terminates. Use for: cleanup, archiving logs, generating session summaries.
Example: delete temporary analysis files created during the session. Archive audit logs.
Full lifecycle mapping
A CI/CD pipeline agent with 5 needs maps each to the right hook:
| Need | Hook type | Why this timing |
|---|---|---|
| Load CI config | SessionStart | One-time setup at start |
| Inject PR context into prompts | UserPromptSubmit | Per-message context |
| Block deploys to production | PreToolUse | Must intercept before execution |
| Redact secrets from tool outputs | PostToolUse | Must access results after execution |
| Archive logs at session end | SessionEnd | Cleanup after all work complete |
Why PreToolUse-only doesn’t work
A team proposes: “Just use PreToolUse for everything — block bad actions before they happen.”
This fails for two of five common needs:
- Output sanitization: PreToolUse fires before the tool runs. There is no output to sanitize. Secret redaction in tool results requires PostToolUse.
- Complete audit logging: PreToolUse captures what was requested, but not what was returned. A tool call that was attempted but failed looks identical to one that succeeded. PostToolUse captures the complete picture.
Comprehensive audit: Pre + Post together
Compliance requires logging both inputs AND outputs per tool call. Register PreToolUse (log tool name, parameters, timestamp) AND PostToolUse (log result, status, duration) to capture the complete request-response cycle. Using only one misses half the audit trail.
Stop/SessionEnd-based batch logging risks data loss if the session crashes — real-time per-call logging via Pre+Post is more reliable.
SessionStart ≠ PreToolUse
SessionStart fires once. PreToolUse fires per tool call. Using SessionStart for per-tool input validation doesn’t work — it can’t intercept individual tool calls. Conversely, using PreToolUse for one-time config loading wastes processing (runs the loading check on every tool call when it only needs to run once).
One-liner: Five hooks across the lifecycle: SessionStart (one-time setup), UserPromptSubmit (per-message context), PreToolUse (block/modify before execution), PostToolUse (transform/log after execution), SessionEnd (cleanup) — use PreToolUse+PostToolUse together for complete audit, and never use PreToolUse for output transformation.