【AIエージェントの解剖学:第4回】ワーキングメモリの科学:Prompt & Context Engineeringの限界突破
【新連載:AIエージェントの解剖学】
※本連載は、何も話せない空っぽの「チャットボット」の前に立ち、彼に命を吹き込みながら、自分の意志で動く「AIエージェント」へとパーツごとに作り上げていく開発ドキュメンタリーです。
1. プロローグ:次のパーツ「情報の洪水から視界を絞るフォーカスレンズ」
前回、私たちはロボットの肩に、あらゆる外部のデータベースやAPIと一撃で接続できる共通ソケット「MCP(Model Context Protocol)」を取り付けました。
これにより、彼はインターネットの向こう側にある無限の情報へアクセスできる広大な「手足」を手に入れました。
しかし、大量のツール定義や検索されたデータを、彼の脳の作業領域である「コンテキストウィンドウ(ワーキングメモリ)」へ無制限に流し込んだ結果、予期せぬ副作用が起きてしまいました。
彼は「情報のノイズ」に圧倒され、最も重要な基本命令や、本来目指すべきゴールを見失ってしまい、指示を無視して暴走し始めたのです。
今回は、限られた脳の作業スペースを効率的に管理し、膨大な情報から必要な指示だけに焦点を絞り込む集中力コントロールモジュール、「Prompt & Context Engineering」のフィルタレンズを彼のセンサー部に装着します。
ノイズを遮断し、視界をクリアにしましょう。
2. システムプロンプト:エージェントにおける「基本憲法」
対話型のAIを使う際、「あなたはプロのエンジニアです」といった簡易的な指示(ペルソナ)を与えることがあります。
しかし、自律的に動く「AIエージェント」におけるシステムプロンプトは、単なるキャラクター付けではありません。それは、そのエージェントが破ってはならない「基本憲法(行動規範)」です。
【エージェント用システムプロンプトの主な記述内容】
1. 役割と目的(例: 「あなたはGitリポジトリを修正するエージェントです」)
2. 使用可能なツールの一覧と、それらを呼び出す厳密なトリガー条件
3. 出力フォーマットの絶対的な制約(例: 「JSON以外は1文字も出力してはならない」)
4. エラー発生時や、答えが見つからない場合の例外処理ルート
このシステムプロンプトという「憲法」が、大量に読み込まれた外部データ(検索ログやAPIレスポンス)の中に埋もれてしまうと、エージェントは自分のルールを忘れ、「普通のチャットボット」に戻って世間話を始めてしまったり、指示とは異なる形式で出力するなどの暴走を引き起こします。
3. 脳の科学的トラップ:「Lost in the Middle(情報の埋もれ)」
近年のLLMは、数万〜数十万トークンという超長大なコンテキストを受け入れられるようになりました。
しかし、言語モデルの注意(Attention)メカニズムには、人間の認知に非常によく似た重大な弱点があります。それが「Lost in the Middle(情報の埋もれ)」現象です。

※図:コンテキストの最初と最後でRecall率(指示の記憶率)が高く、中間部分で極端に低下するLost in the Middle現象(AI生成ダイアグラム)
多くの実験により、LLMは「コンテキストの最初(ヘッド)と最後(テール)に書かれた情報は極めてよく記憶し再現できるが、中間の長いテキストの間に置かれた指示やデータは、見落とし確率が劇的に跳ね上がる(U字型の曲線を描く)」ことがわかっています。
RAG(外部検索結果)のテキストや、巨大なツールの実行結果をそのままプロンプトの「真ん中」へ無計画に挿入すると、LLMの集中力はどん底まで低下し、必要なデータや指示を見失ってしまうのです。
4. 解決策:コンテキストの「構造化」と「圧縮」
このLost in the Middleを回避するため、エージェント開発者は以下のプロンプト配置エンジニアリング(Context Engineering)を徹底する必要があります。
-
重要な指示は「末尾」に再配置する:
システムプロンプトなどの最重要指示は、プロンプトの最初だけでなく、すべてのデータを並べた後の「最も最後(末尾)」に、ダメ押しとしてもう一度補強配置します。 -
データのフィルタリング(コンテキスト圧縮):
ツールから返ってきた長いJSONレスポンスなどをそのまま流し込まず、プログラム側で「本当に必要なキーの値」だけを抜き出して文字数を10分の1以下に圧縮してからLLMに渡します。
5. 【体験】プロンプト最適化フィルターを動かそう
渡された長いツールデータからノイズを削り、最優先のシステム指示を自動的に「末尾」に再構成する、手元で動くPythonのプロンプト最適化フィルターです。
手元の環境で実行してみてください。
import json
# ツールから返ってきた「ノイズの多い巨大なJSONデータ」(ダミー)
raw_api_response = {
"status": "success",
"meta_data": {"api_version": "v3.2", "server_id": "srv-992", "response_time_ms": 142},
"items": [
{"id": 1, "name": "Tokyo", "weather": "Sunny", "humidity": 45},
{"id": 2, "name": "Osaka", "weather": "Rainy", "humidity": 80}
]
}
# 1. コンテキストの圧縮処理
# 不要なmeta_dataなどを削り、必要な情報だけを抽出する
def compress_context(raw_data: dict) -> str:
cleaned_items = []
for item in raw_data.get("items", []):
cleaned_items.append(f"{item['name']}: {item['weather']}")
return ", ".join(cleaned_items)
# 2. プロンプトの再構成(Lost in the Middle対策)
def build_optimized_prompt(user_query: str, raw_data: dict) -> str:
# 最重要指示(システムプロンプト)
system_instruction = "【重要ルール】回答は必ず日本語で、天気マーク(晴れ☀️ / 雨☔)をつけて短く出力してください。"
# データを圧縮
compact_data = compress_context(raw_data)
# 悪い例: データの後にシステム指示を置き、最後にユーザー質問を置く(埋もれやすい)
# 良い例: データ(ノイズ)を中央に挟み、最重要指示を「末尾(End)」に補強する
optimized_prompt = f"""
[System Role]: あなたはお天気アシスタントです。
[Context Data]: {compact_data}
[User Query]: {user_query}
{system_instruction}
"""
return optimized_prompt.strip()
# 実行
final_prompt = build_optimized_prompt("東京と大阪の天気を要約して", raw_api_response)
print("📝 最適化されてLLMに送られる最終プロンプト:\n")
print(final_prompt)
このコードを実行すると、余計なメタデータがカットされ、かつ最重要の行動制約ルール(天気マークの付与など)が全体の最下部に配置され、LLMが最も高い集中力(Attention)を保った状態で処理できる状態に変換される流れが分かります。
6. エピローグ:研ぎ澄まされた集中力

※画像:ロボットの入力センサーに、膨大な文字のノイズから重要指示だけを浮かび上がらせるフォーカスレンズを取り付けるイメージ(AI生成画像)
これで、ロボットに「Prompt & Context Engineering」のレンズが取り付けられ、情報のノイズをシャットアウトして目的のデータ一点に焦点を絞る「集中力」が実装されました。
しかし、いくら賢く情報を処理できるようになっても、AIエージェントにはもう一つ、致命的な「死の脆弱性」があります。
もし、呼び出したツールや、AI自身が生成して動かしたPythonプログラムに「無限ループ(永久に終わらないバグ)」が含まれていた場合、エージェント全体のプログラムが永遠にフリーズし、サーバーのCPUを食いつぶして暴走し続けてしまいます。
次回、第5回。
実行時の予期せぬ暴走やハングアップを強制的に検知・遮断し、安全な牢獄の中でコードを実行させる防壁、「Loop Controlと安全なコード実行サンドボックス」の安全弁を彼に装着します。
知能が、絶対的な「安全性」の盾を手に入れる瞬間へと進みましょう。