mcpField
O
okl — Observed Knowledge Ledger

okl — Observed Knowledge Ledger

本地服务
github.com记忆与知识42 天前更新

关于 okl — Observed Knowledge Ledger

okl 是面向编码 Agent 的工程经验记录与验证工具,会在任务开始时提供相关经验,并在代码变化后标记过时内容。它用可执行检查证明经验,支持在推送或 CI 阶段阻止未处理的漂移。

主要功能

  1. 01按任务内容筛选经验并提供简报
  2. 02记录规则、决策和已知缺陷
  3. 03通过用户指定的检查验证经验
  4. 04代码变更时检测经验漂移
  5. 05支持推送钩子或 CI 门禁

适用场景

  1. 01避免 Agent 重复已修复的缺陷
  2. 02向新任务提供项目规范和架构决策
  3. 03代码变更后重新验证相关经验

MCP 相关

提供 okl_check、okl_record 等 MCP 工具,供 MCP Agent 获取任务简报和记录经验。也可通过 Claude Code 钩子自动提供简报。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"emeraldleaf-okl": {
"command": "uvx",
"args": [
"observed-knowledge-ledger"
]
}
}
}
启动命令uvx observed-knowledge-ledger

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypiobserved-knowledge-ledger0.9.0

工具

6

收录的工具列表 · 更新于 2 天前

参数类型必填说明
repoany否
taskstring是
limitany否
compactboolean否

详细介绍

okl logo: a tree's growth rings around a healed scar, in an engraved frame with okl in the gap

okl — 观察知识账本

为编码 Agent 提供经过验证的记忆,以及让记忆始终真实可靠的闭环。
你的规则、架构决策、过往缺陷、文档和图表:只需记录一次, 每项任务开始前都会向你的 Agent 简报(通过 Claude Code 中的 hook;任何 MCP Agent 都可以请求相同的简报), 每条记录都由你选择的检查加以验证;当其覆盖范围发生变化时,会在推送前(或 CI 中)发出标记,并在构建过程中进行修正或退役。提示词提供建议;门禁负责强制执行。可以在一个代码库中使用,也可以让团队运行的所有代码库共用一个存储。
底层采用类型化记录、关键词搜索和单步链接。默认不使用嵌入,不在闭环中调用模型,也不会自动捕获;另有一个可选的本地嵌入模块,经过测量,在你启用前保持关闭(REPORT §4q)。一条经验是有意写下的,并由检查加以验证。

PyPI Python ci okl-verify Claude Code plugin License: MIT

🚀 快速入门 · 📘 开始使用 · 📥 加载你的规则 · 🔬 工作原理 · 📊 效果 · 🧪 评估报告 · 🧩 插件

pipx install 'observed-knowledge-ledger[mcp]'   # the command it installs is `okl`
okl init --repo my-repo                         # hooks, MCP server, push gate, starter lessons

42% → 7%。 在专门设计来诱发存储中已有缺陷的八项任务中,未收到简报的尝试有 163 次,其中 68 次重犯了某个缺陷;收到简报的尝试有 164 次,其中 11 次重犯。数据汇总自七轮 A/B 测试,且评判模型与生成模型不同(相关记录,§5 发现 7)。样本量小,且是在诱饵任务上一次性生成代码;了解这些结果能说明什么、不能说明什么。

加载你的规则。让 Agent 遵守规则。构建过程中持续学习。分为五个阶段:预先加载你的规则、ADR、标准和规范,以及针对你所用技术栈的入门经验;存储,即一个本地文件;每项任务开始前向 Agent 提供简报;随着代码演进实施门禁,每次推送时检查;在构建过程中持续学习,从错误、偏差和失败的测试中总结新经验,更新时保留验证依据,退役时保留原因。每项任务开始前的简报和会话结束时的问题由 Claude Code hook 提供;其他 MCP Agent 可以调用 okl_check,推送门禁适用于任何 Agent。六张卡片:每条经验采用统一格式(何时遇到、怎么做、原因);作用域决定适用范围;经过筛选,而非略读;印章代表证据,没有运行记录支撑的印章即未验证;过期内容会阻止推送;修正已有内容,而非只添加新内容。系统会以失败关闭,保留每次检查运行记录,并通过四条命令快速开始:安装、运行 okl init、使用规则所管辖的文件运行 okl record,以及使用能证明规则有效的检查运行 okl verify。 ## 哪些情况会出问题,okl 如何发现
情况okl 的处理方式
Agent 即将重复你已经为之付出代价的缺陷任务开始前,简报会根据任务中的措辞,向 Agent 提示相关经验
某条经验涉及的代码在上次检查后发生了变化okl drift 会标红;推送前钩子会拦截推送(或 CI 失败),直到检查再次通过,或代码恢复为已通过检查的状态;下一次简报会将该经验标记为 STALE
某条经验被证明有误okl retire --reason 会保留该经验,并在简报中将其标记为 AVOID,避免有人再次复述;不会删除任何内容
某条经验被替换okl retire --by <new-id>;简报会指向替代经验
无法访问存储库Claude Code 钩子会阻止提示词,并说明原因;MCP 工具会说明该经验未纳入简报。绝不会直接显示“没有适用规则”
一个会话修改了文件,却没有记录任何内容Stop 钩子会询问一次学到了什么,并列出该会话涉及的经验

快速入门

刚开始使用?docs/GETTING-STARTED.md 会介绍设置方法,以及在开发功能时添加经验的习惯。 已经有 CLAUDE.md、ADR、标准或规范?加载你的规则 会说明如何加载这些内容、验证重要规则,并保持内容最新。

1. 安装 CLI。 Python 3.11+(0.8.9 是支持 Python 3.10 的最后一个版本),用于检查代码漂移的 git。 支持 macOS 和 Linux;Windows 尚未测试 (#85)。1

pipx install 'observed-knowledge-ledger[mcp]'

2. 配置你的代码仓库,在仓库根目录运行:

okl init --repo my-repo --dry-run   # lists every file it would write; writes nothing
okl init --repo my-repo             # config, Claude Code hooks, MCP server, pre-push drift gate, starter lessons

init 会检测你的技术栈(*.csproj、package.json、pyproject.toml 等),据此设置仓库关注领域,并在存储库中填入 20 条适用于几乎任何代码库的入门经验,以及适配你技术栈的内置规则包,让第一个提示词就能获得简报(--interests 可选择你自己的主题;--no-seed 会让存储库保持为空)。如果仓库有 .claude/ 目录,或 claude 位于 PATH 中,init 会配置 Claude Code(--claude / --no-claude);还会安装一个仅在经验发生漂移时才拦截推送的推送前钩子(--no-git-hook 可跳过;--ci 会改为安装 GitHub 工作流,--ci --git-hook 则两者都安装),并记住这两项选择。它写入的每个路径及其用途见: okl init 会写入什么。

3. 添加你自己的规则。 入门经验都是通用的;真正有价值的是只有你的代码库才知道的信息。告诉你的 Agent——“为这个仓库记录一条 okl 规则:查询范围限定为已登录的客户;适用于 app/orders.py”——它就会通过 okl 的 okl_record MCP 工具记录经验(在 Claude Code 中,/record 会先起草内容并征求你的同意)。 底层实际执行的是一条 CLI 命令,你也可以自己运行:

okl record --type Rule --scope repo --id order-owner-scope \
  --title "Order lookups are scoped to the signed-in customer" \
  --symptom "an endpoint fetches an order by id with no owner filter" \
  --fix "filter by the caller's customer id in the query; return 404 on no match"

然后验证它:okl verify order-owner-scope --run "pytest -q tests/test_orders.py" --expect passed。加载你已经编写的规则、ADR 和规范,以及内置规则包,参见 填充经验。

4. 检查是否运行正常:

okl check --task "add an endpoint that returns an order for the logged-in user"
okl doctor                  # flags other memory tools, double wiring, and where drift is gated
不同 Agent 的适用方式
Claude Code任何 MCP Agent(Cursor、Codex、Copilot 等)任何 Agent,或不使用 Agent
每项任务前提供简报每条提示词都会自动触发钩子,失败时会阻止继续Agent 调用时使用 okl_check 工具在终端或脚本中运行 okl check
记录学到的内容每个修改过文件的会话结束时,Stop 钩子会询问一次使用 okl_record 工具运行 okl record
验证与漂移检查okl verify、okl reverify、okl drift使用相同命令使用相同命令
把关推送前钩子推送前钩子推送前钩子,或 CI 工作流(okl init --ci)

这些钩子属于 Claude Code;其他所有功能都是命令或 MCP 工具,可在任何地方使用。 配置其他 Agent:开始使用。

普通的一天是什么样的

  • 照常输入提示词。 任务开始前的钩子会对你输入的内容运行 okl check,并在 Agent 开始前将相关经验教训放入其上下文中,同时显示一行文字 — okl · briefed 9 lesson(s): … — 让你看到它正在运行(OKL_QUIET=1 可隐藏这行文字)。
  • 学到值得留存的内容时 — 一个决策、Agent 违反的约定、你修复的 bug — 告诉 Agent,它就会记录下来(okl_record 或 okl record),并附上该经验教训适用的文件。在 Claude Code 中,Stop 钩子也会在修改过文件的会话结束时询问一次:学到了什么;它还会列出本次会话获得简报的经验教训,以及本次会话修改过其适用文件的经验教训,让 Agent 可以提议修正或废止其中一条(由你批准)。
  • 使用其他 Agent? 简报和记录功能是 MCP 工具(okl mcp);注册这些工具,并在你的 AGENTS.md 中添加一行:每项任务开始前调用 okl_check。自动执行这些操作的钩子属于 Claude Code;请参阅入门指南。
  • **需要修正某条经验教训时,**从简报中找到它的 [id],只修改错误之处:okl update <id> --fix "..."(或使用 okl_update 工具)会保留其余内容,包括证明,除非你修改了它适用的 --files:此时需要重新验证,而 okl reverify 会重新运行已存储的检查。okl show <id> 会打印完整的经验教训,并显示其检查通过和失败的次数:每次运行 okl verify 和 okl reverify 的结果都会保留,因此检查发现变更时会留下记录。再次记录已有的 id 会被拒绝,因为此前这会替换原有经验教训并抹去其证明。
  • **经验教训有误或已被替代时,**说明原因并将其废止;不会删除任何内容。okl retire <id> --reason "..." 会将错误的经验教训保留在简报中并标记为 AVOID,避免有人再次陈述它;--by <new-id> 会将被替代的经验教训从简报中移除,并指向新条目;如果经验教训所涉及的主题已不存在,则使用 --obsolete。已修复的缺陷不应废止:应继续在简报中提醒,防止它再次出现。
  • 证明经验教训属实,要运行检查,而不是设置标志: okl verify <id> --run "pytest -q tests/test_orders.py" --expect "passed"。
  • **经验教训适用的代码发生变更时,**在其检查再次通过,或代码恢复为上次检查通过时的状态之前,okl drift 会显示红色(通过 --files 记录的经验教训在首次运行 okl verify 前也会显示红色)。简报也会说明这一点:此类经验教训会标记为 STALE(或 UNVERIFIED、UNPROVEN),并注明发生变更的文件,以便 Agent 对照代码确认,而不是盲目信任。确认之后,okl reverify 会重新运行每条发生偏移的经验教训所存储的检查。使用 GitHub 工作流(okl init --ci)时,CI 会读取已提交的快照 okl-drift.json;首次验证一条带有 --files 的经验教训时,okl verify 会创建该快照,此后会保持其最新状态:验证代码变更后提交该文件。在此之前,CI 会发出 "Drift not checked" 警告,这是预期行为。不使用该工作流时,除非已有快照被提交,否则 okl verify 不会写入快照。
  • 无头运行(claude -p、脚本、CI Agent)会设置 OKL_DISABLED_HOOKS=encode,否则会话结束时的问题会替代打印的答案。

它解决的问题

一个团队或 Agent 修复了一个隐蔽的 bug,弄清了它发生的原因,并写下一条规则来防止问题再次发生。几周后,在另一个文件或另一个仓库中,同类 bug 再次出现,因为负责新工作的人员或 Agent 从未看到过这条规则。相关知识明明存在,却没有在需要的人最需要的时候呈现在他们面前。而且即使看到了,这些知识也往往已经过时:它所描述的代码早已变化。

okl 两方面都能解决。相关经验会在任务开始时自动读取,而不是靠有人记得去查找;经验要么仍然有效,要么会明确过期:每条经验都通过你选择的检查来验证;覆盖范围内的代码发生变化时,这条经验就会重新打开。

这是一个 v0 入门版本,尚未经过生产环境加固。 它附带端到端测试套件(在你的环境中运行 pytest -q 会显示套件及其结果)。核心部分仅使用标准库,没有必需依赖项。

okl 是什么

一个用于存储工程经验的库,以及一套确保这些经验持续有效的机制。 它包含有类型的记录(规则、架构决策、已知缺陷、门禁、墓碑、撤回记录),会在任务开始前将这些记录简报到 Agent 的上下文中;当它们描述的代码发生变化时,也会明确标记为过期。evals/REPORT.md 中衡量的所有内容都在评估这一点。

值得准确说明这个库里主要存放什么,因为“代码库学到的经验”容易让人联想到 bug 数据库。在 seed/ 中的 183 条记录里,大多数并非如此:有 110 条规则、20 条决策和 7 条门禁,而缺陷有 36 条——记录的是代码遵循的约定和已达成共识的权衡,而不是故障账本。你可以自己统计:

python3 -c "import json,glob,collections; c=collections.Counter(
  n['type'] for f in glob.glob('seed/*.json') for n in json.load(open(f))['nodes']); print(c)"

软件包还附带另一个可选组件:okl scaffold,用于搭建库所依赖的仓库内工作规范的入门套件(精简的规则文件、机械化门禁、审查 Agent、评估框架)。它从未经过衡量;你可以用它让新仓库达到可供经验库关联内容的状态。

okl 不适用于什么

okl 保存的是经验:Agent 会看到或执行什么(症状)、应该怎么做(修复方法)、原因,以及如何验证(检查)。完善的 Agent 配置大多由其他内容组成,而这些内容放在别处会更合适:

如果它是……放在这里为什么不放在 okl
每个会话都需要遵守的规则,无论任务是什么CLAUDE.md / AGENTS.md这些文件每次都会完整加载;简报则会按任务挑选经验
一套流程:如何发布、迁移或设置技能、操作手册或脚本流程需要按顺序完整阅读;简报只提供少量简短记录
命令,以及“要完成 X,请阅读 Y”之类的指引CLAUDE.md / AGENTS.md,或技能这是 Agent 在每个相关任务中都需要的导航图
格式和代码风格格式化工具或 linter工具会检查每一行;经验只能起提醒作用
尚未解决的 bug问题跟踪系统跟踪系统负责尚未完成的工作;okl 保存修复问题后总结出的经验
秘密、凭据、个人数据远离 okl经验库由多人共享,其中的内容会复制到 Agent 的上下文中

任何包含症状和修复方法的内容都适合放在这里:代码遵循的约定、有意作出的决策,以及你已经为之付出过代价的缺陷类别。入门指南 也从记录的角度说明了相同的区分。

它能防止哪些内容发生漂移,以及如何防止

知识会以一种特定方式腐化:代码变了,所有关于代码的文字也会悄无声息地失去准确性。下表中的每一项都能捕捉一种不同的情况。了解每项能捕捉什么很重要,因为它们彼此并不重叠。

漂移检测方式工作原理触发条件
规则与其约束的代码不一致okl drift --gate记录声明其约束的路径 glob,okl verify 则记录其检查通过时的提交这些文件在该提交与 HEAD 之间发生了变化(如果验证没有记录提交,或本地克隆中没有该提交,则改为比较提交时间);或者规则从未验证过,因此新的 --files 规则在首次运行 okl verify 前会显示为红色;或者其标记没有对应的已观测检查
已退役的标识符重新出现在文档中check-tombstones.sh在工作树的源代码、文档、注释和配置中搜索每个已标记为退役的名称命中任何未列入允许列表的内容
已撤回的说法被再次陈述check-retractions.sh在工作树的 Markdown 文件中搜索撤回登记表中的完整引述内容引述内容出现在登记表之外
没有任何链接指向的文档check-doc-orphans.sh检查每个顶层 docs/ 文档或图片是否被某个中心文件或 docs/*.md 文件提及(仅一跳,不递归)没有任何文件提及它,因此它会悄然漂移,始终无人阅读
指向已移动文件的链接check-links.sh读取 git ls-files 列出的每个 Markdown 文件,并检查每个本地链接的目标在工作树中是否存在目标不存在
没有渲染图像的图表源文件check-diagram-pairs.sh为每个可编辑源文件匹配其导出文件;通过 OKL_DIAGRAM_SRC_EXT/OUT_EXT 支持任意格式审阅者将看不到任何内容。手工编写但没有源文件的图片只会被记录,不会导致失败;而没有图表源文件的仓库会直接通过,不做任何操作
验证悄然过期TTL + verified_by记录会注明上次验证的时间和所用的已观测检查;TTL 仅适用于通过 --ttl-days 指定的记录(默认没有)超过 TTL 后,记录会被降级显示,而不会被删除

这张表有三个需要坦诚说明的限制:

  • 图表的内容仍然需要人工检查。 check-diagram-pairs.sh 能证明渲染后的图片存在;但没有任何机制能证明它与导出它的源文件一致,或证明二者都与代码一致。为此,请在记录的 --files 中同时列出图表和它所展示的代码,这样代码变更后,漂移门禁就会变红,直到有人重新验证图表为止。本仓库的 README 就是这样管理的;其流水线图则由代码生成,并且在提交的渲染结果不再匹配时代码测试会失败。
  • 只有墓碑门禁会检查注释。 它会在 .md、.py、.ts、.tsx、.cs、.yaml、.yml、.json 和 .sh 文件中查找已退役的名称;撤回门禁只读取 Markdown。其他过时注释都不会被发现,而且 okl reverify 会在不读取注释的情况下重新标记受管文件,因此检查必须验证注释所陈述的内容,漂移检查才有意义。
  • okl drift 只监控记录声明的内容。 没有任何记录约束的文件不会受到任何机制的监控。覆盖范围取决于整理决策,而在问题出现之前,覆盖缺口是不可见的——这就是为什么上面的机械门禁会扫描整个仓库(墓碑门禁和撤回门禁会搜索工作树),而不是只扫描已纳入管理的内容。

okl 的不同之处

  • 与记忆层(mem0、Zep、Letta、Claude Code 记忆插件)相比:它们会回忆 Agent 经历过的事情;okl 保留必须始终成立的内容,并通过你选择的检查来证明。
  • 与规则文件(CLAUDE.md、AGENTS.md)相比:任务简报会选出与任务匹配的少数经验;规则文件每次都会完整加载,而且不会对其内容进行任何重新检查。
  • 与指令文件检查工具相比:它们会检查规则文件提及的路径或命令是否仍然存在;okl 会运行你的检查,并在相关代码发生变动时阻止推送。
  • 与文档平台相比:它们会起草和审阅;okl 不起草任何内容,并会阻止推送。
最适合取舍
规则文件每次会话都需要的五条规则完整加载;没有证明,也不会按任务筛选
记忆层回忆 Agent 见过的内容使用时依赖模型判断;与你的检查或推送都没有关联
okl包含症状、修复方法和检查的经验由你有意编写,并确保其经过验证

详细说明,包括比较表以及如何让 okl 与其他记忆工具搭配使用: okl 的定位。它采用默认失败关闭的设计:存储不可访问时会阻止操作或发出警告,绝不会报告“一切正常”。

研究文献在 2026 年测量了什么,相关数据均摘自论文,每项结果旁还附有“okl 的定位”一栏:相关工作。

测得的效果及其局限

一次固定其他条件的 A/B 测试(8 个编写好的任务,每组每次运行采样 3 次;生成器和盲测评审使用不同模型;方法和原始记录见 evals/REPORT.md):

  • 同一模型,提供简报与否:在最初的 3 次采样运行(2026-08-30)中,缺陷复现率从 33% → 4%(sonnet),以及 38% → 12%(haiku)。随着检索流水线发生变化,后续 sonnet 运行的结果为 35–50% → 4–8%(REPORT §4b–§4i,不含已撤销的 §4d 和由 opus 评审的 §4f;最新的 §4i 为 43% → 8%)。汇总 §4 至 §4h 中使用该测量工具的七次运行(包括已撤销的 §4d),163 次未提供简报的尝试中有 68 次重复了已知缺陷(42%),而 164 次提供简报的尝试中有 11 次重复(7%);REPORT §5 的发现 7 列出了相关记录和其他降低该比例的方法。未提供简报的一组仅仅在不同运行之间就波动了 21 个百分点,而且跨过 §4j 边界后波动了 26 个百分点,因此噪声下限至少为 21 个百分点(§2b、§4m)。每个“复现”的都是本知识库已经付出代价才学到的缺陷类别——篡改价格时的回退逻辑、Web 存储中的令牌、未固定版本的 CI 门禁、不检查输出便信任退出码为 0 的脚本,以及未将失败率放在首位的评估摘要——而不是 lint 噪声。两个任务(一个 IDOR 端点、一个 React fetch)在任何已提交的记录中都从未在未提供简报时复现(每个任务有 46–48 个未提供简报的样本),因此无法显示降幅;限流器在未提供简报时复现了 41 次中的 1 次(§4m),在提供简报时复现了 44 次中的 2 次(REPORT §4d、§4m、§5 发现 6)。
  • 值得记住的结果来自最初几次运行:提供简报的 haiku(12%)优于未提供简报的 sonnet(33%)。这表明简报不仅是质量杠杆,也是成本杠杆——在组织已知的失败模式上,它能让成本更低的模型保持在前沿模型未提供简报时的基准线之上。需要注意两点:haiku 运行从未重复过,而且由 sonnet 评审;sonnet 运行则由 haiku 评审。
  • 上述所有运行都早于简报的 Decisions 部分:直到最近,赢得展示名额的 Decision 都会被静默丢弃;现在它会显示在自己的标题下。没有任何评估任务的简报包含过 Decision,因此无论采用哪种方式,测得的八份简报字节内容都完全相同。
  • 上述所有运行也都早于每条简报中的经验条目现在携带的 [id]。这部分内容并非字节完全相同:八份评估简报的体积增加了 5%,但保留了每条经验的全部内容(REPORT §4j)。这次运行(2026-10-10)的结果为 17% → 0%,但未提供简报的一组本身比 §4i 下降了 26 个百分点,说明原因更可能在于生成器而非 okl,因此这次运行开启了一个新系列,不与上述运行合并统计。

这个数字也是一项迁移效果。八个任务都是根据任务提示词新编写的代码,而这些任务容易引发的缺陷类别是在其他项目中学到的:每个任务都在 evals/tasks.jsonl 中标明了对应经验,而这些经验来自十二个种子包中的六个。在一个项目中付出代价学到的经验,避免了另一个项目所写代码中的缺陷。汇总运行中,简报包含了每个任务对应的经验,但有三个例外;这些任务的测试组测得的是不含该经验时的简报效果:exit_code_trust 的经验在每次运行中都排在十二条记录的截断位置之后,直到 2026-10-22 加入症状信息后才出现(REPORT §4b、§4o);rate_limiter 的经验在已撤销的 §4d 运行中被筛掉;react_fetch 的经验在依据本仓库声明的关注领域进行的两次运行中被筛掉(§4h)。如何在组织范围内运行这套方法,以及对经验的要求,见跨组织应用。

这并不能说明什么:这些任务是专门编写来引发知识库所记录的缺陷类别的,因此它测量的是在存在直接相关经验时简报的效果,而不是一般代码质量,也不是大规模检索的效果。样本量很小;应将其视为附有记录的试点,而非基准测试。

工作原理

顶部的概览由 docs/overview/okl-overview.html 渲染。下方的结构剖析 以 okl 自身的输出,完整追踪一节课程的全过程;它由 docs/overview/okl-anatomy.html 渲染,而 docs/overview/anatomy-story.sh 会在一个临时仓库中运行同一过程。

okl 的结构剖析、经验证的记忆,以及让它保持正确的循环:载入规则,让 Agent 遵守规则,并在构建过程中不断学习。围绕存储库的环形流程包含六个步骤:课程从规则、ADR、标准和规范以及适用于技术栈的入门课程中预先载入,也会在构建过程中从新规则、错误、门禁发现的偏差、失败的测试和评审中不断补充;每条课程都会被记录下来;okl 使用你选择的检查来验证;每项任务开始前都会提供简报(通过 Claude Code hook;其他 MCP Agent 可以调用 okl_check);它所涵盖的文件发生变化时,pre-push hook 会暂停推送,直到检查再次通过,或代码恢复到已通过检查的状态;然后重新检查、修复或废弃课程。下方展示了真实的 okl 输出,追踪“订单查询限定于已登录的客户”这条课程,从 okl 记录到推送受阻;重新运行检查后,发现某项变更移除了所有者检查。接着展示课程的存放方式(仅提供简报、监控偏差、阻止构建);简报的效果(在 8 轮专门设计来诱发某种缺陷的 A/B 测试中,186 次未收到简报的尝试里有 78 次重现已知缺陷,而 188 次收到简报的尝试里有 13 次);以及它的排序方式、成本和失效场景。
简报实际上是如何生成的

okl check 是一条检索流水线:它会搜索任务的主题词,然后将整个语料库缩小到 Agent 会完整阅读的至多五条记录,并用一行列出其余匹配项。有两个阶段可能会根据记录的主题将其排除,但只有一个阶段有权这么做:这个项目曾在此处犯错,并通过测量找到了解决办法(REPORT §4d)。

接下来是判定。只有当一条记录的标题、症状、别名和触发条件中包含任务的三个主题词,或两个与某条记录中的词语罕见程度相近的主题词时,才会将其加入简报。触发条件是在记录课程时写下的、描述适用场景的措辞。该门槛是根据 282 条没有自身主题的真实提示词设定的,因此这类提示词中约每 20 条会获得一条简报;最多有五条记录能达到门槛。其他匹配项不会被隐藏:超过五条限制但达到门槛的记录,以及早期词语门槛筛选出的记录,都会各占一行(包含 ID、标题和修复方法开头,最多 12 个词),方便 Agent 用 okl show <id> 查看其中任何一条(REPORT §4y)。

该方法是在一套旨在作出决策的基准测试上测量的:519 个生成的查询、550 条没有自身主题的真实提示词,以及选择写下后仅运行一次的留出半集。与之前的流水线相比:

之前的流水线当前门槛,含触发条件
留出集召回率74.4%90.0%
每个查询的课程数11.84.7
获得简报的无主题提示词268 条中 149 条268 条中 9 条

真实提示词比基准测试中的查询更简短。对于人们输入的提示词,与存有已记录课程的存储库相比(REPORT §4x),仅使用该门槛找到的适用课程约为早期规则的三分之一。这就是为什么默认情况下会用一行列出其余匹配项(REPORT §4y,留出集):

真实提示词、真实存储、留出集早期规则(阈值)仅显示单行默认:两级
应用的经验教训(共 115 条)9038102(38 条完整显示,64 条显示为单行)
每条提示词完整显示的经验教训数7.71.81.8,另有 7.6 条显示为单行
完整显示的经验教训中适用的比例9.8%17.8%17.8%
简报中位长度(token)1,424113721

团队自己的经验教训需要触发词才能进入第一级:okl record 会提示填写触发词,okl triggers 会列出缺少触发词的经验教训,而 /triggers 会在 Claude Code 中起草触发词。证据、未胜出的替代方案(重排器、图、查询时生成、对话上下文)及其成本,见 docs/RETRIEVAL.md、REPORT §4w、§4x 和 §4y。 --decision calibrated 仅显示单行,生成最精简的简报;--decision floor 使用早期规则(两个共有主题词,每条匹配结果都完整显示,最多十二条记录)。

语料库;任务的主题词(对于由测试框架编写、且没有任何简报消息的消息);BM25 获取数量为上限三倍的记录,并像症状一样为触发词加权;范围门控;排他的 applies_to 筛选器;包容性的 tags-times-interests 筛选器;校准后的界线:标题、症状、别名和触发词中有三个共有主题词,或某条记录中有两个几乎与一个词一样罕见的共有主题词,同时排除已停用的经验教训;最佳五条完整显示;其余匹配项、超过五条且达到界线的项,以及词数阈值保留的项,各用一行列出,最多十二条;按类型分桶;以及渲染。每个阶段都会显示通过该阶段的记录数量。

启用可选语义分支(okl check --hybrid --decision floor)后,第二个候选来源会在门控前加入:将任务作为一个向量,按余弦相似度选出最近的记录,并融合两种排序。它需要词数阈值:仅凭含义找到的记录与任务没有共有词,因此校准界线无法将其纳入简报。测量结果表明,语义匹配与词数相结合效果最佳。如此一来,EmbeddingGemma-300m 将留出集召回率从 90.0% 提高到 95.2%,但提示词钩子每次运行都要花约两秒加载模型,因此要等到有进程能保持模型加载后再启用(REPORT §4w)。它由同一个生成器通过同一代码路径生成,REPORT §4q 说明了它的收益与成本。随后测量了对这些候选项运行本地交叉编码器的效果(okl check --rerank)(REPORT §4t):留出集中有一个释义变体被选中,却返回了一份 bug 报告,因此它作为一个默认关闭的标志发布。

启用语义分支后的同一条处理流程:在全文检索旁边,将任务嵌入为一个 512 维向量,并按余弦相似度选出最近的记录;再通过凸组合与全文检索排序融合;随后是范围门控、applies_to 筛选器、tags 筛选器、同时也会纳入余弦相似度不低于 0.40 的记录的阈值、截断、分桶和渲染器

图中的每个计数都经过追踪,而非手动抄录:docs/render_pipeline_diagram.py 会针对由 seed/ 初始化的存储,运行真实的 briefing_terms、store.search、core._in_scope、core._live_hits 和 decide.select;如果已提交的渲染结果与生成器当前生成的结果不符,test_pipeline_diagram_is_current 就会失败。修改 BM25 权重或筛选谓词,图表也会随之变红。生成器曾在 okl check 改为使用主题词后,仍搜索原始句子,而该测试无法察觉;现在,追踪结果会与 _live_hits 交叉核对。

经验教训与链接

经验教训分为几种类型:

类型记录内容
缺陷发生过的具体错误或失误,以及原因。
关卡能捕获某类缺陷的自动化检查。
规则应遵循的标准(“做 X,绝不做 Y”)。
撤回后来被证实为错误并撤回的说法。
墓碑已弃用且不得再次出现的标识符(名称、文件、端点)。
决策有意作出的选择,避免日后被悄然推翻。

每条经验都包含 症状 → 原因 → 修复方法:看到这种情况时,原因是这个,照此处理。 这让经验变得可执行,而不只是提供信息。经验之间会相互链接:关卡通过 CATCHES 关联缺陷,决策通过 SUPERSEDES 关联较早的决策,因此查询时会一并提取相关背景。

两项操作。 check:描述任务;okl 会搜索存储库,筛选出适用于当前范围的经验、排序,并返回一份简报,先列出具体操作(看到……时,执行修复:…… → ……),再列出已经有意作出的决策。record:修复问题或作出决策时,将其记录下来,并注明适用的文件;从此以后,所有类似任务都会收到这份简报。okl update <id> 可以完善记录,同时保留其证明材料。

范围是最重要的决策。repo:<name> 只适用于该项目。org 适用于加载其所在经验包的任何项目;只有当其 applies_to、项目关注点和任务彼此吻合时,才会生成简报。主题标签来自封闭词汇表(store.py 中的 KNOWN_TAGS,可通过 okl record --type Vocabulary 扩充),用于说明经验的主题;okl init --interests 则说明仓库关注的内容(决策)。通过账本仓库和拉取请求,在多个仓库之间共享 org 经验包,并由每个仓库证明其加载的内容:跨组织。

所有这些背后的选择及其原因:docs/DESIGN-CHOICES.md。

数据默认存储在每个克隆各自的一个 SQLite 文件中:.okl/okl.db,并由 git 忽略。若要使用同一个存储库,可将多个仓库指向共享服务(docs/SCAFFOLD.md)。

使用方法

# 1. READ the relevant lessons before starting a task (the load-bearing move)
okl check --task "add an endpoint that returns an order for the logged-in user"
#   add --format actions --limit 3 for a ~350-token version (subagents, CI)

# 2. RECORD a lesson after you learn it, with an actionable symptom/cause/fix
okl record --type Defect --scope org --tags "security" \
  --title  "Trusting a client-supplied price lets the client set it to anything" \
  --symptom "a request body carries a price/amount/status/isAdmin field" \
  --body    "cause: the handler saved the client's value instead of computing it" \
  --fix     "drop those fields from the request; compute them server-side" \
  --files   "**/orders/*.py"         # prints the new record's id

# ...then prove it with a check, rather than asserting it
okl verify <id> --run "pytest -q tests/test_orders.py" --expect "passed"

# 3. SEARCH the stored lessons directly
okl search "price tampering"

# 4. LINK a check to the defect it catches (so a lookup pulls in both)
okl link <gate_id> CATCHES <defect_id>

拒绝执行 okl record --verified:它会以状态码 2 退出,并指向 okl verify,因为印记是运行的证据,而不是一种声明。其他所有命令及其退出码见:docs/COMMANDS.md。为什么一个步骤不能为自己评分,以及 okl 如何应用于自身印记的四个等级: docs/VERIFICATION.md。

--symptom/--fix 能让 check 在开头输出**“照此操作”**的操作清单(“修复:……——看到……时”),而不是一大段文字。--files 用于告知 okl 某条经验适用于哪些源文件,从而支持漂移检测(见下文)。

成本

安装 okl 并非没有代价。在将它接入每个提示词之前,值得准确了解需要承担什么。以下所有数字均为实测值,而非估算值;使用了一个有代表性的任务(“添加一个返回当前登录用户订单的端点”;令牌数 ≈ 字符数 ÷ 4)。大小数据来自一个全新的存储库,其中包含所有捆绑的种子经验包,共 183 条记录(python3 evals/briefing_size.py,收据 evals/results/briefing-size-20261027-0132.json);延迟数据则来自此前捆绑的 161 条种子记录。 你的存储库和任务会有所不同。

每条提示词的开销(安装钩子后):

延迟整个 okl check 过程约 0.1 秒(预热后中位数为 0.07 秒)——一次本地 SQLite 查询,本地模式下无需联网
上下文在一个有代表性的任务中,默认约 1,390 个 token(五条经验完整显示,另有十二条以一行列出;使用 --decision calibrated 时约 730 个,使用 --decision floor 时约 1,730 个);在真实提示词中,中位数为约 720 个(REPORT §4y)。使用 --limit 3 时,仅显示操作列表可缩减至约 350 个

每个会话: Stop hook 会在会话结束时中断一次,询问学到了什么。它只会阻止第一次停止,而回答这个问题就是整个写入环节。提问时,它会列出本次会话中最多五条失败命令,这些命令来自会话自身的记录——它们只是候选项,并非记录:每次工具调用都不会运行 hook,也不会调用模型来总结任何内容。随后,okl recap 会列出本次会话涉及的经验:最多五条它最常收到简报的经验,以及最多五条其受管文件被它修改过的经验,每条都附有用于更正、废弃或重新验证它的命令。Agent 会用一行提出修改建议,并在你同意后进行一次修改。要在之后回顾整个会话,okl recap --report 会根据存储自身的日志,列出简报内容、记录和废弃的经验、运行和失败的检查、提交记录,以及目前已过时的内容。

按照上述测量,完整简报约需1,390 个 token(仅一行约 730 个;使用 floor 模式下的十二条时约 1,730 个)。对于窗口较大的主会话,这个开销不高;但对于在几千个 token 内工作的子 Agent 来说,仍占了相当大的比重。这种差异很重要,因为组织规则恰恰最容易在子 Agent 这里丢失:专注处理单个子任务的工作者上下文最少,却最需要“这是此代码库已经犯过的错误”。

在每个打包的种子包(183 条记录)上测量,一个有代表性的任务(测量凭证):仅操作列表在 --limit 3 时约为 350 个 token,在 --limit 5 时约为 580 个,在 --limit 12 时约为 1,010 个(其一行条目会遵循 limit),而完整简报约为 1,390 个。成本足够低,可按每个子任务调用;--decision calibrated 会为最短的列表省略一行条目。

对于上下文窗口较小、每条提示词都会附带简报的模型主会话,情况也一样。设置 OKL_BRIEFING_COMPACT=1 后,提示词 hook 只会发送操作列表(okl check --compact);设置 OKL_BRIEFING_LIMIT=3 后,它会显示三条记录并列出另外三条,而不是显示五条并列出十二条。按照上述测量,两者结合后约为 350 个 token,而不是 1,390 个。在 Agent 启动的位置设置这些变量:hook 会继承其环境。不是大于零的整数的 limit 会被忽略;对于不支持 --compact 的旧版 okl,简报会完整发送,不会阻塞提示词。与 --format actions 一样,紧凑简报不会说明删减了多少条记录。

okl check --format actions 仅包含指令,大小约为一半;--format json 是供脚本使用的原始结果;--format hook 是 Claude Code hook 打印的内容;--limit N 会使用较少的记录,并说明删减了多少条。

所有可调项、okl init 会写入的内容、如何关闭部分功能,以及选择加入的架构审查:Costs and knobs。子 Agent 和小窗口:docs/SUBAGENTS.md。

问题

如何避免我的 Agent 重复犯它已经修复过的错误? 将修复记录为一条经验,注明症状、修复方法和适用文件,然后用能证明修复有效的测试运行 okl verify。任何与这条经验内容相关的任务,都会先收到它的说明;如果它涵盖的代码发生变化,推送就会等到检查再次通过后才能进行。

经验涵盖的代码发生变化时会怎样? okl drift 会列出这些经验,推送前钩子会阻止推送(或 CI 会失败),下一次说明则会将其标记为 STALE。okl reverify 会重新运行已存储的检查;通过后会重新盖章。将代码恢复原状也会清除该状态。

它能与 Cursor、Codex 或 Copilot 配合使用吗? 存储、命令、推送门禁和六个 MCP 工具都可以。每次提示词前的说明和会话结束时的问题是 Claude Code 钩子;其他 Agent 可调用 okl_check(方法)。

它会自动记录我的会话吗? 不会。只有在你有意要求时,你或 Agent 才会编写经验;Stop 钩子会询问一次。它不会记录工具调用,循环中也不会调用任何模型。

我可以将它与 claude-mem、mem0 或其他记忆工具一起运行吗? 可以;它们属于不同层。okl doctor 会列出已安装的内容和三个已知冲突(它的定位)。

它适合生产环境使用吗? 不适合:这是一个 v0 版本,是个人项目,配有端到端测试套件和上述测量数据。它不适用的场景和其限制都是有意明确说明的。

作为 Claude Code 插件安装

/plugin marketplace add emeraldleaf/okl
/plugin install okl@okl

该插件包含两个钩子、MCP 工具和初始化命令,但不包含 okl 本身:请先安装 CLI,并启用 MCP 额外组件,因为该插件会注册 okl mcp 服务(pipx install 'observed-knowledge-ledger[mcp]');然后在仓库中运行 okl init,创建存储并设置漂移门禁(一个 pre-push 钩子;GitHub 工作流使用 --ci)。启用插件后,init 会跳过钩子和 MCP 注册,因为重复注册会导致每条提示词都收到两次说明。okl doctor 会报告同时启用了插件和项目钩子的仓库。要从检出目录加载插件并仅用于一个会话:claude --plugin-dir <path>。

安装

pipx install observed-knowledge-ledger   # provides the `okl` command
pip install -e .                   # or from a clone of this repo

核心部分(本地端 + 客户端 + CLI)仅使用标准库——没有必需依赖。 额外组件可按需启用:

pip install "observed-knowledge-ledger[service]"    # FastAPI shared service
pip install "observed-knowledge-ledger[postgres]"   # Postgres backend (psycopg)
pip install "observed-knowledge-ledger[mcp]"        # MCP server for Claude Code / Cursor / Copilot
pip install "observed-knowledge-ledger[all]"

Agent 集成(MCP)

pip install "observed-knowledge-ledger[mcp]"
okl mcp     # register in your coding agent's tool config

向编码 Agent 提供六个工具:okl_check(在任务开始前读取经验)、okl_record(记录新经验)、okl_update(按 ID 优化一条经验,同时保留其证明)、okl_retire(说明原因后撤回一条经验)、okl_get(获取一条完整经验)和 okl_search。okl_check 会明确报告服务中断——如果无法访问已配置的共享实例,它会如实说明,而不是返回令人安心的“未找到内容”,因为从 Agent 的角度看,这两种情况无法区分,只有其中一种是安全的。与钩子不同,工具结果无法阻止 Agent,只能向它发出警告。

目录结构

src/okl/
  store.py        # the database: lesson + link schema, swappable SQLite/Postgres backend
  core.py         # check / record / search / link — the logic, independent of transport
  client.py       # resolves local-file vs. shared-service; fails closed
  cli/            # the `okl` command, one module per command group (cli/__init__.py maps them)
  drift.py        # source-vs-spec drift detection
  ownership.py    # okl-fingerprint lines: which installed files are okl's, and untouched
  coexist.py      # `okl doctor`: detects other agent-memory plugins and double wiring
  bootstrap.py    # propose starter lessons from a repo's git history + docs
  service.py      # the shared web service (the [service] extra)
  mcp_server.py   # coding-agent tools (the [mcp] extra)
  seed.py         # load a JSON seed file
  scaffold_cmd.py # the `okl scaffold` starter-files stamper
seed/             # starter lesson files (examples + genuinely useful defects)
docs/decisions/   # design decision records
tests/            # end-to-end tests

测试

pip install -e . --group dev   # from a clone of this repo (pip 25.1+; or `uv sync`)
pytest -q                 # full suite

在 git 不可用(或 git init 被阻止),或未安装 service 等可选额外组件时,部分测试会跳过而不是失败。

许可证

MIT。

贡献

有关设置、仓库自身规则(镜像文件、漂移、基于证据的验证)以及最需要帮助的方面,请参阅 CONTRIBUTING.md。 docs/DEVELOPING.md 介绍 okl 的端到端开发流程:日常循环、CI、拉取请求、发布、评估以及可观察的内容。 安全策略和部署威胁模型:SECURITY.md。

Footnotes

  1. PyPI 上的名称有所不同,因为 PyPI 认为 okl 与 oki 容易混淆;之后你输入的所有内容都是 okl。 ↩

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。