Appearance
onErrorOccurred Hook 在 Agent 会话发生错误时触发,可以记录错误详情、向 AI 提供处理建议、触发告警通知。返回 null 使用默认错误处理,返回自定义对象可以修改错误响应方式。
GitHub Copilot SDK onErrorOccurred Hook:自定义错误处理与监控
基本结构
typescript
const session = await createSession({
hooks: {
onErrorOccurred: async (context) => {
const { error, toolName, sessionId } = context
// 错误处理逻辑
return null // 使用默认错误处理
}
}
})错误日志记录
typescript
onErrorOccurred: async ({ error, toolName, sessionId }) => {
// 结构化日志,便于后续分析
errorLogger.log({
timestamp: new Date().toISOString(),
sessionId,
toolName: toolName ?? 'session',
errorCode: error.code,
errorMessage: error.message,
stack: error.stack
})
return null // 让 AI 自己处理错误
}按错误类型分类处理
typescript
onErrorOccurred: async ({ error, toolName }) => {
switch (error.code) {
case 'TIMEOUT':
// 超时:提示 AI 换更高效的方式
return {
userMessage: `工具 "${toolName}" 执行超时,请尝试分批处理或缩小操作范围。`
}
case 'PERMISSION_DENIED':
// 权限不足:直接告知
return {
userMessage: `没有权限执行 "${toolName}",请检查当前用户的权限配置。`
}
case 'NETWORK_ERROR':
// 网络错误:可以重试
return {
userMessage: '网络连接异常,请稍后重试或检查网络配置。',
retry: true // 部分 SDK 版本支持自动重试提示
}
default:
return null // 其他错误用默认处理
}
}触发告警
对于需要人工介入的严重错误,触发外部告警:
typescript
onErrorOccurred: async ({ error, sessionId, toolName }) => {
const isCritical = ['DISK_FULL', 'OUT_OF_MEMORY', 'DB_CONNECTION_FAILED'].includes(error.code)
if (isCritical) {
// 非阻塞告警(不 await)
alerting.notify({
level: 'critical',
message: `Copilot SDK 严重错误: ${error.code}`,
sessionId,
tool: toolName
}).catch(e => console.error('告警发送失败:', e))
}
// 记录所有错误的统计
metrics.increment('sdk.errors', 1, { code: error.code, tool: toolName ?? 'session' })
return null
}错误模式分析
typescript
const errorCounts = new Map<string, number>()
onErrorOccurred: async ({ error }) => {
// 统计错误频率
const count = (errorCounts.get(error.code) ?? 0) + 1
errorCounts.set(error.code, count)
// 某个错误频繁出现时,给 AI 提供针对性建议
if (error.code === 'FILE_NOT_FOUND' && count > 3) {
return {
userMessage: '多次出现文件未找到的错误,建议先用 list_directory 工具确认目录结构,再操作具体文件。'
}
}
return null
}最佳实践
1. 总是记录错误:即使使用默认处理,也要记录错误日志。没有日志,就无法分析问题模式。
2. 区分工具错误和会话错误:toolName 有值时是工具执行失败,为 null 时是会话级别的错误(通常更严重)。
3. 避免 Hook 本身抛出异常:如果错误处理 Hook 本身出错,会造成双重错误,难以排查。在 Hook 内部做 try-catch:
typescript
onErrorOccurred: async (context) => {
try {
await errorLogger.log(context)
} catch (loggingError) {
// 静默处理日志错误,不向上传播
console.error('错误日志记录失败:', loggingError)
}
return null
}常见问题
Q: onErrorOccurred 和 session.on('session.error') 有什么区别?
A: session.on('session.error') 是事件监听,只能被动接收;onErrorOccurred Hook 可以修改错误的处理方式(如提供 userMessage)。通常两者配合使用:Hook 做处理,事件监听做 UI 更新。
Q: 返回 userMessage 后,AI 会怎么处理这个消息?
A: userMessage 会作为工具执行的错误响应返回给 AI,AI 会基于这个信息决定下一步。如果消息清晰,AI 通常能自动调整策略。
Q: 可以在 Hook 中重试工具调用吗?
A: Hook 本身不能直接触发重试。可以在 userMessage 中提示 AI 重试,让 AI 自主决定是否再次调用工具。