純正の『次世代エンタープライズサーチ』を開けたら、検索エンジンが入っていなかった
Anthropic の knowledge-work-plugins にある enterprise-search を clone して、検索の中身を読んだ。intent 分解・並列検索・dedup・authority 階層・confidence スコアリングと、検索結果を束ねる設計はどれも秀逸だった。だが BM25 もベクトルもハイブリッド融合もリランクも、検索エンジンそのものは一行も入っていなかった。全部 MCP の向こう側に委ねられていた。
このシリーズでは、Anthropic の業種特化エージェント製品を clone して基盤開発者の目で読んできた。トポロジー(cookbook の5分類)、セキュリティ(権限と継ぎ目)、スキルのライフサイクル。今回は、自分の基盤の核に一番近いものを開ける——検索だ。
knowledge-work-plugins には enterprise-search というプラグインがある。「自然言語の質問を、社内の全ソースを横断する並列検索に変える次世代サーチ」を謳う。RAG とハイブリッド検索を自前で組んでいる身としては、純正がどう実装したのかを真っ先に見たかった。
結論から書く。検索エンジンは入っていなかった。
判定——検索の「上の層」だけがあって、エンジンが無い
3つの検索・データ系プラグインを開けて、こう判定した。
| プラグイン | 判定 | 中身 |
|---|---|---|
| enterprise-search | 設計は秀逸/実装は MCP 依存 | クエリ分解・並列検索・dedup・ランキング・synthesis の手順は充実。BM25・ベクトル・ハイブリッド融合・リランクの実装はゼロ |
| data | 検証・スキーマ発見は厚い/ingest は薄い | validate-data の QA チェックリストは優秀。PDF/CSV→構造化の ETL 実装は無し |
| pdf-viewer | ビューアのみ | テキスト抽出すら自分ではやらない |
順に、何が入っていて何が入っていないかを見ていく。
enterprise-search に「入っていたもの」——検索結果を束ねる設計
enterprise-search/skills/ を開けると、検索の知性が4つのスキルに分かれていた。これらの設計は、素直に盗める。
1. intent でクエリを7分類して、ソース優先度を変える
search-strategy/SKILL.md は、自然言語の質問をまず7つの intent に分類する。
| intent | 例 | 戦略 |
|---|---|---|
| Decision | "What did we decide about X?" | 会話(chat / email)を優先、結論シグナルを探す |
| Status | "What's the status of Project Y?" | 直近の活動・タスクトラッカーを優先 |
| Document | "Where's the spec for Z?" | Drive・wiki・共有ドキュメントを優先 |
| Person | "Who's working on X?" | タスク割当・発言者・共同編集者を探す |
| Factual | "What's our policy on X?" | wiki・公式ドキュメント、次いで確認用の会話 |
| Temporal | "When did X happen?" | 広い日付レンジ、タイムスタンプを探す |
| Exploratory | "What do we know about X?" | 全ソースを広く、synthesize する |
質問の「型」によって、どのソースを信用するかが変わる。これは検索の前段(query understanding)の良い設計だ。
2. クエリ型ごとに重みの変わるランキング
search-strategy/SKILL.md の Relevance Scoring には、こんな表が直書きされている。
| Factor | Decision | Status | Document | Factual |
|---|---|---|---|---|
| Keyword | … | … | … | … |
| Freshness | 0.3 | 0.4 | 0.2 | 0.1 |
| Authority | 0.2 | 0.1 | 0.3 | 0.4 |
status の質問なら freshness を重く、factual なら authority を重く。スコアの重みを query type で動かすという発想だ。ベクトル類似度とキーワードスコアを単純加算せず、質問の性質で配合を変える——RAG のランキングを組むときに効く設計思想がここにある。
ただし注意。これは表であって、式ではない。重みを使って実際に並べ替えるコードは無い。LLM がこの表を読んで、頭の中で重み付けする。
3. authority hierarchy と confidence スコアリング
knowledge-synthesis/SKILL.md が「最後の1マイル」を担う。複数ソースの生結果を、信頼できる1つの答えに束ねる。
authority の階層は質問型ごとに定義される。
factual/policy 質問: Wiki/公式doc > 共有doc > Email告知 > Chat
status 質問: タスクトラッカー > 直近chat > statusドキュメント > Email
そして confidence を freshness × authority × ソース合致度 で表現する。
When confidence is high (multiple fresh, authoritative sources agree) ... When confidence is low (old data, informal source, or conflicting signals) ...
新しくて権威があって複数ソースが一致するなら高信頼、古くて非公式で食い違うなら低信頼。検索結果に信頼度のラベルを付けて返す設計だ。
4. 並列実行と dedup を含む synthesis ワークフロー
並列実行は明確に命じられている。
Always execute searches across sources in parallel, never sequentially. The total search time should be roughly equal to the slowest single source, not the sum of all sources.
そして synthesis 全体はこの流れになる。
intent 分解 → ソース別翻訳 → 並列検索 → dedup → rank → confidence → 整形。検索エンジンの周りを固める設計としては、よく出来ている。
enterprise-search に「入っていなかったもの」——検索エンジン本体
では、その並列検索の各ソースは、どう検索しているのか。search/SKILL.md を見ると、こう書いてある。
Use available search and read tools for your chat platform Use available email search tools Use available file search tools
「使えるツールを使え」。 それだけだ。.mcp.json には Slack / Notion / Guru / Atlassian / Asana / MS365 / Gmail——8つの MCP サーバーの URL が並んでいて、enterprise-search 自身がやるのは、これらの search ツールを呼んで結果を受け取ることまで。
つまり、検索の実体は MCP の向こう側にある。プラグインの中には:
- 埋め込み(embedding)が無い — どのモデルでベクトル化するか、という話が出てこない
- BM25 が無い — キーワード検索のスコアリングは各ソース任せ
- ハイブリッド融合が無い — BM25 とベクトルのスコアをどう正規化して混ぜるか、という肝心の部分が空白
- リランクが無い — cross-encoder で並べ直す層が無い
- チャンキングが無い — 長文をどう分割して入れるか、の知見が無い
さっきの「重みの表」も「confidence スコアリング」も、検索エンジンが返したスコアを前提に、その上で束ねる設計だった。肝心の「検索エンジンがどうスコアを出すか」は、まるごと MCP に委ねられている。
data と pdf-viewer も同じ構図だった
data プラグインは、validate-data の QA チェックリスト(join explosion、survivorship bias、average of averages……データ分析の落とし穴集)が見事だ。だが ingest——PDF や CSV や非構造データを構造化形式に変える ETL——の実装は薄く、data-context-extractor も「スキーマを discovery する手順」止まり。実データの取得は BigQuery / Snowflake などの MCP 経由の SQL に委ねられている。
pdf-viewer に至っては、description にこう書いてある。
Not for summarization or text extraction (use native Read instead).
要約もテキスト抽出も「native Read を使え」。このプラグインは注釈・フォーム入力・署名配置のためのビューアであって、文書から中身を取り出す ingest は守備範囲外だと明言している。OCR も table 抽出も無い。
なぜこの分業なのか——そして基盤開発者への含意
これは批判ではない。むしろ正しい設計判断だと思う。Slack の検索は Slack が、Notion の検索は Notion が一番うまくやる。各 SaaS が持つ検索 API を MCP で叩き、純正はその上で結果を束ねる層に集中した。車輪を再発明していない。
だが基盤を作る側にとって、ここははっきりした分割線になる。
- 盗めるのは「検索エンジンの上の層」 — intent によるクエリ分解、ソース別のクエリ翻訳、並列実行、クロスソース dedup、authority hierarchy、confidence スコアリング、synthesis ワークフロー。これらは純正の設計をそのまま土台にできる。
- 自作が要るのは「検索エンジンそのもの」 — 埋め込み、ベクトル検索、BM25、両者のスコア融合、リランク、チャンキング、そして文書を取り込む ingest → extract のパイプライン。純正のどこにも実装は無い。
「次世代エンタープライズサーチ」を期待して開けると、肩透かしを食う。だが裏を返せば、検索の難しいところ——ハイブリッド融合と ingest——は、お手本にすら実装が無い空白地帯だということだ。純正が用意したオーケストレーション層を土台に、その下に本物の検索エンジンを敷く。そこが、ただの SaaS 連携ツールと、資料をまとめて持ってくる基盤との分かれ目になる。
検索結果を賢く束ねる作法は、純正から学べる。検索そのものは、まだ自分で書くしかない。