KB-METABOLISM · 机制图解

hooks 是怎么生效的:门的第二形态

MCP 工具靠 agent 自觉调用——它有时不会去搜。hooks 把"走门"从选择变成管道的必然:每条提问自动检索、相关就注入、不相关就沉默。本页拆解从 kb hook install 到摘要出现在模型上下文里的每一步。

CONTEXT DISPATCH / LIVE MODEL

在 Agent 思考之前

选择一种真实场景,观察问题如何穿过 hook。橙色数据包代表本轮输入;只有相关知识通过判准,才会进入模型上下文。

VAULT · 276 NOTES
USER
PROMPT
免费 AI 课程平台详细调研里有哪些平台?
01收到输入stdin JSON
02触发 hookbefore model
03字面检索local SQLite
04相关判准top 3 / silence
05交给模型extra context
准备就绪。点击“运行演示”,查看相关笔记如何自动出现在上下文里。
本轮输入 已完成阶段 零输出,正常放行

PROMPT → INJECTED CONTEXT

再看几个实际案例

左边是你对 Agent 说的话,右边是 hook 在模型思考前补进去的内容。它只提供命中的笔记摘要,不会替 Agent 生成最终答案。

01
项目调研
“免费 AI 课程平台有哪些?帮我对比一下。”
INJECTED<kb-context> 10-projects/38-agent面试备考/免费AI课程平台详细调研.md 的标题与摘要片段进入上下文;需要细节时 Agent 再调用 kb_read
02
个人基础设施
“腾讯服务器和 Mac 服务器分别部署了什么?”
INJECTED<kb-context> 命中 30-resources/腾讯服务器和mac服务器.md。Agent 优先基于你的真实机器记录回答,而不是凭通用经验猜测。
03
历史积累
“Claude Code 的 hooks 配置要注意哪些坑?”
INJECTED<kb-context> 命中 40-archive/claudeCode/Claude Code 深度教程/06-附录.md 等相关教程,最多注入 3 篇摘要。
04
提示词资料
“我保存的 Opus 5 System Prompt 讲了什么?”
INJECTED<kb-context> 命中 90-system/01-提示词/opus-5-SystemPrompt.md。摘要先回答“库里有没有”,全文读取才产生更强的续命信号。
05
普通问题
“17 × 23 等于多少?”
EMPTY零输出 没有笔记同时满足相关性判准。Host 不添加任何知识库内容,Agent 直接回答原问题。
06
会话事件
Codex 启动、恢复或压缩上下文
STATUS<kb-status> 注入“276 条、L0 2/100”、最近读过的 3 篇和消化提醒。它不是检索结果,而是一次会话连续性快照。
00

为什么需要第二形态

形态一 · MCP 工具(自觉) agent 觉得需要才调 kb_search。它经常不觉得需要——直接凭训练知识回答,你的积累被绕过,笔记拿不到续命信号。
形态二 · hooks(管道) Claude Code / Codex 在每条提问进入模型之前强制运行一段外部命令。检索不再依赖 agent 的判断——它发生在 agent 思考之前。
01

安装那一刻发生了什么

kb hook install 往 Claude Code 的 ~/.claude/settings.json 写两条挂点;kb hook install --client codex 则写 Codex 的 ~/.codex/hooks.json(两者都会先备份 .bak;加 --project 改为项目级配置):

{
  "hooks": {
    "UserPromptSubmit": [{ "hooks": [{ "type": "command",
      "command": "\"/path/to/node\" \"/path/to/cli.js\" hook prompt --vault \"/你的/vault\"" }] }],
    "SessionStart":     [{ "hooks": [{ "type": "command",
      "command": "\"/path/to/node\" \"/path/to/cli.js\" hook session --vault \"/你的/vault\"" }] }]
  }
}
02

每条提问的完整时序(UserPromptSubmit)

从你按下回车到模型开始思考之间,发生了这 8 步——全程毫秒级:

AGENT HOST你提交一条消息。在把它交给模型之前,Claude Code / Codex 发现 UserPromptSubmit 挂点上注册了命令,同步执行它,把 {"prompt": "即将发送的内容", …} 以 JSON 写进该进程的 stdin。这个字段可能夹带 ambient UI、IDE 文件状态等机器包装。
KB 进程 · 输入净化kb hook prompt 先取出 Codex 的 My request for Codex 段,并剥离 Claude 的 IDE/任务通知块;纯机器事件直接变为空查询。信号日志也只记录净化后的用户原话。
守门 · 提前退出提问不足 4 个字符 → 直接退出,零输出。(另有总闸:任何异常都被吞掉静默退出——hook 永不打断你的提问。)
KB 进程只读打开派生索引 .kb/kb.db(SQLite),跑 纯字面检索 hookSearch——刻意不走 embedding:hook 阻塞提问,不能付网络延迟。英文按完整词匹配,in 不再碰瓷 interface
统一判准精确命中也没有免检通道。每篇候选必须同时满足:原始有效词覆盖 ≥ 35%idf 加权覆盖 ≥ 50%至少 1 个有效主题词命中标题。英文停用词、纯标点不参与评分,正文偶遇一句“怎么修复”不能直接获得注入资格。取 top 3。
纪律 · 宁沉默没有一篇过线 → 零输出退出。Agent host 收到空 stdout = 什么都不注入。沉默是合格行为,不是故障。
信号记账每篇被注入的笔记追加一行 kb_inject.kb/access.log.jsonl(含 query 前 80 字、路径、kb_id)——这是第三档存活证据,免死 30 天
注入stdout 输出 <kb-context> 块(每篇一行:路径 — 标题:摘要片段,外加一句"如需全文用 kb_read")。Agent host 把这段文本放进本轮模型上下文——模型"未卜先知"地知道了你的相关积累。
03

会话开始时(SessionStart)

新会话(含 resume)第一时间注入一次 <kb-status>,内容三样:库概况(总数、L0 容量)、最近经门读过的 3 篇(按 kb_id 解析成当前路径——笔记移动过也指得到新家,给会话连续性),以及距上次消化超一周时的提醒("请转告用户")。库为空则沉默。

04

注入在信号经济里的位置

hooks 不只是便利功能——它是信号经济的一环。协议 v2 起,注入是第三档存活证据:

kb_cite
被引用进产出 · 免死 180 天
kb_read
被读取全文 · 免死 90 天
kb_inject
被注入且真相关 · 免死 30 天
search / ui
不续命

为什么注入配续命:摘要一眼够用的短笔记最有用,却恰恰因此永远不会被点开全文——v1 时代它们会被法医冤杀。为什么只有 30 天:注入是机器行为,效力必须低于人/agent 亲手读取与引用。为什么先收紧判准再给续命:判准不准,注入续命就是滥发免死金牌——顺序不能反。

05

三条纪律与三个坑

纪律(刻在代码里)

坑(使用前想清楚)

① 绝对路径固化hooks 配置里的命令写死了安装时的 node、cli.js 与 vault 路径。升级 node 大版本、重装 kb、移动 vault 之后,重跑一次对应 client 的 kb hook install,否则 hook 会静默失效(它连报错都不会——纪律①)。
② user 级 = 全局生效默认装在用户级配置——你在任何项目的每条提问都会检索这个 vault 并可能注入个人笔记摘要。在意隔离就用 --project 只装到特定项目。Codex 首次安装后还需用 /hooks 审核并信任。
③ 静默失效怎么察觉正因 hook 从不报错,判断它活着的办法是看信号:kb stats/管理台信号页里有没有新的 kb_inject;或新开会话看有没有 <kb-status>
06

命令速查

命令作用
kb hook install [--client claude|codex] [--project]写入两条挂点(备份 .bak,幂等),新会话生效
kb hook uninstall [--client claude|codex] [--project]按标记精确移除
kb hook show [--client claude|codex]打印配置片段,手动粘贴用
kb hook prompt / session挂点本体(Agent host 调用,不需要手动跑)
源码:packages/cli/src/hooks.ts(挂点与安装)· packages/core/src/search.tshookSearch(判准)· 协议 v2 信号规则见 协议规范 · 全系统一张图见 设计全景