コンテキスト設計 — context window の配分 — 結局どうすればいいか
20本の原典が同じ制約を別の角度から言っている。「context は有限の予算であり、多く入れるほど良いわけではない」。 ここではその制約から実際の手順を導く。
1. 前提: 大きいほど良くはない
1M トークンの window があっても、埋めれば性能が落ちる。
more context isn’t automatically better. As token count grows, accuracy and recall degrade, a phenomenon known as context rot. —
context-windowscontext は多いほど自動的に良くなるわけではない。トークン数が増えるにつれて正確性と再現率は劣化する —— context rot として知られる現象である。
The context window is a public good —
agent-skills-best-practicescontext window は公共財である。
したがって設計上の問いは「どれだけ入るか」ではなく「何を入れないか」になる。
注意すべき非対称性: 入れるのは一瞬だが、出すのは難しい。/clear 以外の方法(compaction、context editing)は何が消えるかを完全には制御できない。だから入れる前に判断するほうが安い。
2. まず測る。手当てはその後
原典が繰り返し言うのは「どこにトークンが消えているかを特定してから手を選べ」ということ。
| 測る手段 | 分かること |
|---|---|
/context(Claude Code) | カテゴリ別の消費と最適化の提案。どの CLAUDE.md と auto memory がロードされたかも出る |
/usage(Claude Code) | skill / subagent / plugin / MCP サーバ別の内訳。10%以上を占める振る舞いにフラグが立つ |
/mcp | MCP サーバごとのトークンコスト |
usage フィールド(API) | input_tokens / cache_read_input_tokens / cache_creation_input_tokens の内訳 |
count_tokens + context_management | context editing を適用した場合の削減量を送信前に見積もる |
測らずに手を打つと、効かない場所を最適化する。 programmatic-tool-calling は「効くのは fan-out 型だけで、逐次型では 8% 高くつく」と明記している。
3. 5つの手。層をなす
制約から出てくる手は、文書をまたいで同じ5つに収束する。排他ではなく重ねる。
① 使うまでロードしない(progressive disclosure)
最も費用対効果が高い。 「あるが読まれていない」状態を作る。
| 機構 | ロードのされ方 |
|---|---|
| skill | 起動時は name と description(約100トークン)だけ。本体は使うとき。参照ファイルは読むまでゼロ |
| MCP tool search | ツール名だけ。スキーマは必要時。既定で有効 |
.claude/rules/ の paths: | マッチするファイルを読む・書く・編集するときだけ |
skill の paths: | 同上 |
なぜこれが効くか: agent-skills-overview の数字が明快。Level 1 が約100トークン、Level 2 が 5k 未満、Level 3 は読むまでゼロ。だから「skill をいくつ入れても context のペナルティがない」。
設計上の含意: 同梱するコンテンツの量に実質的な上限がない。 API ドキュメント全文でも、大きなデータセットでも、使わなければコストはゼロ。むしろ「本体を痩せさせて参照に逃がす」ことが正しい。
作者はコアを痩せさせておき、「フォームを埋めるときにだけ Claude が
forms.mdを読む」ことを信頼する —equipping-agents-for-the-real-world-with-agent-skills
② 別の context に追い出す
要約だけを返させる。
| 機構 | 返ってくるもの |
|---|---|
| subagent | 最終テキストと小さなメタデータのみ。実測で 6,100トークン読んで 420トークン返す |
| workflow | 中間結果はスクリプト変数に留まり、Claude の context には最終回答だけ |
| programmatic tool calling | 中間の tool_result が一切 context に入らない |
| code execution with MCP | 同上。150,000 → 2,000 トークン(98.7%減) |
共通する構造: 「大量に読む主体」と「結果を受け取る主体」を分離する。
③ context の外に状態を置く
セッションを跨ぐには、context 以外の場所が要る。
| 置き場 | 誰が書くか | ロード |
|---|---|---|
| CLAUDE.md | 自分 | 毎セッション全文 |
| auto memory | Claude | 毎セッション(MEMORY.md の先頭200行 or 25KB) |
| memory tool(API) | Claude(実行は自分のアプリ) | 必要時に読む |
progress.txt + feature_list.json + git | エージェント | 毎セッション冒頭に自分で読ませる |
重要な帰結: effective-harnesses-for-long-running-agents の harness は、この③だけで「記憶を持たないエージェントが毎回同じ場所から立ち上がる」を実現している。context を増やすのではなく、context の外に状態を置いた。
④ 要らなくなったら捨てる
| 手段 | 何が起きるか | 制御できるか |
|---|---|---|
/clear | 全部捨てる。コストゼロ | 完全に制御できる |
| compaction(自動) | 古いツール出力を先に捨て、次に会話を要約 | 部分的。焦点は指定できる |
/compact <focus> | 焦点を指定して要約 | 部分的 |
| context editing(API) | 古い tool_result / thinking を要約せず落とす | 細かく制御できる(keep / exclude_tools / clear_at_least) |
| compaction(API・閾値) | サーバ側で要約し、ブロックより前を全部捨てる | instructions で要約方針だけ(compaction-threshold) |
| compaction(API・要求時) | 要約だけを取りに行き、返ったブロックで要約範囲を置き換える | いつ・どこまで要約するかを決められる。API は送ったメッセージを全部要約し、要約を頼んだ後に進んだターンはブロックの後ろにそのまま続く(compaction-on-demand)。使えるならこちら(compaction)。残したターンの thinking を有効に保つには3条件が要る。破っても compact は成功し、検査が強制される環境で残した thinking を送る最初のリクエストが既定で 400 になる(drop_block や Batches ではエラーにならず黙って捨てられるので、input_transformations を見る。compaction-thinking-blocks) |
/compact と /clear のコストが違うことは見落とされやすい。
/compactは要約対象の会話を読むので、それ自体が大きなリクエスト。継続が要らないなら/clearはコストゼロ —costs
⑤ そもそも入れない
| 手段 | 効き方 |
|---|---|
Read deny ルール | ビルド成果物・生成コード・vendored 依存を開かせない |
claudeMdExcludes | 触らないパッケージの CLAUDE.md をロードしない |
MCP より CLI(gh、aws、gcloud) | ツール一覧に載らないぶん、MCP より context 効率が良い |
| hook で前処理 | 1万行のログを grep して該当行だけ返す。数万トークン → 数百トークン |
| code intelligence プラグイン | 「定義へジャンプ」1回が grep + 複数ファイル読みを置き換える |
削っても落ちなかった
Claude Code は Opus 5 / Fable 5 向けの system prompt を8割以上削っても、コーディングの評価が測れるほど落ちなかった(new-rules-of-context-engineering)。原因は過剰な制約で、system prompt・skill・ユーザーの依頼が1つのリクエストの中で矛盾していた。規則より判断、例より道具の設計、全部前置きより段階的な開示、繰り返しより簡潔なツール説明。CLAUDE.md は軽く保ち、トークンの大半をコードベースの落とし穴に使う。
費用の側からも同じ結論になる —— CLAUDE.md は毎ターン送り直され、context が大きいほど1ターンが高い(what-a-task-costs-on-opus-5-5)。
4. compaction で何が消えるか(最も間違えやすい点)
「CLAUDE.md に書いたから残る」は半分しか正しくない。
| 機構 | compaction 後 |
|---|---|
| system prompt / output style | どちらも引き続き効く |
プロジェクトルートの CLAUDE.md、paths なしの rule | ディスクから再注入される |
| auto memory | ディスクから再注入される |
paths: を持つ rule | 失われる。該当ファイルを再度読むまで戻らない |
| サブディレクトリのネストした CLAUDE.md | 失われる。同上 |
| 起動した skill の本体 | 再注入されるが 1本 5,000 / 合計 25,000 トークンで打ち切り。古い順に落ちる |
| skill の description 一覧 | 再注入されない。実際に起動した skill だけ残る |
ここから出てくる3つの実務ルール:
- compaction を跨いで確実に残したいルールは、
paths:を外してプロジェクトルートの CLAUDE.md に置く SKILL.mdは重要な指示を先頭に置く(切り詰めは先頭を残す)- 長いセッションで計画を守りたいなら、計画をファイルに保存する(会話履歴は要約される)
長いセッションは途中で compaction されるが、保存した計画は会話履歴が消えても残る —
large-codebases
5. キャッシュを壊さない
context を減らす手がキャッシュを壊すことがある。両立させるための規則。
キャッシュの階層は tools → system → messages。ある段の変更はその段以降を全部無効化する。
| 操作 | キャッシュへの影響 |
|---|---|
| ツール定義の変更 | 全キャッシュが飛ぶ。ただし inline-tools-2026-09-15 beta で会話途中の system メッセージの tool_addition ブロックとして足すなら、tools を編集しないので接頭辞は一致したまま(prompt-caching) |
effort の変更 | messages が必ず飛ぶ(effort はプロンプトにレンダリングされる) |
thinking 設定の変更 | 同上 |
tool_choice の変更 | messages のみ |
| tool result clearing | キャッシュを壊す |
thinking block clearing(keep: "all") | 保つ(むしろヒットを最大化する) |
defer_loading(tool search) | 保つ(prefix に触らない設計) |
運用ルール:
- 会話ごとに
thinking設定とeffortを決めて固定する(既定値を明示的に書くのは省略と同じで壊さない。per-message effort に対応したモデルなら、role: "system"メッセージで運ぶ変更も壊さない) - 会話の途中で system 指示を足すなら、トップレベルの
systemを編集せず{"role": "system"}メッセージをmessagesに足す(対応モデルなら system も messages も飛ばない。Sonnet 5 は非対応) - ターン単位で思考量を調整したいなら、パラメータではなく per-message prompting で(最新の user メッセージへの追記は前方の breakpoint を壊さない)
- breakpoint は「リクエスト間で内容が同一である最後のブロック」に置く。タイムスタンプなど変わるものに置くとハッシュが一致しない
使われ方の変化が費用の重心を動かした
集計で、Claude Code の1リクエストの context は2.6倍、入力と出力の比は 189:1 → 324:1 になった(opus-5-5-for-longer-coding-sessions)。費用の大半は送り直す context のキャッシュ読み取りになり、渡す context が本当に必要か、そのできるだけ多くがキャッシュから読まれているかが効く。守り方は「モデルはセッションの初めに決める」「compact は席を離れる前に」「API キーかクラウドプロバイダなら長いセッションで1時間キャッシュ」。
memory を外に置くときは、エージェントが既に使う道具の上に置く —— Managed Agents の memory はファイルシステムに載り、Claude は bash とコード実行でそれを扱う(managed-agents-memory)。
6. 長いセッションで利用が跳ねる理由
「たいして使っていないのに上限に当たる」の原因は5つある。 どれも context のサイズに起因する。
| 原因 | 中身 |
|---|---|
| long context | 全会話が毎リクエスト送られる。一日開けたセッションでの一言の質問も、会話全体分の利用量を消費する |
| cache miss | キャッシュ寿命を超えた中断の後、最初のメッセージが全 context を再処理する |
| scheduled tasks | idle でも間隔ごとに全 context を送る |
| cross-session messages | 他セッションからのメッセージが新ターンとして配送され、毎回全 context を送る |
| compaction 自体 | 要約対象を読むので大きなリクエストになる |
→ 対処は「context を小さく保つ」の一点に集約される。
7. 手順にまとめる
API でエージェントを組むとき
- 測る ——
count_tokens/usageの内訳。compaction を使うならトップレベルのusageは要約の分を含まないので、usage.iterationsを合計する(compaction-threshold) - prompt caching —— 初日から。ツール定義が安定しているなら常に
- ツールが 20個超 —— tool search(
defer_loading) - fan-out がある —— programmatic tool calling(逐次型なら入れない)
- 会話が長引く —— compaction(server-side)。使えるなら要求時方式(いつ要約するかを自分で決め、裏でも走らせられる。Bedrock では閾値方式)。要約せず古いツール結果を消すだけなら context editing
- セッションを跨ぐ —— memory tool。context の外に状態を置く
- effort と thinking —— 会話ごとに固定。ターン単位は per-message prompting
Claude Code を使うとき
- 測る ——
/contextと/usage CLAUDE.mdを 200行以内に —— 超えたら skill か path-scoped rule へ- 無関係な作業に移る ——
/clear(コストゼロ。/compactより安い) - 調査が重い —— subagent に委譲
- 読ませたくないものがある ——
Readの deny ルール、claudeMdExcludes - 冗長な出力 —— hook で前処理して絞る
- MCP より CLI ——
gh/aws/gcloudが使えるならそちら - 型付き言語 —— code intelligence プラグイン
8. 判断に迷ったときの原則
この3つは原典が繰り返し言っている。
- 入れる前に判断する。 出すのは難しく、何が消えるかを完全には制御できない
- 「あるが読まれていない」を作る。 progressive disclosure が最も費用対効果が高い
- 読む主体と受け取る主体を分ける。 subagent / workflow / code execution はすべてこの形
そして、やりすぎの兆候も原典が指摘している。
Too much can fill up your context window, but it can also add noise that makes Claude less effective; skills may not trigger correctly, or Claude may lose track of your conventions —
features-overview多すぎれば context window を埋めるだけでなく、Claude の性能を落とすノイズにもなる。skill が正しく起動しなかったり、Claude が規約を見失ったりする。
context を減らす工夫そのものが増えすぎると、今度は選択の精度が落ちる。 測ってから足す。