エージェンティック & コンテキストエンジニアリング
AI エージェントの設計原理と、効果的なコンテキスト構築の技術
Part A: エージェンティックエンジニアリング
A-1. エージェンティックエンジニアリングとは
エージェンティックエンジニアリングとは、AI が単発の質問応答を超えて、目標を自律的に分解・実行・評価するシステムを設計・構築する技術領域です。
従来のプロンプトエンジニアリングとの違い
| 観点 | プロンプトエンジニアリング | エージェンティックエンジニアリング |
|---|---|---|
| 実行モデル | 1 入力 → 1 出力 | 目標 → 計画 → ループ実行 → 完了 |
| ツール使用 | なし(テキスト生成のみ) | ファイル・API・コード実行を呼び出す |
| 状態管理 | ステートレス | セッションを通じて状態を保持 |
| エラー処理 | ユーザーが手動で再試行 | 自動で検出・回復・再計画 |
| 設計者の役割 | 最良のプロンプトを書く | アーキテクチャ・ツール・評価を設計する |
| 主な課題 | 出力品質の向上 | 信頼性・安全性・コスト最適化 |
A-2. エージェントのアーキテクチャパターン
ReAct(Reasoning + Acting)
最も基本的なパターンです。思考(Reasoning)と行動(Acting)を交互に繰り返すことで、複雑なタスクを段階的に解決します。
Plan-and-Execute(計画・実行分離)
大規模タスクに向いたパターンです。プランナーが全体計画を立て、エグゼキューターが個々のステップを実行します。
Multi-Agent(複数エージェント協調)
専門分化したエージェントがオーケストレーターの指揮のもとで協働するパターンです。
パターン選択ガイド
| タスクの特性 | 推奨パターン |
|---|---|
| 探索的・対話的(次のステップが結果に依存) | ReAct |
| 明確な要件・並列処理が有効 | Plan-and-Execute |
| 専門領域が分かれている・大規模プロジェクト | Multi-Agent |
A-3. ツール使用(Tool Use)の設計原則
エージェントの能力はどんなツールを持たせるかで決まります。ツール設計には明確な原則があります。
原則 1: 単一責任
1 つのツールは 1 つのことだけを行います。複雑な処理を 1 ツールに詰め込むと、エージェントが予測不能な使い方をするリスクが高まります。
# 悪い例: 責任が混在している
def file_manager(action: str, path: str, content: str = ""):
if action == "read":
return open(path).read()
elif action == "write":
open(path, "w").write(content)
elif action == "delete":
os.remove(path)
# 良い例: 責任を分離する
def read_file(path: str) -> str: ...
def write_file(path: str, content: str) -> None: ...
def delete_file(path: str) -> None: ...原則 2: 冪等性と副作用の明示
副作用のあるツール(削除・送信・決済)は名前と説明で明確に区別し、エージェントが慎重に扱えるようにします。
# ツール定義の例(Claude の tool_use 形式)
tools = [
{
"name": "search_web",
"description": "Web を検索して情報を取得します(読み取り専用・副作用なし)",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "検索クエリ"}
}
}
},
{
"name": "send_email",
"description": "【副作用あり・不可逆】メールを送信します。実行前に必ずユーザーに確認してください",
"input_schema": {
"type": "object",
"properties": {
"to": {"type": "string"},
"subject": {"type": "string"},
"body": {"type": "string"}
},
"required": ["to", "subject", "body"]
}
}
]原則 3: エラーメッセージの品質
ツールのエラーメッセージはエージェントが自己回復できる情報を含める必要があります。
# 悪い例
raise Exception("Error")
# 良い例: エージェントが回復アクションを判断できる
raise ToolError(
code="FILE_NOT_FOUND",
message=f"ファイル '{path}' が見つかりません",
suggestion="ls コマンドで利用可能なファイル一覧を確認してください",
recoverable=True
)A-4. エージェントの自律性レベル
エージェントへの人間の関与度合いはタスクのリスク・重要度に応じて設計します。
| レベル | 説明 | 適用例 |
|---|---|---|
| 1: 完全手動 | AI はアドバイスのみ、実行は人間 | 重要な設定変更 |
| 2: 提案のみ | AI が計画を提示し、人間が承認して実行 | コードリファクタリング提案 |
| 3: 承認後実行 | AI が計画を立て、重要ステップで確認を求める | PR 作成・デプロイ |
| 4: 監視下自動 | AI が自律実行、異常時のみアラート | テスト実行・ビルド |
| 5: 完全自律 | 人間の介在なしに目標を達成 | バッチ処理・定期レポート |
Claude Code のデフォルトはレベル 3〜4。
--dangerously-skip-permissionsでレベル 5 に近づけることができますが、本番環境での使用は推奨しません。
A-5. エージェントの評価とテスト
エージェントの品質は従来のソフトウェアテストとは異なる方法で評価します。
評価の 3 つの軸
テスト手法
# エージェントのテスト構造例
class AgentTestSuite:
def test_task_completion(self):
"""タスクが正しく完了するか"""
result = agent.run("src/utils.ts に JSDoc コメントを追加して")
assert result.status == "completed"
assert "JSDoc" in read_file("src/utils.ts")
def test_error_recovery(self):
"""エラー発生時に自己回復できるか"""
# 存在しないファイルを指定
result = agent.run("nonexistent.ts を編集して")
assert result.recovery_attempted == True
assert result.status in ["recovered", "escalated"]
def test_boundary_respect(self):
"""スコープ外の操作をしないか"""
result = agent.run("src/ のコードを改善して")
touched_files = result.get_modified_files()
assert all(f.startswith("src/") for f in touched_files)
def test_efficiency(self):
"""無駄なツール呼び出しがないか"""
result = agent.run("package.json のバージョンを確認して")
assert result.tool_call_count <= 3 # 読み込み・確認・返答の 3 回以内A-6. 実装例: Claude Code のエージェント機能
Task ツールを使ったサブエージェント起動
Claude Code のメインセッションから Task ツールでサブエージェントを起動し、並列処理を実現します。
# メインエージェントのプロンプト(CLAUDE.md または直接指示)
以下を並列で実行してください:
Task 1: src/api/ ディレクトリ内の全エンドポイントを解析し、
認証されていないエンドポイントのリストを作成してください。
Task 2: test/ ディレクトリを確認し、カバレッジが 80% 未満の
ファイルを特定してください。
Task 3: package.json の依存関係で脆弱性があるものを
npm audit の結果から抽出してください。
3 つのタスクが完了したら結果を統合して改善提案をまとめてください。Hooks を使った安全ネット
// .claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo '実行コマンド: ' $CLAUDE_TOOL_INPUT | tee -a ~/.claude/audit.log"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx tsc --noEmit 2>&1 | head -20"
}
]
}
]
}
}Part B: コンテキストエンジニアリング
B-1. コンテキストエンジニアリングとは
コンテキストエンジニアリングとは、LLM のコンテキストウィンドウに何を入れ、何を除外し、どの順序で提示するかを体系的に設計する技術です。
「プロンプトエンジニアリングが "何を言うか" を最適化するなら、コンテキストエンジニアリングは "AI が見る世界全体" を設計する」
なぜプロンプトだけでは不十分か
B-2. コンテキストウィンドウの理解と最適化
コンテキストウィンドウの構造
トークン消費の最適化指針
| 手法 | 効果 | 実装コスト |
|---|---|---|
| 不要な履歴の圧縮・要約 | 大(最大 60% 削減) | 中 |
| 構造化データを JSON → テーブルに変換 | 小〜中 | 低 |
| 関連コードのみを抜粋して注入 | 大 | 中 |
| 繰り返し情報の参照化(「前述の通り」) | 小 | 低 |
| ファイル全体でなく差分のみを提示 | 大 | 高 |
B-3. コンテキストの 4 つの構成要素
① 指示(Instructions)
AI の振る舞いを宣言的に制御するテキストです。優先度順に読み込まれます。
優先度(高)
↑ システムプロンプト(Claude 自体の設定)
│ ~/.claude/CLAUDE.md(グローバル設定)
│ <project-root>/CLAUDE.md(プロジェクト設定)
↓ <subdir>/CLAUDE.md(サブディレクトリ指示)
優先度(低)② 知識(Knowledge)
タスクに必要な情報を動的に注入します。静的なものと動的なものがあります。
| 種類 | 例 | 注入タイミング |
|---|---|---|
| 静的知識 | API 仕様書・設計ドキュメント | セッション開始時 |
| 動的知識 | RAG 検索結果・DB クエリ結果 | ツール実行時 |
| 揮発性知識 | リアルタイム価格・最新ニュース | 必要時に取得 |
③ ツール(Tools)
エージェントが実行できる能力の定義です。適切なツール定義がコンテキストの質を左右します。
④ 履歴(History)
過去のやり取りを引き継ぐ仕組みです。長くなりすぎると品質が劣化するため、定期的な圧縮が必要です。
B-4. RAG(Retrieval-Augmented Generation)との関係
RAG はコンテキストエンジニアリングの知識注入を自動化する重要な技術です。
RAG を使うべきシーン
- コードベースが大規模で全体をコンテキストに入れられない場合
- 社内ドキュメントなど LLM の学習データにない知識が必要な場合
- 最新情報(API 仕様の更新など)を動的に参照したい場合
B-5. プロジェクトコンテキスト設計(CLAUDE.md / .cursorrules)
効果的な CLAUDE.md テンプレート
# プロジェクト: <名前>
## 1. 技術スタック
- 言語: TypeScript 5.x(strict mode 必須)
- フレームワーク: Next.js 15(App Router)
- DB: PostgreSQL 16 + Prisma ORM
- テスト: Vitest + Testing Library
## 2. コーディング規約
- 関数は純粋関数を優先。副作用は I/O 層に閉じ込める
- エラーは `Result<T, E>` 型で表現(throw 禁止)
- `any` / `unknown` 使用時は型ガードを必ず付ける
- コメントは「なぜ」を書く(「何をするか」はコードが語る)
## 3. ディレクトリ構造
src/
app/ # Next.js App Router
domain/ # ビジネスロジック(フレームワーク非依存)
infra/ # DB・外部API・ストレージ
shared/ # 共通型・ユーティリティ
## 4. 禁止事項
- `console.log` をコミットしない(`logger` モジュールを使う)
- 環境変数の直書き禁止(`config/env.ts` 経由)
- `any` キャストを PR にコミットしない
## 5. よく使うコマンド
- `npm run dev` 開発サーバー起動
- `npm test` テスト実行(watch モード)
- `npm run check` 型チェック + lint + format チェック.cursorrules との比較
| 観点 | CLAUDE.md | .cursorrules |
|---|---|---|
| 対象 AI | Claude Code | Cursor(内部 Claude/GPT) |
| 読み込み範囲 | サブディレクトリも有効 | プロジェクトルートのみ |
| スキル定義 | .claude/ で可能 | 不可 |
| 共通化 | グローバル設定あり | プロジェクト単位のみ |
B-6. コンテキスト圧縮と要約のテクニック
長期セッションではコンテキストが肥大化します。戦略的な圧縮が品質を維持する鍵です。
圧縮の実践パターン
パターン 1: タスク完了後の要約コミット
<!-- コンテキスト圧縮メモ(セッション途中で記録) -->
## 完了済みタスク要約(2025-06-01)
### 認証モジュールのリファクタリング
- 変更ファイル: src/auth/jwt.ts, src/auth/middleware.ts
- 変更内容: RS256 署名方式に移行、リフレッシュトークン追加
- テスト: auth.test.ts 全 12 ケースパス
- 注意点: 既存セッションは移行期間中 HS256 でも有効パターン 2: ファイル内容の参照化
# 悪い例(トークン消費大)
以下のファイルを修正してください:
[src/utils.ts の全 200 行を貼り付け]
# 良い例(参照のみ)
src/utils.ts の formatDate 関数(L45-L72)を修正してください。
現在の問題: タイムゾーン非対応B-7. 実践: 効果的なコンテキスト設計のハンズオン
演習 1: CLAUDE.md の作成
自分のプロジェクトに CLAUDE.md を作成してみましょう。以下のチェックリストで評価できます。
CLAUDE.md 品質チェックリスト:
□ 技術スタックとバージョンが明記されている
□ ディレクトリ構造の説明がある
□ コーディング規約(型・命名・エラー処理)が書かれている
□ よく使うコマンドが記載されている
□ 禁止事項・注意点が明確になっている
□ 200 行以内に収まっている(長すぎると逆効果)
□ 「なぜこのルールか」の背景が少なくとも重要なものに書かれている演習 2: コンテキスト最適化の比較実験
同じタスクを 2 つのコンテキスト設定で実行し、品質・速度・トークン消費を比較します。
実験設定:
タスク: 「新しい API エンドポイント /api/users/:id/preferences を実装して」
設定 A(最小コンテキスト):
- システムプロンプトのみ
- ユーザー指示のみ
設定 B(最適化コンテキスト):
- CLAUDE.md(プロジェクト規約)
- src/api/users.ts(既存エンドポイントの例)
- src/types/user.ts(User 型定義)
- docs/api-conventions.md(API 設計規約)
比較指標:
1. コードの品質(型安全性・エラー処理・命名)
2. 修正回数(1 発で完成するか)
3. トークン消費量(コスト)演習 3: エージェントパイプラインの設計
以下のタスクについて、どのアーキテクチャパターンを使うかを設計してください。
タスク: 「GitHub のオープン Issue を分析して優先度ランキングを作成する」
設計事項:
1. どのパターンを使うか(ReAct / Plan-and-Execute / Multi-Agent)
2. 必要なツールは何か(GitHub API / ファイル書き込み / ...)
3. 人間の関与レベルはどこか(レベル 1〜5)
4. 何をテストするか(タスク達成率 / 効率 / 安全性)
ヒント: Issue の数・複雑さ・結果のフォーマットを考慮してください。まとめ: エージェンティック & コンテキストエンジニアリングの全体像
| キーワード | 一言まとめ |
|---|---|
| ReAct | 思考と行動を交互に繰り返す最も基本的なパターン |
| Plan-and-Execute | 計画と実行を分離して大規模タスクを処理する |
| Multi-Agent | 専門化されたエージェントがオーケストレーター指揮で協働 |
| コンテキスト 4 要素 | 指示・知識・ツール・履歴をバランスよく設計する |
| CLAUDE.md | プロジェクトの「憲法」。AI の振る舞いを宣言的に制御 |
| RAG | 大規模・最新・社内知識を動的にコンテキストへ注入 |
| コンテキスト圧縮 | 長期セッションの品質を維持するための必須テクニック |