はじめに
エージェントに「セッションを跨ぐ記憶」を持たせる話になると、まずベクトル DB の選定から入る空気があります。埋め込みモデルは何にするか、Qdrant か pgvector か、チャンクサイズはいくつか。筆者もそう考えていました。
ところが 2026 年 8 月時点で動いている主要な実装のドキュメントを一次情報で読み直したところ、記憶の「正典」を置く形として、独立に設計された複数の実装が同じ場所に着地していることが分かりました。その形はこうです。
YAML frontmatter 付きの Markdown ファイルを、ディレクトリに置いて、git で管理する。
ベクトル DB が要らなくなったわけではありません。正典から派生インデックスへ降り、位置が変わったというのがこの記事の結論です。
事実部分はすべて各プロジェクトの公式ドキュメント・仕様書・リポジトリのソースを出典とし、末尾の「参考」に列挙しています。収束の理由の分析は筆者の推論であり、その旨は本文中でも都度明示します。
1. 並べてみる — 6つの実装は記憶をどこに置いているか
まず事実を並べます。それぞれ、公式ドキュメントが「記憶(あるいは知識)の実体はここにある」と述べている場所です。
| 実装 | 記憶の置き場所 | 形式 |
|---|---|---|
| Obsidian | ローカルフォルダ(vault) | Markdown + YAML properties |
| OKF v0.2 | Knowledge Bundle(git リポジトリ推奨) | Markdown + YAML frontmatter |
| Letta MemFS | git 管理下のファイルシステム | Markdown + YAML frontmatter |
| Claude Code | リポジトリ / ホーム配下 |
CLAUDE.md + MEMORY.md + トピックファイル |
| Anthropic Memory tool | アプリ側の任意ストレージ(/memories) |
形式は非規定(操作は6コマンド) |
| TencentDB Agent Memory(OSS) |
~/.openclaw/memory-tdai/ の上層 |
persona.md / scenarios/ / refs/
|
1.1 Obsidian — vault はただのフォルダ
Obsidian の vault は「A vault is a folder on your local file system, including any subfolders.」と定義されています。ノートは Markdown のプレーンテキストなので、公式ドキュメントも「you can use other text editors and file managers to edit and manage notes」と明記しています。
メタデータは Properties(YAML frontmatter)で持ちます。ただしサポート型は Text / List / Number / Checkbox / Date / Date & time / Tags の7種のみで、ネストしたプロパティは非対応、プロパティ内に Markdown は書けません。この制約は 5.2 で効いてきます。
1.2 OKF — 「cat できれば読める」を仕様にした
OKF(Open Knowledge Format)は Google Cloud が 2026-06 に公開した交換フォーマットです。バンドル構造の予約ファイル名は index.md と log.md の2つだけで、それ以外のすべての .md が概念ドキュメントになります。
path/to/bundle/
index.md # Optional. Directory listing for progressive disclosure.
log.md # Optional. Chronological history of updates.
<concept>.md # A concept at the bundle root.
<subdirectory>/ # Subdirectories organize concepts into groups.
index.md
<concept>.md
frontmatter で必須なのは type ただ1つ。仕様書は自らのスコープを、スキーマレジストリなし・中央権威なし・必須ツールなしと規定しています。要するに「cat できれば読めるし、git clone できれば配れる」ということです(筆者による要約です。原文は SPEC.md を参照してください)。
適合(conformant)条件も3つだけです。予約名以外のすべての .md がパース可能な YAML frontmatter を持つこと、すべての frontmatter が空でない type を持つこと、予約ファイルが存在する場合は規定構造に従うこと。
重要なのは非目標(Non-goals)を明示している点で、ストレージ・配信・クエリ基盤の規定は「やらない」と宣言しています。つまり OKF はメモリ「サービス」とはレイヤが違います。
1.3 Letta MemFS — 「すべての記憶編集を git にコミットする」
Letta(旧 MemGPT)の現行の主メモリ系は MemFS で、公式ドキュメントはこう定義しています。
the git-backed filesystem where a Letta agent stores long-term memory
記憶は YAML frontmatter 付きの Markdown ファイルとして格納されます。system/ 配下(persona.md, human.md)は毎ターン system prompt に自動ロードされ、それ以外(reference/, skills/)は関連性に応じて選択ロードされます。そして、
Every memory edit is committed to the MemFS git repository
記憶の編集が git コミットになるということは、記憶に diff と履歴とレビューが付いてくるということです。さらに記憶を整理する subagent(dreaming / sleep-time)は git worktree を使って本体をブロックせずに並行更新します。git を「たまたま使っている」のではなく、並行制御の道具として使っている構成です。
1.4 Claude Code と Memory tool — 人が書く分も Claude が書く分もファイル
Claude Code のドキュメントは、セッションを跨いで知識を運ぶ機構が2つあると明言しています。「CLAUDE.md files(instructions you write)」と「Auto memory(notes Claude writes itself)」、つまり人が書く分と Claude が自分で書く分です。
Auto memory の保存先は ~/.claude/projects/<project>/memory/、構成は MEMORY.md(インデックス)+トピックファイルです。ロードには明確な予算があり、MEMORY.md は先頭 200 行または 25KB のいずれか早い方までしか毎セッション冒頭にロードされません。トピックファイルは必要になったときに読まれます。つまり**インデックスは「常時ロードされる代わりに短くしなければならない」**わけで、OKF の index.md と同じ progressive disclosure を、明示的な予算付きで実装したものと読めます。
API 側の Memory tool(memory_20250818、Messages API で GA)はもっと直接的です。
The memory tool operates client-side: Claude requests file operations, and your application executes them. You control where and how the data is stored through your own infrastructure.
コマンドは view / create / str_replace / insert / delete / rename の6つ。/memories は「a prefix that your handler maps onto real storage」で、実際の保存先はアプリケーション側の自由です。API レベルで規定されているのはストレージではなくファイル操作のセマンティクスで、ベクトル検索も埋め込みも出てきません。Claude が記憶を扱うときの操作語彙が、おおむね ls / cat / sed -i / mv に対応しています。
1.5 TencentDB Agent Memory
TencentDB Agent Memory の OSS 版は、L0 Conversation → L1 Atom → L2 Scenario → L3 Persona という階層を持つ、作り込まれたランタイムです(公式表現では「语义金字塔」)。ストレージは SQLite + sqlite-vec または Tencent Cloud VectorDB、リコールは embedding + BM25 を RRF で融合するハイブリッドが既定で、ファイル群は ~/.openclaw/memory-tdai/ 配下に置かれます。そのストレージ設計の方針を README はこう述べています。
下層は DB やアーカイブファイルに生の事実・ログ・実行トレースを置き、上層はビジネスが読める Markdown(persona.md、scenarios/、atoms/、refs/)に置く。ベクトル DB をフルに使っている実装ですら、人が読む層は Markdown のファイルツリーになっています。
2. 収束の中身を分解する
6つを並べると、共通しているのは「Markdown だから」という表面的な一致ではなく、もう少し構造的な4点だと分かります。
① メタデータは frontmatter、中身は本文
OKF は type を必須にし、generated / verified / status / stale_after といった信頼性・鮮度の情報も frontmatter に置きます。Claude Code の Auto memory も書き込み時刻を frontmatter の modified に記録します(公式が「never adds frontmatter to a file that has none」と明記しているとおり、もともと frontmatter を持つファイルに限られます)。機械が絞り込むための情報は frontmatter、人と LLM が読む情報は本文という分担が、どこでも同じです。
② ディレクトリ階層が名前空間
OKF の Concept ID は「バンドル内のファイルパスから .md を除いたもの」です。Letta MemFS は system/ と reference/ と skills/ でロード戦略を切り替えます。フォルダを切ることが、そのままスコープとロード優先度の宣言になっているわけです。
③ インデックスファイルが必ずある
OKF の index.md、Claude Code の MEMORY.md、Letta の system/persona.md、TencentDB の persona.md。呼び方は違いますが、「まず読む1枚」があり、そこから必要に応じて掘るという progressive disclosure の構造は共通です。
④ 編集の単位がファイル操作
Anthropic Memory tool の6コマンド、Letta の「編集ごとに git commit」、Obsidian の Vault.process()。いずれも「レコードを UPDATE する」ではなく「ファイルを書き換える」という粒度です。
3. なぜこの形なのか(筆者の推論)
ここから先は公式が述べた設計指針ではなく、上に並べた事実からの帰結として筆者が考えたことです。「Markdown + frontmatter + git」が満たしている要請は、おそらく次の4つです。
① 人が直接読んで訂正できる
エージェントが書いた記憶は必ず間違えます。SELECT を書かずに cat して直せることの価値は大きく、OKF が v0.2 で verified を入れて Unverified / Machine-confirmed / Human-reviewed のトラストティアを導出する設計にしたのも、「人が確認したかどうか」を機械可読に持ち回るためです。
② git で差分・履歴・レビューが取れる
記憶が壊れたとき、いつ壊れたかを git log で追える。Letta が「Every memory edit is committed」と言い切り、並行更新に worktree を使っているのは、この性質を実装の中核に据えているということです。
③ ベンダー・モデル・アプリを跨いで持ち運べる
Obsidian は公式サイトのトップで「Obsidian uses open file formats, so you're never locked in.」と明言し、OKF は「git clone できれば配れる」と書きます。エージェント基盤の乗り換えサイクルが年単位より短い現状で、記憶を1つのランタイムの内部形式に固定するのは合理的とは言いにくいところです。
④ LLM がそのまま読める
Markdown は LLM にとって追加のパーサが要らない形式です。ベクトル DB から取り出した結果も結局テキストに戻すのだから、最初からテキストで持っておけば変換の往復が消えます。
裏を返すと、ベクトル DB のみに記憶を置く構成はこの4つを全部失います。検索は速くても、人は読めないし、diff は取れないし、持ち出せないし、そのままプロンプトには入りません。
4. ただし Markdown だけでは足りない
収束の話をしたので、逆側も書いておきます。Markdown ファイルツリーだけでは意味的な想起ができません。
Obsidian の Search コアプラグインでドキュメント化されている演算子は file: tag: line: block: section: などと正規表現、プロパティ検索で、セマンティック検索・ベクトル検索の記載は一切ありません。ロードマップの検索項目も「Sort search results by relevance」が Planned にあるだけです。Letta の MemFS もベースでは通常のファイル検索で探す設計で、ハイブリッド検索は「MemFS Search mod」という追加機能です。
つまりどの実装も、正典(Markdown)と索引(ベクトル / BM25 / グラフ)を分けています。TencentDBは、まさにこの二層をストレージレベルで表現したものです。
ここから導かれる設計指針を1つに畳むと、こうなります。
正典は Markdown。インデックスは派生物として、いつでも正典から再構築できる状態に保つ。
索引が壊れたら作り直せばよく、索引を捨てても記憶は失われない。この非対称性を維持できているかどうかが、運用が長くなるほど効いてきます。
なお Mem0 や Zep のように「ランタイム側が正典」という設計も当然あります。Zep の基盤である Graphiti の EntityEdge は valid_at / invalid_at / expired_at を持ち、古い事実を削除せず失効時刻を記録する bi-temporal モデルを実装していますが、これはファイルツリーでは表現しにくい領域です。どちらが正しいという話ではなく、「人が読んで直す運用を回すか」で分岐する、というのが筆者の見立てです。
5. 自分の Vault をエージェントの書き込み先にするときの5つの指針
筆者は Obsidian Vault を Claude の各種スキルの入出力先にしています。上の整理を踏まえると、押さえるべき点は次の5つです。いずれも一次情報からの帰結であって公式推奨ではありません。
5.1 書き込みは append 中心、1ファイル1ライター
Obsidian の Plugin API には Vault.process() があり、公式ガイドは「Always prefer Vault.process() over Vault.read()/Vault.modify() to avoid unintentional loss of data.」と書いています。ただしこの atomicity が効くのはアプリ内です。外部プロセス向けのロック・楽観排他・ETag・バージョン番号は、Vault API / CLI / URI のいずれのドキュメントにも記載がありません。
そして Obsidian Sync の競合処理は、Markdown なら Google の diff-match-patch による自動マージが既定です。それ以外の形式は last-modified-wins で、分岐ファイル(... (Conflicted copy device-name YYYYMMDDHHMM).md)はそう設定した場合に作られます。エージェントの書き込みと人の編集がぶつかったとき、黙ってマージされる方がむしろ気づきにくいわけです。保険の File recovery コアプラグインも、公式が明確に「not a complete backup solution」と書いています。
実務的な緩和は、エージェント専用の追記先(raw/ に日付別・エージェント別で置く)を、人が直す領域(wiki/)から分離することです。エージェントは wiki/ には提案までで止める。
5.2 frontmatter はフラットに設計する
Properties は7型・ネスト不可・Markdown 不可です。エージェント記憶に典型的な「信頼度スコア+出典配列+タイムスタンプ+関連エンティティ」をそのまま入れ子で持たせることはできません。回避策は、キー名で階層をエンコードするか、スカラーの List に収まる形まで落とすかです。
---
type: Reference
status: stable
stale_after: 2026-11-08
source_url: https://example.com/spec
source_date: 2026-08-08
generated_by: claude-opus-5
verified_by: human:ryoji
---
この例の generated_by / verified_by は OKF のキーではありません。OKF v0.2 が定義しているのは generated: { by, at } と verified: [{ by, at }] という入れ子の形なので、そのままでは Properties に載りません。上の例は、それをキー名側に畳んだ筆者の書き方です。
ただし畳めば済むとも限りません。OKF の sources は id / resource / title / author / usage_count / last_modified を持つ mapping の list で、Obsidian の List 型(スカラーの並び)には収まりません。frontmatter に持たせられない構造化データは、本文のコードブロックに置くのが現実的な落とし所です。
5.3 埋め込みは外部に持ち、いつでも再構築できるようにする
Obsidian にベクトル検索はなく、ロードマップにもありません。したがって RAG 的な想起には埋め込みインデックスを外部で二重に維持することになります。重要なのは、この二重維持を「同期が必要な2つの真実」にしないことです。索引は捨てて作り直せる派生物として扱い、vault から丸ごと再構築するスクリプトを1本用意しておくだけで、整合性の悩みがかなり消えます。
5.4 インデックスファイルの読み込み予算を意識する
Claude Code の MEMORY.md は先頭 200 行または 25KB のいずれか早い方までしかロードされません。OKF の index.md も progressive disclosure のためのディレクトリリスティングであって、内容そのものを置く場所ではありません。
インデックスは「索引」であって「要約」ではない、という区別を守る必要があります。1行1エントリでリンクと一言の説明だけを置き、中身はトピックファイルに逃がす。これを崩すと、静かに打ち切られた後半が二度と読まれなくなります。
# MEMORY.md(索引に徹する)
- [記事の実測値3原則](feedback_measured_numbers.md) — 1回の観測で断定しない
- [連載の章立て設計](project_series.md) — 全7回、第4回まで草案済
5.5 type を1つ足すだけで OKF conformant になる
適合条件は前述の3つだけなので、既存の Markdown ノートに type を入れるだけで適合します。Obsidian の公式コミュニティプラグインレジストリには OKF を名指しするプラグインが4件登録されていて、okf-enforcer(検証・強制)と frontmatter-operator(vault 横断の frontmatter 一括編集)を組み合わせれば、「検証だけ回す → type を一括付与する」という最小の導入パスが取れます。
ただしこの4件はすべて「This plugin has not been manually reviewed by Obsidian staff.」付きで、レジストリの説明文もまだ v0.1 表記のままです。入れるなら中身を自分で確認してからにしてください。
ハマりどころ
常時稼働エージェントから Obsidian のインデックスは使えない
2026 年に Obsidian CLI(Obsidian 1.12 インストーラが必要。Windows のみ 1.12.7+)と Obsidian Headless(open beta)が出て、エージェントが叩ける公式インターフェースは大きく増えました。CLI は backlinks / links / orphans / tags / base:query を JSON 出力付きで提供します。
ところがCLI は Obsidian アプリの起動を要求し(未起動なら初回コマンドが自動で起動します)、Headless が扱うのは Sync と Publish で、クエリ/インデックス系のコマンドを持ちません。結果として、GUI を常駐させられないサーバー側エージェントが Obsidian のインデックスを使う公式手段は、2026-08 時点では見当たりませんでした。現実的には、ファイルシステム直読み+自前インデックスに寄せることになります。
OKF は v0.1 と v0.2 が混在している
これは実際に踏みました。公式ブログは 2026-07-24 に v0.2 をアナウンスし、spec はリポジトリの okf/ にあると書いています。しかし 2026-08-08 に main/okf/SPEC.md の raw を直接取得した時点では、冒頭は "Version 0.1 — Draft" のままで、節構成も v0.1 のものでした。
その後 2026-08-11 に取り直したところ、SPEC.md は "Version 0.2" に更新され、sources も §5.1 に定義されていました。ところが同じリポジトリの okf/README.md は、この時点でも「Read the Open Knowledge Format v0.1 specification → SPEC.md」のままです。アナウンスから半月経っても、仕様本体とその README ですら版の表記が揃っていないわけです。
v0.1 → v0.2 の破壊的変更は2点。timestamp → generated.at、本文の # Citations セクション → frontmatter の sources です。仕様の側がこの状態なので、「OKF 対応」と書いてあっても、どちらの版を指しているかは確認したほうが安全です。
なお、OKF のホストリポジトリの root README には "This repository and its contents are not an official Google product." と明記されています。Google Cloud 公式ブログでアナウンスされてはいますが、成果物自体は公式プロダクトのサポート対象ではありません。「Google の標準」と言い切るのは言い過ぎです。
vault 全体を渡す MCP サーバーは権限が粗い
Obsidian は公式に「Due to technical limitations, Obsidian cannot reliably restrict plugins to specific permissions or access levels.」と述べています。vault 全体への read/write を持つ MCP サーバーを入れるのは、実質的に個人の知識ベース全部への読み書き権限をモデルに渡すのと同じです。MCP 仕様自身も、ツール呼び出しを拒否できる human in the loop を SHOULD としています。
Markdown に寄せると失うものもある
Graphiti の bi-temporal モデルのように、事実の時間的妥当性を厳密に扱う機能は、ファイルツリーでは素直に表現できません。「いつからいつまで真だったか」を機械的にクエリしたい要件があるなら、Markdown の正典に寄せる設計は向いていません。
まとめ
- Obsidian / OKF / Letta MemFS / Claude Code / Anthropic Memory tool / TencentDB Agent Memory の6実装は、互いに独立でありながら「YAML frontmatter 付き Markdown をディレクトリに置き、git で管理する」という同じ形に収束している
- 共通構造は4点。frontmatter がメタデータ・本文が中身、ディレクトリが名前空間、インデックスファイルによる progressive disclosure、編集単位がファイル操作
- 満たしている要請は、人が訂正できる/git で差分が取れる/持ち出せる/LLM がそのまま読める、の4つ(ここは筆者の推論)。ベクトル DB のみの構成はこの4つを全部失う
- ただし Markdown だけでは意味的想起ができない。正典は Markdown、インデックスは再構築可能な派生物という二層構成が現実的な落とし所
- Vault をエージェントの書き込み先にするなら、append 中心・1ファイル1ライター、フラットな frontmatter、再構築可能な外部索引、インデックスの読み込み予算、
typeを入れて OKF conformant、の5点を押さえる
ベクトル DB の選定から入るのをやめて、「正典をどこにどう置くか」から入る。それだけで、後から効いてくる可搬性と可監査性がだいぶ変わります。
参考
仕様・フォーマット
- OKF SPEC.md(2026-08-11 時点で v0.2 に更新済み)
- okf/README.md(同時点でも v0.1 表記のまま)
- knowledge-catalog root README("not an official Google product" の免責)
- OKF v0.2 公式アナウンス(trust signals)
- okf-enforcer
Obsidian
- obsidian.md 公式トップ("you're never locked in")
- How Obsidian stores data
- Properties
- Search
- Obsidian CLI
- Obsidian Headless
- Troubleshoot Sync
- File recovery
- Plugin security
- Plugins / Vault guide
エージェント記憶の実装
- Letta MemFS
- Letta memory & dreaming
- Claude Code memory
- Anthropic memory tool
- TencentDB-Agent-Memory README_CN.md
- Zep concepts
- Graphiti
- MCP spec: Tools