🪝 OpenClaw Agent Hook机制指南

在关键时刻插入你的代码——钩子的艺术

什么是Hook机制?

Hook(钩子)是一种在特定时刻插入自定义代码的机制。就像装修房子时的"预留点位"——你可以在这些点位安装任何设备。OpenClaw的Hook机制让你能够在Agent执行的关键节点插入自己的逻辑。

💡 类比理解:Hook就像是Agent生命周期中的"插件接口"——你可以在请求发送前、响应返回后、工具执行时、错误发生时等节点,插入自己的代码。

Hook类型全景图

生命周期钩子

Hook名称 触发时机 用途
onInit Agent初始化时 加载配置、注册工具
onRequest 发送请求前 修改prompt、添加上下文
onResponse 收到响应后 后处理、格式化输出
onToolCall 工具调用前 参数校验、权限检查
onToolResult 工具执行后 结果处理、错误转换
onError 发生错误时 错误处理、降级策略
onComplete 任务完成时 清理资源、记录日志

Hook实战

请求拦截

在发送请求前修改prompt或添加上下文:

agent.hook('onRequest', async (context) => {
  // 添加时间上下文
  const now = new Date().toLocaleString('zh-CN');
  context.prompt = `[当前时间: ${now}]\n\n${context.prompt}`;
  
  // 检查敏感词
  if (containsSensitiveWords(context.prompt)) {
    throw new Error('Prompt包含敏感内容');
  }
  
  // 添加用户偏好
  if (context.userPrefs) {
    context.systemPrompt += `\n用户偏好: ${JSON.stringify(context.userPrefs)}`;
  }
  
  return context;
});

响应处理

在收到响应后进行后处理:

agent.hook('onResponse', async (response, context) => {
  // 格式化输出
  response.content = formatMarkdown(response.content);
  
  // 添加来源水印
  response.content += '\n\n---\n*由妙趣AI生成*';
  
  // 内容安全检查
  const safetyCheck = await checkContentSafety(response.content);
  if (!safetyCheck.safe) {
    response.content = '内容安全检查未通过,已隐藏';
    response.flagged = true;
  }
  
  // 记录token使用
  metrics.track('token_usage', {
    input: response.usage.inputTokens,
    output: response.usage.outputTokens,
    model: context.model
  });
  
  return response;
});

工具调用拦截

最常用的Hook场景——控制工具执行:

agent.hook('onToolCall', async (toolCall) => {
  // 参数校验
  validateParams(toolCall.name, toolCall.arguments);
  
  // 权限检查
  if (!hasPermission(toolCall.name, context.user)) {
    return {
      error: '权限不足',
      suggestion: '请联系管理员授权'
    };
  }
  
  // 限流检查
  if (isRateLimited(toolCall.name)) {
    return {
      error: '操作频率过高',
      suggestion: '请稍后再试'
    };
  }
  
  // 记录审计日志
  audit.log({
    user: context.user.id,
    tool: toolCall.name,
    params: toolCall.arguments,
    timestamp: Date.now()
  });
  
  return toolCall; // 继续执行
});

工具结果处理

agent.hook('onToolResult', async (result, toolCall) => {
  // 结果缓存
  if (result.cacheable) {
    cache.set(toolCall.cacheKey, result);
  }
  
  // 错误转换
  if (result.error) {
    result.error = translateError(result.error, 'zh-CN');
    result.suggestion = suggestFix(result.error);
  }
  
  // 大数据截断
  if (result.data && result.data.length > 10000) {
    result.data = result.data.slice(0, 10000);
    result.truncated = true;
    result.note = '数据已截断,完整数据请另存';
  }
  
  return result;
});

中间件模式

链式中间件

OpenClaw支持Express风格的中间件链:

// 日志中间件
agent.use(async (context, next) => {
  console.log(`[${new Date().toISOString()}] 请求开始`);
  const result = await next();
  console.log(`[${new Date().toISOString()}] 请求完成`);
  return result;
});

// 限流中间件
agent.use(async (context, next) => {
  if (await rateLimiter.isLimited(context.user.id)) {
    throw new Error('请求频率过高');
  }
  await next();
  await rateLimiter.increment(context.user.id);
});

// 计费中间件
agent.use(async (context, next) => {
  const result = await next();
  await billing.record({
    user: context.user.id,
    tokens: result.usage.totalTokens,
    cost: calculateCost(result.usage)
  });
  return result;
});

中间件顺序

⚠️ 注意顺序:中间件按注册顺序执行。日志中间件应该在最前面(最先执行),计费中间件应该在最后面(最后执行)。

高级用法

条件Hook

// 只对特定工具触发
agent.hook('onToolCall', {
  filter: (toolCall) => toolCall.name === 'send_email',
  handler: async (toolCall) => {
    // 只对邮件工具执行特殊处理
    await checkSpamContent(toolCall.arguments.body);
    return toolCall;
  }
});

异步Hook

// 异步执行,不阻塞主流程
agent.hook('onComplete', async (context) => {
  // 不等待异步任务完成,直接返回
  backgroundTasks.add(async () => {
    await sendAnalytics(context);
    await updateUserStats(context.user.id);
  });
  
  return context;
});

Hook组合

// 组合多个Hook为中间件
const auditMiddleware = AuditMiddleware.create({
  hooks: ['onRequest', 'onToolCall', 'onComplete'],
  logLevel: 'info'
});

agent.use(auditMiddleware);

最佳实践

  1. ✅ Hook处理要快,避免阻塞主流程
  2. ✅ 使用条件Hook减少不必要的执行
  3. ✅ 错误处理Hook要返回清晰的错误信息
  4. ✅ 日志Hook记录关键信息,不过度记录
  5. ✅ 工具Hook校验参数后再执行
  6. ✅ 中间件按逻辑顺序注册
  7. ✅ 异步任务用后台执行,不阻塞

常见问题

Q: Hook可以修改请求内容吗?

可以。onRequest Hook可以修改prompt、添加system message、调整参数等。

Q: 多个Hook的执行顺序是什么?

按注册顺序执行,先注册先执行。可以使用priority参数控制优先级。

Q: Hook抛出错误会怎样?

会中断当前请求,触发onError Hook。可以在onError中降级处理或返回备用结果。

📅 最后更新:2026年5月2日 | 作者:妙趣AI