AIエージェントとの会話は、コンテキストウィンドウが閉じた瞬間にリセットされる。設計判断も、ドメイン固有の発見も、運用上の注意点も、どこかに書き出しておかなければ次のセッションには残らない。この「記憶をどこに置くか」という問いに対して、外部DBを一切使わず、Gitリポジトリの中のMarkdownだけで答えようというのが OKF Agent Memory だ。2026-09-05 に公開され、翌日には266★に到達している。

OKF Agent Memoryの検索レイテンシが概念数8で315µs、50で2.46ms、200で12.7ms、500で46.1ms、1000で102.4msへ増える実測グラフ
本記事の実測。公称「300µs未満」が成立するのは同梱バンドル規模(8概念)まで。概念数に対してほぼ線形に伸びる(v0.1.1・Apple Silicon・プロセス内計測)

30秒でわかる OKF Agent Memory

実体knowledge/ 配下のMarkdown群を読み書きするGo製CLI+MCPサーバー。外部DB・埋め込みAPIを使わない
準拠仕様:Google の OKF v0.2(Apache-2.0・★9,079)。本体はMITの独立実装で、Google公式製品ではない
実測で成立した公称値:依存ゼロ(go.mod に require 0件)/RSS 15MB未満(実測4.7MB)/リリース資産のSHA-256一致
条件付きだった公称値:「検索300µs未満」は8概念で315µs、50概念で2.46msと概念数に比例して伸びる
日本語の落とし穴:日本語だけの概念は検索0件。トークナイザが英数字以外を捨てる
MCP常駐コスト:6ツール・860トークン(cl100k_base)=当サイト計測11サーバー中もっとも軽い部類

この記事のポイント

・公称「検索300µs未満」が成立するのは同梱バンドルと同じ8概念規模までで、50概念で2.46ms・1,000概念で102msと概念数に線形に伸びる
日本語だけで書いた概念は検索0件。トークナイザが英数字以外をすべて捨てるため、英語キーワードの併記が事実上必須
・MCPサーバーの常駐コストは6ツール・860トークン(cl100k_base)で、当サイトが同一プローブで測った11サーバー中もっとも軽い

記憶をどう持たせるかはエージェント設計の一部であり、フレームワーク側の選択とも絡む。全体像は AIエージェントフレームワーク比較2026|LangGraph・CrewAI・Dify等9種をStar数・実コードで検証 にまとめてあるので、そちらとあわせて読むと位置づけが掴みやすい。

本記事は v0.1.1(2026-09-06 15:21 UTC リリース)の公式ビルド済みバイナリ okf-darwin-arm64 を対象に、checksums.txt とのSHA-256照合を済ませたうえで実測している。検証環境は macOS 14(Darwin 23.5.0)/ Apple Silicon (arm64) / Go 1.26.5。

OKF Agent Memoryとは——Google OKF v0.2をGitの中で回す記憶層

まず土台の仕様から確認する。OKF(Open Knowledge Format)は実在するGoogleCloudPlatform/knowledge-catalog(★9,079・Apache-2.0)で公開されており、okf/SPEC.md の冒頭に「Version 0.2」と明記されている。仕様本文は「ディレクトリに置かれたYAMLフロントマター付きMarkdown」以上のことをほとんど要求しない——スキーマレジストリも、中央機関も、必須ツールも無い、と自ら宣言する最小主義の仕様だ。

そのうえで OKF v0.2 が「素のMarkdown+フロントマター」に足しているのは、エージェントが知識を書き続ける前提から出てくる3つのメタデータである。provenance(何から作られ、どう検証されたか)/trust(どれだけ信用してよいか)/freshness(まだ真か)CLAUDE.mdAGENTS.md のようなアドホックなMarkdownには無く、かといってベクトルDBに沈めると人間から見えなくなる情報を、フロントマターの sources / trust / status / stale_after として一級市民にしている。

OKF Agent Memory は、この仕様に沿ったバンドルを読み書き・検証・検索するツール側の実装だ。整理すると5層になる。

flowchart TD A["OKF v0.2 仕様
Markdown+YAMLフロントマター"] --> B["Agent Memory Convention
検索してから書く・信頼度を付ける"] B --> C["Agent Skill
エージェント向けの操作手順"] C --> D["Goツール層
パーサ・検証・BM25検索・MCP"] D --> E["knowledge/ バンドル
プロジェクトの実際の記憶"]

重要なのは、この5層のうちGoogleのものは最上段の仕様だけという点だ。リポジトリ名・バッジ・「Built on Google OKF v0.2」という表現から Google 製と読み違えやすいが、okf-memory/okf-agent-memory は MIT ライセンスの第三者実装で、Google の関与を示す記述はリポジトリ内には無い。仕様がオープンなので準拠実装を名乗るのは正当だが、「Google製ツール」ではない

実際に1つの概念ファイルがどう書かれるかを見ると、仕様の狙いが分かりやすい。同梱バンドルの概念は、フロントマターに okf_version / type / id / title / description を必須で持ち、任意で status(active / deprecated など)、trustgeneratedverified か)、sources(何を根拠に書いたか)、stale_after(いつまで有効とみなすか)を持つ。本文はそのまま人間が読むMarkdownだ。

この設計の効き目は「エージェントが書いた内容を、人間が後から棚卸しできる」点にある。ベクトルDBに沈めた記憶は、間違いが混ざっても外からは見えない。対して OKF バンドルは、trust: generated のまま放置されている概念を grep で洗い出せるし、git log で「いつ誰(どのエージェント)が書き換えたか」を追える。記憶を監査可能な資産として扱うという立場が、フォーマットの選択そのものに出ている。

ツール側もこの立場を強制する仕組みを持っている。validate は単なるYAMLの構文チェックではなく、概念間リンクの切れ(broken link)・どこからも参照されていない概念(orphan)・stale_after を過ぎた概念(stale)を検出する。--strict を付けると接続性の警告がエラーに昇格し、--drift を付けると index.md に書かれた説明文が各概念の description と食い違っていないかまで見る。知識ベースが「書きっぱなしで腐る」典型的な失敗に対して、機械的なゲートを1枚用意しているわけだ。

もうひとつ、運用ルール側の柱が Search-Before-Write(書く前に必ず検索する)である。同じ概念が別名で二重に作られるのを防ぐための規約で、Agent Skill 側のプロンプトにも組み込まれている。ただしこれは規約であってツールの強制ではない——okf create は既存概念を検索せずに実行しても止まらない。エージェントが規約を守るかどうかに依存する部分は残る。

同じ「Markdownで記憶を持つ」路線としては、当サイトでも EverOS徹底解説|AIエージェントに永続記憶を与えるMarkdownネイティブ記憶OS を扱っている。OKF Agent Memory との違いは、EverOS が独自の記憶ランタイムを定義するのに対し、こちらは外部の公開仕様に乗り、ツールは仕様の実装に徹するという立て付けにある。

インストールと基本コマンド——公式バイナリのSHA-256照合まで

v0.1.0 / v0.1.1 のどちらのリリースにも、okf-darwin-arm64 / okf-darwin-amd64 / okf-linux-amd64 / okf-linux-arm64checksums.txt が付いている。ソースビルドが唯一の導線ではない。実際に落として照合した手順が以下だ。

# 1. 公式リリースのバイナリを取得(v0.1.1・Apple Silicon)
curl -sL -o okf https://github.com/okf-memory/okf-agent-memory/releases/download/v0.1.1/okf-darwin-arm64
chmod +x okf

# 2. 配布されている checksums.txt と照合する(ここを飛ばさない)
curl -sL https://github.com/okf-memory/okf-agent-memory/releases/download/v0.1.1/checksums.txt | grep darwin-arm64
shasum -a 256 okf

# 3. 版の確認
./okf version

実行結果は、checksums.txt 側の 2b80a404ab2972e8c6a91eda8c8df7b1c4df38dfbc8cf26af7f605561f899bc8 と手元の shasum 出力が一致./okf versionokf version v0.1.1 (OKF v0.2 specification) を返した。バイナリサイズは 2,341,202 バイト(約2.2MB)。

ソースからビルドする場合は make build で、手元では約24秒・3,915,842バイトのバイナリになった(リリース版のほうが小さいのは、リリースビルドがシンボルを落としているため)。ここでREADMEのバッジとの食い違いが1つある。バッジは Tooling: Go 1.26 と表示するが、go.modgo 1.22.0 で、CI(.github/workflows/ci.yml / release.yml)はいずれも go-version-file: 'go.mod' を指定している。実際にビルドに使われる版は1.22.0系であり、Go 1.26 が要るわけではない。

同梱の knowledge/ バンドルに対する検証コマンドも実行できる。

./okf validate knowledge --strict --drift

出力は OKF v0.2 check of "knowledge" (v0.2): 8 concept(s), 0 error(s), 0 warning(s); 0 broken link(s), 0 orphan(s), 0 stale [--strict]. Conformant. だった。自リポジトリのバンドルは自ツールの厳格モードを通る。

同梱バンドルは8概念。READMEはグラフ検証の速度を「50+ concepts」を前提に語るが、リポジトリに入っている knowledge/ は概念8本・合計30KBである。後述の速度の話は、この規模差を踏まえて読む必要がある。

【実測】「検索300µs未満」はどこまで成立するか

READMEの目玉は < 300 µs (Microseconds, In-Memory BM25) という検索レイテンシだ。これを検証するにあたり、まずCLIの実行時間で測っても意味がないことを確認しておく。okf search の実測はプロセス起動を含めて最良7.3ms・中央値16.7ms で、µs のオーダーとは2桁違う。公称値は明らかに「プロセス内の検索処理そのもの」を指している。

そこで、公開APIである pkg/okfLoadBundle()Bundle.Search() を直接叩くGoプログラムを書き、プロセス起動を含まない純粋な検索時間を測った。ウォームアップ3回のあと200回実行し、最良値を採る。あわせて、同じ形式の合成バンドル(1概念あたり約3.2KBの英語本文)を概念数を変えて生成し、スケーリングを見た。

概念数 検索(1語クエリ) 検索(3語クエリ) バンドル読み込み
8(同梱バンドル相当) 315 µs 461 µs 312 µs
50 2.46 ms 3.73 ms 1.75 ms
200 12.7 ms 15.7 ms 12.5 ms
500 46.1 ms 70.2 ms 64.9 ms
1,000 102.4 ms 123.6 ms 230.4 ms

結論はこうだ。「300µs未満」は同梱バンドルと同じ8概念規模でだけ成り立つ(315µsなので、厳密にはそこでもわずかに超えた)。概念50本で2.46ms=公称の約8倍、500本で46ms=約150倍、1,000本で102ms=約340倍になる。伸び方は概念数に対してほぼ線形で、これは同じ計測を3回繰り返しても再現した。

なぜ線形に伸びるのか。pkg/okf/search.go を読むと理由がはっきりする。この実装は転置インデックスを持たない。クエリのたびに全概念をループし、各概念の Title + Description + Tags + ID + Body を毎回 strings.ToLower で連結し、tokenize() を呼び直している。つまり「インメモリ索引を引く」のではなく「全件を毎回スキャンして採点する」構造で、コーパスが増えれば増えた分だけ比例して遅くなる。

もう1点、用語の精度について。README は一貫して「BM25」と書くが、実装のスコア式にあるのはIDF(平滑化あり)とフィールド別の重み付きTFで、BM25を特徴づける k1 の飽和項と b の文書長正規化が無い。重み付きTF-IDFと呼ぶのが正確だ。小規模なプロジェクト知識を引く用途では実害は出にくいが、「BM25だから長文に強い」といった期待は置かないほうがいい。

実運用のイメージに落とすと、こうなる。数十本のADR(アーキテクチャ決定記録)を貯めた程度なら、検索は数ミリ秒で返るので体感上は問題にならない。エージェントが1タスクで数回検索する程度の使い方なら、この規模では十分に速い。一方、コードベース全体の関数や型を概念として登録していくような使い方——数百〜数千概念——では、1回の検索が数十〜数百ミリ秒になる。エージェントがループの中で繰り返し検索する設計だと、ここが積み上がって効いてくる。

なお、バンドル読み込み(LoadBundle)の数値は検索よりばらつきが大きい。ディスクI/Oを含むため並行負荷の影響を受けやすく、200概念と500概念で順序が逆転する計測も出た(本記事の計測中も3セッションが同一マシンで走っていた)。検索側は3回の反復で安定して同じ傾向を再現したので、スケーリングの根拠としては検索の値を採っている。

公称値そのものを否定しているわけではない。8概念で315µsという値自体は再現した。問題は、公称値がどの規模で測ったのかREADMEに書かれていないことと、その規模がリポジトリ同梱バンドル(8概念)と一致し、README自身がグラフ検証の説明で使う「50+ concepts」とは食い違っていることにある。数百概念まで育てる前提なら、この数字を性能の根拠にはできない。

【実測】日本語だけで書いた概念は検索に出てこない

日本語話者にとっては、速度より先にこちらが問題になる。同梱バンドルに対して4つのクエリを投げた結果が以下だ。

クエリ 返却件数
architecture(英語) 8件
アーキテクチャ 0件
設計 0件
アーキテクチャ layers(混在) 8件

原因は pkg/okf/search.gotokenize() にある。分割の述語が「a-z でも A-Z でも 0-9 でもない文字はすべて区切り」と定義されているため、日本語の文字はすべて区切り文字として捨てられ、トークンが1つも残らない。クエリ側でトークンが0個になれば Search() は即座に nil を返す。混在クエリ アーキテクチャ layers が8件返るのは、日本語部分が消えて英語の layers だけが効いているからで、日本語が効いているわけではない。

これは設定で回避できるオプションではなく、トークナイザの実装そのものに由来する。日本語のプロジェクト知識を貯める用途で使うなら、title / tags / id に英語のキーワードを必ず併記する運用が事実上必須になる。CJKの語境界がASCIIトークンを巻き込む類の問題は当サイトでも繰り返し踏んでおり、memory-os解説|AIエージェントの記憶をローカル完結でOS的に階層管理する7層メモリ基盤OSS で扱った階層メモリ系でも、日本語の扱いは実装ごとに大きく違う。

MCPサーバーの常駐コストを、同じ物差しの11サーバーと並べる

okf mcp <bundle> で stdio のMCPサーバーが立ち上がる。エージェントに接続した瞬間から、ツール定義はツールを1つも呼ばなくてもコンテキストに常駐し続ける固定費になる。当サイトでは同一プローブでMCPサーバーの tools/list を測り続けているので、そこへ並べた。

公開されるツールは6つ。okf_search / okf_show / okf_validate / okf_create / okf_update / okf_relate で、CLIのサブコマンドとほぼ一対一に対応する。

指標 実測値(v0.1.1)
ツール数 6
tools/list バイト数 3,541 バイト
トークン数(cl100k_base / tiktoken 860 トークン
1ツールあたり 143.3 トークン
認証 不要(ローカルのバンドルを読むだけ)

接続設定は他のstdio系MCPサーバーと同じ形で、バンドルのパスを引数に渡すだけでいい。

{
  "mcpServers": {
    "okf-memory": {
      "command": "/absolute/path/to/okf",
      "args": ["mcp", "/absolute/path/to/your-project/knowledge"]
    }
  }
}

同じ payload 定義・同じ cl100k_base で測った既定設定の他サーバーと比べると、860トークンは当サイトの計測対象のなかで最も軽い。次点が Microsoft Learn MCP の1,097、以下 zvec-grep 1,575、Obscura 3,355、Supabase 5,713、Chrome DevTools 6,010、Backlog 11,680、draw.io 15,383、Notion 21,831、OpenKnowledge 39,710 と続く。ツール数を6に絞り、引数スキーマを単純に保っていることが効いている。

トークナイザ名を省略しない。ここで挙げた数値はすべて cl100k_base(OpenAI のトークナイザ)である。Anthropic の count_tokens で測ると同じペイロードが1.35〜1.65倍に振れ、倍率は対象ごとに違うので一律換算もできない。他所の「MCPは何トークン」という数字と突き合わせるときは、まずトークナイザを揃える必要がある。

なお v0.1.0 時点のコミットで測ったときは 2,655バイト / 658トークンで、v0.1.1 の「dynamic bundle resolution」対応でスキーマが増えた分だけ重くなっている(ツール数は6のまま)。ツール数を絞る設計判断が、そのまま常駐コストの差として出ている。

「トークン80%削減」は何の数字か——再現していない点を明示する

READMEは -80% token reduction を掲げ、make benchmark で自分のハードウェアでも再現できると案内している。本記事ではこれを再現していない。 理由は2つある。

1つは実行条件だ。このベンチマークは LM Studio / Ollama 上のローカルLLM(Gemma・Qwen・Llama)を必要とし、TTFT(Time-To-First-Token)とトークン数を測る構成になっている。本記事の他の計測がすべて決定論的に再現できるのに対し、ここだけモデル・量子化・ハードウェアに強く依存する。

もう1つはより本質的で、この80%は「monolith な1枚ドキュメント」対「OKFバンドルに分割したもの」という、リポジトリ側が用意した対の比較である(benchmarks/data/ に両者のフィクスチャが置かれている)。つまり測っているのは「大きな文書を丸ごと読ませる代わりに、索引を辿って必要な概念だけ読ませればトークンが減る」というprogressive disclosure という手法の効果であって、OKF Agent Memory というツール固有の性能ではない。同じことは他の階層的なドキュメント構成でも起こる。削減率の絶対値は、比較対象に選んだ monolith がどれだけ冗長かで決まる。

したがって本記事では、この数字をベンダー公称値として記載するに留め、実測値としては扱わない。逆に、決定論的に確認できた公称値は次のとおりだ。

README の主張 判定 実測の根拠
外部依存ゼロのGoツールチェーン 成立 go.modrequire が1件も無い
RSS 15MB未満 成立 validate 実行時の最大RSS 4,947,968バイト(約4.7MB)
単一バイナリで配布 成立 公式リリース資産2.2MB・SHA-256一致
OKF v0.2 準拠 成立 仕様は実在(Apache-2.0)。validate --strict が自バンドルを通す
検索 300µs 未満 条件付き 8概念で315µs。50概念で2.46ms、1,000概念で102ms
プロセス起動 4ms 未満 測定条件に依存 最良4.07msを観測したが、並行負荷下では12〜19msまで振れた
グラフ検証 約4.0ms(50+概念) 未確認 同梱バンドルは8概念。50概念以上の実バンドルが無い
トークン80%削減 未再現 ローカルLLMとフィクスチャ対に依存。手法の効果でありツール固有の値ではない
BM25 不正確 IDF+重み付きTFはあるが、k1の飽和項とbの文書長正規化が無い

OKF Agent Memoryは誰に向いていて、誰に向かないか

ここまでの実測を踏まえると、適合条件はかなりはっきりする。

まず、記憶層としての位置づけを整理しておく。下の表は仕組みの違いをまとめたもので、速度の数値は本記事で実測したOKF Agent Memoryの列だけが実測値、他列は各プロジェクトの設計上の性質を示す(他ツールの速度は本記事では測っていない)。

  OKF Agent Memory ベクトル検索型(mem0 / Letta 等) アドホックMarkdown(CLAUDE.md 等)
保存先 リポジトリ内 knowledge/ 外部ベクトルDB リポジトリ内の単一ファイル
検索方式 語彙一致(重み付きTF-IDF) 埋め込みベクトルの類似度 全文をコンテキストへ投入
表記ゆれ・言い換え 吸収できない 吸収できる (検索という段階が無い)
日本語クエリ 0件になる(v0.1.1実測) 埋め込みモデル次第 該当なし
外部API課金 不要 埋め込みAPIの費用が継続 不要
人間によるレビュー git diff で可能 DBの中身は不透明 git diff で可能
信頼度・鮮度の管理 trust / stale_after で一級 実装依存 無い
規模の上限 数十〜百概念が実用域 大規模に耐える コンテキスト長が上限

この並びで見ると、OKF Agent Memory が置き換えようとしているのはベクトルDBではなく、むしろ CLAUDE.mdAGENTS.md に何でも書き足していく運用のほうだと分かる。単一ファイルが肥大化してコンテキストを圧迫する問題に対し、索引を辿って必要な概念だけ読ませる構造を与える——これが README の言う progressive disclosure であり、前節の「80%削減」が測っているものでもある。

噛み合うケース:記憶の中身を git diff / git log でレビューしたい。外部DBや埋め込みAPIをプロジェクトに持ち込みたくない。扱う知識が数十概念規模に収まる。チーム内の設計判断(ADR的なもの)を、エージェントと人間の両方が読む場所に置きたい。MCPの常駐コストを可能な限り抑えたい。

噛み合わないケース:日本語だけで知識を書きたい(検索が機能しない)。数百〜数千概念のコーパスを想定している(検索が線形に劣化する)。表記ゆれや言い換えを吸収したい(語彙の完全一致・前方一致しか見ないため、ベクトル検索型の Letta Code徹底解説|記憶を持つステートフルAIエージェントCLIの仕組みと使い方 系が向く)。

最後に、プロジェクトの若さについて事実だけ置いておく。リポジトリ作成は2026-09-05、本記事執筆時点でコミットは3本、リリースは v0.1.0 と v0.1.1 の2本、Issue・PRともにオープン0件、266★。執筆の途中で v0.1.1 が公開され、MCPのJSON-RPC 2.0通知準拠が修正された(そのため本記事は v0.1.1 に測り直している)。動きは速く、設計の方向性も明快だが、公称値の一部が同梱バンドル規模でしか成立しない状態でREADMEに書かれている点は、採用判断の前に自分のコーパス規模で測り直す理由になる。本記事の計測は data/measurements/ に登録してあり、同じ手順で追試できる。

参照ソース