Skip to main content

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:

  1. PreToolUse - Before tool execution
  2. PostToolUse - After tool execution
  3. SessionStart - When agent session starts
  4. SessionEnd - When agent session ends
  5. UserPromptSubmit - When user submits a prompt
  6. Stop - When agent stops
  7. SubagentStart - When subagent starts
  8. SubagentStop - When subagent stops
  9. PreCompact - Before context compaction
  10. Notification - System notifications
  11. PermissionRequest - When permission is needed

Hook Documentation​

By Category​

Tool Control:

Session Lifecycle:

  • Session Hooks - SessionStart, SessionEnd, UserPromptSubmit, Stop, SubagentStop

System Events:

Comprehensive Guides​

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​

  1. Error Handling: Hooks should never crash - wrap in try/catch
  2. Timeouts: Hooks have 30s timeout - keep them fast
  3. Side Effects: Be cautious with file system operations
  4. Logging: Use console.log for debugging (visible in agent logs)
  5. Type Safety: Import hook input types from @anthropic-ai/claude-agent-sdk; use @agentrix/shared for HookFactory and AgentrixContext

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​

Getting Help​