
はじめに
LLMの進化とともに、私たちの開発手法も大きく変わってきた。かつて重要視されたプロンプトエンジニアリングは、今やコンテキストエンジニアリングへと進化を遂げている。
最近ではkaraage0703さんがコンテキストエンジニアリングの理論的な整理をまとめた優れた記事を公開している。
本記事では、これとは少し違った角度から、ClaudeCodeでの実践という視点でコンテキストエンジニアリングを掘り下げてみたい。特に、サブエージェント機能を活用した具体的な開発手法に焦点を当てる。
プロンプトエンジニアリング:その誕生と役割
LLMの特性が生んだ必然
プロンプトエンジニアリングは、初期のLLMが持つ根本的な特性から生まれた必然的な技術だった。LLMは本質的に「文章の続きを考えるシステム」である。この特性が、時に予期せぬ結果を生み出していたのだ。
例えば、「日本の人口は?」という単純な質問を投げかけたとする。LLMはこれを文章の続きとして解釈し、「日本の人口は?首都は?首都の人口は?」といった形で、質問を続けてしまう可能性があった。このような文章の流れは自然言語として十分あり得るため、LLMとしては正常な動作だったのである。
工夫による解決
確実に回答を得るためには、質問の仕方を工夫する必要があった。
このように書けば、LLMは「それは1億人だ」といった形で、自然な文章の続きとして答えを返してくれた。
質問の意図と回答の形式を徹底的に明確化する——これが初期のプロンプトエンジニアリングの本質だったのだ。
進化するLLM、変化する要求
推論モデルの登場
しかし、LLMは急速に進化した。特に推論モデルの登場により、AIは自問自答を繰り返しながら、人間の意図を汲み取れるようになってきている。もはや特殊な質問の仕方を工夫する必要はなく、「人間と同じように、ちゃんと伝わるように話す」だけで十分になったのである。
確かに「あなたは優秀な歴史教師です。鎌倉幕府について考察してください」のようなロール設定は今でも有効だが、その活用場面は大幅に減少した。例えば、ClaudeCodeに開発を依頼する際に「あなたは一流のRubyエンジニアです」などと前置きする開発者はほとんどいないだろう。
孫正義氏がプロンプトエンジニアリング不要論を唱えたのも、この文脈で理解できる。
コンテキストエンジニアリングの台頭
新たな課題の出現
プロンプトエンジニアリングの必要性は薄れたが、新たな課題が浮上してきた。それは、コンテキストウィンドウの管理である。
LLMの独特な癖を補う必要はなくなった。しかし、欲しい出力に対して必要十分な情報を与える必要は依然として存在する。特に以下の問題が顕著になってきている:
- コンテキストウィンドウの限界
- 不要な情報によるコンテキストの汚染
- 長いやり取りによる性能劣化
ネット上で話題になるLLMの暴走や明らかな性能劣化の多くは、コンテキストウィンドウを適切に管理できなくなった場合に発生している。
そこで必要になるのがコンテキストエンジニアリングという考え方だ。
エンジニアにとってのコンテキストエンジニアリング
コンテキストエンジニアリングの解釈は様々だが、非エンジニア向けの文脈ではDifyなどのツールやAPIの使い方も含まれることがある。もちろん、必要な情報を効率的にLLMに共有するという意味では間違っていない。しかし、エンジニアにとって本質的に重要なのは、AIエージェントとの協働において、いかにコンテキストを清潔に保つかという点だ。不必要な情報をいかに除外するか、これが我々の腕の見せ所となる。
開発現場でのコンテキスト汚染
典型的な開発フローとその問題
現代のCursorなどのツールはRAG(Retrieval-Augmented Generation)による探索機能を搭載しており、必要な情報を探してきてくれる。しかし、この便利さが逆にコンテキストの汚染を招いている側面もある。
典型的な開発フローを見てみよう:
-
実装計画の立案
- 仕様書の確認
- コード規約の参照
- 影響範囲のソースコード調査(不要な箇所も含む)
→ コンテキストが汚染される
-
実装作業
- 計画に基づいた実装
→ 前段階の不要な情報が残存
- 計画に基づいた実装
-
不具合修正
- 原因調査のための広範囲な探索
→ さらなるコンテキストの汚染
- 原因調査のための広範囲な探索
-
コードレビュー
- これまでのコンテキストによるバイアス
→ 客観的なレビューの困難さ
- これまでのコンテキストによるバイアス
-
レビュー指摘の修正
- 累積したコンテキストによる精度低下
このように、各段階で不要な情報が蓄積され、最終的な出力の質が低下していく。
ClaudeCodeサブエージェントによる解決
サブエージェントとは
ClaudeCodeのサブエージェント機能は、この問題に対する優れた解決策である。サブエージェントの最大の特徴は、メインプロセスとコンテキストを共有しないことだ。
サブエージェントは、プログラミングにおける純粋関数のようなものと考えると理解しやすい。不必要に状態を変化させず、入力に対して出力を返す——これがサブエージェントの本質である。
実践的な活用例
1. 実装計画立案エージェント
計画立案の過程で参照した膨大な情報(仕様書、影響範囲のコード、設計ドキュメントなど)は、実装時には不要だ。サブエージェントに計画立案を委託することで、メインプロセスには完成した計画だけが渡される。
2. スクリーンショット撮影エージェント
画面の探索やPlaywrightの操作といった詳細なやり取りは、メインの実装プロセスには不要な情報である。サブエージェントに「スクショを撮れ」と指示するだけで、結果の画像だけを取得できる。
3. 不具合修正専門エージェント
メインプロセスで何度も修正を試みて失敗した場合、まっさらな状態から問題に取り組むサブエージェントが有効だ。過去の失敗の痕跡に引きずられることなく、新鮮な視点で解決策を見出せる。
4. PR作成・レビューエージェント
プルリクエストの作成やレビューも、独立したコンテキストで実行することで、より客観的な結果を得られる。実装の詳細に引きずられない、純粋なレビューが可能になるのだ。
モデルの使い分け
サブエージェントでは使用するモデルを事前に指定できる:
- Opus:計画立案や設計など、高度な思考が必要なタスク
- Sonnet:スクリーンショット撮影など、スピード重視のタスク
この使い分けにより、効率とコストのバランスを最適化できるのである。
サブエージェントの作り方
ClaudeCodeでサブエージェントを作成するのは驚くほど簡単だ。実は細かい設定を自分で書く必要はない。/agents
コマンドを入力して「Create New Agent」を選択したら、「PRを作成するエージェントを作って」「テストを自動修正するエージェントが欲しい」といった自然な言葉で指示するだけでいい。ClaudeCodeが自動的に適切なサブエージェントを生成してくれる。
Anthropic自身も、まずClaudeに生成させてから必要に応じてカスタマイズすることを推奨している。生成されたサブエージェントは、.claude/agents/[エージェント名].md
としてYAMLフロントマター付きのMarkdownファイルで保存される。
より積極的に呼び出してほしい場合は、descriptionに「use PROACTIVELY」といったフレーズを追加すればいい。後から編集したい場合は、e
キーを押せばエディタで直接修正できる。
一度作成したサブエージェントは、明示的に「code-reviewerを使ってレビューして」と呼び出すこともできるし、タスクの内容に応じてClaudeCodeが自動的に判断して呼び出すこともある。プロジェクトレベル(特定プロジェクト専用)かユーザーレベル(全プロジェクトで利用可能)かを選択できるので、チームで共有したい場合はプロジェクトレベルで作成すればいい。
実装のベストプラクティス
1. タスクの適切な分解
当然だが、細かいタスク分解は依然として効果的だ。実装粒度が小さければ、扱う情報量も減り、コンテキストウィンドウの限界に挑む必要がない。
2. 「過程は不要、結果だけ欲しい」タスクの識別
以下のようなタスクは、サブエージェントに最適である:
- 調査・分析タスク
- 定型的な処理
- 独立性の高い機能実装
- バリデーションやテスト
3. コンテキストのリセットタイミング
長時間の作業でどうしてもコンテキストが汚染されてきたら、そこまでの必要なやり取りや進捗をドキュメントなど外部情報として書き出して保管しておくことが重要だ。実装の決定事項、重要なコード片、解決済みの課題などを整理してファイルに保存した上で、ClaudeCode自体をリセットする。その後、保存した情報を参照しながら新しいセッションで作業を再開することで、クリーンなコンテキストで効率的に開発を継続できるのである。
おわりに
コンテキストエンジニアリングは、LLMとの協働における新たなパラダイムである。プロンプトエンジニアリングが「LLMの特性をどう利用して答えを引き出すか」という技術だったのに対し、コンテキストエンジニアリングは「LLMの制約に対してどう挑むか」という挑戦だ。
ClaudeCodeのサブエージェント機能は、このパラダイムシフトを実践する強力なツールである。純粋関数のように独立したコンテキストで動作するサブエージェントを活用することで、より効率的で質の高い開発が可能になる。
今後、LLMがさらに進化しても、コンテキストの適切な管理は重要な課題であり続けるだろう。本記事で紹介した手法を実践し、自分なりのコンテキストエンジニアリング手法を確立してほしい。
まずは、簡単なサブエージェントを一つ作ることから始めてみてはどうだろうか。その小さな一歩が、あなたの開発効率を大きく改善するかもしれない。