Feature Specification: YAML-Definable Hooks System¶
Feature Branch: feature/007-claude-agent-features
Spec ID: 028-yaml-hooks-system
Created: 2026-03-28
Status: Shipped on the Claude backend via 021; OpenAI parity is 035 T6
Input: Expose the Claude Agent SDK's full hook system to YAML users, allowing declarative hook definitions for all SDK event types with no-code actions (log, reject, modify, notify, script).
User Scenarios & Testing (mandatory)¶
User Story 1 - Block Dangerous Tool Calls (Priority: P1)¶
A security-conscious team wants to prevent their Claude agent from executing destructive shell commands. They define a PreToolUse hook in YAML that rejects Bash tool calls matching dangerous patterns (e.g., rm -rf, DROP TABLE).
Why this priority: Safety-critical. Hooks that block dangerous operations are the highest-value use case and address a real production concern where static permission modes are too coarse.
Independent Test: Define a PreToolUse hook in agent.yaml that rejects Bash calls containing rm -rf, run a test case that would trigger such a call, and verify the call is blocked with the configured rejection message.
Acceptance Scenarios:
- Given a
PreToolUsehook matching toolBashwith a reject action when input containsrm -rf, When the agent attempts to runrm -rf /tmp/data, Then the tool call is blocked and the agent receives the rejection message. - Given the same hook, When the agent runs
ls -la, Then the tool call proceeds normally (no match). - Given multiple
PreToolUsehooks with different matchers, When a tool call matches the first hook, Then only the first matching hook's action is applied.
User Story 2 - Log All Tool Usage to a Webhook (Priority: P1)¶
An observability team wants to track all tool invocations for audit and debugging. They define a PostToolUse hook that sends tool call details to a webhook endpoint.
Why this priority: Observability is a core production need. While OTel covers some tracing, webhook-based logging allows integration with custom dashboards and alerting systems.
Independent Test: Define a PostToolUse hook with a notify action pointing to a webhook URL, run a test case, and verify the webhook receives the tool call payload.
Acceptance Scenarios:
- Given a
PostToolUsehook with anotifyaction targetinghttps://hooks.example.com/log, When any tool completes execution, Then the hook sends a payload with tool name, input, output, and duration to the webhook. - Given the webhook is unreachable, When a tool completes, Then the hook failure is logged as a warning but does not block agent execution.
- Given a
PostToolUsehook with a tool name matcher, When a non-matching tool completes, Then the webhook is not called.
User Story 3 - Run a Custom Script on Session Events (Priority: P2)¶
A team wants to trigger custom automation when an agent session starts or stops -- for example, initializing a temporary workspace on start and cleaning it up on stop. They define SessionStart and Stop hooks that execute shell scripts.
Why this priority: Session lifecycle hooks enable advanced automation patterns but are less common than tool-level hooks.
Independent Test: Define a Stop hook with a script action, run a test session, and verify the script is executed when the session ends.
Acceptance Scenarios:
- Given a
Stophook with ascriptaction pointing to./scripts/cleanup.sh, When the agent session ends, Then the script is executed. - Given a script hook where the script returns a non-zero exit code, When the hook fires, Then the failure is logged as a warning but does not affect the session result.
User Story 4 - Modify Tool Input Before Execution (Priority: P3)¶
A user wants to inject default parameters into tool calls -- for example, always adding a --safe-mode flag to Bash commands. They define a PreToolUse hook with a modify action that transforms the tool input.
Why this priority: Input modification is a powerful but advanced use case. Most users will start with reject/log actions before needing input transformation.
Independent Test: Define a PreToolUse hook that appends --dry-run to all Bash tool inputs, run a test case, and verify the modified input is passed to the tool.
Acceptance Scenarios:
- Given a
PreToolUsehook with amodifyaction that prependsset -e;to Bash command inputs, When the agent runs a Bash command, Then the SDK receives the modified command with the prefix.
Edge Cases¶
- What happens when multiple hooks match the same event? Hooks are evaluated in declaration order; the first matching hook with a terminal action (reject) stops evaluation. Non-terminal actions (log, notify) allow subsequent hooks to fire.
- What happens when a hook's matcher regex is invalid? A validation error is raised at config load time.
- What happens when internal tool-tracking hooks conflict with user-defined hooks? User-defined hooks are merged with internal hooks; internal hooks always fire (they are non-terminal logging hooks).
- What happens when a
notifywebhook times out? The timeout is configurable (default: 5 seconds). Timeout failures are logged as warnings and do not block execution.
Requirements (mandatory)¶
Functional Requirements¶
- FR-001: System MUST accept a
hookssection underclaudein agent YAML containing a list of hook definitions. - FR-002: Each hook definition MUST specify an
eventtype matching one of the SDK's supported event types (PreToolUse, PostToolUse, PostToolUseFailure, Stop, Notification, and others as supported). - FR-003: Each hook definition MUST specify an
actiontype: one oflog,reject,modify,notify, orscript. - FR-004: Hook definitions MAY include a
matcherwith a tool name pattern (glob or regex) to filter which tool calls trigger the hook. - FR-005: The
rejectaction MUST include amessagefield that is returned to the agent as the rejection reason. - FR-006: The
notifyaction MUST include aurlfield for the webhook endpoint and MAY includeheadersand atimeout(default: 5 seconds). - FR-007: The
scriptaction MUST include acommandfield with the shell command or script path to execute. - FR-008: The
modifyaction MUST include a transformation specification for altering tool input. - FR-009: System MUST validate hook definitions at config load time (valid event types, valid matchers, required action fields).
- FR-010: System MUST merge user-defined hooks with internal tool-tracking hooks, preserving internal hooks.
- FR-011: Hook failures (webhook timeout, script error) MUST be logged as warnings and MUST NOT block agent execution.
- FR-012: The
logaction MUST write hook event details to the application log at a configurable level (default: info).
Key Entities¶
- HookDefinition: A declarative hook configuration with event type, optional matcher, and action.
- HookAction: One of log, reject, modify, notify, or script -- each with type-specific fields.
- HookMatcher: Optional filter for tool name patterns (glob or regex).
Success Criteria (mandatory)¶
Measurable Outcomes¶
- SC-001: Users can define hooks in agent YAML that block specific tool calls, verified by the agent receiving a rejection message instead of executing the tool.
- SC-002: Users can define hooks that log or notify on tool events, verified by webhook receipt or log output.
- SC-003: Invalid hook configurations produce clear validation errors at config load time, before agent execution.
- SC-004: Hook failures (webhook timeout, script error) do not interrupt agent execution, verified by successful agent completion despite hook failures.
- SC-005: Internal tool-tracking hooks continue to function alongside user-defined hooks.
Assumptions¶
- The Claude Agent SDK's hook system supports registering multiple callbacks for the same event type.
- Hook actions are evaluated synchronously within the hook callback (the SDK waits for the hook to return before proceeding).
- The
modifyaction's transformation specification will follow a simple field-level patch format (e.g., prepend/append to specific input fields) rather than arbitrary code execution, to maintain the no-code principle. - Not all 13+ SDK event types need to be supported in the first release. The spec covers the most valuable subset: PreToolUse, PostToolUse, PostToolUseFailure, Stop, and Notification. Additional event types can be added incrementally.