2026年10月24日、LangChainが「Context Engineering for AI Agents Starts with Retrieval」と題した記事を公開した。LLMの普及とともにエージェント活用が広がる一方、「コンテキストウィンドウに何を入れるか」という設計上の問題が実運用の壁として浮上している。本記事はその核心に踏み込み、検索(Retrieval)を起点としたコンテキスト設計の具体的な手法を体系的に解説している。
なぜ今、エージェントの「検索設計」が問われるのか
LLMの文脈長は年々拡大しているが、コンテキストウィンドウが広がれば問題が解決するわけではない。コンテキストに無関係な情報が混入すれば精度は落ち、大量の情報を詰め込めばレイテンシとトークンコストが跳ね上がる。LangChainをはじめ、LlamaIndexやAutoGenなど主要なエージェントフレームワークが「何をどう検索してコンテキストに渡すか」を設計の中核に置くようになっているのはこのためだ。
エージェントは人間と同様、すべての情報を記憶しているわけではない。タスクに応じて情報を検索(Retrieve)して取り込む必要があるが、そこには3つの構造的な問題がある。
- 非効率な検索:1回の検索ごとにトークンと時間を消費する。ファイルを片っ端から開いたり、同じクエリを言い換え続けたりすると、有用な情報にたどり着く前にコンテキストウィンドウが埋まる。
- 一度に入りすぎる情報:1回の検索で大量のドキュメントを取得すると、それだけでコンテキストが満杯になり、本来の作業スペースがなくなる。
- 無関係・古い情報の混入:モデルにとって、正しい情報も間違った情報も見た目は同じように「もっともらしい」。誤情報が一度コンテキストに入ると、その後のすべてのステップに影響する。
記事ではこれらの問題を、競合分析エージェント(毎週月曜日に数百社の競合を調査してレポートを書く)という具体例を使って解説している。
問題1:非効率な検索をどう防ぐか
まずファイル名とキーワードで絞る
エージェントがファイルシステムを検索する際、ファイルを片っ端から開くのは最悪のパターンだ。開くたびにコンテキストウィンドウを消費する。
賢いアプローチは、本の索引をスキャンするように名前とキーワードで先に絞り込むこと。LangChainのDeep Agentsハーネスには以下のツールが標準で搭載されている。
- **
glob**:ファイル名パターンで検索(例:**/company-a*.md) - **
grep**:ファイルを読み込まずに内容を検索し、マッチした行だけを返す
キーワードで足りなければセマンティック検索を追加する
grepは完全一致しか探せない。「Company A funding」で検索しても「Company A closes $50M Series B」というタイトルの記事はヒットしない。意味で検索したい場合は、ベクトルストアをバックエンドに持つリトリーバルツールを追加する。
リトリーバルツールのデータソースはベクトルストアに限らず、SQLデータベース、検索API、MCPサーバーなど様々な選択肢がある。
検索タイミングはエージェント自身に判断させる
従来のRAG(Retrieval-Augmented Generation)は「最初に1回検索してから回答」という2ステップ構造が多い。しかし調査型エージェントでは、途中で予期しない情報が見つかり、追加検索が必要になるケースが頻繁に起きる。
Deep Agentsではデフォルトで**Agentic RAG**(エージェントがループの中で必要に応じて何度でも検索を呼び出す方式)が採用されている。
検索ノウハウを「スキル」としてパッケージ化する
どのインデックスを使うか、クエリをどう書くか、引用をどうフォーマットするか——こうした検索ノウハウはスキルとして定義できる。スキルはタスクが要求するときだけロードされる(プログレッシブディスクロージャーと呼ばれる手法)ため、不要な時にコンテキストを圧迫しない。
問題2:一度に入りすぎる情報をどう制御するか
正しい検索をしても、返ってくるデータが大きすぎることがある。40,000行の市場データから1つの数字を探す場合、全行を読み込むのは論外だ。
大きなファイルはページ単位で読む
read_fileはデフォルトで100行ずつしか読まない。offset(開始行)とlimit(行数)を指定することで、必要な箇所だけにジャンプできる。まずgrepでマッチ箇所を特定し、その周辺だけをread_fileで読む、というパターンが効率的だ。
ハーネスが大きすぎる結果を自動オフロードする
ツールの返り値が約20,000トークンを超える場合、Deep Agentsハーネスは自動的にその内容を/large_tool_results/配下のファイルに保存し、エージェントにはパスと短いプレビューだけを渡す。エージェントはその後、必要な部分だけをread_fileで読み返せる。
リトリーバルツール自体にファイルパスを返させる
この考え方を自作のリトリーバルツールにも適用できる。検索結果をファイルに書き出し、パスだけを返すようにする。記事では以下のような実装例が紹介されている(「retrieve, offload, delegate」パターンの最初のステップ)。
backend = StateBackend()
@tool
def search_news(query: str) -> str:
"""Search the news archive and save each result to a file."""
docs = vector_store.similarity_search(query, k=4)
files = [(f"/retrieved/result_{i}.md", doc.page_content.encode()) for i, doc in enumerate(docs)]
backend.upload_files(files)
return "Saved results to: " + ", ".join(path for path, _ in files)
これにより、メインエージェントは4本の記事全文ではなく、4つの短いパスだけを受け取る。
問題3:無関係・古い情報の混入をどう防ぐか
サブエージェントにフィルタリングを任せる
パスを受け取ったメインエージェントが自分でファイルを読もうとすると、無関係なファイルを開いた時点でそれがコンテキストに入ってしまう。ここで「retrieve, offload, delegate」パターンの核心が登場する。
サブエージェントに各ファイルを読ませ、重要な事実だけを要約して返させる。
chunk_analyst = {
"name": "chunk-analyst",
"description": "Analyze one retrieved file. Pass the question and a single path under /retrieved/.",
"system_prompt": "Use read_file to read the assigned file. Return the key facts and the source URL.",
}
agent = create_deep_agent(
model=model,
tools=[search_news],
backend=backend,
subagents=[chunk_analyst],
)
フローはこうなる:
- Search:メインエージェントが
search_newsを呼び出し、4つのパスを受け取る - Delegate:各パスをchunk-analystサブエージェントに送る(並列実行可能)
- Synthesize:各サブエージェントが要約と出典URLを返す。メインエージェントはそれらを統合し、必要なら追加検索する
無関係なコンテンツはサブエージェントのコンテキストウィンドウの中で完結し、メインエージェントのコンテキストは結論だけで埋まる。
新鮮なデータソースを使う
フィルタリングで無関係な情報は排除できても、古い情報は「関連あり・ただし古い」として通過してしまう。検索APIやMCPサーバーを使ってリアルタイムの情報を取得するか、データに日付フィールドがあれば日付フィルタリングをリトリーバルツール内に組み込む。
プロンプトインジェクションへの注意
取得したテキストはデータであって命令ではないが、悪意あるコンテンツがプロンプトインジェクションを含む可能性がある。出力の検証(回答が期待するソースを引用しているか、内容がソースと一致しているか)は必ず行うべきだ。
まとめ:ハーネス設計で押さえるべき原則
記事の末尾では、ハーネスに依存しない汎用的な原則としてまとめられている。
- 使えるツールの中で最も効率的なものを選ぶ:キーワードが分かるなら
grep、意味で探すならセマンティック検索。 - ページ単位で読む:大きなファイルを一度に全部読まない。
- ペイロードではなくポインタを返す:取得した内容はファイルに書き出し、パスだけを渡す。
- 読む作業をサブエージェントに委ねる:メインエージェントは結論だけを受け取る。
- グラウンディングを検証する:回答がソースと一致しているか確認する。
これらの原則は、LangChainのDeep Agentsに限らず、エージェント設計全般に適用できる考え方だ。「コンテキストウィンドウに何を入れないか」を意識的に設計することが、エージェントの精度と効率を左右する。エージェント開発に取り組む実務者にとって、具体的な実装パターンと設計思想の両面で参考になる内容となっている。
※編集部の考察:コンテキスト設計の問題は、モデルの性能向上だけでは解決しない構造的な課題だ。本記事が提示する「委譲と圧縮」のアーキテクチャは、モデルの能力に依存しすぎず、エンジニアリングで制御可能な範囲を最大化しようとする実践的なアプローチといえる。
詳細はContext Engineering for AI Agents Starts with Retrievalを参照していただきたい。