作者:木卫四AI安全研究小组
如果你做过 Android 逆向、Linux 内核、安全或者性能分析,那么看到 Claude Code、OpenClaw、DeepSeek Harness 都开始大谈 Hook 时,很容易产生一种错觉:
难道 Agent Runtime 也开始搞 Inline Hook、GOT/PLT 劫持了?
当然不是。
但有趣的是,如果暂时抛开具体实现,只看计算机系统背后的抽象,今天 Agent Runtime 中所谓的 Hook,与我们熟悉的 Linux Kprobe、Android ART Hook、Xposed Hook,确实来自同一个思想:
在原有控制流的关键路径上建立一个稳定的拦截点,让第三方逻辑能够观察、修改,甚至改变后续执行。
区别只在于,以前我们 Hook 的是 CPU 指令、Native Function、Java Method 和 System Call;今天开始 Hook 的,则是:
text
Prompt Build
Model Call
Tool Call
Permission
SubAgent
Context Compact
Turn Stop
Agent Finalize
Hook 的抽象层级,正在从"函数"一路爬升到"智能体生命周期"。
而我认为,这件事的意义远远不只是"Agent 又多了一个插件机制"。
Hook 正在逐渐成为 Agent Runtime 的控制平面。
一、Hook 从来都不只是"替换一个函数"
先从我们熟悉的世界说起。
Linux Kernel 官方对 Kprobes 的描述非常直接:它允许我们动态地进入内核例程,在某个内核代码地址建立 probe,并在命中时执行 handler;Kretprobe 则把拦截点放到了函数返回路径。
抽象一下,其实就是:
text
Original Control Flow
│
▼
Hook Point
│
▼
Handler
│
┌────┴─────┐
│ │
observe modify
│ │
└────┬─────┘
▼
Continue / Redirect / Block
Android 里的 Xposed、ART Hook、Native Inline Hook,本质上也没有逃出这个模型。
比如:
text
Caller
│
▼
foo()
│
├──────→ hook_before()
│
├──────→ original foo()
│
└──────→ hook_after()
区别只是"如何把 Hook 塞进去"。
Native Inline Hook 可能修改机器指令。
PLT/GOT Hook 修改动态链接路径。
ART Hook 修改 Runtime 中的方法入口或调用结构。
Kprobe 依赖 Linux Kernel 提供的动态探针机制。
到了 Agent Runtime,这一步发生了根本变化:
我们已经不需要偷偷劫持控制流,因为 Runtime 自己主动把 Hook Point 暴露出来了。
于是:
text
Machine Code Hook
↓
侵入式改变控制流
Agent Runtime Hook
↓
Runtime 主动调用扩展点
在软件工程术语里,后者其实更像 Middleware、Interceptor、Callback、AOP。
但"Hook"这个名字反而很准确,因为它描述的并不是实现,而是能力:
我能不能在这个控制流节点把执行钩住?
二、理解 Agent Hook,首先必须把 Model 和 Runtime 分开
很多关于 Agent 的讨论都有一个基础误区:
把"大模型"和"Agent"视为同一个东西。
实际上,一个最小的 LLM 调用可能只是:
text
Prompt
│
▼
LLM
│
▼
Completion
但一个真正的 Coding Agent 更接近:
text
User
│
▼
┌─────────────────────────┐
│ Agent Runtime │
│ │
│ Build Context │
│ ↓ │
│ Model Request │
│ ↓ │
│ Parse Tool Call │
│ ↓ │
│ Permission / Policy │
│ ↓ │
│ Execute Tool │
│ ↓ │
│ Append Tool Result │
│ ↓ │
│ Call Model Again │
│ │
└────────────┬────────────┘
│
▼
Final Answer
它本质上是一个循环。
简化以后就是:
python
while True:
context = build_context()
response = model(context)
if response.has_tool_call():
result = execute_tool(
response.tool_call
)
context.append(result)
continue
return response
真正定义一个 Agent 行为边界的,很多时候并不是模型,而是包裹模型的这一层:
Agent Runtime / Agent Harness / Agent Loop / Orchestrator。
DeepSeek Harness 的架构文档甚至非常明确地区分了 Step 和 Turn:一次 Step 是一次模型请求以及由该响应触发的工具调用,而一个 Turn 可以包含零到多个 Step。其执行流从 agent/pre-step、agent/request,一路进入 tools/pre-execute、tools/execute、tools/post-execute,最后抵达 agent/turn-stopping。
于是我们第一次可以非常准确地定义 Agent Hook:
Agent Runtime Hook,是 Runtime 在 Agent Loop 的生命周期关键节点上暴露出来的可编程拦截点。
三、Agent Runtime Hook 到底 Hook 了什么?
一个支持 Hook 的 Agent Loop,可以近似写成:
python
while True:
emit("before_prompt_build")
prompt = build_prompt()
emit("before_model_call")
response = model(prompt)
emit("after_model_call")
if response.tool_call:
decision = emit(
"before_tool_call",
response.tool_call
)
if decision.block:
continue
result = execute_tool(
decision.input
)
result = emit(
"after_tool_call",
result
)
add_tool_result(result)
continue
decision = emit("before_stop")
if decision.continue_running:
continue
return response
注意这里发生了一件非常重要的变化。
传统 Event Bus 往往只是:
text
Something happened
│
▼
notify listeners
而 Agent Hook 很多时候是:
text
Something is ABOUT to happen
│
▼
Handler
│
▼
Decision
│
┌───────┼────────┐
▼ ▼ ▼
Allow Modify Deny
因此 Hook 不再只是"通知"。
它可以拥有真正的控制权。
这也是为什么我倾向于把一个成熟的 Agent Hook 抽象成:
text
Hook =
Point
+ Context
+ Handler
+ Decision
+ Ordering
+ Failure Semantics
换成数学一点的表达:
text
H = <P, C, F, D, O, E>
其中:
text
P = Hook Point
C = Execution Context
F = Handler
D = Decision
O = Handler Ordering
E = Error / Timeout Semantics
后面的 Ordering 和 Failure Semantics 特别关键。
因为一旦 Hook 能改变 Agent 行为,问题就不再是"Hook 有没有执行"。
而变成:
text
两个 Hook 冲突怎么办?
A allow,B deny,听谁的?
Hook timeout 是 fail-open 还是 fail-closed?
一个 Plugin 能不能覆盖另一个 Plugin 的安全策略?
Hook 能不能再次触发 Hook?
Stop Hook 能不能无限阻止 Agent 停止?
这时候,它已经不是普通插件系统的问题了。
它开始变成 Runtime 的控制平面设计问题。
四、Tool Hook 是整个 Agent Hook 体系里最关键的拦截点
为什么各家 Runtime 都非常重视 Tool Hook?
因为 LLM 本身只能"建议一个动作"。
真正让这个动作影响现实世界的是 Tool Executor。
比如模型输出:
json
{
"tool": "Bash",
"input": {
"command": "rm -rf build"
}
}
没有 Hook 时:
text
LLM
│
│ Tool Call
▼
Bash Executor
│
▼
Operating System
加入 Tool Hook:
text
LLM
│
▼
Tool Call
│
▼
┌────────────────────┐
│ Before Tool Hook │
└──────────┬─────────┘
│
Policy Check
│
┌────┴────┐
▼ ▼
Allow Deny
│
▼
Tool Executor
│
▼
┌────────────────────┐
│ After Tool Hook │
└──────────┬─────────┘
│
Audit / Rewrite
│
▼
Tool Result
Claude Code 当前将这种生命周期事件直接命名为 PreToolUse 和 PostToolUse。官方文档说明,PreToolUse 在工具真正执行之前触发并能够阻止调用,而 PostToolUse 在工具成功后触发;此外还有 PermissionRequest、PostToolUseFailure、PostToolBatch 等更细粒度节点。
官方甚至给出了一个非常典型的例子:
text
PreToolUse
↓
matcher = Bash
↓
检查 command
↓
发现 rm -rf
↓
permissionDecision = deny
↓
Tool 不执行
也就是说,对 Agent 来说:
text
Prompt:
"不要运行危险命令"
和:
text
PreToolUse:
if dangerous:
deny
完全不是一种东西。
前者是:
text
LLM Soft Constraint
后者是:
text
Runtime Hard Constraint
这可能是理解 Agent Hook 最重要的一道分界线。
五、为什么 Agent 时代比过去更需要 Hook?
传统程序大多数控制流是确定性的:
text
if A:
call B()
else:
call C()
所以安全边界通常直接写进程序。
但 Agent 的决策核心是概率模型:
text
Context
│
▼
Transformer
│
▼
"我认为下一步应该调用 Bash"
你可以在 System Prompt 里写:
text
Never delete production data.
但从系统设计角度来说,它仍然只是自然语言约束。
真正稳健的 Agent Runtime 必须形成两层:
text
LLM
│
Reasoning / Planning
│
Soft Policy
│
▼
┌──────────────┐
│ Agent Runtime│
└──────┬───────┘
│
Hook / Permission
│
Hard Policy
│
▼
Tools
于是 Hook 实际上完成了一个非常重要的架构转换:
把"希望模型遵守规则",转换成"Runtime 强制执行规则"。
这也是为什么企业 Agent、Coding Agent、Computer Use Agent 最终几乎一定都会需要一种 Runtime-level interception mechanism。
只靠 Prompt 很难承担系统安全边界。
六、Claude Code:Hook 是生命周期协议
Claude Code 是目前非常容易观察这种设计思想的实现之一。
截至 2026 年 9 月,其官方文档已经把 Hook 明确定义为:
在 Claude Code 生命周期特定节点自动执行的用户定义 Handler,Handler 可以是 shell command、HTTP endpoint、MCP tool、LLM prompt 或 subagent。
换句话说:
text
Claude Code Runtime
│
├── SessionStart
│
├── UserPromptSubmit
│
├── PreToolUse
│
├── PermissionRequest
│
├── PostToolUse
│
├── SubagentStart
│
├── Stop
│
├── PreCompact
│
└── SessionEnd
这里最值得关注的不是事件数量,而是 Claude Code 已经把生命周期分成不同频率:
text
Session Level
↓
Turn Level
↓
Agentic Loop Level
↓
Tool Level
官方目前明确区分了"每 Session""每 Turn"和"Agent Loop 内每次 Tool Call"触发的 Hook。
这意味着 Hook 已经不再是某个辅助功能。
它其实开始定义:
Agent Runtime 的 Extension ABI。
七、比 PreToolUse 更有意思的是 Stop Hook
Tool Hook 很容易理解。
真正体现 Agent Runtime 特性的,是 Stop Hook。
想象 Agent 做完了一轮工作:
text
修改代码
↓
认为任务完成
↓
准备输出 Final Answer
传统 Runtime:
text
Model says done
↓
Finish
加入 Stop Hook 后:
text
Model says done
│
▼
Stop Hook
│
▼
run_tests.sh
│
┌────┴────┐
▼ ▼
PASS FAIL
│ │
Finish │
▼
"测试未通过"
│
▼
LLM
│
▼
再执行一轮
Claude Code 的 Stop Hook 正是可以控制 Claude 是否继续执行:返回 block,可以阻止本次停止,并告诉 Claude 为什么需要继续。它现在还支持通过 additionalContext 给模型反馈,并带有循环保护。
甚至 Hook Handler 自己也可以由 LLM 执行。
Claude Code 的 prompt-based Hook 会把 Hook 输入和指定 Prompt 发给一个模型,让模型返回结构化 Decision。例如 Stop Hook 可以再调用一个模型判断:
text
"当前任务真的完成了吗?"
然后决定是否允许主 Agent 停止。
于是系统开始出现一种很有意思的结构:
text
Main Agent
│
▼
wants to stop
│
▼
Judge Hook
│
▼
Another LLM
│
┌──┴──┐
▼ ▼
Yes No
│ │
Stop Continue
这里已经隐约出现了:
Agent Supervisor。
Hook 不再只是前置/后置脚本。
它甚至能够成为另一个智能体。
八、Hook 还有一种传统程序很少见的能力:修改"认知环境"
传统函数 Hook 常见能力是:
text
修改参数
修改返回值
阻止调用
记录调用
Agent Hook 多出了一种极其特殊的能力:
text
Inject Context
例如一个文件修改完成之后,PostToolUse Hook 可以告诉模型:
text
这个文件是自动生成文件。
真正需要修改的是:
src/schema.ts
然后重新执行 generate。
Claude Code 当前提供的 additionalContext 就是这种机制:Hook 输出可以被包装为额外上下文,在下一次模型请求中进入 Claude 的 context window。
于是出现了:
text
Tool Result
+
Hook Context
+
Conversation History
│
▼
LLM
这非常重要。
因为 Agent Hook 不只是修改:
text
程序下一步执行什么
它还能修改:
text
模型下一步"看到什么"
于是 Hook 的作用对象从:
text
Control Flow
扩展到了:
text
Control Flow + Cognitive Context
这是 Agent Runtime 与传统 Runtime 最大的区别之一。
九、DeepSeek Harness:把 Hook 做成 Typed Interception Pipeline
如果 Claude Code 很适合理解"生命周期协议",那么 DeepSeek Harness 更适合理解 Hook 的 Runtime 内部实现。
它没有把 Hook 仅仅设计成:
text
event -> shell script
而是直接把 Runtime 内部关键边界暴露为 typed extension points。
典型执行路径是:
text
agent/pre-step
↓
agent/request
↓
LLM
↓
tool/call
↓
tools/pre-execute
↓
tools/execute
↓
tools/post-execute
↓
tool/result
↓
agent/turn-stopping
这些 extension point 中相当一部分采用 waterfall 语义:Listener 必须通过 next() 把控制权继续传递给下一个 Handler。
例如官方 Cookbook 中的 permission gate,本质上就是:
ts
ctx.on(
"tools/pre-execute",
async (exec, next) => {
if (!(await isAllowed(exec))) {
return {
kind: "deny",
reason: "Denied by policy."
};
}
return next();
}
);
如果你做过 Web Backend,这一眼看上去就是 Middleware:
text
Middleware A
│
▼
Middleware B
│
▼
Middleware C
│
▼
Tool Executor
所以 Agent Hook 在这里几乎可以准确翻译成:
Typed Runtime Interceptor。
十、DeepSeek Harness 中一个很重要的设计:Waterfall 和 Monotonic Guard 是不同东西
这一点特别值得 Runtime 设计者注意。
普通 Waterfall 可以:
text
Handler A
↓
Decision
↓
Handler B
↓
rewrite Decision
但安全策略往往不能这么做。
假设:
text
Security Hook:
DENY
↓ 下一层
Business Plugin:
ALLOW
如果后面的 Plugin 能覆盖前面的 Deny:
text
DENY → ALLOW
整个安全模型就崩了。
DeepSeek Harness 因此把普通 tools/pre-execute waterfall 与 ctx.tools.guard() 的 monotonic final denial 区分开。官方 Cookbook 明确把 guard 描述为适合那些需要"单调最终拒绝"的 invariant。
这个设计非常值得借鉴。
因为一个成熟 Agent Runtime 的权限 Decision 并不应该只是:
text
boolean allow
而应该形成某种决策代数:
text
PASS
DENY
ASK
MODIFY
RETRY
ADD_CONTEXT
FORCE_CONTINUE
其中部分 Decision 应该满足:
text
DENY 不可被普通 Plugin 覆盖
Tool Scope 只能缩小,不能偷偷扩大
Sandbox Constraint 只能加强,不能放松
OpenClaw 目前也能看到类似思想:多个 before_prompt_build Hook 返回的 tool restrictions 会做交集,也就是进一步收窄当前 Turn 可以提交给模型的工具集合,而不是后来的 Plugin 任意扩权。
这已经很接近 Capability Security 的思路了。
十一、"DeepSeek Harness 支持 Claude Code Hook"究竟是什么意思?
这句话很容易被误解成:
text
DeepSeek Harness 内部
=
Claude Code Hook Runtime
其实不是。
DeepSeek Harness 自己有 Native Typed Hook:
text
tools/pre-execute
tools/post-execute
agent/pre-step
agent/turn-stopping
...
与此同时,它提供 compatibility bridge,把 Claude Code 的 Hook 协议映射到自己的扩展点。
官方文档给出的对应关系非常直观:
| Claude Code Hook | DeepSeek Harness Extension Point |
|---|---|
SessionStart |
agent/session-start |
UserPromptSubmit |
agent/pre-step |
PreToolUse |
tools/pre-execute |
PostToolUse |
tools/post-execute |
Stop |
agent/turn-stopping |
SubagentStart |
subagent/start |
SubagentStop |
subagent/end |
也就是说实际架构是:
text
Claude Code hooks.json
│
▼
┌────────────────────────┐
│ Compatibility Adapter │
└────────────┬───────────┘
│
▼
DeepSeek Harness
Typed Interception API
│
▼
Agent Loop
其中尤其有趣的是 Stop Hook。
DeepSeek Harness 的 bridge 会把 Claude Code Stop 的阻塞语义映射到 agent/turn-stopping,然后通过 steer 让 Agent 再执行一步。
于是:
text
External Hook Dialect
↓
Adapter
↓
Canonical Runtime Decision
这实际上已经非常接近编译器里的:
text
Frontend Language
↓
Intermediate Representation
↓
Backend
也许未来 Agent Hook 生态同样会出现一种:
Hook IR。
不同 Runtime 对外兼容 Claude Code、Codex 等协议,但内部统一映射到自己的 Typed Interception Model。
十二、OpenClaw:开始显式定义 Hook 的"执行契约"
OpenClaw 的方向又不同。
它目前明确区分三套概念:
text
Typed Plugin Hooks
Internal Hooks
HTTP Webhooks
Typed Plugin Hook 用于 Agent / Tool 生命周期;Internal Hook 更多服务于 /new、/reset、/stop、bootstrap 等 Gateway 事件;Webhook 则是外部系统通过 HTTP 触发 Agent。官方文档明确强调,这三者不是同一套 Hook API。
更有意思的是,它开始按照执行语义给 Hook 分类。
目前可以看到:
text
Modify
Claim
Gate
Observe
Sync Modify/Gate
Evaluate
这比简单定义:
text
before_xxx
after_xxx
更进一步。
因为它实际上开始回答:
text
这个 Hook 能不能改数据?
能不能终止后续 Hook?
返回值有没有意义?
多个 Handler 是串行还是并发?
谁的结果优先?
Timeout 以后发生什么?
例如:
text
Modify
↓
顺序执行并合并结果
Claim
↓
第一个 handled=true 获胜
Gate
↓
第一个 block 立即终止
Observe
↓
并发执行
返回值忽略
到这里,Hook 已经明显不再是"回调函数"。
它更像:
Runtime-level execution contract。
十三、Hook 和 Event Bus、Middleware、Policy Engine 到底有什么区别?
它们很像,但最好不要混为一谈。
可以用一个非常简单的判断方法。
Event Bus 关注的是:
text
发生了什么?
Middleware 关注的是:
text
请求经过哪些处理层?
Policy Engine 关注的是:
text
这个动作允许执行吗?
Hook 关注的是:
text
这个生命周期节点,
允许第三方拥有多大控制权?
因此一个成熟 Agent Hook 系统实际上会把这三者全部吸收进来:
text
Hook System
│
┌─────────┼──────────┐
│ │ │
Observe Modify Gate
│ │ │
Event Bus Middleware Policy
这就是为什么简单使用:
ts
EventEmitter.emit(...)
最终通常不足以支撑复杂 Agent Runtime。
当系统进入生产环境以后,很快就会出现:
text
Priority
Timeout
Cancellation
Isolation
Context Injection
Decision Merge
Permission
Retry
Tracing
Reentrancy
Loop Protection
Hook 最终会变成一个完整的 Runtime 子系统。
十四、Agent Hook 最大的价值:它正在形成 Agent Control Plane
如果站得再高一点,我们可以把一个现代 Agent 系统拆成:
text
┌─────────────────────────────────┐
│ Model Plane │
│ │
│ Reasoning / Planning / Tokens │
└────────────────┬────────────────┘
│
▼
┌─────────────────────────────────┐
│ Runtime Plane │
│ │
│ Session / Turn / Step / Context │
└────────────────┬────────────────┘
│
▼
┌─────────────────────────────────┐
│ Control Plane │
│ │
│ Hook / Policy / Approval │
│ Sandbox / Permission / Guard │
└────────────────┬────────────────┘
│
▼
┌─────────────────────────────────┐
│ Tool Plane │
│ │
│ Bash / Browser / FS / MCP / API │
└─────────────────────────────────┘
LLM 决定:
text
我想做什么
Runtime 决定:
text
Agent Loop 怎么运行
Hook / Policy 层决定:
text
这件事到底能不能发生
Tool 层决定:
text
如何真正影响外部世界
这也解释了为什么 Hook 会越来越重要。
Agent 越自主:
text
Autonomy ↑
Runtime 对确定性控制机制的需求反而越高:
text
Deterministic Control ↑
这是一个看似矛盾,实际上非常自然的趋势。
十五、但 Hook 自己也会成为新的攻击面
千万不能因为 Hook 被用于"安全",就认为 Hook 本身是安全边界。
恰恰相反。
Hook 往往拥有极高权限。
Claude Code 官方安全文档明确提醒:Command Hook 会以当前用户的完整权限执行 Shell 命令,因此能够读取、修改和删除该用户有权限访问的文件。
OpenClaw 同样提醒,native plugin 直接运行于 Gateway 进程,因此只能安装可信插件。
因此:
text
LLM Tool Call
│
▼
Security Hook
并不自动意味着:
text
系统安全了
真正的问题变成:
text
谁能注册 Hook?
Hook 在哪个权限域执行?
Project Hook 能不能覆盖 Org Hook?
Hook 是否运行在 Sandbox?
Hook timeout 是 fail-open 还是 fail-closed?
Hook 是否能读取完整 Conversation?
Hook 能否修改 Prompt?
Hook 是否可以扩大 Tool Capability?
插件供应链是否可信?
所以成熟 Agent Runtime 最终很可能需要两套不同的 Hook 层:
text
Trusted Runtime Policy
│
▼
Security Invariants
│
▼
Extension Hooks
│
▼
User Plugins
不能把所有 Handler 都塞进一条无差别 Middleware Chain。
十六、如果今天让我设计一个 Agent Runtime,我会怎样设计 Hook?
我不会从:
ts
on("event", callback)
开始。
我会先定义整个 Agent Lifecycle:
text
SessionStart
│
▼
TurnStart
│
▼
BeforePromptBuild
│
▼
AfterPromptBuild
│
▼
BeforeModelCall
│
▼
AfterModelCall
│
▼
BeforeToolCall
│
▼
PermissionCheck
│
▼
ToolExecute
│
▼
AfterToolCall
│
▼
BeforeNextStep
│
▼
BeforeStop
│
▼
BeforeFinalAnswer
│
▼
TurnEnd
│
▼
SessionEnd
然后明确每个 Hook Point 属于哪种 Contract:
text
OBSERVE
MODIFY
GATE
AROUND
TERMINAL
最后定义强类型 Decision:
ts
type Decision<T> =
| { kind: "pass" }
| { kind: "allow" }
| { kind: "deny"; reason: string }
| { kind: "ask"; prompt: string }
| { kind: "modify"; value: T }
| { kind: "context"; text: string }
| { kind: "retry"; reason?: string }
| { kind: "continue"; reason: string };
但到这里仍然没有结束。
真正难的是定义:
text
Decision Composition
比如安全边界我会倾向:
text
Monotonic Deny
也就是:
text
一旦 Trusted Guard = DENY
普通 Extension
不能把它重新改成 ALLOW
工具权限采用:
text
Capability Intersection
也就是:
text
Runtime Tools
∩
Organization Policy
∩
Project Policy
∩
Agent Policy
=
Effective Tools
这样 Capability 永远只能收窄。
而不是:
text
某插件 return allow
=
突然获得新权限
这会比"所有 Hook 返回一个 boolean"健壮得多。
十七、从 Android Hook 回头看 Agent Hook,会发现一条非常漂亮的演进路径
我们可以重新排列整件事情:
text
CPU Instruction
│
▼
Native Function
│
▼
Java Method
│
▼
System Call
│
▼
Runtime API
│
▼
Tool Call
│
▼
Agent Step
│
▼
Agent Turn
│
▼
Agent Lifecycle
对应的 Hook 也一路向上:
text
Breakpoint
↓
Inline Hook
↓
PLT/GOT Hook
↓
ART/Xposed Hook
↓
Kprobe/eBPF
↓
Middleware
↓
Tool Hook
↓
Agent Lifecycle Hook
层级越高:
text
Hook 的对象越语义化
以前我们只能知道:
text
openat("/data/a.txt")
后来可以知道:
text
Java:
FileInputStream.open()
到了 Agent Runtime:
text
Agent 正准备调用 Bash,
目的是修改生产环境配置,
这是本轮推理的第三个工具动作。
Hook 得到的不再只是:
text
Registers
Arguments
Return Value
而可能是:
text
Session
Turn
Agent
Tool
Intent
Context
Permission
Model
Conversation
这意味着 Hook 的抽象能力大幅增强。
与此同时,它承担的责任也更大。
十八、未来真正值得关注的,可能不是某一个 Hook API,而是 Agent Runtime ABI
DeepSeek Harness 能够把 Claude Code Hook 映射到自己的 Typed Interception Points,其实已经透露出一个非常重要的趋势。
今天我们看到的是:
text
Claude Code Hook
OpenClaw Hook
Codex Hook
DeepSeek Harness Hook
但它们底层表达的语义高度相似:
text
Before Prompt
Before Model
Before Tool
After Tool
Permission
SubAgent Start
Turn Stop
Session End
那么下一步很自然:
text
不同 Hook Dialect
│
▼
Canonical Agent Lifecycle
│
▼
Typed Decision IR
│
▼
Different Agent Runtimes
如果这一层最终稳定下来,它可能会扮演类似:
text
POSIX
JVM TI
Servlet Middleware
OpenTelemetry
那样的角色。
不是规定模型怎么思考。
而是规定:
一个 Agent Runtime 在哪些稳定边界上,允许外部世界观察和控制它。
我认为这比"哪家 Agent 的 Prompt 写得更好"重要得多。
因为模型会持续变化。
Claude、GPT、DeepSeek、Gemini 都可以被替换。
但一旦一个 Agent 真正进入生产环境,你最终需要稳定下来的东西其实是:
text
Tool Contract
Session Contract
Permission Contract
Lifecycle Contract
Hook Contract
换句话说:
Model 是可替换的智能内核,Runtime 才是 Agent 真正的操作系统。
而 Hook,就是这个"Agent OS"留给外部世界的系统调用边界与控制接口。
结语
我最开始研究 Hook,是在 Android 和 Linux 的语境里。
那时候 Hook 解决的问题是:
text
这个函数什么时候被调用?
参数是什么?
能不能替换?
能不能阻止?
今天回头看 Agent Runtime,问题其实没有变。
只是我们 Hook 的东西变成了:
text
模型什么时候被调用?
Agent 为什么调用这个 Tool?
这个动作能不能执行?
Tool Result 能不能重写?
上下文能不能注入?
Agent 现在真的可以结束了吗?
从 Inline Hook 到 Agent Hook,看起来跨度巨大。
但在系统软件的视角下,它们遵循的始终是同一个古老原则:
text
找到控制流
↓
建立稳定拦截点
↓
暴露上下文
↓
执行外部逻辑
↓
形成决策
↓
恢复或改变控制流
只是过去我们在 Hook 程序。
现在,我们开始 Hook 智能体的行为过程。
而当 Hook 能够控制 Prompt、Tool、Permission、Context、SubAgent 和 Stop Condition 时,它事实上已经不再只是一个插件机制。
它正在成为 Agent Runtime 中负责确定性、权限和治理的那一层:
Agent Control Plane。