Open Knowledge Format(OKF)解决了一个重要问题:如何用可移植的 Markdown 和 YAML frontmatter 描述 Agent 所需的上下文,并通过 provenance、verification、freshness、attestation 等信号判断这份上下文是否值得信任。但当知识包从一个团队扩展到整个组织时,单独维护一个 Git 仓库就不够了。
Knowledge Catalog 可以把 OKF bundle 映射为目录中的 Entry、EntryType 和 AspectType。这样,知识概念就能和 BigQuery 表、Cloud Storage 对象、业务应用及其他技术元数据一起被搜索、授权和发现。
OKF 解决了什么,Knowledge Catalog 补上了什么
一个 OKF v0.1 bundle 通常由 Markdown 文件组成,每个文件携带 YAML frontmatter,并遵循固定的文档约定。OKF v0.2 又加入了机器生成内容必须具备的信任信号,例如:
generated:记录最近一次有意义变更的操作者和时间。sources:记录来源材料及其修改时间、作者等信息。verified:记录验证事件;人工验证可以代表更高的信任等级。status:表示draft、stable或deprecated。stale_after:内容必须重新确认的绝对时间点。
这些规范适合描述“知识包应该长什么样”,却没有规定组织如何集中共享和治理多个 bundle。Git 仓库虽然便携,但存在几个实际限制:它不一定和被描述的数据一起搜索,不能直接复用组织的身份与合规策略,下游 Agent 还必须预先知道每个 bundle 的存放位置。
Knowledge Catalog 的做法是把 bundle 变成目录原生资源:
- 用一个
EntryGroup保存某个 bundle。 - 用名为
okf-bundle的EntryType表示 bundle 中的概念。 - 用名为
okf的AspectType保存 OKF 的结构化信号。 - 用通用
overviewAspect 保存 Markdown 正文。 - 把显示名、描述和标签放在 Entry 本身。
目录已有的搜索、IAM、血缘、所有权和跨项目发现能力,会因此同样作用于 OKF 概念。
一次映射,保留完整的知识结构
推送一个 bundle 后,每个概念 Markdown 文件都会变成一个 okf-bundle Entry。目录中的 index.md 也会成为 Entry,并作为目录树中的父节点;bundle 根部的 log.md 则会带有 okf_type: Log。因此,原本的目录层级不会在导入过程中消失。
一个概念 Entry 通常包含两个 Aspect。overview 保存完整 Markdown 内容,okf 保存结构化 frontmatter。以一个收入指标为例,Entry 的结构可以概括为:
{
"entryType": ".../entryTypes/okf-bundle",
"entrySource": {
"displayName": "Revenue",
"labels": {
"finance": "true",
"headline-metric": "true"
}
},
"aspects": {
".../aspectTypes/overview": {
"data": {
"contentType": "MARKDOWN",
"content": "# Definition\n\nRevenue is ..."
}
},
".../aspectTypes/okf": {
"data": {
"okf_type": "Metric",
"status": "stable",
"stale_after": "2026-12-31T00:00:00Z"
}
}
}
}
okf AspectType 覆盖 OKF v0.2 的 13 类字段,包括 runtime、parameters、computation、executor 和 attester。顶层标量字段以及记录字段中的标量子字段可以直接参与搜索。例如,可以用 okf_type 筛选所有 Metric。数组字段如 sources、verified 和 parameters 的子字段则需要在客户端通过 entries.get 和 view=ALL 获取后再过滤。
日期字段的搜索有一个容易踩坑的边界:stale_after、generated.at 和 usage_window.from/to 使用裸日期或范围比较,例如 stale_after=2026-12-31 或 stale_after>2026-01-01,不要把完整 RFC3339 时间戳直接放进谓词。
可复制的端到端推送流程
下面的流程以 Google Cloud 项目和示例仓库为前提。请把 <your-project> 和 <your-location> 改成实际值;示例中的 bundle 路径也应替换为团队自己的目录。
# 安装 Bun,并准备示例仓库
curl -fsSL https://bun.sh/install | bash
export BUN_INSTALL="$HOME/.bun"
export PATH="$BUN_INSTALL/bin:$PATH"
git clone https://github.com/GoogleCloudPlatform/knowledge-catalog
# 构建 kcmd(Metadata-as-Code CLI)
cd knowledge-catalog/toolbox/mdcode
npm install
npm run build
# 登录并启用 Knowledge Catalog 所需 API
gcloud auth login
gcloud config set project <your-project>
gcloud config set compute/region <your-location>
gcloud services enable dataplex.googleapis.com
gcloud auth application-default login
# 创建 EntryGroup、EntryType 和 AspectType,并推送 bundle
cd demo/okf
bun run setup.ts --entry-group acme-retail
bun run push.ts --bundle okf/bundles/acme_retail
setup.ts 会生成 catalog.yaml,因此通常不需要手工修改清单。之后再次推送是幂等 upsert:不会产生重复 Entry,但每次会写入 bundle 中的所有 Entry。若需要删除整个 bundle,可以使用示例的 cleanup.ts;它只删除 EntryGroup 及其 Entries,不会删除供其他 bundle 共用的 okf AspectType 和 okf-bundle EntryType。
生产环境可以把 kcmd push 接入 CI,在 bundle 仓库每次提交后同步。执行推送的服务账号需要目标 EntryGroup 上的 roles/dataplex.catalogEditor。读取 Agent 则需要 roles/dataplex.catalogViewer,以访问 searchEntries、LookupContext 和 entries.get。
Agent 如何发现并读取上下文
一个典型 Agent 流程分成三步。已经知道具体 Entry 名称时,可以跳过搜索。
- 使用
searchEntries找到候选概念。 - 对最相关的 Entry 调用
LookupContext,得到适合直接注入上下文的 YAML。 - 使用
entries.get?view=ALL读取结构化 OKF Aspect,并在需要时检查来源、验证状态或新鲜度。
例如,下面的 HTTP 请求可以取回一个收入指标的上下文。context_budget 用于限制返回内容的大小,每次调用最多指定十个资源。
POST https://dataplex.googleapis.com/v1/projects/acme-analytics/locations/us-central1:lookupContext
Authorization: Bearer <access-token>
Content-Type: application/json
{
"resources": [
"projects/acme-analytics/locations/us-central1/entryGroups/acme-retail/entries/metrics/revenue"
],
"options": {
"format": "yaml",
"context_budget": "8000"
}
}
LookupContext 会返回预格式化 YAML,其中包含 Entry 的描述、标签和 overview 中的完整 Markdown。它不会渲染自定义 okf Aspect,因此需要结构化信号的 Agent 仍应执行 entries.get,并使用 view=ALL 读取 okf_type、generated、sources 等字段。
搜索时,可以把 OKF 概念和其他目录资源放在同一个查询范围内。例如,下面的谓词可以筛选 Metric:
aspect:acme-analytics.us-central1.okf.okf_type=Metric
真实 API 响应和搜索谓词中的 Aspect、EntryType 可能使用项目编号作为键;文档示例使用项目 ID 是为了便于阅读。
Agent 不会自动沿着 Markdown 中的链接继续读取其他概念。若 sources[] 或正文引用了另一个 Entry,Agent 必须解析出目标 Entry 名称,再把它显式加入下一次 LookupContext 请求。把 bundle 的 EntryGroup 放在与其描述的数据相同的 location,有助于在一次上下文查询中读取两类资源。
治理和生命周期上的关键决定
最大的收益不是把 Markdown 换了一个存储位置,而是让知识和数据使用同一套组织治理模型。EntryGroup 上的 IAM 会级联到其中的 Entries。一个 Agent 同时请求 OKF 概念和它依赖的 BigQuery 表时,每个资源仍按已有权限返回,不会因为知识包另建一套权限系统而绕过访问控制。
多团队场景可以按 bundle 所属团队划分 EntryGroup,并在组级别分配权限。这样既能保持团队边界,也能让拥有权限的 Agent 通过组织级搜索发现资源。
采用前,建议确认以下事项:
- 为每个团队或治理边界定义 EntryGroup 归属。
- 在 bundle 中强制填写
status、generated、verified和stale_after。 - 对 Attested Computation 固化
parameters,不允许调用方任意改写 SQL 或计算逻辑。 - 在 CI 中执行幂等推送,并监控推送失败。
- 将需要保留审计证据的来源和验证事件写入 OKF Aspect。
- 为过期内容建立重新验证或标记
deprecated的流程。 - 明确删除策略:删除单个 Entry 使用
kcmd delete,整体清理使用cleanup.ts。
OKF 规定了可信上下文的表达方式,Knowledge Catalog 则提供了组织级的索引、权限和访问入口。对于已经使用 Knowledge Catalog 读取数据元数据的 Agent,接入 OKF 的价值在于无需新增一套 bundle 注册表或权限判断:搜索、取上下文、读取信号,仍然沿用目录已有的调用路径。