AgentHook¶
AgentHook is the core router type for custom callback apps.
It provides a decorator-based API for registering hook handlers while keeping provider-specific parsing and response rendering below the app layer.
Think "FastAPI for hook callbacks": you implement business logic against typed event objects, and Agent Hooks handles provider payload normalization plus provider-specific response wire shapes.
Decorator routes
Register behavior with handlers like @app.permission(), @app.stop(), and @app.notification().
Typed event injection
Write against PermissionRequestEvent, StopEvent, CallbackRequest, and DisplayTransport instead of raw JSON.
Unified schema
Claude PermissionRequest and Codex PreToolUse both arrive as the same normalized permission event.
What You Write Vs What Agent Hooks Handles¶
| You write | Agent Hooks handles |
|---|---|
| business rules for allow, deny, notify, or stop behavior | provider detection and payload parsing |
| typed handlers with route decorators | mapping raw provider event names into normalized events |
generic responses like HookResponse(...) |
rendering the correct provider response JSON |
a button choice like DialogButton.ALLOW_ONCE |
building provider-specific permission payloads |
Minimal Example¶
from __future__ import annotations
from agent_hooks import (
AgentHook,
HookResponse,
PermissionRequestEvent,
StopEvent,
build_permission_response,
)
from agent_hooks.enums import DialogButton
app = AgentHook()
@app.permission()
def permission_handler(hook_event: PermissionRequestEvent):
if hook_event.tool_name == "Bash" and hook_event.tool_input.command.startswith("git status"):
return build_permission_response(DialogButton.ALLOW_ONCE, hook_event)
return build_permission_response(DialogButton.DENY, hook_event)
@app.stop()
def stop_handler(hook_event: StopEvent) -> HookResponse:
return HookResponse(
suppress_output=False,
system_message=f"Handled locally for {hook_event.provider.value}.",
)
build_permission_response() lets you choose the policy outcome once and have Agent Hooks render the right provider-specific permission response. HookResponse(...) is the generic top-level response model for non-permission events.
Running The Router¶
Directly:
Through the CLI:
Route Decorators¶
AgentHook exposes the following route decorators:
notification()permission()pre_tool_use()session_start()user_prompt_submit()post_tool_use()stop()stop_failure()middleware()
pre_tool_use() is an alias for permission(), which keeps Codex PreToolUse aligned with the provider-neutral permission event model.
Response Primitives¶
Out-of-the-box response building is intentionally small and typed:
HookResponsefor generic top-level response fields such ascontinue_,stop_reason,system_message,decision, andreasonbuild_permission_response(DialogButton, hook_event)when you want Agent Hooks to generate the correct provider-specific permission payloadAppleScriptDialogResponseas the concrete normalized permission-response model returned bybuild_permission_response()
Fallback Processor¶
AgentHook defaults to fallback_to_default_processor=True.
That means:
- if a route is registered, the route runs
- if a route is missing, the default processor can still handle supported built-in behavior
Set fallback_to_default_processor=False if you want your router to fully own the events it registers and return empty responses for everything else.
Provider Default¶
You can optionally bind a default provider at router construction time:
That provider becomes the default for parsing and response rendering unless the CLI or runtime config overrides it.