给 Agent 知识库换个标准格式:OKF 转换实战
Google 刚发了 Open Knowledge Format (OKF) v0.1。我用了两天,把自己 270 份知识文档全部转了过去。这篇文章是转换过程中的真实体验——踩了什么坑,哪些是白送的,以及我为什么觉得这个格式值得一试。
一次真实的 Agent 知识 OKF 化记录:199 个概念文档,5 个 bundle,100% 合规。
一切从一个念头开始
事情是这样的。
六月中旬,Google Cloud 发了 OKF v0.1(Open Knowledge Format)。当时扫了一眼,心想:又一个大厂标准?没太当回事。
但隔了几天刷到社区讨论时,我越看越觉得眼熟。
OKF 的核心描述是:一个目录的 Markdown 文件,每份文件带 YAML frontmatter,用 type 字段标记概念类型。
这不就是我那个 compound-system 知识库在用的格式吗?
我的 solutions/ 目录下,bug 记录、知识条目、模式提取——全是 Markdown + YAML frontmatter,只是 type 字段叫的是 problem_type。
这种巧合让人手痒。
加上我之前一直有个困扰——compound-system 跑了一年,攒了快 170 份文件,但除了我没人能摸清里面有什么。没有目录索引,没有统一元数据,想让另一个 agent 读一读都不知道从哪下手。
OKF 说它解决的就是这个问题:让 agent 能遍历你的知识库,而不是在文件名列表里瞎猜。
那行,试试吧。
OKF 到底是什么
先简单交代一下格式,如果你已经看过 SPEC,这段可以跳过去。
OKF 定义了一种叫 Knowledge Bundle 的东西:一个目录树,里面全是 .md 文件。
每个 .md 文件代表一个 概念(Concept),由两部分组成:
---
type: Bug
title: 修复了一个 compression 导致的 session 分裂
tags: [hermes-agent, compression]
timestamp: 2026-06-21T00:00:00Z
---
这里是概念的正文,标准的 Markdown。
唯一必须有的字段就是 type。其他都是推荐——title、description、tags、timestamp、resource。
整个格式的约束少得可怜:
- 每个概念的
type不能为空 - 不能把概念叫
index.md或log.md(这是保留文件名,用于目录索引和变更日志) - 其他任何额外字段都可以保留,消费者不能拒收
加上一个 optional 的 index.md 作目录索引,然后就没有了。
没有 schema registry,没有 SDK,没有 schema 注册中心。
bundle/
├── index.md ← okf_version: 0.1
├── bugs/
│ ├── index.md ← 目录索引
│ ├── fix.md ← type: Bug
│ └── crash.md ← type: Bug
└── patterns/
├── index.md
└── tdd-workflow.md
要是这个格式看着像 Obsidian vault 或者任何一个 LLM wiki 仓库,那是因为它本来就是从这些模式里萃取出来的。
Google 团队做的事情不是发明新格式,而是把已经存在的模式明确写成了规范。
说实话,这个思路本身也是一种 OKF 式的实践——把隐式知识显式化。
我的文档长什么样
动手之前,我先做了个全量盘点。作为一个长期跑 compound-system 的人,我的知识文档散落在这些地方:
| 来源 | 文件数 | 已有 frontmatter | 主要问题 |
|---|---|---|---|
| compound-system 知识库 | ~170 | ✅ 全有,但 type 字段错位 | 用 problem_type 代替 type |
| Hermes skills (SKILL.md) | ~42 | ✅ 全有,type 缺失 | 用 type 字段的只有 PM skill |
| dual-form 自动挖掘 | ~46 | ✅ 全有 | 缺标准元数据 |
| ~/docs/ 文档目录 | ~20 | ❌ 一个都没有 | 纯 Markdown |
| 各项目 AGENTS/HANDOVER | ~55 | ❌ 一个都没有 | 纯 Markdown |
总计:大约 270 份可转换的知识文件。
其中约有 55 份是已经很接近 OKF 的——有 frontmatter、有关键元数据、有 Markdown 正文,只是差一个 type 字段。
另外大约 215 份是纯 Markdown 文档,什么都没有。
还有一个特殊群体:compound-system 里 auto-mined 的 70 多条机器记录。它们的前置元数据是用 JSON dump 直接写的,YAML 解析器看了直接报错。
这种我才不转。
转换过程:几个值得说的点
1. type 字段是最后的那层纸
compound-system 的 frontmatter 长这样:
---
title: "CodexPlusPlus #1303 UA cache fix"
module: hermes-agent
tags: [task, auto-reflection]
problem_type: knowledge
severity: low
created: 2026-07-02
---转成 OKF 只需要做一件事:加一个 type: SessionKnowledge,把 problem_type 原样保留(OKF 允许扩展字段),把 created 标准化为 timestamp。
整个转换最重的逻辑就是这个。剩下的都是体力活。
2. 半成品知识不值得归档
compound-system 里有一批 auto-mined 条目,是 pipeline 自动扫描 session 后生成的 bug 记录。它们的 title 字段直接塞了 JSON 片段:
title: '{"content": "1|[package]\n2|name = "codex-plus-core"\n3|version.workspace = tr'
这不是 YAML 格式的问题,这是内容本身就坏了——标题里塞了 raw 日志输出,引号没转义,换行符没处理。
开始我试图让转换器处理这些边缘情况——写自定义 YAML representer、手动构造安全输出、加 fallback 编码函数。搞了两轮后我意识到:不值得。
这些不是知识文档,是管线中间产物。它们有文件名、有记录、但没有人会主动翻阅。OKF 的设计哲学里有一条很重要的假设:知识是被策划的(curated),不是被倾倒的。
所以我加了过滤:源文件 YAML 解析失败的自动跳过。73 条记录,全部跳过,一条不亏。
3. 纯 Markdown 文档反而最简单
那些没有 frontmatter 的文档——AGENTS.md、HANDOVER.md、~/docs/reports/ 下的报告——处理方式反而纯粹:从第一个 # 标题 提取 title,根据文件名推断 type,自动生成 frontmatter。
---
type: AgentInstruction
title: Agent Workspace — lennney
timestamp: 2026-07-05T16:23:18+00:00
---这种推断不是完美的。比如 ~/AGENTS.md 的 description 是我截取的第一段有意义文字——"项目地图"的表格开头。它不够优雅,但足够让 agent 在浏览目录索引时知道自己找到了什么。
OKF 的渐进式暴露机制(progressive disclosure)解决的就是这个问题:不要试图一次给全部信息,先给一个摘要,用户/agent 感兴趣再点进去。
最终结果
处理完 270 份源文件后,产出是 5 个 bundle:
| Bundle | 概念文件 | 目录索引 | 类型分布 |
|---|---|---|---|
| compound-system | 71 | 7 | Bug(8) + Knowledge(40) + Pattern(6) + SessionKnowledge(4) + PiInsight(1) + Archive(12) |
| skills | 82 | 54 | HermesSkill(16) + Reference(39) + 已有 type(27) |
| dual-form | 46 | 26 | SourcePattern(23) + HermesSkill(19) + SubAgentConfig(4) |
| docs | 20 | 5 | Report(6) + Plan(5) + Doc(6) + Requirement(2) + MemoryReport(1) |
| projects | 51 | 8 | AgentInstruction(15) + HandoverDoc(8) + Readme(8) + 其他(20) |
| 合计 | 270 | 100 | ✅ 100% OKF v0.1 合规 |
这 100 个 index.md 是我最在意的产出。每个目录一个索引文件,agent 可以从 bundle root 开始,逐层展开,找到它需要的知识。
以前的方式是:agent 拿到一个 "BUGS-2026-07-05-foobar.md" 文件名,猜内容。现在的方式是:agent 读到 bugs/index.md,看到每条记录的 title 和 description,再做决定。
区别就像从文件名猜书的内容,变成了翻目录。
几个意料之外的事
写转换器的时间少于写格式适配的时间
整个 okf-convert.py 大约 650 行。写第一版大概花了四十分钟。剩下的时间全花在:
- 处理坏掉的 YAML frontmatter
- 调整 index.md 的排版
- 修复 bundle root 元数据被覆盖的问题
- 验证 270 个文件都能被 YAML 解析器读回去
格式转换从来不是技术问题,是数据质量问题。
中间产物最难处理
这一点前面说过了,但值得再提一下。我没想到 compound-system 里 auto-mined 记录的比例这么高——170 条里有 73 条。这意味着 pipeline 自动产出的东西,真正有价值的不到 60%。
但这个比例本身就很有意思——如果知识管线产出的东西大部分是垃圾,问题可能不在 OKF 转换,而在管线本身。
index.md 的生成比想象中有用
开始我把 index.md 当作一个"顺便做了"的 feature。实际生成后,我第一次用 cat bugs/index.md 看了一眼——发现几条记录的 title 显示为 Untitled——因为源文件根本没有标题。
这些小问题以前淹没在文件列表里,index.md 把它暴露了出来。
现在能用 OKF 做什么
OKF 的生态还在早期,目前能做的是这些:
- Git clone 就是知识转移 —— bundle 是一个目录,你可以
git push、打 tar 包、或者直接 rsync。不需要任何服务端,不需要数据库 - Agent 可以遍历 —— 从
index.md开始,逐层深入到具体概念。Google 的 reference agent 演示了这种模式 - 可视化 —— Google 给了
viz.html生成器,一个 HTML 文件就能把 bundle 渲染成交互图 - 任意框架消费 —— OKF 不绑定 agent 框架。Google ADK、LangChain、甚至 Hermes 的 skill 系统都能读
但对我的实际场景来说,最有价值的是第三条——viz.html。一图胜千言,对非技术队友尤其如此。
下一步
OKF 还只是一个 v0.1 草案,很多问题还没答案:
- Bundle 大了之后怎么办?200 个文件以上的搜索和检索,不能全靠遍历 index.md
- 多 bundle 之间怎么交叉引用?目前只能在一个 bundle 内链接
- 如何保证知识不过期?OKF 有 timestamp 字段但没有过期策略
这些问题不是格式能解决的,需要上层工具。
不过从另一个角度看:一份格式在 v0.1 阶段就能把 270 份文档干净利落地组织起来,已经相当了不起了。
以上,既然看到这里了,如果觉得不错,随手点个赞、在看、转发三连吧~
谢谢你看我的文章,我们,下次再见。
/ 作者:Lennney