エージェント用の知識管理、と聞くとベクトルDBを建てたくなる。RAGを組んで、埋め込みを作って、検索を載せて。でもGoogleが先日出した Open Knowledge Format(OKF)は、その手前で止まる。中身は「Markdownフォルダをgitで配るだけ」。必須フィールドは type ひとつだった。
仕様を最初に読んだとき、スカスカすぎて拍子抜けした。だから手を動かして確かめた。bundleを書いて、準拠チェッカーを書いて、消費する側のコードも回した。先に結論を書く。仕様に準拠するのは5分で終わる。難しいのはそこじゃなかった。
OKF v0.1 は 2026年6月12日に Google Cloud が公開した、エージェント向けの知識記述フォーマット。SPECとサンプル bundle が GitHub に置いてある(GoogleCloudPlatform/knowledge-catalog)。
OKFは「スカスカ」が仕様の核
要点はこれだけ。
- bundle = Markdownファイルが入ったディレクトリツリー
- 1概念 = 1 Markdownファイル(YAML frontmatter + 本文)
- frontmatter の必須は
typeだけ。titledescriptionresourcetagstimestampは全部任意 -
index.mdとlog.mdは予約名で、概念ファイルには使わない - 消費側は寛容に読む。未知のtype・未知のキー・リンク切れ・index欠落で「拒否してはいけない」
スキーマレジストリも中央管理もSDKもない。cat で読めて git clone で配れる。それがOKFの全部。
ここが直感に反する。フォーマットは項目をきっちり定義するほど偉い、と普通は考える。OKFはそこを捨てた。厳格なスキーマは陳腐化するし、ベンダーごとに方言が増えてロックインになる。だから producer の自由を最大化して、整合性の担保は消費側の寛容さに寄せている。XMLの厳格バリデーションでみんな疲れた、あの反省の延長にいる設計だと思う。
まず最小のbundleを書く
理屈より現物。売上まわりの小さい bundle を書いてみた。
okf_demo/
├── index.md # 予約名・frontmatterなし
├── log.md # 予約名・更新履歴
├── tables/
│ ├── orders.md
│ └── customers.md
├── metrics/
│ └── revenue.md
└── glossary/
└── churn.md
概念ファイルはこんな感じ。tables/orders.md:
---
type: BigQuery Table
title: Orders
description: 完了した顧客注文が1行ずつ入るテーブル。
resource: bq://acme.sales.orders
tags: [sales, revenue]
timestamp: 2026-05-28T14:30:00Z
---
# Schema
- `order_id` (STRING): 注文の一意キー
- `customer_id` (STRING): [Customers](/tables/customers) への参照
- `amount_jpy` (INT64): 税込の支払額
リンクの /tables/customers は bundle ルート相対。これで概念どうしの関係を張れる。概念IDは「ファイルパスから .md を取ったもの」なので、このリンクは tables/customers.md を指す。
仕様準拠チェッカーを書く
準拠の条件は3つだけ。予約名以外の全 .md が parse できる frontmatter を持つ。その中に空でない type がある。予約ファイルは決められた構造に従う。PyYAML で素直に書ける。
import re, yaml
from pathlib import Path
RESERVED = {"index.md", "log.md"}
FM = re.compile(r"^---\n(.*?)\n---\n?(.*)$", re.S)
def load(bundle):
out = {}
for f in sorted(Path(bundle).rglob("*.md")):
if f.name in RESERVED:
continue
m = FM.match(f.read_text())
meta = yaml.safe_load(m.group(1)) if m else None
out[f.relative_to(bundle).as_posix()[:-3]] = (meta, m.group(2) if m else f.read_text())
return out
def check_conformance(concepts):
errors = []
for cid, (meta, _body) in concepts.items():
if meta is None:
errors.append(f"{cid}: frontmatter が無い/壊れている")
elif not (isinstance(meta.get("type"), str) and meta["type"].strip()):
errors.append(f"{cid}: 必須フィールド type が空")
return errors
さっきの bundle にかけると通る。
## OKF conformance
PASS
試しに type を書き忘れたファイルと、frontmatter なしの素のメモを混ぜると、ちゃんと弾く。
## OKF conformance
NG note: frontmatter が無い/壊れている
NG orphan: 必須フィールド type が空
準拠チェックはこれで完成。30行も書いていない。仕様が小さいんだから当然なんだよね。
「準拠」と「使える」は別物だった
問題はここから。準拠している bundle が、そのままエージェントから使える知識かというと、別だった。仕様がスカスカということは、品質チェックが丸ごと自分の宿題になるという意味でもある。
同じ bundle に「運用リンタ」をかけたら、conformance は PASS なのにこれだけ出た。
## operational lint (仕様は通るが運用で困る点)
⚠ type 表記ゆれ: ['BigQuery Table', 'bigquery table'] は同一視されない(routing が割れる)
⚠ glossary/churn: description が無い(一覧で何の概念か読めない)
⚠ glossary/churn: timestamp が 226日前(陳腐化の疑い)
⚠ metrics/revenue: 内部リンク切れ -> /tables/order (仕様上は合法だが解決不能)
全部、仕様上はセーフ。でも現場では効く。
一番こわいのが先頭の type 表記ゆれ。orders.md は BigQuery Table、customers.md は bigquery table と書いた。仕様には「type は消費側で routing に使う」とある。じゃあ消費側で生の文字列のままフィルタしたらどうなるか。
# "BigQuery Table" で絞ると customers が静かに消える
tables = [cid for cid, m in meta_by_id.items()
if m.get("type") == "BigQuery Table"] # -> ['tables/orders'] だけ
customers が落ちる。エラーは出ない。消費側で casefold して初めて両方拾える。
=== type=bigquery table の概念 ===
- tables/customers: 顧客マスタ。1顧客1行。 resource=bq://acme.sales.customers
- tables/orders: 完了した顧客注文が1行ずつ入るテーブル。 resource=bq://acme.sales.orders
仕様の「未知の type を寛容に扱え」は、裏を返すと「type の正規化は消費側の責任」ということ。producer はいくらでも揺らせるので。
リンク切れも同じ構造だった。revenue.md から /tables/order に張ったけど、正しくは orders。仕様は「リンク切れは malformed ではない、消費側は耐えろ」と明記している。壊れていても準拠は通る。だから準拠チェッカーとは別に、リンク健全性を見る運用リンタを持っておくのが現実的だった。
ちなみに index.md をうっかり概念ファイルとして書くと事故る。予約名なので frontmatter を入れてはいけない。最初これで、index が概念として二重に出てきてハマった。
で、これは何に効くのか
OKFは知識を agent-ready にするための最小公倍数だと思う。MCPサーバーを建てる前、RAGを組む前に、社内のテーブル定義や用語集をまず bundle にしておく。すると、どのエージェントにもツールにも同じ素材を流し込める。gitに乗るから差分が見えるし、レビューもロールバックもできる。ドキュメントをコードと同じ運用に落とせるのが地味に大きい。
今日触って確信したのは、仕様の薄さは「楽」ではなく「責任の移譲」だということ。準拠は5分で終わるけど、type の正規化・リンクの健全性・鮮度は全部こっち持ちになる。だから OKF が普及するとしても、伸びるのはフォーマット本体じゃなくて、この運用リンタやビルダーのレイヤーになるはず。今のうちに準拠チェックと運用リンタをCIに差しておくと、bundle が増えても腐らない。まずは自分のチームのテーブル定義20個くらいを bundle 化するところから始めるのが、ちょうどいい入り口だと思う。
参考: OKF SPEC / サンプル bundle(GitHub) ・ How the Open Knowledge Format can improve data sharing(Google Cloud Blog)