「さっきまで賢かったのに」と感じたことはないか
AIエージェントを使っていると、こんな経験をしたことはないでしょうか。
- 最初は的確に動いていたのに、 30分も作業させると頓珍漢な変更を提案しはじめる
- 一度間違えた前提を、こちらが訂正してもなぜか引きずり続ける
- ツールがたくさん使えるはずなのに、肝心な場面で違うツールを呼んでしまう
「モデルが悪い」「運が悪い」で片付けられがちですが、 2025〜2026年にかけて、本当の原因はエージェントのコンテキスト (短期記憶) の壊れ方にあるとわかってきました。 この現象を context suicide (コンテキスト自殺) と名付けたのが StackOne、壊れ方を 4 種類に分類したのが Drew Breunig 氏です。
参考情報
- StackOne: AIエージェント向けの統合プラットフォームを提供する企業 (17,000+ アクション・ 270+ コネクタを SaaS 連携用に提供)。 多数のコネクタを実装する中で context window が破綻する現象を日常的に目にしており、 CTO の Guillaume Lebedel 氏が現場の知見をブログにまとめている
- Drew Breunig氏: AI / データ系の独立した執筆者。 LLM のコンテキスト失敗モードを、学術論文や各社レポートから横断的に整理した解説記事を書いている
この記事では、まずコンテキストとは何かを押さえ、どんな壊れ方をするのか、どう防げるのかを順に見ていきます。
そもそもコンテキストとはなにか
LLM には、 1 回の応答で読み込める文章の長さに上限があります。 これを コンテキストウィンドウ といい、ざっくり言えば AI の短期記憶のサイズです。 2026 年 5 月時点で、主要モデルはおおむね 1M トークン (長編小説 6〜8 冊分) まで広がっています。
| モデル | コンテキストウィンドウ |
|---|---|
| Claude Opus 4.7 / Sonnet 4.6 | 1Mトークン |
| Claude Haiku 4.5 | 200Kトークン |
| GPT-5.5 / GPT-5.5 Pro | 1Mトークン |
| Gemini 3 Pro / Gemini 3.1 Pro | 1Mトークン |
| Gemini 3 Flash | 200Kトークン |
「1M あれば余裕でしょ」と思いがちですが、ここが落とし穴です。 コンテキストは広いほど詰め込みやすくなり、 10 万トークンを超えたあたりから精度が落ち始める、という研究報告もあります。 「広い = 安全」ではなく、広いからこそ油断すると壊れる、と思って読み進めてください。
セッションを起動した瞬間、ユーザーが何も打つ前から、すでに以下のものが短期記憶に乗っています。
| 詰め込まれるもの | 具体例(2026年版) | 主な発生源 |
|---|---|---|
| システムプロンプト | 「あなたはClaude Codeです…」のようなエージェント本体の役割定義 | エージェント本体 |
| プロジェクト指示書 | リポジトリ直下の CLAUDE.md (Claude Code) / AGENTS.md (Cursor・Codex等)。 親ディレクトリの CLAUDE.md も連結して全部ロードされる |
./CLAUDE.md、 ./AGENTS.md
|
| 個人指示書 |
~/.claude/CLAUDE.md (全プロジェクト共通)、 ./CLAUDE.local.md (gitignoreされた個人用) |
ホームディレクトリ |
| Auto memory (MEMORY.md) | Claude Code v2.1.59+で、エージェント自身がユーザーの好み・過去のミスを学習して書き溜めるメモ。 **MEMORY.md の先頭200行(または25KB)**が毎セッション自動注入される |
~/.claude/projects/<project>/memory/ |
| Path-scoped rules |
.claude/rules/*.md のフロントマターに paths: ["src/api/**/*.ts"] のように書かれたルール。 該当ファイルを開いたときだけ注入される |
.claude/rules/ |
| Skillのメタ情報 |
~/.claude/skills/<name>/SKILL.md のフロントマター(description / when_to_use 等)が常時リスト化されてcontextに乗る。 SKILL.md本体は呼び出し時のみ展開(progressive disclosure) |
.claude/skills/、 ~/.claude/skills/
|
| Subagentの定義 |
.claude/agents/*.md に書いた description / tools / model などが、 delegate判断のためにメイン側に居る |
.claude/agents/ |
| MCPサーバーのツール定義 | 有効化中のMCPサーバーが提供する全ツールのJSONスキーマ。 1サーバーで数千ツール露出することもある(例: GitHub MCP、 Linear MCP、 Slack MCP) |
mcp_servers 設定 |
| 会話履歴 | これまでのユーザー入力+アシスタント応答すべて | セッション中に蓄積 |
| ツール実行結果 |
Read で読んだファイル全文、 Bash の標準出力、 Grep のヒット行など |
ツール呼び出しごと |
| RAG /添付ドキュメント | Cursorの @Docs 参照、添付ファイル、ベクトル検索の結果 |
RAGパイプライン |
Skill / Subagent / MCP のフロントマターは「呼び出していないときも全部読み込まれる」
SKILL.md のフロントマター (description)、 Subagent の description、 MCP のツールスキーマは、いずれも常時コンテキストに居座ります。 登録数が増えれば起動時の消費が線形に膨らむので、後で出てくる「ツール定義の肥大」 (パターン 2) の主因はここです。
エージェントは、毎ターンこの「全部入りの短期記憶」を読み直して次の行動を決めます。 ここに余計な情報や誤った情報が混ざると、それ以降の判断がずっと引きずられる、という仕組みです。
「コンテキスト自殺」というのはこういう現象
context suicide は、エージェント自身の行動でコンテキストが汚れ、自分の判断を狂わせてしまう現象です。 外部からの攻撃ではなく、エージェントが普通に仕事をしているだけで自然に起きてしまいます。 StackOne の記事は、この本質を一文で言い切っています。
Tool call looks reasonable. The 150K response is fatal.
(ツール呼び出しは合理的に見える。しかし 150K の応答が致命傷になる)
クラッシュも例外も出ず、エージェント自身に自覚もなく、 1 ステップずつ見れば全部「合理的な判断」。 だから内側からは止められません。
リファクタ依頼が3分で詰むまでの流れ
Claude Code に「UserService を整理してリファクタして」と頼んだとき、何が起きるかを時系列で追ってみます。
| 時刻 | エージェントの行動 | 消費 |
|---|---|---|
| 0:00 | セッション開始。 CLAUDE.md / Skill / MCP のツール定義で すでに 30K 消費
|
30K |
| 1:00 |
UserService.ts と依存ファイル、テストを連続で読み込む |
70K |
| 1:30 | 推測で「findByEmail() があるはずだ」と仮定して案を書き始める ← 自己汚染
|
80K |
| 2:30 | 「findByEmail が存在しない…?」と気づくが、架空メソッド前提の計画は履歴に居座ったまま |
140K |
| 3:00 | 再調査でさらにファイルを読み込み、最初の指示が履歴の彼方に ← 散漫 | 170K / 200K |
ひとつひとつは「次の行動として最も自然な判断」なのに、 3 分後にはコンテキストの 8 割以上が中間調査と架空メソッド前提で埋まり、最初の指示はもうほぼ霞んでいます。 残り 30K で完了させようとして雑な変更が混ざり始める、というのが典型的な詰み方です。
悪意も外乱もなく、放っておくと勝手にこうなるのがコンテキスト自殺の特徴です。 だからこそ、エージェント任せにせず、外側から先回りして防ぐ必要があります。
壊れ方を4種類に分けてみる (Drew Breunigの分類)
Drew Breunig 氏が 2025 年に整理した 4 つの失敗モードを使うと、壊れ方を俯瞰しやすくなります。
1. Context Poisoning (コンテキスト汚染) — 嘘がじわじわ広がる
誤った情報がコンテキストに紛れ込み、正しいかのように繰り返し参照される状態です。 DeepMind の Gemini 2.5 テクニカルレポートには、エージェントにポケモンをプレイさせたら「目標」欄に架空の達成条件が書き込まれてしまい、何時間も達成不能なゴールを追い続けた事例が紹介されています。 一度入った誤情報は参照と上書きを重ねて複雑化していき、後からどこが間違いだったかを切り分けるのは非常に難しくなります。
身近な例: 「
UserService.findByEmail()があるはずだ」と推測で書くと、その後のコード生成が架空のメソッドを前提に進み、テストもその前提で書かれてしまう。
2. Context Distraction (コンテキスト散漫) — 履歴に引きずられる
コンテキストが長くなりすぎて、モデルが訓練知識より直近の履歴に過剰適応してしまう状態です。 Databricks の研究では、 Llama 3.1 405B は 32K トークンあたりから精度が落ち始め、 100K を超えると「過去の行動パターンの繰り返し」に陥る、と報告されています。 履歴に引っ張られて、新しい戦略を試せなくなる、ということです。
身近な例: 会話が長くなるほど最初のルールが薄れる、同じ修正をループする、新しい解決策が出てこなくなる。
3. Context Confusion (コンテキスト混乱) — ツールが多いほど迷う
ツール定義が多すぎてモデルが混乱する状態です。 UC Berkeley の Function-Calling Leaderboard では「すべてのモデルが、ツールが 1 つでも増えると性能低下する」ことが確認されています。 量子化版の Llama 3.1 8B は、 46 個のツール定義つきだと失敗するクエリが 19 個に絞ると成功した、という報告もあります (どちらも 16K トークン以内)。 経験則としては 30 ツールあたりから精度が落ち始め、 100 ツールを超えるとほぼ機能しなくなると言われています。
身近な例: MCP サーバーを片端から有効化していると、似た名前のツールを取り違えたり、無関係なツールを呼び始めたりする。
4. Context Clash (コンテキスト衝突) — 途中の間違いが尾を引く
後から積まれた情報が、最初の指示と矛盾して挙動が崩れる状態です。 Microsoft / Salesforce の「Lost in Conversation」研究では、同じ情報を複数ターンに分けて渡すと平均 39% の性能低下が観察され、 OpenAI の o3 でもベンチマークが 98.1 → 64.1 まで落ちています。 序盤に情報不足で下した「仮の間違った答え」がコンテキストに残り、後の推論を引きずる、という現象です。 論文ではこれを「いったん誤った方向に進むと、もう戻れない」と表現しています。 エージェントの運用では中間結果がそのまま積もり続けるので、特に出やすい問題です。
身近な例: 「最初の仕様」と「途中で追加した仕様」の衝突、複数の MCP が似た役割のツールを別名で提供しているとき、調査途中の仮説がそのまま実装方針として残ってしまうとき。
現場でよく見る6つの症状 (StackOneのまとめ)
Breunig の 4 分類が壊れ方の見取り図だとすると、 StackOne がまとめた 6 パターンは現場で実際に出てくる症状リストです。 4 分類のどこに対応するかも併記します。
| # | パターン名 | こんな状況で発生 | 4分類 |
|---|---|---|---|
| 1 | RAGプリロード過多 | RAGで関連ドキュメントを50件読み込んだ時点で、 20万トークンの62%が埋まっている。 ユーザーの入力前から余裕がない | Distraction |
| 2 | ツール定義の肥大 | MCPサーバーで500個以上のツールを露出。 JSONスキーマの定義だけで10万トークンを消費する | Confusion |
| 3 | 貪欲なfile read | サイズを確認せずファイルを連続で読み込む。 3ファイルのつもりが10ファイルに膨らみ、ある瞬間に上限に当たる | Distraction |
| 4 | 会話履歴の肥大 | 圧縮なしで20ターンの会話を続けると20万トークンを超える。 長時間使うコーディングエージェントで頻発する | Distraction |
| 5 | 自己汚染(poisoning) | エージェント自身が出した誤情報を、後段の自分が真として扱い、その上に間違った計画を積み上げていく | Poisoning |
| 6 | 中間結果の累積 | APIを30回呼んだ結果を保持し続けると、 1回3Kトークン × 30回で9万トークンが履歴に積もる | Distraction |
数値は2025年時点の例です。 コンテキスト長の改善とともに閾値はずれる前提で読んでください。
「量」の問題か、「正しさ」の問題か
6 つのパターンを並べてみると、大事な違いが見えてきます。
- 1, 2, 3, 4, 6 は「量」の問題: 単純に情報が多すぎる。 圧縮や絞り込みで減らせば解決する
- 5 (自己汚染) だけは「正しさ」の問題: 量を減らしても、誤情報が残っていれば同じことが起きる
ここを区別しないと、対策が空振りします。
たとえば自己汚染を「コンテキストが長いから」と要約だけで対処すると、誤情報が圧縮されて凝縮された誤った前提だけが残り、かえって悪化することがあります。
切り分けの軸はシンプルです。
量の問題はコンテキストエンジニアリング側で、正しさの問題は推論・検証側で対処する。
対策はどこに入れるか
Breunig 氏のフレームワーク (Tool Loadout / Pruning / Quarantine / Summarization) と Anthropic 公式の context engineering ベストプラクティスを突き合わせると、対策の入れどころは大きく 4 つに分けられます。
| 戦略 | 何をする | 主な手段 | 効くパターン |
|---|---|---|---|
| 量を減らす | 起動時に積まれる情報を絞る | 不要な MCP を disable / CLAUDE.md を短く保つ / Skill で progressive disclosure 化 |
1 / 2 / 3 / 6 |
| 隔離する | 重い処理をメイン履歴から切り離す | subagent で別 context に逃がす / Plan mode で計画と実装を分ける | 1 / 3 / 4 / 6 |
| 圧縮する | 蓄積した履歴を要約して短くする |
/compact で要約 / /clear で再起動 / NOTES.md に状態を逃がす |
4 / 6 |
| 正しさを担保する | 自己汚染を検証で塞ぐ | think ツールで推論を明示化 / 実装前に grep で裏取り / レビュー | 5 |
Anthropic は、タスクの形に応じて戦略を使い分けることを推奨しています。 双方向の会話が多ければ compaction、反復開発なら note-taking、並列探索なら multi-agent、といった具合です。 1 つの戦略で全部解こうとしないほうがうまくいきます。
自己汚染 (パターン 5) を「圧縮」だけで解こうとしないでください。 誤情報を要約すると、凝縮された誤った前提だけが残ります。 量を絞った後に正しさチェックを入れる、という順序が大事です。
用語ミニ辞典 — Tool Loadout / Quarantine / Compaction など
- Tool Loadout: タスクごとに、今このセッションで使うツールだけに絞り込む発想 (RPG の出撃装備のメタファー)
- Context Pruning: 古い、関連の薄い履歴を能動的に削除する
- Context Quarantine: 重い処理をサブエージェントや別スレッドに切り出し、メインの履歴を汚さない
-
Context Compaction: 長くなった履歴を要約して短くする (Claude Code の
/compactがこれ) - Note-taking / External memory: NOTES.md や TODO.md など外部ファイルに状態を逃がし、コンテキストではなくファイルで管理する
- think ツール: 計画段階の思考を明示的に書き出させ、推論の途中を見える化する Anthropic 提唱の手法
-
Progressive disclosure: Skill のように、必要なときだけ詳細を展開する仕組み (普段は短い
descriptionだけがコンテキストに居る)
普段の作業に落とし込む
ここからは Claude Code を実際に触る前提の実務編です。 設計 (起動コストを下げる) → ランブック (違和感への即応) → 運用 (定期メンテ) の順に見ていきます。
1. 設計 — スコープを意識して起動コストを下げる
エージェントは、起動した瞬間にすでに数万トークンを消費しています。 ここで意識したいのが、ユーザースコープ (~/.claude/) とプロジェクトスコープ (./.claude/) の使い分けです。 user scope に置いたものはどのプロジェクトでも毎回ロードされるので、ここが肥えると一番響きます。
判断軸はシンプルに「全プロジェクトで本当に毎日使うか?」。 Yes なら user scope、 No なら project scope。 迷ったら project scope に置く。
ユーザースコープ (~/.claude/) は絞る
-
~/.claude/CLAUDE.mdは 100 行以内に抑える (公式推奨は 200 行だが、毎回読まれる分その半分以下が安全)。 細かい好みは Auto memory に任せる -
~/.claude/skills/は毎日使う汎用 Skill だけ (コミットメッセージ作成、 PR レビュー等)。 プロジェクト固有のものは置かない -
~/.claude/agents/は基本空でよい - グローバル MCP は最小限に。 GitHub / Linear / Slack のようなプロジェクト依存の MCP を user scope に入れない。 これだけでツール定義が万単位で削れる
プロジェクトスコープ (./.claude/) に集約
-
./CLAUDE.mdは 200 行以内。 超えたら path-scoped rules (.claude/rules/*.mdのpaths) に分割する。 なお@import構文はメンテナンス性向上が目的で、 import 先も起動時に全部ロードされるためサイズ削減にはならない点に注意 - プロジェクト固有の MCP・ subagent・ Skill はそれぞれ project scope にまとめる
-
モノレポなら
claudeMdExcludesで他チームのCLAUDE.mdを除外
起動時の負荷を測る・抑える
-
ENABLE_TOOL_SEARCH=autoを設定すると、 MCP ツールスキーマが deferred load になる。 これだけで起動時の数万トークンが浮く -
起動直後に
/contextで構成を確認する習慣をつけると、「30K だった起動が 60K になっている」と気づける
2. ランブック — 違和感を覚えたら打つ手
作業中に「あれ、おかしいぞ」と感じたとき、症状ごとに最初の一手を決めておくと迷いません。
| 症状 | 該当パターン | 対応策 |
|---|---|---|
| 指示をだんだん忘れる、長文の返答が雑になる | 3 / 4 / 6 (Distraction) |
/compact で要約 → 必要なら /clear で新規セッション |
| 違うツールを使い始める、選択を間違える | 2 (Confusion) |
claude mcp list で確認 → 不要な MCP を disable → 再起動 |
| 訂正しても同じ間違いを繰り返す、架空の関数名を使う | 5 (Poisoning) |
/rewind の Conversation only モードで汚染前に巻き戻す (/clear より損失が少ない) |
| 「最初の指示と違うことをしている」 | 4 (Clash) | 仕様を 1 メッセージにまとめ直して再投入 |
| 重い調査でコンテキストが爆発しそう | 1 / 3 (Distraction) | Plan mode (Shift+Tab) または subagent で別コンテキストに逃がす |
起動直後なのに /context が埋まっている |
1 / 2 | user scope の肥大を疑い、 project scope に移す |
| 議論は続けたいが実装方針を変えたい | — |
/rewind の Code only モード |
| 別アプローチを試したいが今の流れも残したい | — |
claude --continue --fork-session で branch を作る |
3. 運用 — 仕組みに焼き付け、定期的に手入れ
毎回手で操作するのは続かないので、設定ファイルに焼き付けたうえで、月 1 回くらい棚卸しする運用にします。
仕組みに焼き付ける (subagent / Skill / Hook)
-
subagent (
.claude/agents/) — リサーチ、レビュー、重い調査を分離します。model: claude-haiku-4-5を指定すれば、安いモデルにオフロードしてコストも下げられます--- name: research description: コードベースを横断して情報を集める。 メインを汚さない model: claude-haiku-4-5 tools: Read, Grep, Glob --- リサーチ専門エージェント。 結果は3〜5行の要約で返してください。 -
Skill (
.claude/skills/) — 何度も使う手順を progressive disclosure 化します。!`<command>`記法を使えば、!`git diff HEAD`のようにシェル実行結果をその場で差し込めるので、最新の状態を CLAUDE.md に書き込んで毎回ロードする必要がなくなります -
より強い分離が必要なとき — git worktree で別ディレクトリに作業環境を切る、もしくは Agent teams で複数エージェントを別セッションで並列動作させる
-
PreToolUse hook — 1MB 超のファイル読み込みを deny するなど、暴走を構造的に止められます
月1回のPruning
設定ファイルは放っておくと膨張するので、月 1 回くらい棚卸しします。
-
~/.claude/CLAUDE.mdの古い指示やプロジェクトの名残を削る -
~/.claude/skills/の中で、 1 ヶ月以上呼んでいない Skill を削除 -
/memoryでMEMORY.mdを整理する (先頭 200 行が毎セッション注入されるので、古い学習が残ると毎回そのぶんコンテキストを失う) -
skillOverridesで常時不要な Skill をname-onlyかoffに -
使っていない MCP を disable する。
/usageで実際の使用統計を見て判断する
要約と外部メモの運用
長時間のタスクでは、履歴を膨らませず外部に逃がすのが基本です。
- 30〜60 分ごとに
/compact、その前にNOTES.mdに決定事項を書き出してファイルに逃がしておく - マイルストーン型のタスクは
TODO.mdを主役にして、進捗をコンテキストではなくファイルで管理する (Anthropic 公式が note-taking パターンとして推奨)
Rewind と Branch (Claude Code固有の精密な巻き戻し)
Claude Code は、プロンプト送信ごとに自動でチェックポイントを取ってくれています。 /rewind は、 /clear の全消しより細かく、 /compact の要約より確実に「特定のターンだけ消す」ことができるので、コンテキスト汚染が起きたときの効きが良いです。
| モード | 戻る | 残る | 使い所 |
|---|---|---|---|
| Conversation only | 会話・コンテキスト | ファイル | 自己汚染が起きたときの第一選択 |
| Code only | ファイル | 会話 | 議論は続けたいが実装方針を変えたい |
| Both | 両方 | — | 全部やり直したいとき |
意図的に分岐したいときは claude --continue --fork-session で branch を作れます。 元セッションを残したまま別ルートを試したいときに便利です。
ただし、 checkpoint は 30 日で自動削除されますし、 bash で変更したファイル (rm / mv など) は追跡されません。 Git コミットの代わりにはならないので、その点だけ注意してください。
最後に: AI が出した「事実」は実装前に必ず grep で裏取りする
存在しない関数名・型・ファイルパスを使い始めたら、すぐに止める。 これが自己汚染 (パターン 5) への唯一の根本対策です。
裏取りは省略しないようにしてください。 自己汚染は「量」を絞っても解けません。 「たぶん本当だろう」で扱った瞬間に、コンテキストの汚染が始まります。
参考