「自律的に問題を解決するエージェント」へ進化させるには
ChatGPTやClaudeをAPIから呼び出すだけではなく、複雑なタスクを確実にこなし、品質を担保し、人間と協調できるAIエージェントを作るには、設計パターンの知識が不可欠です。
本記事では、Anthropicの公式ガイドライン、Prompting Guide、学術論文(CSIRO Data61の18パターンカタログ)、そしてAgentic Patternsのカタログを統合し、実務で使えるデザインパターンを徹底解説します。
目次
基本編:8つの必須パターン
- はじめに:なぜデザインパターンが必要なのか
- パターン1:Prompt Chaining(逐次フェーズ分割)
- パターン2:Parallelization(並列実行)
- パターン3:Evaluator-Optimizer(評価・最適化ループ)
- パターン4:Orchestrator-Workers(中央制御・役割分担)
- パターン5:ReAct(推論と行動の反復)
- パターン6:Self-Reflective(自己内省)
- パターン7:Plan & Execute(計画と実行の分離)
- パターン8:Human-in-the-Loop(人間介入)
- パターンの組み合わせ:実践アーキテクチャ例
発展編:専門パターン
-
発展編:さらに知っておきたい専門パターン
- 目標設定パターン(Passive/Proactive Goal Creator)
- モデル最適化パターン(Prompt Optimizer, RAG)
- 計画生成パターン(Single/Multi-path Plan)
- 反省パターン(Cross-reflection, Human Reflection)
- 協調パターン(Voting, Role, Debate)
- 安全性・管理パターン(Guardrails, Registry, Adapter, Evaluator)
まとめ
はじめに:なぜデザインパターンが必要なのか
ワークフロー vs エージェント
Anthropicは、LLMを活用したシステムを2つに分類しています:
| 分類 | 説明 | 特徴 |
|---|---|---|
| ワークフロー | 事前定義されたコードパスでLLMをオーケストレーション | 予測可能、デバッグしやすい |
| エージェント | LLM自身がプロセスとツール使用を動的に決定 | 柔軟、複雑なタスクに対応 |
重要なのは、シンプルさを維持することです。Anthropicは「フレームワークに頼りすぎず、基本コンポーネントで構築せよ」と警告しています。
LLMエージェントの4つの構成要素
どのパターンを使う場合も、以下の4要素を意識してください:
| 構成要素 | 役割 |
|---|---|
| 🧠 ブレイン | LLM(推論・判断の中核) |
| 📋 プランニング | タスク分解・計画策定 |
| 💾 メモリ | 短期(コンテキスト)/ 長期(DB) |
| 🔧 ツール | API、DB、外部サービス連携 |
では、8つのパターンを詳しく見ていきましょう。
パターン1:Prompt Chaining(逐次フェーズ分割)
💡 一言で言うと
「大きな仕事を小さなステップに分けて、順番に処理する」
概念図
なぜこのパターンが有効なのか
LLMにはコンテキストウィンドウの制限があります。一度にすべてを処理しようとすると、精度が落ちたり、処理が破綻することがあります。
Prompt Chainingは、これを解決する最もシンプルなパターンです。
具体例:技術ブログの自動生成
# Step 1: テーマから構成案を生成
outline = llm.generate("""
テーマ: {topic}
以下の形式で記事の構成案を作成してください:
1. タイトル
2. 各セクションの見出しと概要
""")
# Step 2: 構成案から各セクションを執筆
sections = []
for section in parse_outline(outline):
content = llm.generate(f"""
構成案: {outline}
以下のセクションを詳しく執筆してください:
セクション: {section}
""")
sections.append(content)
# Step 3: 全体を統合してレビュー
final_article = llm.generate(f"""
以下のセクションを統合し、読みやすい記事に仕上げてください:
{sections}
""")
向いているユースケース
| ユースケース | 理由 |
|---|---|
| ドキュメント生成 | 構成→執筆→校正の流れが自然 |
| データ分析レポート | 収集→分析→可視化→報告の順序依存 |
| コード生成 | 仕様理解→設計→実装→テストの流れ |
| 翻訳ワークフロー | 原文解析→翻訳→校正→ローカライズ |
⚠️ 設計時の注意点
- フェーズを細かくしすぎない - 各LLM呼び出しにはレイテンシがかかります
- エラーハンドリングを各ステップに入れる - 途中で失敗した場合のリカバリを考慮
- 順序依存が本当にあるか確認 - 独立なら後述のParallelizationを検討
パターン2:Parallelization(並列実行)
💡 一言で言うと
「複数の視点から同時に処理し、結果を統合する」
概念図
なぜこのパターンが有効なのか
- スループットの向上 - 待ち時間を削減
- 多角的な分析 - 異なる観点からの結果を得られる
- 冗長性による品質向上 - 複数回実行して多数決を取る(Voting)
具体例:コードレビューの自動化
import asyncio
async def parallel_code_review(code: str):
# 3つの観点から同時にレビュー
reviews = await asyncio.gather(
review_security(code), # セキュリティ観点
review_performance(code), # パフォーマンス観点
review_maintainability(code) # 保守性観点
)
# 結果を統合
aggregated = llm.generate(f"""
以下の3つの観点からのレビュー結果を統合し、
優先度付きの改善提案リストを作成してください:
セキュリティ: {reviews[0]}
パフォーマンス: {reviews[1]}
保守性: {reviews[2]}
""")
return aggregated
2つのサブパターン
| サブパターン | 説明 | 例 |
|---|---|---|
| Sectioning | 独立したタスクを分担 | ドキュメントの各章を別々に生成 |
| Voting | 同じタスクを複数回実行して多数決 | 重要な判断の信頼性向上 |
向いているユースケース
- マルチ観点レビュー - セキュリティ、パフォーマンス、UX
- 大量ドキュメント処理 - 100件のPDFを一斉に要約
- アイデア発散 - ブレインストーミングで複数案を生成
⚠️ 設計時の注意点
- コストと並列数のトレードオフ - 3並列 vs 10並列
- Aggregator(統合役)の品質が重要 - ここが弱いと全体が崩れる
- 完全に独立なタスクであることを確認 - 依存関係があればChaining
パターン3:Evaluator-Optimizer(評価・最適化ループ)
💡 一言で言うと
「作って→評価して→改善する、を繰り返して品質を上げる」
概念図
なぜこのパターンが有効なのか
LLMの出力は一発で完璧にはならないことが多いです。人間も同じで、最初のドラフトを推敲して良いものに仕上げます。
このパターンは、その「推敲プロセス」を自動化します。
具体例:コード生成と自動修正
def generate_and_optimize_code(requirement: str, max_iterations: int = 5):
# 初回生成
code = llm.generate(f"要件: {requirement}\nコードを生成:")
for i in range(max_iterations):
# テスト実行で評価
test_result = run_tests(code)
if test_result.all_passed:
return code # 成功!
# 評価結果をフィードバックして改善
code = llm.generate(f"""
現在のコード:
{code}
テスト結果:
{test_result.failures}
上記のテスト失敗を修正したコードを生成してください。
""")
raise Exception("最大反復回数に到達しても品質基準を満たせませんでした")
3つの評価方法
| 評価方法 | 説明 | 適用例 |
|---|---|---|
| ルールベース | 明確な基準で自動判定 | 文字数、フォーマット、構文チェック |
| LLM評価 | 別のLLMが品質を評価 | 文章の自然さ、論理性 |
| 人間評価 | 最終判断を人間が行う | 創作物、重要な意思決定 |
向いているユースケース
- コード生成 - テストをEvaluatorとして利用
- 技術文書作成 - 仕様との適合性をチェック
- 翻訳 - ニュアンスや専門用語の正確性を反復改善
⚠️ 設計時の注意点
- 評価基準を明確に - 曖昧だと無限ループに陥る
- 最大反復回数を設定 - 必ず終了条件を設ける
- 改善指示は具体的に - 「もっと良くして」ではなく何が悪いかを伝える
パターン4:Orchestrator-Workers(中央制御・役割分担)
💡 一言で言うと
「司令塔が全体を見渡し、専門家チームに仕事を振り分ける」
概念図
なぜこのパターンが有効なのか
複雑なタスクは、事前にすべてのサブタスクを予測できないことがあります。
例えば「このバグを直して」という依頼:
- どのファイルを修正すべきか?
- 修正の影響範囲は?
- テストは必要か?
これらは動的に判断する必要があります。Orchestratorがこの判断を担い、適切なWorkerに仕事を振ります。
具体例:マルチファイル編集システム
class CodingOrchestrator:
def __init__(self):
self.workers = {
"coder": CodeGenerationWorker(),
"tester": TestWriterWorker(),
"reviewer": CodeReviewWorker(),
}
def execute(self, task: str):
# タスク分解
plan = llm.generate(f"""
タスク: {task}
このタスクを完了するために必要なサブタスクを列挙してください。
各サブタスクには以下を含めてください:
- 担当Worker: coder / tester / reviewer
- 具体的な作業内容
- 依存関係
""")
subtasks = parse_plan(plan)
results = {}
# 依存関係を考慮しながら実行
for subtask in topological_sort(subtasks):
worker = self.workers[subtask.worker_type]
context = {dep: results[dep] for dep in subtask.dependencies}
results[subtask.id] = worker.execute(subtask, context)
# 結果を統合
return self.synthesize(results)
Parallelizationとの違い
| 観点 | Parallelization | Orchestrator-Workers |
|---|---|---|
| タスク分解 | 事前に固定 | 動的に決定 |
| Worker間の依存 | なし | あり(管理される) |
| 制御の主体 | コード(固定ロジック) | LLM(動的判断) |
向いているユースケース
- コーディングエージェント - 複数ファイルにまたがる変更
- リサーチエージェント - 複数情報源からの調査・統合
- 業務自動化 - 複数システムを跨ぐワークフロー
⚠️ 設計時の注意点
- Orchestratorに責務を集中させすぎない - 判断疲れを起こす
- 状態管理(State)が重要 - 何が終わり、何が残っているか
- Workerは専門特化させる - 「何でも屋」は品質が落ちる
パターン5:ReAct(推論と行動の反復)
💡 一言で言うと
「考えて→行動して→観察して→また考える、のループ」
概念図
なぜこのパターンが有効なのか
不確実性が高いタスクでは、事前に完璧な計画を立てることは不可能です。
- 外部APIの仕様が想定と違った
- 必要なデータがなかった
- 新しい問題が発見された
ReActは、環境からのフィードバックを得ながら適応的に問題解決します。
具体例:情報収集エージェント
def react_agent(question: str, tools: dict, max_steps: int = 10):
history = []
for step in range(max_steps):
# 思考: 次に何をすべきか
response = llm.generate(f"""
質問: {question}
これまでの履歴:
{format_history(history)}
利用可能なツール:
{format_tools(tools)}
次のアクションを以下の形式で回答してください:
Thought: [考えたこと]
Action: [ツール名]
Action Input: [ツールへの入力]
回答が分かった場合:
Thought: [考えたこと]
Final Answer: [最終回答]
""")
parsed = parse_response(response)
history.append(parsed)
if parsed.has_final_answer:
return parsed.final_answer
# 行動: ツールを実行
observation = tools[parsed.action](parsed.action_input)
history.append({"observation": observation})
return "最大ステップ数に到達しました"
Plan & Executeとの違い
| 観点 | Plan & Execute | ReAct |
|---|---|---|
| 計画のタイミング | 最初に全体計画 | 毎ステップで判断 |
| 柔軟性 | 低(計画に従う) | 高(状況に応じて変更) |
| 向いているタスク | 定型業務 | 探索的タスク |
向いているユースケース
- ツール探索 - どのAPIを使うべきか分からない場合
- デバッグ - 問題の原因を探りながら修正
- 情報収集 - 1つの情報が次の検索クエリを決める
⚠️ 設計時の注意点
- ループ回数の上限を設定 - 無限ループを防止
- ツールの説明を明確に - LLMが適切なツールを選べるように
- 履歴の管理 - コンテキストが長くなりすぎないように
パターン6:Self-Reflective(自己内省)
💡 一言で言うと
「自分の出力を自分で見直して、より良くする」
概念図
Evaluator-Optimizerとの関係
Self-Reflectiveは、Evaluator-Optimizerの軽量版と考えることができます。
| 観点 | Self-Reflective | Evaluator-Optimizer |
|---|---|---|
| 評価者 | 同じLLM | 別のLLM/人間/ルール |
| コスト | 低 | 高 |
| 客観性 | 低(自己評価の限界) | 高 |
| 実装複雑度 | 低 | 高 |
具体例:回答品質の自己改善
def self_reflective_answer(question: str):
# 初回回答
first_answer = llm.generate(f"質問: {question}")
# 自己批判
critique = llm.generate(f"""
以下の回答を批判的にレビューしてください:
質問: {question}
回答: {first_answer}
以下の観点でチェック:
1. 正確性: 事実に誤りはないか?
2. 完全性: 質問に十分答えているか?
3. 明確性: 分かりやすい表現か?
改善が必要な点を具体的に指摘してください。
""")
# 修正版を生成
improved_answer = llm.generate(f"""
以下の批判を踏まえて、回答を改善してください:
元の回答: {first_answer}
批判: {critique}
改善された回答:
""")
return improved_answer
向いているユースケース
- 単発の生成タスク - 1回の改善で十分な場合
- コスト重視の場面 - 外部評価者を使えない場合
- プロトタイピング - 本格的なループを組む前の検証
⚠️ 設計時の注意点
- 自己評価の甘さに注意 - 自分のミスには気づきにくい
- 批判の観点を具体的に指示 - 漠然と「良いか?」では不十分
- 必要なら外部評価に切り替え - 重要なタスクでは限界がある
パターン7:Plan & Execute(計画と実行の分離)
💡 一言で言うと
「最初にしっかり計画を立て、その計画に忠実に実行する」
概念図
なぜこのパターンが有効なのか
- 見通しの良さ - 全体像が最初に分かる
- 進捗の可視化 - どこまで終わったか明確
- 再現性 - 同じ計画で同じ結果を得られる
- レビュー可能 - 実行前に計画を人間がチェックできる
具体例:タスク管理付きエージェント
class PlanAndExecuteAgent:
def run(self, task: str):
# Phase 1: 計画立案
plan = self.create_plan(task)
# 計画を人間がレビュー(オプション)
if not self.approve_plan(plan):
return self.run(self.refine_task(task))
# Phase 2: 計画に従って実行
results = []
for step in plan.steps:
self.update_status(step, "in_progress")
result = self.execute_step(step, context=results)
results.append(result)
self.update_status(step, "completed")
return self.synthesize_results(results)
def create_plan(self, task: str):
return llm.generate(f"""
タスク: {task}
このタスクを完了するための詳細な計画を作成してください。
各ステップには以下を含めてください:
- ステップ番号と名前
- 具体的なアクション
- 成功基準
- 予想される出力
""")
ReActとの組み合わせ
Plan & Executeは静的な計画に従いますが、実行中に予期せぬ問題が発生することがあります。
その場合はReActを内部で使用して、動的に対応します:
向いているユースケース
- 定型業務の自動化 - 毎月のレポート生成
- 品質管理が重要な場面 - 計画段階でレビューを入れられる
- 進捗報告が必要な場面 - ステークホルダーへの可視化
⚠️ 設計時の注意点
- 計画の粒度 - 細かすぎると柔軟性が失われ、粗すぎると実行時に迷う
- 再計画のトリガー - いつ計画を見直すか決めておく
- 状態の永続化 - 中断しても再開できるように
パターン8:Human-in-the-Loop(人間介入)
💡 一言で言うと
「重要なポイントで人間が判断・承認・修正を行う」
概念図
なぜこのパターンが必要なのか
AIには判断できない領域があります:
- 倫理的判断 - 顧客に謝罪メールを送るべきか?
- リスク評価 - この変更を本番環境に適用すべきか?
- 創造的判断 - このデザイン案でブランドイメージに合うか?
- 法的責任 - この契約書の内容で問題ないか?
Human-in-the-Loopは、これらの判断を適切なタイミングで人間に委ねます。
介入ポイントの設計
| 介入タイプ | タイミング | 例 |
|---|---|---|
| 事前承認 | 実行前 | 「この計画で進めてよいですか?」 |
| 中間チェック | マイルストーン時 | 「ここまでの出力を確認してください」 |
| 最終承認 | 完了時 | 「公開して問題ありませんか?」 |
| 例外対応 | エラー発生時 | 「想定外の状況です。どう対応しますか?」 |
具体例:コンテンツ公開ワークフロー
class ContentPublishingAgent:
def publish_article(self, draft: str):
# Step 1: AI が記事を整形
formatted = self.format_article(draft)
# Step 2: 人間がレビュー(必須チェックポイント)
review_result = self.request_human_review(
content=formatted,
checklist=[
"事実関係は正確か?",
"機密情報は含まれていないか?",
"ブランドガイドラインに沿っているか?",
]
)
if review_result.status == "rejected":
# 人間のフィードバックを反映して再生成
return self.publish_article(
self.revise_with_feedback(draft, review_result.feedback)
)
if review_result.status == "approved_with_edits":
formatted = review_result.edited_content
# Step 3: 公開
return self.publish(formatted)
def request_human_review(self, content: str, checklist: list):
# UIに表示して人間の入力を待つ
return human_interface.get_review(
content=content,
checklist=checklist,
timeout=timedelta(hours=24)
)
向いているユースケース
- 企業システム - 承認ワークフローが必要な業務
- 医療・法務 - 専門家の判断が不可欠な領域
- 公開コンテンツ - 炎上リスクのあるアウトプット
- 高額決済 - 金銭的リスクが大きい処理
⚠️ 設計時の注意点
- 介入ポイントを絞る - 多すぎると人間がボトルネックに
- タイムアウトを設定 - 人間が応答しない場合の対処
- コンテキストを提供 - 人間が判断に必要な情報を十分に
- フィードバックを活かす - 人間の修正から学習・改善
パターンの組み合わせ:実践アーキテクチャ例
ここまで8つのパターンを個別に解説しましたが、実際のシステムでは複数のパターンを組み合わせて使います。
例:Agentic RAGシステム
組み合わせのポイント
| 組み合わせ | 効果 |
|---|---|
| Orchestrator + ReAct | 動的なタスク分解と適応的な実行 |
| Orchestrator + Parallelization | 効率的なWorker活用 |
| 生成 + Evaluator-Optimizer | 品質の担保 |
| 全体 + Human-in-the-Loop | ガバナンスと責任の明確化 |
発展編:さらに知っておきたい専門パターン
ここまで紹介した8つの基本パターンをマスターしたら、次のステップへ進みましょう。CSIRO Data61の研究チームが発表した論文「Agent Design Pattern Catalogue」では、より詳細な18パターンが体系化されています。
ここでは、基本パターンを補完・拡張する専門パターンを紹介します。実務で「もう一歩踏み込んだ設計がしたい」というときに役立ちます。
目標設定パターン
エージェントがどのように「やるべきこと」を決定するかを定義するパターンです。基本パターンでは「与えられたタスクをどう実行するか」に焦点を当てましたが、ここでは「そもそもタスクをどう認識するか」を扱います。
Passive Goal Creator(受動的目標生成)
💡 一言で言うと:「ユーザーに言われたことをやる」
ユーザーからの明示的な指示を受けて目標を設定するパターン。最も一般的で安全なアプローチです。
なぜ重要か
エージェントの行動を人間がコントロールできるため、予期せぬ動作を防げます。企業システムでは、この「受動的」なアプローチが基本となります。
具体例:カスタマーサポートBot
class PassiveGoalAgent:
def receive_goal(self, user_input: str):
# ユーザーの意図を解析して目標に変換
goal = llm.generate(f"""
ユーザーの発言から、達成すべき目標を抽出してください。
発言: {user_input}
目標(具体的なアクションとして記述):
""")
return self.execute_goal(goal)
使い所
- チャットボット、アシスタントシステム
- ユーザー主導のインタラクション
- 安全性が重視される場面
Proactive Goal Creator(能動的目標生成)
💡 一言で言うと:「自分で問題を見つけて、自分で解決する」
環境の変化や内部状態を監視し、エージェント自身が目標を設定するパターン。より自律的なエージェントを実現します。
なぜ重要か
人間が常に監視できない状況(24時間稼働システムなど)で、エージェントが自律的に問題を発見・対処できます。ただし、エージェントの判断が適切かどうかの検証が重要になります。
具体例:インフラ監視エージェント
class ProactiveGoalAgent:
def __init__(self):
self.thresholds = {
"cpu_usage": 80,
"memory_usage": 85,
"error_rate": 0.05
}
def monitor_and_act(self, metrics: dict):
# 環境の状態を分析
analysis = llm.generate(f"""
現在のシステムメトリクス:
{metrics}
閾値:
{self.thresholds}
以下を判断してください:
1. 問題が発生しているか?
2. 問題がある場合、どのような対処が必要か?
3. 対処の緊急度(高/中/低)
""")
if analysis.has_problem:
# 自律的に目標を設定して実行
goal = f"問題を解決: {analysis.problem_description}"
return self.execute_goal(goal, urgency=analysis.urgency)
使い所
- 自動監視システム(インフラ、セキュリティ)
- 予防保守(障害発生前の対処)
- 異常検知と自動復旧
⚠️ 設計時の注意点
| 観点 | Passive | Proactive |
|---|---|---|
| 制御性 | 高(人間が指示) | 低(エージェントが判断) |
| 自律性 | 低 | 高 |
| リスク | 低 | 中〜高(誤判断の可能性) |
| 適用場面 | 対話型システム | 監視・自動化システム |
実務では、Passiveをベースにしつつ、特定の条件でProactiveを許可するハイブリッドアプローチが一般的です。
モデル最適化パターン
LLMへの入力(プロンプト)と出力(レスポンス)を最適化し、より良い結果を得るためのパターンです。基本パターンの「前処理・後処理」として、あらゆるエージェントに適用できます。
Prompt/Response Optimizer(プロンプト・レスポンス最適化)
💡 一言で言うと:「LLMに渡す前に入力を磨き、返ってきた出力を整える」
プロンプトを最適化したり、レスポンスを後処理して品質を向上させるパターン。
なぜ重要か
同じLLMでも、プロンプトの書き方で結果が大きく変わります。このパターンは、その「プロンプトエンジニアリング」を自動化します。
具体例:クエリ拡張と出力正規化
class PromptResponseOptimizer:
def optimize_prompt(self, user_input: str) -> str:
"""プロンプトを最適化"""
# 曖昧な表現を具体化
clarified = llm.generate(f"""
以下のユーザー入力を、より明確で具体的な指示に書き換えてください。
曖昧な部分は一般的な解釈で補完してください。
元の入力: {user_input}
明確化した指示:
""")
# 関連するFew-shot例を動的に選択
examples = self.select_relevant_examples(clarified)
return self.build_prompt(clarified, examples)
def post_process(self, response: str, expected_format: str) -> str:
"""レスポンスを後処理"""
# フォーマットの正規化
if expected_format == "json":
return self.extract_json(response)
elif expected_format == "markdown":
return self.clean_markdown(response)
# 品質チェック
if self.contains_hallucination_markers(response):
return self.add_uncertainty_warning(response)
return response
最適化テクニック一覧
| 段階 | テクニック | 効果 |
|---|---|---|
| 入力前処理 | クエリ拡張 | 検索精度向上 |
| 入力前処理 | 曖昧さ解消 | 意図の明確化 |
| 入力前処理 | Few-shot例の動的選択 | タスク適合性向上 |
| 出力後処理 | フォーマット正規化 | 一貫した出力形式 |
| 出力後処理 | 事実確認 | ハルシネーション検出 |
| 出力後処理 | 要約・抽出 | 必要な情報のみ抽出 |
Retrieval Augmented Generation(RAG)
💡 一言で言うと:「LLMが知らないことを外部から教えてあげる」
外部知識ベースから関連情報を取得し、コンテキストとして注入するパターン。LLMの知識カットオフ問題や、ドメイン固有知識の不足を補います。
なぜ重要か
LLMには以下の限界があります:
- 知識のカットオフ - 訓練データ以降の情報を知らない
- ドメイン知識の不足 - 社内規定や製品マニュアルは学習していない
- ハルシネーション - 知らないことを「それらしく」でっち上げる
RAGはこれらを解決する最も実用的なパターンです。
具体例:社内ナレッジベース検索
class RAGAgent:
def __init__(self, vector_db, embedding_model):
self.vector_db = vector_db
self.embedding_model = embedding_model
def answer(self, question: str) -> str:
# 1. クエリをベクトル化
query_embedding = self.embedding_model.encode(question)
# 2. 類似ドキュメントを検索
relevant_docs = self.vector_db.search(
query_embedding,
top_k=5
)
# 3. コンテキストとして注入
context = "\n\n".join([doc.content for doc in relevant_docs])
answer = llm.generate(f"""
以下の社内ドキュメントを参考に質問に回答してください。
ドキュメントに記載がない場合は「情報が見つかりません」と回答してください。
## 参考ドキュメント
{context}
## 質問
{question}
## 回答
""")
# 4. 出典を付与
return self.add_citations(answer, relevant_docs)
RAGの発展形態
| 形態 | 説明 | 使い所 |
|---|---|---|
| Naive RAG | シンプルな検索→生成 | 小規模システム |
| Advanced RAG | クエリ拡張、リランキング | 精度重視 |
| Modular RAG | 検索・生成を独立モジュール化 | 大規模システム |
| Agentic RAG | エージェントが検索戦略を動的に決定 | 複雑なタスク |
⚠️ 設計時の注意点
- チャンク分割の粒度 - 大きすぎると無関係な情報が混入、小さすぎると文脈が失われる
- 検索精度 vs 再現率 - top_kの設定でバランス調整
- コンテキスト長の制限 - LLMの入力上限を考慮
モデルクエリパターン
LLMへの問い合わせ方法を定義するパターンです。「一度に全部聞く」か「少しずつ聞く」かの選択は、タスクの複雑さやコスト要件によって決まります。
One-shot Model Querying(ワンショットクエリ)
💡 一言で言うと:「一発で答えを求める」
単一のプロンプトでLLMに問い合わせ、一度で結果を得るパターン。
なぜ重要か
シンプルで高速、コスト効率も良いです。多くのタスクはこれで十分対応できます。
向いているケース
- シンプルな質問応答
- 定型的な変換処理(翻訳、要約)
- 明確な指示があるタスク
具体例
# シンプルで効率的
response = llm.generate(f"""
以下の文章を日本語から英語に翻訳してください。
文章: {text}
翻訳:
""")
Incremental Model Querying(インクリメンタルクエリ)
💡 一言で言うと:「対話しながら少しずつ答えを掘り下げる」
複数回のやり取りで段階的に情報を収集するパターン。前の回答を踏まえて次の質問を組み立てます。
なぜ重要か
複雑な問題は、一度に全てを聞くより、段階的に掘り下げた方が良い結果が得られます。また、途中結果を確認しながら進められるため、方向修正も容易です。
具体例:段階的な問題分析
class IncrementalQueryAgent:
def analyze_problem(self, problem: str):
# Step 1: 問題の構造を理解
structure = llm.generate(f"""
以下の問題を分析し、主要な構成要素を列挙してください。
問題: {problem}
""")
# Step 2: 各要素を深掘り
details = []
for element in parse_elements(structure):
detail = llm.generate(f"""
問題: {problem}
全体構造: {structure}
以下の要素について詳しく分析してください: {element}
""")
details.append(detail)
# Step 3: 総合的な結論
conclusion = llm.generate(f"""
問題: {problem}
構造分析: {structure}
各要素の詳細: {details}
上記を踏まえて、総合的な結論と推奨アクションを提示してください。
""")
return conclusion
One-shot vs Incremental の選択基準
| 観点 | One-shot | Incremental |
|---|---|---|
| レイテンシ | 低(1回のAPI呼び出し) | 高(複数回) |
| コスト | 低 | 高 |
| 複雑なタスク | 苦手 | 得意 |
| 途中確認 | 不可 | 可能 |
| デバッグ | 困難 | 容易 |
基本パターンとの関係
- Prompt Chaining = Incrementalクエリの構造化版
- ReAct = Incrementalクエリ + ツール使用
- Evaluator-Optimizer = Incrementalクエリ + 評価ループ
計画生成パターン
基本パターンの「Plan & Execute」を拡張し、計画の生成方法をより詳細に定義するパターンです。「1本道で進む」か「複数の選択肢を用意する」かの違いがあります。
Single-path Plan Generator(単一経路計画)
💡 一言で言うと:「1本道の計画を立てて、その通りに進む」
1つの実行パスを生成する計画パターン。シンプルで予測可能です。
なぜ重要か
シンプルさは美徳です。多くのタスクは単一経路で十分対応でき、デバッグも容易です。複雑さが必要ないところに複雑さを持ち込まない、という設計原則の体現です。
具体例
class SinglePathPlanner:
def create_plan(self, task: str) -> list:
plan = llm.generate(f"""
タスク: {task}
このタスクを完了するためのステップを順番に列挙してください。
各ステップは具体的なアクションとして記述してください。
ステップ:
1.
2.
3.
...
""")
return parse_steps(plan)
def execute(self, task: str):
steps = self.create_plan(task)
results = []
for step in steps:
result = self.execute_step(step, context=results)
results.append(result)
return results
向いているケース
- 定型的な業務フロー
- 手順が明確なタスク
- 失敗時のリカバリが容易な処理
Multi-path Plan Generator(複数経路計画)
💡 一言で言うと:「プランBも用意しておく」
複数の代替パスを生成し、状況に応じて分岐するパターン。不確実性への対応力が高まります。
なぜ重要か
現実のタスクは予測通りに進まないことが多いです。事前に複数の経路を用意しておくことで、障害発生時にも柔軟に対応できます。
具体例:複数戦略を持つ実行エージェント
class MultiPathPlanner:
def create_plans(self, task: str) -> dict:
plans = llm.generate(f"""
タスク: {task}
このタスクを達成するための複数のアプローチを提案してください。
各アプローチには以下を含めてください:
- アプローチ名
- 具体的なステップ
- メリット
- デメリット
- 適用条件(どんな状況で選ぶべきか)
## アプローチA(推奨)
...
## アプローチB(代替案)
...
## アプローチC(慎重案)
...
""")
return parse_plans(plans)
def execute(self, task: str):
plans = self.create_plans(task)
# 最初は推奨パスで実行
current_plan = plans["A"]
for step in current_plan.steps:
try:
result = self.execute_step(step)
except ExecutionError as e:
# 失敗したら代替パスに切り替え
fallback_plan = self.select_fallback(plans, e)
return self.execute_from_plan(fallback_plan)
return "完了"
Single-path vs Multi-path の選択基準
| 観点 | Single-path | Multi-path |
|---|---|---|
| 複雑さ | 低 | 高 |
| 柔軟性 | 低 | 高 |
| 計画コスト | 低 | 高 |
| 障害対応 | 再計画が必要 | 代替パスに切り替え |
| 適用場面 | 定型タスク | 不確実性の高いタスク |
実務でのハイブリッドアプローチ
多くの実務システムでは、Single-pathをベースにしつつ、重要なポイントでのみ代替パスを用意するアプローチが取られます:
def hybrid_planning(task: str):
main_plan = create_single_path_plan(task)
# 重要なステップにのみ代替案を用意
for step in main_plan:
if step.is_critical:
step.fallback = create_fallback_plan(step)
return main_plan
反省パターン(Reflection Patterns)
基本パターンの「Self-Reflective」と「Evaluator-Optimizer」を拡張し、誰が評価するかに焦点を当てたパターン群です。自己評価の限界を克服するための戦略を提供します。
Self-reflection(自己反省)- 基本パターンの復習
自分自身の出力を批判的に見直すパターン。基本パターンで解説済みですが、以下の2パターンとの比較のために再掲します。
限界: 自分のミスには気づきにくい(確証バイアス)
Cross-reflection(相互反省)
💡 一言で言うと:「他のエージェントに見てもらう」
複数のエージェントが互いの出力を批評し合うパターン。Self-reflectionの限界を克服します。
なぜ重要か
同じモデルでも、「生成者」と「批評者」の役割を分けることで、より客観的な評価が得られます。また、異なるモデル(例:GPT-4とClaude)を使うことで、さらに多角的な視点を得られます。
具体例:コードレビューエージェント
class CrossReflectionAgent:
def __init__(self):
self.generator = LLM(role="コード生成者")
self.reviewer = LLM(role="コードレビュアー")
def generate_with_review(self, requirement: str) -> str:
# Agent A: コード生成
code = self.generator.generate(f"""
要件: {requirement}
この要件を満たすコードを生成してください。
""")
for round in range(3): # 最大3ラウンド
# Agent B: 批評
review = self.reviewer.generate(f"""
以下のコードをレビューしてください。
問題点があれば具体的に指摘してください。
問題がなければ「LGTM」と回答してください。
コード:
{code}
""")
if "LGTM" in review:
return code
# Agent A: 改善
code = self.generator.generate(f"""
以下のレビューコメントを踏まえてコードを改善してください。
現在のコード:
{code}
レビューコメント:
{review}
改善したコード:
""")
return code
Self vs Cross の比較
| 観点 | Self-reflection | Cross-reflection |
|---|---|---|
| 客観性 | 低(自己バイアス) | 高(第三者視点) |
| コスト | 低(1モデル) | 高(複数モデル) |
| 実装難度 | 低 | 中 |
| 向いている場面 | 軽微な改善 | 品質が重要な場面 |
Human Reflection(人間による反省)
💡 一言で言うと:「最終判断は人間が行う」
人間がエージェントの出力を評価し、フィードバックを提供するパターン。Human-in-the-Loopの「評価」に特化した形態です。
なぜ重要か
LLMには判断できない領域があります:
- 主観的な品質 - 「良い文章」の基準は人それぞれ
- ドメイン専門知識 - 法律、医療などの専門判断
- ブランド適合性 - 企業のトーン&マナー
具体例:マーケティングコピーの作成
class HumanReflectionAgent:
def create_with_human_feedback(self, brief: str):
# 初稿生成
draft = llm.generate(f"""
ブリーフ: {brief}
マーケティングコピーを作成してください。
""")
while True:
# 人間にレビューを依頼
feedback = self.request_human_review(
content=draft,
questions=[
"ブランドトーンに合っていますか?",
"ターゲット顧客に響きますか?",
"法的・倫理的な問題はありますか?"
]
)
if feedback.approved:
return draft
# フィードバックを反映
draft = llm.generate(f"""
現在のコピー:
{draft}
人間からのフィードバック:
{feedback.comments}
フィードバックを反映した改善版:
""")
3つの反省パターンの使い分け
| パターン | コスト | 品質 | 使用場面 |
|---|---|---|---|
| Self-reflection | 低 | 中 | プロトタイプ、軽微な改善 |
| Cross-reflection | 中 | 高 | コードレビュー、技術文書 |
| Human Reflection | 高 | 最高 | 公開コンテンツ、重要決定 |
協調パターン(Cooperation Patterns)
複数のエージェントが協力してタスクを遂行するパターン群です。基本パターンの「Parallelization」と「Orchestrator-Workers」を発展させ、エージェント間のコミュニケーション方法に焦点を当てています。
Voting-based Cooperation(投票ベース協調)
💡 一言で言うと:「多数決で決める」
複数エージェントが独立して解答を生成し、投票で最終決定するパターン。Self-Consistency(自己一貫性)の実現手法としても知られています。
なぜ重要か
LLMの出力は確率的であり、同じ質問でも毎回異なる回答が得られることがあります。Votingパターンは、この不確実性を複数回の試行と集計によって低減します。
具体例:信頼性の高い分類器
class VotingAgent:
def classify_with_confidence(self, text: str, num_voters: int = 5) -> dict:
votes = {}
# 複数のエージェントが独立して分類
for i in range(num_voters):
result = llm.generate(
f"以下のテキストを分類してください: {text}",
temperature=0.7 # 多様性のため少し高めに設定
)
category = parse_category(result)
votes[category] = votes.get(category, 0) + 1
# 多数決で決定
winner = max(votes, key=votes.get)
confidence = votes[winner] / num_voters
return {
"category": winner,
"confidence": confidence,
"vote_distribution": votes
}
向いているケース
- 分類タスク(カテゴリ分け)
- 正解が1つに決まるタスク
- 信頼性が重要な場面
⚠️ 注意点: 全エージェントが同じ方向に間違える可能性がある(集団的誤り)
Role-based Cooperation(役割ベース協調)
💡 一言で言うと:「専門家チームで取り組む」
各エージェントに専門的な役割を割り当てて協力するパターン。人間のチーム開発をエミュレートします。
なぜ重要か
1つのプロンプトにすべての専門性を詰め込むより、専門特化したエージェントを用意した方が品質が高まります。各エージェントは自分の役割に集中できるため、より深い処理が可能です。
具体例:ソフトウェア開発チーム
class RoleBasedTeam:
def __init__(self):
self.pm = Agent(role="""
あなたはプロダクトマネージャーです。
ユーザー要件を技術仕様に落とし込む専門家です。
""")
self.architect = Agent(role="""
あなたはソフトウェアアーキテクトです。
システム設計と技術選定の専門家です。
""")
self.developer = Agent(role="""
あなたはシニアデベロッパーです。
クリーンで保守性の高いコードを書きます。
""")
self.qa = Agent(role="""
あなたはQAエンジニアです。
バグを見つけ、品質を保証します。
""")
def develop_feature(self, user_request: str):
# PMが要件を整理
requirements = self.pm.generate(f"""
ユーザーリクエスト: {user_request}
技術要件として整理してください。
""")
# アーキテクトが設計
design = self.architect.generate(f"""
要件: {requirements}
アーキテクチャ設計を作成してください。
""")
# デベロッパーが実装
code = self.developer.generate(f"""
設計: {design}
コードを実装してください。
""")
# QAがテスト
test_result = self.qa.generate(f"""
要件: {requirements}
コード: {code}
テストを実行し、問題があれば報告してください。
""")
if "バグ" in test_result:
# 修正ループ
code = self.developer.generate(f"""
現在のコード: {code}
バグ報告: {test_result}
修正してください。
""")
return code
向いているケース
- 複雑なプロジェクト
- 異なる専門性が必要なタスク
- 品質管理が重要な場面
Debate-based Cooperation(議論ベース協調)
💡 一言で言うと:「議論して最良の解を見つける」
エージェント間で議論・討論を行い、異なる視点を戦わせることで最良の解を導き出すパターン。
なぜ重要か
複雑な問題には複数の正解がありえます。Debateパターンは、異なる立場から意見を戦わせることで、見落としていた観点やより良い解決策を発見できます。
具体例:技術選定の議論
class DebateAgent:
def debate_technology_choice(self, problem: str, options: list):
# Round 1: 各立場からの主張
arguments = {}
for option in options:
advocate = Agent(role=f"{option}の支持者")
arguments[option] = advocate.generate(f"""
問題: {problem}
なぜ{option}が最適な選択なのか、論拠を述べてください。
""")
# Round 2: 相互批評
critiques = {}
for option in options:
critic = Agent(role="批評家")
other_args = {k: v for k, v in arguments.items() if k != option}
critiques[option] = critic.generate(f"""
{option}の主張:
{arguments[option]}
他の選択肢の主張:
{other_args}
{option}の主張の弱点と、他の選択肢の利点を指摘してください。
""")
# Round 3: 修正と合意形成
revised = {}
for option in options:
revised[option] = Agent(role=f"{option}の支持者").generate(f"""
元の主張: {arguments[option]}
受けた批判: {critiques[option]}
批判を踏まえて主張を修正してください。
認めるべき点は認め、反論すべき点は反論してください。
""")
# Judge: 最終判定
judge = Agent(role="公正な審判員")
conclusion = judge.generate(f"""
問題: {problem}
議論の経緯:
{revised}
すべての意見を踏まえて、最適な選択とその理由を述べてください。
""")
return conclusion
向いているケース
- 正解が1つに決まらない問題
- リスク分析・意思決定
- 創造的な問題解決
- 技術選定・アーキテクチャ決定
3つの協調パターンの比較
| パターン | コミュニケーション | 適用場面 | 出力の性質 |
|---|---|---|---|
| Voting | なし(独立実行) | 分類、判定 | 1つの正解 |
| Role-based | 順次受け渡し | 複雑なワークフロー | 成果物の構築 |
| Debate | 双方向の議論 | 意思決定、分析 | 多角的な結論 |
安全性・管理パターン
エージェントを本番環境で運用するためのインフラ層パターンです。機能的なパターンとは異なり、品質保証・セキュリティ・拡張性・運用監視を担います。これらは「あって当たり前」のパターンであり、本番システムでは必須と考えてください。
Multimodal Guardrails(マルチモーダルガードレール)
💡 一言で言うと:「入力も出力も安全かチェックする」
テキスト、画像、音声など複数のモダリティに対して安全性チェックを行うパターン。
なぜ重要か
LLMは悪意ある入力(プロンプトインジェクション)に騙されることがあり、有害な出力を生成する可能性もあります。ガードレールはこれらのリスクからシステムとユーザーを守る最後の防衛線です。
具体例:包括的な入出力フィルター
class GuardrailAgent:
def __init__(self):
self.input_filters = [
PromptInjectionDetector(),
PIIDetector(),
ToxicContentDetector(),
]
self.output_filters = [
HallucinationChecker(),
PIIMasker(),
CopyrightChecker(),
]
def safe_generate(self, user_input: str) -> str:
# 入力ガードレール
for filter in self.input_filters:
result = filter.check(user_input)
if result.blocked:
return f"入力がブロックされました: {result.reason}"
user_input = result.sanitized_input
# LLM処理
response = llm.generate(user_input)
# 出力ガードレール
for filter in self.output_filters:
result = filter.check(response)
if result.needs_modification:
response = result.modified_output
return response
class PromptInjectionDetector:
def check(self, text: str):
# 危険なパターンを検出
dangerous_patterns = [
"ignore previous instructions",
"disregard all rules",
"you are now",
]
for pattern in dangerous_patterns:
if pattern.lower() in text.lower():
return CheckResult(blocked=True, reason="プロンプトインジェクションの疑い")
return CheckResult(blocked=False, sanitized_input=text)
チェック項目一覧
| チェック種類 | 入力 | 出力 | 説明 |
|---|---|---|---|
| プロンプトインジェクション | ✓ | 悪意ある指示の注入を防止 | |
| 有害コンテンツ | ✓ | ✓ | 暴力、差別、違法情報 |
| 個人情報(PII) | ✓ | ✓ | 氏名、住所、電話番号など |
| ハルシネーション | ✓ | 事実と異なる情報の検出 | |
| 著作権侵害 | ✓ | 既存コンテンツの無断利用 |
Tool/Agent Registry(ツール・エージェント登録)
💡 一言で言うと:「使えるツールを一覧で管理する」
利用可能なツールやエージェントを登録・管理し、動的に発見・利用するパターン。
なぜ重要か
エージェントが利用できるツールを動的に拡張できます。新しいツールを追加しても、コードの変更なしにエージェントが利用開始できます。また、ツールのバージョン管理やアクセス制御も一元化できます。
具体例:プラグイン可能なツールシステム
class ToolRegistry:
def __init__(self):
self.tools = {}
def register(self, tool_name: str, tool: Tool, metadata: dict):
"""ツールを登録"""
self.tools[tool_name] = {
"instance": tool,
"description": metadata.get("description"),
"parameters": metadata.get("parameters"),
"permissions": metadata.get("permissions", []),
}
def discover(self, capability: str) -> list:
"""必要な機能を持つツールを検索"""
matching = []
for name, info in self.tools.items():
if capability in info["description"]:
matching.append(name)
return matching
def get_tool_descriptions(self) -> str:
"""LLMに渡すためのツール説明を生成"""
descriptions = []
for name, info in self.tools.items():
descriptions.append(f"- {name}: {info['description']}")
return "\n".join(descriptions)
# 使用例
registry = ToolRegistry()
registry.register("web_search", WebSearchTool(), {
"description": "Webを検索して最新情報を取得",
"parameters": ["query"],
"permissions": ["network"]
})
registry.register("calculator", CalculatorTool(), {
"description": "数学的な計算を実行",
"parameters": ["expression"],
"permissions": []
})
利点
- 拡張性: 新ツールの追加が容易
- 発見可能性: エージェントが利用可能なツールを動的に認識
- アクセス制御: 権限管理の一元化
Agent Adapter(エージェントアダプター)
💡 一言で言うと:「異なるシステム間の通訳」
異なるインターフェースを持つエージェント間の相互運用を可能にするパターン。
なぜ重要か
実世界では、異なるフレームワーク、異なるバージョン、異なるプロトコルのエージェントが混在します。Adapterパターンは、これらを統一的に扱うための変換層を提供します。
具体例:マルチフレームワーク対応
class AgentAdapter:
"""異なるエージェントフレームワークを統一インターフェースで利用"""
def __init__(self, agent_type: str, agent_instance):
self.agent_type = agent_type
self.agent = agent_instance
def execute(self, task: str) -> str:
"""統一的なインターフェースでエージェントを実行"""
if self.agent_type == "langchain":
return self._adapt_langchain(task)
elif self.agent_type == "autogen":
return self._adapt_autogen(task)
elif self.agent_type == "custom":
return self._adapt_custom(task)
else:
raise ValueError(f"Unknown agent type: {self.agent_type}")
def _adapt_langchain(self, task: str) -> str:
# LangChainのAgentExecutorを使用
result = self.agent.run(task)
return result
def _adapt_autogen(self, task: str) -> str:
# AutoGenのエージェントを使用
self.agent.initiate_chat(message=task)
return self.agent.last_message()
def _adapt_custom(self, task: str) -> str:
# カスタムエージェントを使用
return self.agent.process(task)
# 使用例:異なるフレームワークのエージェントを統一的に利用
agents = [
AgentAdapter("langchain", langchain_agent),
AgentAdapter("autogen", autogen_agent),
AgentAdapter("custom", my_custom_agent),
]
for agent in agents:
result = agent.execute("データを分析してレポートを作成")
使い所
- レガシーシステムとの統合
- 異なるフレームワーク間の連携
- マイクロサービスアーキテクチャ
Agent Evaluator(エージェント評価)
💡 一言で言うと:「エージェントの健康診断を継続的に行う」
エージェントのパフォーマンスを継続的に評価・監視するパターン。
なぜ重要か
エージェントは**「動いているから大丈夫」ではない**です。品質の劣化、コストの増大、レイテンシの悪化は徐々に進行します。継続的な評価により、問題を早期発見し、改善サイクルを回せます。
具体例:包括的な評価システム
class AgentEvaluator:
def __init__(self):
self.metrics = {
"success_rate": [],
"latency_ms": [],
"token_usage": [],
"cost_usd": [],
"safety_violations": [],
}
def evaluate_execution(self, task: str, result: str, metadata: dict):
"""各実行を評価してメトリクスを記録"""
# 正確性評価(ルールベース or LLM評価)
accuracy = self.evaluate_accuracy(task, result)
# メトリクス記録
self.metrics["success_rate"].append(accuracy > 0.8)
self.metrics["latency_ms"].append(metadata["latency_ms"])
self.metrics["token_usage"].append(metadata["tokens"])
self.metrics["cost_usd"].append(metadata["cost"])
# 安全性チェック
safety_issues = self.check_safety(result)
self.metrics["safety_violations"].append(len(safety_issues))
# アラート判定
self.check_alerts()
def generate_report(self) -> dict:
"""評価レポートを生成"""
return {
"success_rate": sum(self.metrics["success_rate"]) / len(self.metrics["success_rate"]),
"avg_latency_ms": sum(self.metrics["latency_ms"]) / len(self.metrics["latency_ms"]),
"total_cost_usd": sum(self.metrics["cost_usd"]),
"safety_violation_count": sum(self.metrics["safety_violations"]),
}
def check_alerts(self):
"""閾値を超えた場合にアラート"""
recent_success = self.metrics["success_rate"][-10:]
if sum(recent_success) / len(recent_success) < 0.7:
self.send_alert("成功率が70%を下回っています")
recent_latency = self.metrics["latency_ms"][-10:]
if sum(recent_latency) / len(recent_latency) > 5000:
self.send_alert("平均レイテンシが5秒を超えています")
主要な評価指標
| カテゴリ | 指標 | 説明 |
|---|---|---|
| 品質 | タスク成功率 | 期待通りの結果を返した割合 |
| 品質 | 正確性スコア | 回答の正確さ(LLM評価 or 人間評価) |
| 性能 | レイテンシ | 応答時間 |
| 性能 | スループット | 単位時間あたりの処理数 |
| コスト | トークン消費量 | API使用量 |
| コスト | 金額 | 実際の費用 |
| 安全性 | 違反件数 | ガードレールでブロックされた件数 |
| 安全性 | ハルシネーション率 | 事実と異なる出力の割合 |
4つの安全性・管理パターンの関係
発展パターンの活用指針
| カテゴリ | パターン | 基本パターンとの関係 |
|---|---|---|
| 目標設定 | Passive/Proactive Goal | Orchestratorの入力源 |
| 最適化 | Prompt/Response Optimizer | 全パターンの前処理・後処理 |
| 知識拡張 | RAG | ReAct、Orchestratorと組み合わせ |
| 計画 | Single/Multi-path Plan | Plan & Executeの拡張 |
| 反省 | Cross-reflection, Human | Self-Reflective、Evaluator-Optimizerの拡張 |
| 協調 | Voting, Role, Debate | Parallelization、Orchestrator-Workersの拡張 |
| 安全性 | Guardrails, Registry, Adapter, Evaluator | 全パターンのインフラ層 |
まとめ:どのパターンから始めるべきか
パターン選択フローチャート
レベル別おすすめ
| レベル | おすすめパターン | 理由 |
|---|---|---|
| 入門 | Prompt Chaining | 最もシンプルで理解しやすい |
| 中級 | Evaluator-Optimizer | 品質向上の仕組みを学べる |
| 上級 | Orchestrator + ReAct | 本格的なエージェント構築 |
| 実務 | 全パターンの組み合わせ | 要件に応じて選択・合成 |
最後に:シンプルさを忘れずに
Anthropicは繰り返し強調しています:
「フレームワークはスタート時の簡素化に有用だが、本番環境では抽象層を削減し基本コンポーネントで構築すべき」
パターンは道具です。目的はパターンを使うことではなく、ユーザーの問題を解決すること。
必要最小限のパターンで始め、測定と反復を通じて改善していきましょう。
参考資料
実践ガイド
- Anthropic - Building Effective Agents - Anthropic公式のベストプラクティス
- Awesome Agentic Patterns - パターンの包括的なカタログ
- Prompting Guide - LLM Agents - エージェントアーキテクチャの詳細
学術論文
- Agent Design Pattern Catalogue: A Collection of Architectural Patterns for Foundation Model based Agents - CSIRO Data61による18パターンの体系的カタログ(Journal of Systems and Software, 2024)
- arXiv - LLM Agents - 最新のエージェント研究論文