01 — 課題

メモリは知識ではない

AIエージェントにはメモリがある——しかしメモリは知識ではない。GoClawには3層のメモリがある:ワーキング → エピソード → セマンティック。しかし、エージェントが特定のドキュメントを見つけたり、ファイル間の相互参照をしたり、ドキュメントの関係をトラッキングする必要がある場合——メモリシステムでは不十分。

1

検索の断片化——各ストアを個別にクエリする必要

2

ドキュメント関係なし——バックリンクが存在しない

3

古いコンテンツ——外部編集がDBに同期されない

Knowledge Vaultは3つすべてを解決:ドキュメントレジストリ + ウィキリンク + ハイブリッド検索 + ファイルシステム同期

02 — アーキテクチャ

メモリシステムの上位クエリレイヤー

Component役割
VaultStoreドキュメントCRUD、リンク管理、ハイブリッド検索(FTS + ベクター)
VaultSearchService検索コーディネーター:vault、エピソード、KG全体の並列ファンアウト
EnrichWorker5フェーズ非同期パイプライン:準備 → 要約 → 埋め込み → 分類 → ウィキリンク
VaultSyncWorkerファイルシステムウォッチャー:変更を検出、コンテンツハッシュを同期
VaultInterceptorファイル操作にフック:エージェント書き込み時に自動登録
VaultRetrievervault検索をエージェントL0メモリにブリッジ

書き込みパス

書き込みパス — エージェントがファイルを記録
エージェントがファイル書き込み → ワークスペースFS
VaultInterceptor (AfterWrite)
EventBus: VaultDocUpserted
P0: Prepare
P1: Summarize
P2: Embed
P3: Classify
P4: Wikilinks

読み込みパス

読み込みパス — エージェント検索
VaultStore
0.4
FTS + Vector
EpisodicStore
0.3
セッション要約
KGStore
0.3
エンティティ類似度
Normalize
Dedup
Sort
Top N

テナント&スコープ分離

各ドキュメントはスコープに属する:personal(エージェントのみ)、team(チームワークスペース)、shared(クロスエージェント、未実装)。テナントAのドキュメントはテナントBと完全に分離——リンクもテナントを越えられない。パーソナルドキュメントはチームドキュメントにリンク可能。

03 — データモデル

vault_documents + vault_links

ドキュメントレジストリ:メタデータポインタ。コンテンツはファイルシステムに保存;DBはパス、ハッシュ、埋め込みを保持。

vault_documents — スキーマ
CREATE TABLE vault_documents ( id UUID PRIMARY KEY, tenant_id UUID NOT NULL, agent_id UUID, -- nullable: team/shared docs team_id UUID, -- team scoping scope TEXT DEFAULT 'personal', -- personal | team | shared path TEXT NOT NULL, -- workspace-relative title TEXT DEFAULT '', doc_type TEXT DEFAULT 'note', content_hash TEXT DEFAULT '', -- SHA-256 summary TEXT DEFAULT '', -- LLM-generated embedding vector(1536), -- pgvector cosine tsv tsvector GENERATED ALWAYS AS ( to_tsvector('simple', coalesce(title,'') || ' ' || coalesce(path,'') || ' ' || coalesce(summary,'')) ) STORED, metadata JSONB DEFAULT '{}', UNIQUE(tenant_id, COALESCE(agent_id, nil-uuid), COALESCE(team_id, nil-uuid), scope, path) );
COALESCEトリック:nil-UUIDプレースホルダーにより、agent_idがNULLの場合に同じパスで複数のドキュメントを許可——エージェント所有権のないチームドキュメントのエッジケースを解決。

インデックス

HNSW(階層型ナビゲーション可能スモールワールド、m=16、ef=64)——意味的に類似したドキュメントを見つけるための専用ベクター検索インデックス。GIN(汎用転置インデックス)——キーワードマッチング用全文検索インデックス。

HNSW
Vector Index
GIN
FTS Index
m=16
HNSW M
ef=64
HNSW ef

vault_links

vault_links — 双方向リンク
CREATE TABLE vault_links ( id UUID PRIMARY KEY, from_doc_id UUID REFERENCES vault_documents(id) ON DELETE CASCADE, to_doc_id UUID REFERENCES vault_documents(id) ON DELETE CASCADE, link_type TEXT DEFAULT 'wikilink', context TEXT DEFAULT '', UNIQUE(from_doc_id, to_doc_id, link_type) );

7種類のリンク:wikilink[[...]]から自動)、referencedepends_onextendsrelatedsupersedescontradicts。セマンティックリンクはLLMにより分類。

04 — ウィキリンク

双方向[[リンク]]

[[target]]形式の双方向Markdownリンク——ObsidianやNotionのように。

internal/vault/links.go
var wikilinkRe = regexp.MustCompile(`\[\[([^\]|]+)(?:\|[^\]]+)?\]\]`) // [[path/to/file.md]] → path-based // [[name|display text]] → display text ignored // Context: ~25 chars before + after

解決戦略

Exact pathGetDocument(tenantID, agentID, target)
Path + .md — Retry with .md suffix
Basename search — Indexed column path_basename
Basename + .md — Last resort. Unresolved = nil

同期戦略

SyncDocLinks()——置換戦略:[[...]]を抽出 → 古い送信ウィキリンクを削除 → ターゲットを解決 → 新規一括作成。セマンティックリンク(LLM分類)は影響を受けない。

05 — ハイブリッド検索

FTS + ベクター + クロスストアファンアウト

なぜ「ハイブリッド」が必要?

エージェントが「ユーザー認証」を検索する場合:FTSは正確なキーワードを見つけるが異なる用語(「ログインフロー」)を使うドキュメントを見逃す。ベクター検索は意味の同等性を理解するが、緩く関連する結果を返すことがある。組み合わせ:FTSは精度、ベクターは再現率。

ステップ1:Vault内のFTS + ベクター

FTS — キーワードマッチ(ts_rank)
SELECT ..., ts_rank(tsv, plainto_tsquery('simple', $1)) AS score FROM vault_documents WHERE tenant_id = $2 AND tsv @@ plainto_tsquery('simple', $1) ORDER BY score DESC LIMIT $N
ベクター — セマンティックマッチ(pgvector cosine)
SELECT ..., 1 - (embedding <=> $1) AS score FROM vault_documents WHERE tenant_id = $2 AND embedding IS NOT NULL ORDER BY embedding <=> $1 LIMIT $N -- Score = 1 - cosine_distance (1.0 = identical)
マージ:FTS 0.4、ベクター 0.6。最大スコアで正規化 → 加重合計。両方にあるドキュメント → スコア加算。

ステップ2:3ソース間のファンアウト

VaultSearchService.Search() — 並列ファンアウト
VaultStore
0.4
FTS + Vector
EpisodicStore
0.3
会話履歴
KGStore
0.3
ナレッジグラフ
Normalize (max=1.0)
IDで重複除外
加重降順ソート
Top N

グレースフルデグラデーション:ストアがnil → スキップ。

オーバーシューティング:各ストアがmaxResults*2を返す。

チームコンテキスト:RunContextから——スプーフィング防止。

06 — 豊富な処理パイプライン

5フェーズ非同期ワーカー

ドキュメントが書き込まれても、検索-readyではない。EnrichWorkerが5フェーズを通じて処理し、検索可能にする。

P0Prepare
P1Summarize
P2Embed
P3Classify
P4Wikilinks
Phase 0: Prepare

重複チェック(docID + ハッシュ)→ メタデータ一括取得 → ファイル読み込み(最大4MB)→ すでに要約済みのドキュメントをフィルタ。

Phase 1: Batch Summarize

5ドキュメントを1つのLLM呼び出しにパック。温度0.2、最大1536トークン。JSON出力:[{"idx":1,"summary":"..."}]LLM呼び出しを5倍削減。

Phase 2: Embed

タイトル + パス + 要約を結合 → 1536次元埋め込みベクター。テキストを意味空間の座標に変換。

Phase 3: Classify Links

FindSimilarDocs(コサイン ≥ 0.7)→ LLMが6種類のリンクタイプに分類。温度0.1。意味のある関係がない場合はSKIPを出力。

Phase 4: Wikilink Sync

[[...]]を抽出 → ターゲットを解決 → 古いウィキリンクを削除 → 新規一括作成。重複除外マップは10Kエントリに制限、25%をエビクト。

チューニング定数

5
Batch Size
3
Max Concurrent
3k
Runes/File
0.7
Cosine Min

リトライ:段階的タイムアウト5→7→10分、バックオフ0→2→4秒BatchQueue:テナント:エージェントごとのロックフリーproducer-consumer——再スキャン時のサウンディングハードを防止。

07 — ファイルシステム同期&安全性

ワークスペースの同期と保護

エージェントがファイルを書き込むが、外部から変更される可能性がある(ユーザー編集、git pull)。Vaultには3つの同期メカニズムがある:

VaultSyncWorker

fsnotifyがワークスペースを監視。デバウンス500ms → SHA-256 → DBと比較 → 変更時にEnrichWorkerをトリガー。登録済みドキュメントのみ同期。

SafeWalkWorkspace

ワークスペース全体を walk、制限あり:5Kファイル、合計500MB、ファイルあたり50MB。シンボリックリンク、node_modules.gitをスキップ。パストラバーサルをブロック。

Lazy Hash Sync

VaultInterceptor.BeforeRead()——エージェントのファイル読み込み時に、FSハッシュとDBをチェック。ウォッチャーが実行されていなくても外部編集をキャッチ。

所有権推論

workspace/ → スコープ推論
workspace/ ├── agents/{agent_key}/... → scope="personal" ├── teams/{team_uuid}/... → scope="team" └── anything/else → scope="shared"
08 — 検索統合

エージェントコンテキストに自動注入

VaultRetrieverはエージェントが考える前に関連ドキュメントを自動的にコンテキストに注入——手動のvault_searchは不要。

RetrieverConfig
type RetrieverConfig struct { RelevanceThreshold float64 // 0.3 — 結果が低すぎるものを除外 MaxL0Items int // 5 — コンテキストサイズの制限 TenantID string }

ユーザーが「認証の設定方法」を尋ねる → vaultがdocs/auth.md(スコア0.92)+ SOUL.md(スコア0.45)を自動注入 → より正確な回答。

09 — ユースケース

実世界のアプリケーション

エージェントワークスペースの整理

エージェントがメモを書き、[[wikilinks]]で相互参照。Vaultはリンクを自動検出し、バックリンクを作成、コンテンツをインデックス。

チーム知識共有

パーソナルドキュメントはエージェントのみ表示可能。チームドキュメントは全メンバーが検索可能。パーソナルはチームドキュメントに[[link]]可能。

コンテキスト対応レスポンス

VaultRetrieverはエージェントが応答する前に関連ドキュメントを自動注入。

10 — クイックスタート

ダッシュボードを開いて、すぐに使用

Knowledge Vaultはセットアップ不要——ダッシュボードを開いてすぐに始められる。

localhost:3000/vault
Knowledge Vault Dashboard

Knowledge Vaultを開く

左サイドバー → Vault(DATAセクション)。2パネルUI:ドキュメントリスト(左)+ ナレッジグラフ可視化(右)。タイプフィルターチップ + エージェント/チームドロップダウン。

ドキュメントをアップロード

+(右上)をクリック → 「Upload to Vault」ダイアログ → 宛先を選択(共有/エージェント/チーム)→ ドラッグ&ドロップまたはファイルを選択(.md、.txt、.json、.yaml、.csvなど)→ アップロード。豊富な処理は自動実行。

ワークスペースを再スキャン(オプション)

Rescan workspaceボタン(+ボタンの隣)をクリック → ワークスペースをスキャン、新しい/変更されたファイルを検出し、スコープ(personal/team/shared)を自動推論。

探索、グラフ&検索

サイドバーでタイプ別にドキュメントを閲覧。右パネルにナレッジグラフ——パン/ズームして関係を探索。統合検索用検索バー。詳細パネルで手動リンクを作成。エージェントはvaultを自動使用。

11 — エージェントツール

vault_search

エージェントはvaultと対話するための1つのツールのみを持つ。全知識源を横断する統合検索。

ParamTypeRequired説明
querystring自然言語検索クエリ
scopestringフィルター:personal、team、shared(デフォルト:all)
typesstringカンマ区切り:context、memory、note、skill、episodic(デフォルト:all)
maxResultsnumber最大結果数(デフォルト:10)
vault_search — 例
{ "query": "authentication flow", "scope": "team", "types": "context,note", "maxResults": 10 } // User: "Find documents about authentication" // Agent → vault_search(query="authentication") // → Top 10 from vault + episodic + KG
12 — REST API

HTTPエンドポイント

Documents

MethodEndpoint機能
GET/v1/vault/documentsドキュメント一覧(フィルター:scope、doc_type、team_id)
POST/v1/vault/documents新規ドキュメント作成
GET/v1/vault/documents/{docID}ドキュメント詳細取得
PUT/v1/vault/documents/{docID}メタデータ更新
DELETE/v1/vault/documents/{docID}ドキュメント削除

Links

MethodEndpoint機能
GET.../{docID}/linksOutbound + backlinks
POST/v1/vault/linksリンク作成(from、to、type、context)
DELETE/v1/vault/links/{linkID}リンク削除
POST/v1/vault/links/batch複数のドキュメントIDのリンクを一括取得

検索と運用

MethodEndpoint機能
POST/v1/vault/searchUnified cross-store search
POST/v1/vault/uploadファイルアップロード(最大50ファイル、ファイルあたり50MB)
POST/v1/vault/rescanワークスペースを再スキャン
GET...enrichment-status豊富な処理の進行状況(JSON/SSE)

エージェント別エンドポイント:すべて/v1/agents/{agentID}/vault/...でも利用可能(後方互換)。

同時実行ガード:再スキャンはテナントごとの並列スキャンをブロック。非所有者:パーソナルドキュメント + 自身のチームのみ表示。

13 — スキーマの進化

4 migrations

Migration内容
000038Initial: vault_documents, vault_links, vault_versions
000042summaryを追加、tsvectorを再生成
000043team_idcustom_scopeを追加
000046nullable agent_id、COALESCE制約、自動スコープトリガー
マイグレーション046:エージェントが削除され、ドキュメントにチームがない場合、トリガーが自動的にscope='shared'を設定——孤立ドキュメントを防止。
14 — まとめ

ファイル参照

ComponentFile役割
Vault serviceinternal/vault/*.go検索コーディネーター、豊富な処理、ウィキリンク、FS walk
PG storeinternal/store/pg/vault_*.goハイブリッド検索(FTS + ベクター)、リンク管理
SQLite storeinternal/store/sqlitestore/vault_*.goライト版:FTSのみ
Toolsinternal/tools/vault_*.govault_searchツール、VaultInterceptorフック
HTTP handlersinternal/http/vault_*.goREST API、アップロード、再スキャン、豊富な処理の状況
Migrationsmigrations/000038-000046スキーマの進化(4回のイテレーション)

設計のトレードオフ

Search Weights

FTS 0.4、ベクター 0.6——ベクターはセマンティックを優先;FTSはキーワード精度を追加。クロスストア 0.4/0.3/0.3——Vaultのキュレーションされたコンテンツを優先。

Batch Processing

LLM呼び出しあたり5ドキュメント——スループットと品質のバランス。コサイン 0.7——本当に類似したもののみを分類、ノイズを削減。

Schema Flexibility

nullable agent_id——チームドキュメントはエージェント所有権を必要としない。置換戦略ウィキリンク用——シンプル、冪等。