0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Google OKFを書いて検証した:エージェント用知識の必須項目は1つだけ

0
Posted at

エージェント用の知識管理、と聞くとベクトル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 だけ。title description resource tags timestamp は全部任意
  • index.mdlog.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.mdBigQuery Tablecustomers.mdbigquery 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)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?