跳到主要内容

PreToolUse & PostToolUse 钩子

使用 PreToolUse 和 PostToolUse 钩子控制和监控工具执行。

PreToolUse 钩子​

在每次工具调用之前执行。可以批准、拒绝或请求用户确认。

签名​

import type { PreToolUseHookInput } from '@anthropic-ai/claude-agent-sdk';

export async function PreToolUse(
input: PreToolUseHookInput,
toolUseID: string,
options: { signal: AbortSignal }
): Promise<{
decision?: 'approve' | 'block';
systemMessage?: string;
hookSpecificOutput?: {
hookEventName: 'PreToolUse';
permissionDecision?: 'allow' | 'deny' | 'ask';
permissionDecisionReason?: string;
updatedInput?: Record<string, unknown>;
};
}>

使用场景​

  • 阻止危险操作
  • 对敏感工具进行确认
  • 记录工具使用情况
  • 验证工具输入

示例:阻止危险命令​

export async function PreToolUse(input: PreToolUseHookInput) {
if (input.tool_name === 'Bash') {
const cmd = input.tool_input?.command as string;

const dangerous = [
/rm\s+-rf\s+\//,
/dd\s+if=/,
/mkfs/
];

if (dangerous.some(pattern => pattern.test(cmd))) {
return {
decision: 'deny',
message: 'Dangerous command blocked'
};
}
}

return { decision: 'approve' };
}

示例:要求确认​

export async function PreToolUse(input: PreToolUseHookInput) {
// Require confirmation for Write tool
if (input.tool_name === 'Write') {
return {
decision: 'pending',
message: `Create file: ${input.tool_input?.file_path}`
};
}

// Auto-approve Read
return { decision: 'approve' };
}

PostToolUse Hook​

在每个工具调用之后执行。可以检查结果并记录结果。

签名​

import type { PostToolUseHookInput } from '@anthropic-ai/claude-agent-sdk';

export async function PostToolUse(
input: PostToolUseHookInput,
toolUseID: string,
options: { signal: AbortSignal }
): Promise<{
hookSpecificOutput?: {
hookEventName: 'PostToolUse';
additionalContext?: string;
updatedMCPToolOutput?: unknown;
};
}>

使用案例​

  • 审计日志记录
  • 收集指标
  • 跟踪工具使用
  • 错误监控

示例:审计日志​

import { appendFileSync } from 'fs';

export async function PostToolUse(input: PostToolUseHookInput) {
const log = {
timestamp: new Date().toISOString(),
tool: input.tool_name,
input: input.tool_input,
success: !input.tool_response?.error
};

appendFileSync('audit.log', JSON.stringify(log) + '\n');

return {};
}

示例:指标收集​

const metrics = new Map<string, number>();

export async function PostToolUse(input: PostToolUseHookInput) {
const count = metrics.get(input.tool_name) || 0;
metrics.set(input.tool_name, count + 1);

console.log('[Metrics]', Array.from(metrics.entries()));

return {};
}

组合示例​

export async function PreToolUse(input: PreToolUseHookInput) {
console.log(`[PreToolUse] ${input.tool_name}`);

// Security checks
if (input.tool_name === 'Bash') {
const cmd = input.tool_input?.command;
if (cmd?.includes('rm -rf')) {
return { decision: 'deny', message: 'Blocked' };
}
}

return { decision: 'approve' };
}

export async function PostToolUse(input: PostToolUseHookInput) {
console.log(`[PostToolUse] ${input.tool_name} completed`);

// Log errors
if (input.tool_response?.error) {
console.error('[Error]', input.tool_response.error);
}

return {};
}

相关​