AgentHarness 课程
Hermes 专题/课程概述

第四十三课:Hooks 生命周期

Hook注册事件类型自定义工作流

学习目标

  • 了解 Hooks 的概念和作用
  • 掌握 Hook 注册方法
  • 了解事件类型和使用场景
  • 学会开发自定义 Hooks

一、什么是 Hooks

Hooks 是 Codex 的生命周期钩子,让你可以在特定事件发生时执行自定义逻辑。它就像是代理的"中间件",可以在关键节点插入自定义行为。

1.1 Hooks 的价值

Hooks 的核心价值在于自动化和扩展性:

  • 自动化:在特定事件时自动执行操作,无需人工干预
  • 扩展性:无需修改核心代码即可扩展功能
  • 灵活性:可以根据需要配置不同的 Hooks
  • 可维护性:将自定义逻辑与核心代码分离

1.2 工作原理

代理执行过程中会触发各种事件,Hooks 监听这些事件并在事件发生时执行注册的处理函数。

执行流程:

  1. 用户输入任务
  2. 代理开始执行
  3. 触发 pre-run 事件
  4. 执行任务
  5. 调用工具时触发 pre-tool 事件
  6. 工具执行完成触发 post-tool 事件
  7. 任务完成触发 post-run 事件

二、事件类型

2.1 任务事件

  • pre-run:任务开始前触发,用于准备工作
  • post-run:任务结束后触发,用于清理工作
  • on-error:任务出错时触发,用于错误处理

2.2 工具事件

  • pre-tool:工具调用前触发,用于参数验证
  • post-tool:工具调用后触发,用于结果处理
  • on-tool-error:工具调用出错时触发,用于错误恢复

2.3 会话事件

  • on-message:收到消息时触发,用于消息预处理
  • on-response:生成响应时触发,用于响应后处理

2.4 事件参数

每个事件都携带上下文信息:

  • 任务描述
  • 工具名称和参数
  • 执行结果
  • 时间戳
  • 错误信息

三、注册方法

3.1 配置文件

在配置文件中定义 Hooks:

hooks:
  pre-run:
    - command: "echo 'Starting task'"
    - script: "scripts/pre-run.sh"
  post-run:
    - command: "echo 'Task completed'"
    - script: "scripts/post-run.sh"
  pre-tool:
    - match: "apply_patch"
      command: "echo 'Applying patch'"

3.2 编程方式

import { Codex } from '@openai/codex-sdk';

const codex = new Codex({ apiKey: process.env.OPENAI_API_KEY });

// 注册 pre-run hook
codex.hook('pre-run', async (context) => {
  console.log('Starting task:', context.task);
  // 执行准备工作
});

// 注册 post-tool hook
codex.hook('post-tool', async (context) => {
  console.log('Tool called:', context.tool.name);
  console.log('Result:', context.result);
  // 处理工具结果
});

// 注册 on-error hook
codex.hook('on-error', async (context) => {
  console.error('Error:', context.error.message);
  // 错误处理
});

3.3 条件匹配

可以为特定工具注册 Hook:

hooks:
  pre-tool:
    - match: "shell"
      command: "echo 'Running shell command'"
    - match: "apply_patch"
      command: "echo 'Applying patch'"

四、使用场景

4.1 代码格式化

在文件修改后自动运行格式化:

hooks:
  post-tool:
    - match: "apply_patch"
      command: "prettier --write $FILE"

4.2 测试运行

在任务完成后自动运行测试:

hooks:
  post-run:
    - command: "npm test"

4.3 日志记录

记录所有工具调用:

hooks:
  post-tool:
    - command: "echo '$(date): $TOOL_NAME called' >> codex.log"

4.4 通知发送

在任务完成时发送通知:

hooks:
  post-run:
    - command: "notify-send 'Codex' 'Task completed'"

4.5 代码审查

在代码修改后自动运行审查:

hooks:
  post-tool:
    - match: "apply_patch"
      command: "eslint $FILE"

4.6 备份

在修改文件前自动备份:

hooks:
  pre-tool:
    - match: "apply_patch"
      command: "cp $FILE $FILE.bak"

五、Hook 上下文

5.1 可用信息

Hook 可以访问以下信息:

  • task:任务描述
  • tool:工具信息(名称、参数)
  • result:执行结果
  • error:错误信息
  • timestamp:时间戳
  • session:会话信息

5.2 环境变量

Hook 执行时会设置以下环境变量:

  • CODEX_HOOK_EVENT:事件类型
  • CODEX_TOOL_NAME:工具名称
  • CODEX_TASK_ID:任务 ID
  • CODEX_SESSION_ID:会话 ID
  • CODEX_FILE:当前文件路径

5.3 返回值

Hook 可以返回值来影响后续执行:

  • 返回 true:继续执行
  • 返回 false:阻止执行
  • 返回修改后的参数:替换原始参数

六、最佳实践

6.1 性能考虑

  • Hook 应该快速执行,避免阻塞主流程
  • 避免在 Hook 中执行耗时操作
  • 使用异步执行避免阻塞
  • 设置合理的超时时间

6.2 错误处理

  • Hook 应该处理可能的错误
  • 避免 Hook 失败影响主任务
  • 记录 Hook 执行日志
  • 提供错误恢复机制

6.3 安全性

  • 验证 Hook 输入
  • 限制 Hook 权限
  • 避免执行危险命令
  • 审计 Hook 执行

6.4 可维护性

  • 保持 Hook 简单
  • 提供清晰的文档
  • 版本控制 Hook 配置
  • 定期审查和更新

七、调试技巧

7.1 日志记录

在 Hook 中添加日志,便于调试:

codex.hook('pre-tool', async (context) => {
  console.log('[Hook] pre-tool:', JSON.stringify(context, null, 2));
});

7.2 测试 Hook

单独测试 Hook,确保正确工作:

# 测试 pre-run hook
codex hook test pre-run "test task"

7.3 查看 Hook 列表

codex hook list

八、本课小结

要点说明
Hooks生命周期钩子,插入自定义逻辑
事件类型任务事件、工具事件、会话事件
注册方式配置文件、编程方式
使用场景格式化、测试、日志、通知、审查、备份
上下文任务、工具、结果、错误、时间戳

下一步

下一课我们将进入实战环节。