結論: マルチエージェントAIシステムの成否を決めるのはモデル性能ではなく、エージェント間の「オーケストレーション設計」である。
▶ 関連記事:A2Aプロトコルとは?マルチエージェント連携の標準規格を解説
この記事の要点:
- 要点1: マルチエージェントには4つの基本パターン(Supervisor / Router / Hierarchical / Swarm)があり、用途で使い分ける
- 要点2: GitHubの調査によると、失敗の大半は「構造の欠如」が原因であり、型付きスキーマとアクションスキーマで解決できる
- 要点3: PythonとLangGraphで、今日から動くマルチエージェントシステムを構築できる
対象読者: シングルエージェントは構築済みで、複数エージェントの連携に挑戦したいエンジニア・PM
読了後にできること: LangGraphでSupervisorパターンのマルチエージェントを実装し、ローカルで動かす
「AIエージェントを1つ作ったけど、複数を連携させると途端に崩壊する…」
▶ 関連記事:AIエージェントとは?基礎から仕組み・活用事例まで解説
これは多くの開発チームが直面する壁です。シングルエージェントなら安定して動くのに、2つ以上のエージェントが協調し始めると、タスクの重複、矛盾する出力、無限ループといった問題が頻発します。
GitHub Blogが2026年2月に公開した記事「Multi-agent workflows often fail」では、この原因を明確に指摘しています。エージェントの失敗はモデル性能ではなく、構造の欠如――つまりオーケストレーション設計の問題だと。
この記事では、マルチエージェントの4つのオーケストレーションパターンを、コピペ可能なPythonコード付きで解説します。5分で動くサンプルから始めましょう。
まず試したい「5分即効」セットアップ
以下のコードで、最もシンプルなSupervisorパターンのマルチエージェントを動かせます。
# 動作環境: Python 3.11+, langgraph>=0.3.0, langchain-openai>=0.3.0
# pip install langgraph langchain-openai langchain-core
import os
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState, START, END
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "your-key")
llm = ChatOpenAI(model="gpt-4o")
# リサーチャーエージェント
def researcher(state: MessagesState):
system = "あなたはリサーチ担当です。与えられたトピックについて要点を3つ挙げてください。"
response = llm.invoke([{"role": "system", "content": system}] + state["messages"])
return {"messages": [response]}
# ライターエージェント
def writer(state: MessagesState):
system = "あなたはライター担当です。リサーチ結果をもとに、200字以内の要約を書いてください。"
response = llm.invoke([{"role": "system", "content": system}] + state["messages"])
return {"messages": [response]}
# グラフ構築
graph = StateGraph(MessagesState)
graph.add_node("researcher", researcher)
graph.add_node("writer", writer)
graph.add_edge(START, "researcher")
graph.add_edge("researcher", "writer")
graph.add_edge("writer", END)
app = graph.compile()
result = app.invoke({"messages": [{"role": "user", "content": "AIエージェントの最新トレンド"}]})
print(result["messages"][-1].content)
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
ポイント: このコードは直列パイプライン(Researcher → Writer)ですが、これがマルチエージェントの最小単位です。ここから条件分岐やループを加えることで、本格的なオーケストレーションに発展させます。
4つのオーケストレーションパターンを理解する
マルチエージェントの設計は、大きく4つのパターンに分類できます。用途と複雑度に応じて選択してください。
| パターン | 概要 | 適用場面 | 複雑度 |
|---|---|---|---|
| Supervisor | 1つの管理エージェントがタスクを分解・委任 | CSボット、ドキュメント生成 | ★★☆☆☆ |
| Router | 入力の種類に応じて専門エージェントに振り分け | 問い合わせ分類、マルチスキル対応 | ★★☆☆☆ |
| Hierarchical | Supervisorを階層化し、大規模タスクを分割統治 | 企業の部門横断ワークフロー | ★★★★☆ |
| Swarm | エージェント同士が対等に協調・ハンドオフ | 創造的タスク、ディベート | ★★★☆☆ |
パターン1: Supervisor(最も実用的)
1つの「司令塔」エージェントが全体を統括し、専門エージェントにタスクを割り振るパターンです。Amazon Bedrockのマルチエージェントコラボレーションでも、このSupervisorモードがデフォルトとして採用されています。
# Supervisorパターン — 動的にエージェントを選択
# 動作環境: Python 3.11+, langgraph>=0.3.0
from typing import Literal
from langgraph.graph import StateGraph, MessagesState, START, END
def supervisor(state: MessagesState) -> dict:
"""タスク内容を判定し、適切なエージェントにルーティング"""
last_msg = state["messages"][-1].content.lower()
if "コード" in last_msg or "実装" in last_msg:
return {"next": "coder"}
elif "調査" in last_msg or "リサーチ" in last_msg:
return {"next": "researcher"}
else:
return {"next": "writer"}
def route(state: dict) -> Literal["coder", "researcher", "writer"]:
return state.get("next", "writer")
graph = StateGraph(MessagesState)
graph.add_node("supervisor", supervisor)
graph.add_node("coder", coder_agent) # 各エージェント関数は別途定義
graph.add_node("researcher", researcher_agent)
graph.add_node("writer", writer_agent)
graph.add_conditional_edges("supervisor", route)
graph.add_edge(START, "supervisor")
for node in ["coder", "researcher", "writer"]:
graph.add_edge(node, END)
app = graph.compile()
パターン2: Router(高速振り分け)
Supervisorがタスクを分解するのに対し、Routerは入力をそのまま最適なエージェントに転送します。タスク分解が不要な場合、Routerの方がレイテンシもコストも低くなります。
パターン3: Hierarchical(大規模向け)
Supervisorを入れ子にするパターンです。「経営企画Supervisor → マーケSupervisor → コンテンツAgent / 広告Agent」のように、組織構造をそのままエージェント階層に写像できます。
パターン4: Swarm(対等協調)
OpenAIのSwarmフレームワークで注目されたパターンです。中央の管理者を置かず、エージェント同士が直接ハンドオフします。柔軟性は高いですが、デバッグが難しくなるため、明確なハンドオフルールの設定が必須です。
GitHubが教える「失敗しない」3つの設計原則
GitHubは社内のCopilotやCI/CD自動化でマルチエージェントを大規模運用しており、2026年2月のブログで3つの設計原則を公開しました。
原則1: 型付きスキーマで曖昧さを排除する
エージェント間でやり取りするデータには、必ず型定義を設けます。自然言語のまま受け渡すと、フィールド名のブレや型の不一致で下流が壊れます。
# Pydanticでエージェント間のデータ契約を定義
# 動作環境: Python 3.11+, pydantic>=2.0
from pydantic import BaseModel, Field
from typing import Literal
class ResearchResult(BaseModel):
"""リサーチエージェントの出力スキーマ"""
topic: str = Field(description="調査トピック")
key_findings: list[str] = Field(description="主要な発見(3〜5件)")
sources: list[str] = Field(description="参照ソースURL")
confidence: Literal["high", "medium", "low"] = Field(description="情報の確信度")
class ActionDecision(BaseModel):
"""Supervisorのアクション決定スキーマ"""
action_type: Literal["delegate", "respond", "escalate"] = Field(description="次のアクション")
target_agent: str | None = Field(default=None, description="委任先エージェント名")
reason: str = Field(description="判断理由")
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
ポイント: スキーマ違反は「契約違反」として即座にリトライまたはエスカレーションします。ログから原因を推測する必要がなくなります。
原則2: アクションスキーマで意図を明確にする
「この課題を分析して対応して」という曖昧な指示では、エージェントごとに異なる行動を取ります。許可するアクションを明示的に列挙することで、予測可能な動作を保証します。
原則3: MCPで構造を強制する
Model Context Protocol(MCP)は、ツール呼び出しの入出力スキーマを定義し、実行前にバリデーションを行います。スキーマとアクションの設計を「お約束」から「強制」に昇格させるのがMCPの役割です。
【要注意】よくある失敗パターンと回避策
失敗1: エージェント間で状態が共有されない
❌ 各エージェントが独立してLLMを呼び出し、前のエージェントの出力を参照しない
⭕ StateGraphの共有ステートに結果を書き込み、後続エージェントが参照する構造にする
なぜ重要か: あるエージェントが開いたIssueを、別のエージェントが重複と判断して閉じる――GitHubが実際に報告した典型的な失敗です。
失敗2: 無限ループに陥る
❌ エージェント同士が互いにタスクを投げ合い、終了条件がない
⭕ ループ回数の上限を設定し、上限に達したら人間にエスカレーションする
# ループ上限の設定例
MAX_ITERATIONS = 5
def should_continue(state: dict) -> str:
if state.get("iteration_count", 0) >= MAX_ITERATIONS:
return "escalate_to_human"
return "continue"
失敗3: 全てのタスクをマルチエージェントにする
❌ シンプルなタスクにも複数エージェントを投入し、複雑性とコストが増大
⭕ まずシングルエージェントで解決できないか検討し、本当に分業が必要な場合のみマルチエージェントを採用する
なぜ重要か: エージェントを増やすほどレイテンシとAPI コストが増加します。2エージェントで済むところを5エージェントにしても、品質は上がりません。
失敗4: エラーハンドリングがない
❌ 1つのエージェントが失敗すると、パイプライン全体が停止
⭕ 各エージェントにtry/exceptとフォールバック処理を実装し、障害を局所化する
パターン選定フローチャート
どのパターンを選ぶべきか迷ったら、以下の判断基準を参考にしてください。
| 判断基準 | 推奨パターン | 理由 |
|---|---|---|
| タスクが明確に分業できる | Supervisor | 各エージェントの責務が明確になる |
| 入力タイプで処理が分岐する | Router | 分類→転送のシンプルな構造で十分 |
| 組織の階層構造を反映したい | Hierarchical | 部門ごとのSupervisorで管理範囲を限定 |
| 創造的タスク・議論が必要 | Swarm | 対等な立場での多角的な検討が可能 |
| タスクがシンプル | シングルエージェント | マルチエージェントは過剰設計 |
セキュリティと運用の注意点
マルチエージェントシステムでは、単一エージェント以上にセキュリティリスクが増大します。Adversa AIが2026年3月に公開したレポートでは、エージェント間通信における新たな攻撃面(間接的プロンプトインジェクション、エージェント間のペイロード汚染)が指摘されています。
- プロンプトインジェクション対策: エージェント間で渡すデータは、必ず型付きスキーマでバリデーションし、自然言語の生テキストをそのまま次のエージェントに渡さない
- APIキー管理: 各エージェントが個別にAPIキーをハードコードしない。環境変数またはSecrets Managerを使用する
- コスト上限: マルチエージェントはAPI呼び出し回数が乗算的に増える。1リクエストあたりのトークン上限とループ回数上限を必ず設定する
- ログとモニタリング: 各エージェントの入出力をログに記録し、異常な出力パターンを検知するアラートを設定する
正直にお伝えすると、マルチエージェントシステムの本番運用はまだ発展途上です。完璧な自律動作を期待するのではなく、人間がモニタリングし介入できる「Human-in-the-Loop」設計が現時点でのベストプラクティスです。
参考・出典
- Multi-agent workflows often fail. Here’s how to engineer ones that don’t. — GitHub Blog(参照日: 2026-03-05)
- Top Agentic AI Security Resources — March 2026 — Adversa AI(参照日: 2026-03-05)
- How to choose the right orchestration pattern for multi agent system — Kore.ai(参照日: 2026-03-05)
- Pythonで始めるマルチエージェントAI ―CrewAI入門 — gihyo.jp(参照日: 2026-03-05)
- Multi-agent Systems — LangChain公式ドキュメント(参照日: 2026-03-05)
あわせて読みたい:Mastra TypeScript AIフレームワーク完全ガイド
あわせて読みたい:OpenAI Agents SDK実践ガイド
まとめ:今日から始める3つのアクション
- 今日やること: 冒頭の「5分即効セットアップ」コードをコピペして、Researcher→Writerの直列パイプラインを動かしてみる
- 今週中: 自分の業務で「2つ以上のステップに分解できるタスク」を1つ選び、Supervisorパターンで試作する
- 今月中: 型付きスキーマ(Pydantic)とエラーハンドリングを追加し、チーム内でデモを実施する
あわせて読みたい:
- AIエージェントとは?仕組み・活用事例・作り方を完全解説 — エージェントの基本概念から学びたい方に
- CrewAI vs LangGraph vs AutoGen 徹底比較 — フレームワーク選定で迷っている方に
- AIエージェントフレームワーク勢力図【2026年最新】 — 設計パターンを実装するFWの選定に役立つ最新勢力図
著者: 佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー10万人超。
100社以上の企業向けAI研修・導入支援。著書累計3万部突破。
SoftBank IT連載7回執筆(NewsPicks最大1,125ピックス)。
ご質問・ご相談は お問い合わせフォーム からお気軽にどうぞ。