# AIエージェント設計パターン完全ガイド – Anthropic公式から学ぶ実装戦略

## はじめに

先日、有料で販売されているAIエージェント設計に関する情報を見かけました。内容を確認したところ、この程度なら無料で提供できると確信し、Anthropicの公式ドキュメント「[Building Effective AI Agents](https://www.anthropic.com/engineering/building-effective-agents)」を徹底的に調査しました。本記事では、AIエージェントの設計パターンからハーネス構築まで、実装に必要な知識を体系的にまとめています。

## AIエージェントと従来のLLMアプリケーションの違い

### 単発応答と反復実行の境界

従来のLLMアプリケーションは、ユーザーからの入力を受け取り、1回の推論で結果を返す**単発応答型**のアーキテクチャでした。一方、AIエージェントは**自律的な反復実行**を特徴とします。タスクが完了するまで、エージェント自身が次のアクションを判断し、必要なツールを呼び出し続けます。

この違いは、単なる実装の差ではありません。従来型では「どう答えるか」をプログラマーが制御していましたが、エージェント型では「何をすべきか」の判断をLLM自身に委ねます。これは制御の主体が人間からAIへと移行することを意味しています。

### コンテキストの連続性

従来のLLMアプリケーションでは、各リクエストが独立していました。しかし、AIエージェントは**コンテキストを保持しながら複数のステップを実行**します。前回の実行結果を参照し、次のアクションを決定する能力が求められます。

この連続性を実現するには、適切なメモリ管理とコンテキストウィンドウの活用が不可欠です。[LLMコーディング性能はハーネスで決まる?モデルより重要な「つなぎ方」の話](https://techinnovateit.com/llm-coding-harness-matters/)でも解説していますが、ハーネスの設計がエージェントの性能を左右します。Anthropicの[Tool Use API](https://docs.anthropic.com/en/docs/build-with-claude/tool-use)も活用することで、外部ツールとの連携を効率化できます。

### 失敗からの回復メカニズム

従来型アプリケーションでは、エラーが発生すると処理が停止し、エラーメッセージを返すだけでした。AIエージェントには**失敗から自律的に回復する能力**が期待されます。API呼び出しが失敗したら、別の方法を試す。期待した結果が得られなければ、アプローチを変更する。こうした柔軟性が、エージェントの実用性を決定します。

## 5つの主要設計パターン

Anthropicの公式ドキュメントでは、AIエージェントの設計パターンを5つに分類しています。それぞれの特徴と適用シーンを見ていきます。

### 1. Prompt Chaining(プロンプトチェイニング)

**プロンプトチェイニング**は、複雑なタスクを複数の小さなステップに分割し、それぞれを独立したLLM呼び出しで処理する手法です。各ステップの出力が次のステップの入力となり、連鎖的に処理が進行します。

#### 実装例

“`python
def analyze_customer_feedback(feedback):
# ステップ1: 感情分析
sentiment = llm.call(
prompt=f”以下のフィードバックの感情を分析してください: {feedback}”,
model=”claude-sonnet-4″
)

# ステップ2: カテゴリ分類
category = llm.call(
prompt=f”フィードバック: {feedback}\n感情: {sentiment}\nこのフィードバックをカテゴリに分類してください”,
model=”claude-sonnet-4″
)

# ステップ3: 優先度判定
priority = llm.call(
prompt=f”カテゴリ: {category}\n感情: {sentiment}\n対応優先度を判定してください”,
model=”claude-sonnet-4″
)

return {“sentiment”: sentiment, “category”: category, “priority”: priority}
“`

この手法の利点は、各ステップの品質を個別に最適化できる点です。感情分析には短いプロンプトで十分ですが、カテゴリ分類には詳細な例示が必要かもしれません。ステップごとに異なるモデルを使い分けることも可能です。

### 2. Routing(ルーティング)

**ルーティング**パターンは、入力の特性に応じて処理フローを切り替える手法です。質問の種類、ユーザーの意図、データの形式などに基づいて、最適な処理経路を選択します。

#### 適用シーン

カスタマーサポートボットを例に考えましょう。技術的な質問には技術文書を検索し、請求に関する質問にはアカウント情報を参照し、一般的な質問にはFAQで回答します。このように、入力の種類によって異なるツールやデータソースを使い分けるのがルーティングの本質です。

“`python
def handle_customer_query(query):
# クエリの種類を判定
query_type = llm.call(
prompt=f”以下の質問を分類してください(technical/billing/general): {query}”,
model=”claude-haiku-4″ # 分類タスクには軽量モデルで十分
)

if query_type == “technical”:
return search_technical_docs(query)
elif query_type == “billing”:
return query_billing_system(query)
else:
return search_faq(query)
“`

ルーティングの精度は、システム全体の効率に直結します。不適切なルーティングは、無駄なAPI呼び出しやユーザー体験の低下を招きます。

### 3. Parallelization(並列化)

**並列化**パターンでは、独立した複数のタスクを同時に実行します。これにより、全体の処理時間を大幅に短縮できます。

#### コスト削減効果

並列化の真の価値は、スピードだけではありません。レイテンシとコストの最適化が可能になります。例えば、記事の要約、翻訳、キーワード抽出を順次実行すると3回のAPI呼び出しが必要ですが、並列実行すれば待ち時間は最長のタスク1つ分に圧縮されます。

“`python
import asyncio

async def process_article(article):
tasks = [
llm.call_async(prompt=f”要約: {article}”, model=”claude-sonnet-4″),
llm.call_async(prompt=f”翻訳: {article}”, model=”claude-sonnet-4″),
llm.call_async(prompt=f”キーワード抽出: {article}”, model=”claude-haiku-4″)
]

summary, translation, keywords = await asyncio.gather(*tasks)
return {“summary”: summary, “translation”: translation, “keywords”: keywords}
“`

ただし、並列化にはリスクもあります。複数のAPI呼び出しが同時に失敗すると、リトライ処理が複雑になります。また、レート制限に引っかかる可能性も高まるでしょう。

### 4. Orchestrator-Workers(オーケストレーター・ワーカー)

**オーケストレーター・ワーカー**パターンは、中央の調整役(オーケストレーター)が複数の専門的なワーカーにタスクを割り振る設計です。これは、複雑なマルチステップタスクに適しています。

#### アーキテクチャの利点

このパターンの強みは、責任の分離にあります。オーケストレーターは全体の流れを管理し、各ワーカーは特定のサブタスクに特化します。例えば、リサーチエージェントでは、オーケストレーターが調査計画を立て、情報収集ワーカー、分析ワーカー、レポート作成ワーカーがそれぞれの役割を果たします。

“`python
class ResearchOrchestrator:
def __init__(self):
self.search_worker = SearchWorker()
self.analysis_worker = AnalysisWorker()
self.report_worker = ReportWorker()

def conduct_research(self, topic):
# 調査計画を立てる
plan = llm.call(
prompt=f”{topic}について調査計画を立ててください”,
model=”claude-opus-4″
)

# 情報収集
raw_data = self.search_worker.search(plan)

# 分析
insights = self.analysis_worker.analyze(raw_data)

# レポート作成
report = self.report_worker.generate(insights)

return report
“`

[Google Antigravity IDEとは?エージェントファーストの次世代AI開発環境を徹底解説](https://techinnovateit.com/google-antigravity-ide-agent-first-development/)で紹介されているような統合開発環境でも、このパターンが採用されています。

### 5. Evaluator-Optimizer(評価者・最適化者)

**評価者・最適化者**パターンは、出力の品質を評価し、必要に応じて改善を繰り返す手法です。生成した結果を別のLLM(または同じLLM)が評価し、基準を満たすまで再生成します。

#### 品質保証の仕組み

このパターンは、品質が重要な用途で威力を発揮するでしょう。例えば、法律文書の作成、医療レポートの生成、プログラムコードの自動生成など、エラーが許されない分野で活用されています。

“`python
def generate_legal_document(requirements, max_iterations=5):
for i in range(max_iterations):
# ドキュメント生成
document = llm.call(
prompt=f”以下の要件に基づいて法律文書を作成: {requirements}”,
model=”claude-opus-4″
)

# 評価
evaluation = llm.call(
prompt=f”この法律文書を評価してください: {document}”,
model=”claude-opus-4″
)

if evaluation[“score”] >= 0.9:
return document

# フィードバックを次の生成に反映
requirements += f”\n前回の問題点: {evaluation[‘feedback’]}”

raise Exception(“品質基準を満たすドキュメントを生成できませんでした”)
“`

このパターンの課題は、コストと時間です。複数回の生成と評価を繰り返すため、API呼び出しコストが増加します。品質と効率のバランスを慎重に調整する必要があります。

## 自律型エージェントの設計原則

### 目標設定の明確化

自律型エージェントには、明確な**終了条件**が必要です。「ユーザーが満足するまで続ける」といった曖昧な目標では、エージェントが無限ループに陥る危険があります。具体的な成功基準を定義しましょう。

### 観測可能性の確保

エージェントの動作をリアルタイムで監視できる仕組みが不可欠です。**ログ、メトリクス、トレース**を適切に実装し、問題が発生したときに迅速にデバッグできるようにします。

### 安全性の境界

自律型エージェントには、**行動の制約**を設ける必要があります。無制限にAPIを呼び出したり、外部システムを変更したりできると、予期しない問題を引き起こします。以下のような制約が考えられます:

– API呼び出し回数の上限
– 実行時間の制限
– 変更可能なリソースの範囲
– 確認が必要なアクションの定義

## ハーネス(実行基盤)の役割

### コンテキスト管理

ハーネスの最も重要な役割は、コンテキストの管理です。会話履歴、ツール呼び出しの結果、中間状態などを適切に保持し、エージェントが一貫した動作を維持できるようにします。

コンテキストウィンドウには限界があります。会話が長くなると、古い情報を削除するか、要約する必要があります。どの情報を保持し、どれを削除するかは、タスクの性質次第です。

### ツールインターフェース

エージェントが外部ツールを使うには、標準化されたインターフェースが必要です。ハーネスは、ツールの登録、呼び出し、結果の処理を一元管理します。

“`python
class AgentHarness:
def __init__(self):
self.tools = {}
self.context = []

def register_tool(self, name, function, description):
self.tools[name] = {
“function”: function,
“description”: description
}

def execute(self, task):
while not self.is_complete(task):
# エージェントに次のアクションを決めさせる
action = llm.call(
prompt=self.build_prompt(task),
tools=list(self.tools.values()),
model=”claude-opus-4″
)

# ツールを実行
if action[“type”] == “tool_call”:
result = self.tools[action[“tool”]][“function”](**action[“args”])
self.context.append({“action”: action, “result”: result})
else:
return action[“response”]

def build_prompt(self, task):
context_str = “\n”.join([str(c) for c in self.context])
return f”タスク: {task}\n\n過去の実行履歴:\n{context_str}\n\n次のアクションを決定してください”
“`

### エラーハンドリング

ハーネスは、エラーの検出と回復を担当します。API呼び出しの失敗、タイムアウト、不正な出力など、様々なエラーに対処する必要があります。

エラー発生時の戦略としては、以下が考えられます:

– リトライ(指数バックオフ)
– フォールバック(別の方法を試す)
– 人間への通知(重大なエラーの場合)
– グレースフルデグラデーション(機能を制限しつつ継続)

## 実装時の注意点

### コスト管理

AIエージェントは、複数回のLLM呼び出しを行うため、**コストが急速に増大**します。コスト削減のために、以下の戦略を検討しましょう:

1. タスクに応じたモデル選択: 単純な判断にはHaiku、複雑な推論にはOpusを使う
2. キャッシュの活用: 同じ質問への回答をキャッシュする
3. 並列化の最適化: 不要な並列実行を避ける
4. プロンプトの最適化: 冗長な指示を削除し、トークン数を減らす

### レイテンシの最適化

ユーザー体験を損なわないためには、**応答時間の管理**が重要です。以下の手法が有効です:

– ストリーミング応答: 結果が確定する前に部分的な出力を返す
– 非同期処理: バックグラウンドで時間のかかる処理を実行
– 段階的な情報提供: 最初に概要を示し、詳細は後から追加

### セキュリティとプライバシー

エージェントが外部APIやデータベースにアクセスする場合、**セキュリティリスク**が発生します:

– プロンプトインジェクション: 悪意のある入力でエージェントの動作を操作される
– データ漏洩: 機密情報がLLMのプロンプトに含まれる
– 権限昇格: エージェントが意図しない操作を実行する

これらのリスクに対処するには、入力のサニタイゼーション、アクセス制御、監査ログの実装が必要です。

## まとめ

AIエージェントの設計は、単にLLMを呼び出すだけではありません。適切な設計パターンの選択、ハーネスの構築、エラーハンドリング、コスト管理など、多岐にわたる要素を考慮する必要があります。

本記事で紹介した5つのパターン(Prompt Chaining、Routing、Parallelization、Orchestrator-Workers、Evaluator-Optimizer)は、それぞれ異なる用途に適しています。タスクの性質を見極め、最適なパターンを選択することが成功の鍵です。

また、ハーネスの設計は、エージェントの性能を左右する重要な要素です。コンテキスト管理、ツールインターフェース、エラーハンドリングを適切に実装することで、信頼性の高いエージェントシステムを構築できます。

AIエージェント開発は、まだ発展途上の分野です。この記事が、あなたの実装の出発点となれば幸いです。

**メタディスクリプション**: AIエージェントの5つの設計パターンとハーネス構築を解説。Anthropic公式ドキュメントを基に実装戦略を体系化