Skip to content

Hooks 是 Copilot SDK 的拦截层,通过在 createSession 时传入 hooks 对象,可以在工具调用前后、Prompt 提交时、会话启停时注入自定义逻辑。最常用场景:阻止危险工具、审计日志、上下文注入。

GitHub Copilot SDK Hooks 快速入门:5 分钟添加工具权限控制

最简示例:阻止危险工具

typescript
import { createSession } from '@github/copilot-sdk'

const DANGEROUS_TOOLS = ['delete_files', 'drop_table', 'system_restart']

const session = await createSession({
  hooks: {
    onPreToolUse: async ({ toolName }) => {
      if (DANGEROUS_TOOLS.includes(toolName)) {
        return {
          action: 'deny',
          reason: `工具 "${toolName}" 已被安全策略禁止`
        }
      }
      return null  // 允许其他所有工具
    }
  }
})

5 行代码,Agent 就无法调用危险工具了。

四个核心 Hook 点

Hook触发时机常见用途
onPreToolUse工具调用权限控制、参数校验
onPostToolUse工具调用结果过滤、日志记录
onUserPromptSubmitted用户发送消息后上下文注入、内容过滤
onSessionStart/End会话开始/结束时初始化、清理资源

组合多个 Hook

typescript
const session = await createSession({
  hooks: {
    // 1. 工具调用前:权限检查 + 日志
    onPreToolUse: async ({ toolName, arguments: args }) => {
      console.log(`[AUDIT] 工具调用: ${toolName}`, args)
      
      if (toolName === 'execute_command' && args.command?.includes('rm -rf')) {
        return { action: 'deny', reason: '危险命令已被阻止' }
      }
      return null
    },

    // 2. 工具调用后:脱敏处理
    onPostToolUse: async ({ toolName, result }) => {
      if (toolName === 'read_env' && result.content) {
        // 过滤包含 KEY 或 SECRET 的环境变量值
        const filtered = result.content.replace(
          /([A-Z_]*(KEY|SECRET|TOKEN|PASS)[A-Z_]*=).*/g,
          '$1[REDACTED]'
        )
        return { modifiedResult: { ...result, content: filtered } }
      }
      return null
    },

    // 3. 用户输入:自动追加上下文
    onUserPromptSubmitted: async ({ prompt }) => {
      return {
        additionalContext: `工作目录: ${process.cwd()}`
      }
    }
  }
})

返回值规则

场景返回值
不修改,保持默认nullundefined
允许工具执行{ action: 'allow' }
拒绝工具执行{ action: 'deny', reason: '原因' }
请求用户确认{ action: 'ask', message: '确认提示' }
修改工具调用后的结果{ modifiedResult: {...} }
追加上下文信息{ additionalContext: '...' }

常见问题

Q: Hook 函数可以是 async 的吗?

A: 可以,所有 Hook 都支持 async 函数。但注意 Hook 会阻塞工具调用,async Hook 中的 await 会延迟执行,尽量避免不必要的异步操作。

Q: 多个 onPreToolUse 可以链式调用吗?

A: 不可以,每个 Hook 类型只能注册一次。如果需要多个逻辑,在同一个 Hook 函数中串联处理。

Q: Hook 能改变工具调用的参数吗?

A: onPreToolUse 可以返回 { modifiedArguments: {...} } 修改传给工具的参数。