Hooks System
The Agentrix hooks system allows you to intercept and customize agent behavior at critical lifecycle points.
What are Hooks?
Hooks are TypeScript functions that execute at specific moments during agent execution. They enable you to:
- Control tool execution: Approve, deny, or modify tool calls before execution
- Track sessions: Monitor agent lifecycle events
- Process results: Inspect and transform tool outputs
- Add custom logic: Inject domain-specific behavior
Quick Example
import type { PreToolUseHookInput } from '@anthropic-ai/claude-agent-sdk';
export async function PreToolUse(
input: PreToolUseHookInput,
toolUseID: string,
options: { signal: AbortSignal }
) {
// Block destructive operations
if (input.tool_name === 'Bash' &&
input.tool_input?.command?.includes('rm -rf')) {
return { decision: 'block', systemMessage: 'Destructive command blocked' };
}
return { decision: 'approve' };
}
Available Hooks
Agentrix supports the Claude SDK hook types:
From @anthropic-ai/claude-agent-sdk:
- PreToolUse - Before tool execution
- PostToolUse - After tool execution
- SessionStart - When agent session starts
- SessionEnd - When agent session ends
- UserPromptSubmit - When user submits a prompt
- Stop - When agent stops
- SubagentStart - When subagent starts
- SubagentStop - When subagent stops
- PreCompact - Before context compaction
- Notification - System notifications
- PermissionRequest - When permission is needed
Hook Documentation
By Category
Tool Control:
- PreToolUse & PostToolUse - Control and monitor tool execution
Session Lifecycle:
- Session Hooks - SessionStart, SessionEnd, UserPromptSubmit, Stop, SubagentStop
System Events:
- PreCompact - Context management
- Notification - System notifications
Comprehensive Guides
- Overview - Hook concepts and architecture
- Development Guide - Setting up TypeScript project
- Hook Types Reference - Complete type definitions
- Examples - Real-world patterns
Getting Started
1. Setup Hooks Project
mkdir -p claude/hooks/src
cd claude/hooks
Create package.json:
{
"name": "agent-hooks",
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "tsc",
"dev": "tsc --watch"
},
"dependencies": {
"@agentrix/shared": "latest"
},
"devDependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.1.30",
"@types/node": "^20.0.0",
"typescript": "^5.0.0"
}
}
2. Install Dependencies
npm install
3. Create Hook
Create src/index.ts:
import type { PreToolUseHookInput } from '@anthropic-ai/claude-agent-sdk';
export async function PreToolUse(
input: PreToolUseHookInput,
toolUseID: string,
options: { signal: AbortSignal }
) {
console.log(`[PreToolUse] ${input.tool_name}`);
return { decision: 'approve' };
}
4. Build
npm run build
See Development Guide for complete setup.
Hook Execution Order
When an agent runs, hooks execute in this order:
1. SessionStart
↓
2. UserPromptSubmit (for each user message)
↓
3. PreToolUse (for each tool call)
↓
4. [Tool Executes]
↓
5. PostToolUse (for each tool result)
↓
6. PreCompact (if context limit reached)
↓
7. Stop / SessionEnd (when session ends)
Special hooks:
- SubagentStop: Runs when subagents complete
- Notification: Triggered by system events
Common Patterns
Security Control
export async function PreToolUse(input: PreToolUseHookInput) {
// Deny dangerous bash commands
if (input.tool_name === 'Bash') {
const cmd = input.tool_input?.command;
if (cmd?.match(/rm -rf|dd if=|mkfs/)) {
return { decision: 'deny', message: 'Unsafe command' };
}
}
return { decision: 'approve' };
}
Audit Logging
import { appendFileSync } from 'fs';
export async function PostToolUse(input: PostToolUseHookInput) {
const log = {
timestamp: new Date().toISOString(),
tool: input.tool_name,
success: !input.tool_response?.error
};
appendFileSync('audit.log', JSON.stringify(log) + '\n');
return {};
}
See Examples for more patterns.
Type Safety
Claude hook input types are provided by @anthropic-ai/claude-agent-sdk:
import type {
PreToolUseHookInput,
PostToolUseHookInput,
SessionStartHookInput,
SessionEndHookInput,
UserPromptSubmitHookInput,
StopHookInput,
SubagentStartHookInput,
SubagentStopHookInput,
PreCompactHookInput,
NotificationHookInput,
PermissionRequestHookInput,
} from '@anthropic-ai/claude-agent-sdk';
Best Practices
- Error Handling: Hooks should never crash - wrap in try/catch
- Timeouts: Hooks have 30s timeout - keep them fast
- Side Effects: Be cautious with file system operations
- Logging: Use console.log for debugging (visible in agent logs)
- Type Safety: Import hook input types from
@anthropic-ai/claude-agent-sdk; use@agentrix/sharedforHookFactoryandAgentrixContext
Debugging Hooks
Enable Verbose Logging
DEBUG=agentrix:hooks agentrix run --agent=./my-agent
Check Hook Execution
export async function PreToolUse(input: PreToolUseHookInput) {
console.log('[DEBUG] PreToolUse called:', {
tool: input.tool_name,
input: input.tool_input
});
return { decision: 'approve' };
}
Test Hook Locally
// test/hook.test.ts
import { PreToolUse } from '../src/index';
const mockInput = {
tool_name: 'Read',
tool_input: { file_path: 'test.txt' }
};
const result = await PreToolUse(mockInput, 'test-id', {
signal: new AbortController().signal
});
console.assert(result.decision === 'approve');
Limitations
- Hooks run in isolated process (no shared state between hooks)
- 30 second timeout per hook
- Cannot modify agent's base system prompt
- Cannot add new tools (use MCP servers instead)
Migration from Legacy Hooks
Old format:
export function preToolUse(toolName: string, input: any) {
// ...
}
New format:
import type { PreToolUseHookInput } from '@anthropic-ai/claude-agent-sdk';
export async function PreToolUse(
input: PreToolUseHookInput,
toolUseID: string,
options: { signal: AbortSignal }
) {
// ...
}
Next Steps
- Development Guide - Set up TypeScript project
- Hook Types Reference - All hook signatures
- Examples - Copy-paste patterns
- API Reference - Complete type definitions