# Hooks 与生命周期回调

按事件注册回调，记录工具调用，并处理超时、输出和应用回执。

## 在执行节点接入宿主逻辑

Hooks 适合记录工具动作、补充运行上下文、检查执行条件。它们在运行时声明的事件上触发，和最终结果回调不同。先选事件，再选匹配范围，最后实现回调。

常见事件包括 `PreToolUse`、`PostToolUse`、`PostToolUseFailure`、`UserPromptSubmit`、`Stop`、`SessionStart` 和 `SessionEnd`。公开常量位于 `hook` 包；运行时是否触发特定事件仍取决于实际支持，不要仅根据常量存在来启用产品承诺。

## 添加工具审计回调

```go
options = options.AddHookMatcher(hook.EventPostToolUse, hook.Matcher{
    Matcher: "Write|Edit",
    Timeout: 5 * time.Second,
    Hooks: []hook.Callback{
        func(ctx context.Context, input hook.Input, toolUseID string) (hook.Output, error) {
            if err := ctx.Err(); err != nil { return hook.Output{}, err }
            log.Printf("tool=%s tool_use_id=%s session=%s", input.ToolName, toolUseID, input.SessionID)
            return hook.Output{}, nil
        },
    },
})
```

片段使用 `hook`、`context`、`time`、`log` 包。它只记录关联身份，不打印整个工具输入。接入持久审计时，再记录经过筛选的路径、动作和状态。避免把文件内容、令牌或业务数据写入普通日志。

## 理解输入和输出

`hook.Input` 提供事件相关的类型化字段，例如 ToolName、ToolInput、ToolResponse、SessionID、CWD。不是每个事件都有这些值：工具事件才应读取工具字段，生命周期事件则按其事件含义处理。

空 `hook.Output{}` 表示不附加修改。需要影响运行时行为时，可使用 Continue、StopReason、SpecificOutput 等字段。部分布尔字段是指针，用于区分“不设置”和“明确 false”。不要用零值猜测协议是否会收到字段。

`SpecificOutput` 和 `RawSpecificOutput` 承载事件专属结果。不同事件允许的字段不同；应以 [hook 类型](https://github.com/nexus-research-lab/nexus-agent-sdk-bridge/blob/main/hook/hook.go)及对应运行时契约为准，不要把工具前置事件的响应复用到 Stop 事件。

## 超时与取消

回调在执行链路中。把长网络调用放进 Hook 会增加用户等待时间；使用传入的 context，外部请求也应继承它。设置 Matcher.Timeout 后仍需让你的回调代码响应取消，不要创建脱离上下文的后台写操作。

需要保证的业务审计应由宿主持久化，不应只依赖进程退出时的 SessionEnd。进程崩溃、系统强杀时，正常生命周期回调不一定有机会执行。

## 知道响应何时被应用

`Output.OnApplied` 表示 Hook 响应被运行时应用后的回执入口，与“Go 回调已返回”不同。使用前检查 `CapabilityHookResponseAck`。未协商时不能把本地返回时间当作运行时已采纳结果的时间。

回执适合关联状态变更，不宜作为新的长任务执行入口。保留 request ID 和 tool use ID，便于排查重复响应或取消竞态。

## Hooks 与权限如何配合

权限回调负责未决审批，Hook 负责生命周期节点逻辑。若宿主要求每次写入都经过业务检查，应明确事件、运行时行为和失败处理，而不是仅添加一条“请不要写入”的系统提示。最终隔离仍依赖[进程与工具边界](/docs/sdk-hosting)。
