Pydantic AIではじめるAIエージェント超入門(2) 〜複数エージェントの連携とデータ構造〜
前回の記事 では、Pydantic AIの基礎として、エージェントの構成要素・ツール定義・依存関係の使い方を紹介しました。
今回はそこから一歩進んで、複数のエージェントを連携させて、より実践的なエージェント構築をします。
エージェント間でデータを受け渡しするマルチエージェント
本記事では、次の3つのエージェントが連携して動作する、パイプライン型のエージェントを作成します。
- 「データ収集エージェント」が情報を収集する
- 1 の結果をもとに「データ分析エージェント」が分析を行う
- 2 の結果をもとに「レポート作成エージェント」がレポートを生成する
from pydantic import BaseModel
from pydantic_ai import Agent
# データ収集エージェント
collector = Agent(
model="google-gla:gemini-2.0-flash-lite",
instructions=(
"与えられたトピックについて、"
"分析エージェントに渡すための要約を作成してください。"
"客観的で簡潔に、重要な情報のみを3点程度にまとめてください。"
),
)
# データ分析エージェント
class AnalysisInput(BaseModel):
topic: str
collected_info: str
analyzer = Agent(
model="google-gla:gemini-2.0-flash-lite",
instructions="収集された情報を分析し、ポジティブ・ネガティブ両面から簡潔に要約してください。",
)
# レポート作成エージェント
class ReportInput(BaseModel):
topic: str
summary: str
reporter = Agent(
model="google-gla:gemini-2.0-flash-lite",
instructions="分析結果をもとに、わかりやすい日本語レポートを作成してください。",
)
def run_pipeline(topic: str):
print(f"=== トピック: {topic} ===")
# ステップ1 情報収集
collected = collector.run_sync(f"{topic} に関する情報をまとめて")
print("\n[collector] 要約完了\n", collected.output)
# ステップ2 構造化データの検証
input_data = AnalysisInput(topic=topic, collected_info=collected.output)
analyzed = analyzer.run_sync(
f"{input_data.topic} に関する情報を次のように分析してください:\n{input_data.collected_info}"
)
print("\n[analyzer] 分析完了\n", analyzed.output)
# ステップ3 レポート作成
report_input = ReportInput(topic=topic, summary=analyzed.output)
report = reporter.run_sync(
f"次の要約をもとにレポートを作成してください:\n{report_input.summary}"
)
print("\n[reporter] レポート作成完了\n", report.output)
if __name__ == "__main__":
run_pipeline("AIによる教育支援")
出力例
=== トピック: AIによる教育支援 ===
[collector] 要約完了
AIによる教育支援 に関する要約は以下の通りです。
1. 個別最適化された学習: AIは、生徒の学習進捗や理解度を分析し、個々のニーズに合わせた学習コンテンツや学習方法を提示することで、学習効果の最大化を目指します。
2. 教育業務の効率化: AIは、採点、質問対応、教材作成などの教育業務を自動化し、教師の負担を軽減することで、教師が生徒との対話や指導に集中できる環境を創出します。
3. アクセス格差の是正: AIは、地理的要因や経済的理由で教育機会に恵まれない生徒に対して、オンライン学習プラットフォームなどを通じて、質の高い教育へのアクセスを提供し、教育格差の是正に貢献します。
[analyzer] 分析完了
## AIによる教育支援のポジティブ・ネガティブ要約
ポジティブな側面:
* 学習効果の向上: AIによる個別最適化された学習により、生徒は自身の理解度や進捗に合わせた学習を受け、効率的な学習が期待できます。
* 教師の負担軽減: AIが教育業務を効率化することで、教師はより生徒との対話や指導に時間を割けるようになり、質の高い教育を提供できます。
* 教育格差の是正: オンライン学習などを通じて、地理的・経済的要因による教育機会の格差を是正し、誰もが質の高い教育にアクセスできる可能性を広げます。
ネガティブな側面:
* 現時点では、ネガティブな側面についての記述はありません。しかし、AIの導入には、データのプライバシー保護、AIの誤作動による影響、人間的な触れ合いの減少、教師の役割の変化など、潜在的な課題も存在します。
[reporter] レポート作成完了
## AIによる教育支援:可能性と課題
### はじめに
近年、AI(人工知能)技術の進歩は教育分野にも大きな影響を与え始めています。本レポートでは、AIによる教育支援の可能性と、現時点での課題についてまとめます。
### ポジティブな側面:教育の質の向上と機会均等化
AIによる教育支援は、以下のような点で教育の質と機会均等化に貢献する可能性があります。
* 学習効果の向上: AIは、生徒一人ひとりの理解度や進捗状況を詳細に分析し、個別に最適化された学習プランを提供できます。これにより、生徒は効率的に学習を進め、学習効果を高めることが期待できます。
* 教師の負担軽減: AIは、採点、宿題の作成、学習進捗の管理など、教師の業務を効率化することができます。その結果、教師は生徒との対話や指導に集中できるようになり、より質の高い教育を提供することが可能になります。
* 教育格差の是正: オンライン学習プラットフォームなどを通じて、AIは地理的な制約や経済的な格差を超えて、誰もが質の高い教育にアクセスできる機会を提供します。これにより、教育機会の均等化が促進されます。
### ネガティブな側面:潜在的な課題と今後の展望
現時点では、AIによる教育支援における具体的なネガティブな側面に関する記述はありません。しかし、AIの導入には、以下のような潜在的な課題が存在します。
* プライバシー保護: 生徒の学習データは、AIによる個別最適化の基盤となりますが、そのデータのプライバシー保護は重要な課題です。データの漏洩や不正利用を防ぐための対策が不可欠です。
* AIの誤作動と影響: AIが誤った情報を提供したり、偏った学習を助長したりする可能性も考慮する必要があります。AIの精度と信頼性を高め、人間によるチェック体制を整備することが重要です。
* 人間的な触れ合いの減少: AIの導入が進むことで、教師と生徒の間の人間的な触れ合いが減少する可能性も指摘されています。教育における人間的なコミュニケーションの重要性を忘れずに、AIとのバランスを保つ必要があります。
* 教師の役割の変化: AIの導入は、教師の役割にも変化をもたらす可能性があります。AIが代替できない、生徒との人間的な繋がりを育むための指導力や、問題解決能力、創造性を育むための役割がより重要になると考えられます。
### まとめ
AIによる教育支援は、学習効果の向上、教師の負担軽減、教育機会の均等化など、教育の質の向上に貢献する可能性があります。しかし、データのプライバシー保護、AIの誤作動、人間的な触れ合いの減少、教師の役割の変化など、潜在的な課題も存在します。
AI技術を教育に効果的に活用するためには、これらの課題を認識し、適切な対策を講じることが重要です。今後、AI技術の発展と同時に、教育現場での実証実験や、倫理的な側面に関する議論を重ねながら、より良い教育環境の実現を目指していく必要があります。
run_pipeline 関数の中では、3つのエージェントが順に呼び出され、それぞれの出力結果を次のエージェントへと受け渡しています。
この構造によって、1つのLLMで完結しない複合的な処理を安全に連携できます。
処理の流れは次のとおりです。
- データ収集エージェント (
collector)
- 与えられたトピックについて情報を収集し、要約テキストとして出力
- この出力が次の分析エージェントの入力データになる
- データ分析エージェント (
analyzer)
-
collectorの出力を受け取り、ポジティブ・ネガティブなどの視点で内容を分析する - 分析結果の文字列を
reporterに引き継ぐ
- レポート作成エージェント (
reporter)
-
analyzerの出力を受け取り、自然な日本語のレポート形式でまとめる
このように、1つの関数内でエージェント間のデータを明示的に引き渡すことで、次の利点があります。
- データ構造が明確になる
- 各エージェントの責務が独立して保たれる
- 条件分岐や繰り返し処理を使って、パイプラインの流れをプログラム的に制御できる
- 途中結果を容易に検証できる
エージェント間のデータ構造
ここでは「エージェント同士がどのようなデータ構造で情報をやり取りしているのか」を詳しく確認します。
LLMの出力は文字列のように見えますが、実際には Pydantic モデルを介して構造化されたデータとして扱えます。
この仕組みを理解すると、より安全で再利用可能なAIパイプラインを設計できるようになります。
AgentRunResult
agent.run_sync は AgentRunResult を返します。
このクラス(インスタンス)はエージェント実行結果の 最終的な出力および実行の詳細情報を保持します。
このオブジェクトは、エージェントの最終出力だけでなく、実行時のメッセージ履歴・モデルレスポンス・トークン使用量など、「1回のエージェント実行のすべての情報」を保持しています。
ここからは、前述のコードで生成された AgentRunResult クラスの collected オブジェクトの内容を確認しつつ、主要な属性を紹介します。
output
エージェントの最終的な出力結果を表します。
通常は文字列として返されますが、output_type に BaseModel を指定している場合は、Pydantic モデルとして構造化された出力になります。
print(collected.output[:80])
出力例:
AIによる教育支援 に関する要約は以下の通りです。
1. 個別最適化された学習: AIは、生徒の学習進捗や理解度を分析し、個々のニーズに合わせた学習
all_messages
エージェントがこの実行中にやり取りした「すべてのメッセージ」を返します。
ユーザー入力、モデル出力などがすべて含まれ、プロンプトの流れをデバッグ・検証するのに役立ちます。
all_messages = collected.all_messages()
print(f"{type(all_messages)=}, {len(all_messages)=}")
出力例:
type(all_messages)=<class 'list'>, len(all_messages)=2
print(all_messages[0])
出力例:
ModelRequest(parts=[UserPromptPart(content='AIによる教育支援 に関する情報をまとめて', timestamp=datetime.datetime(2025, 10, 27, 2, 23, 47, 750978, tzinfo=datetime.timezone.utc))], instructions='与えられたトピックについて、分析エージェントに渡すための要約を作成してください。客観的で簡潔に、重要な情報のみを3点程度にまとめてください。')
print(all_messages[1])
出力例:
ModelResponse(parts=[TextPart(content='AIによる教育支援 に関する要約は以下の通りです。\n\n1. 個別最適化された学習: AIは、生徒の学習進捗や理解度を分析し、個々のニーズに合わせた学習コンテンツや学習方法を提示することで、学習効果の最大化を目指します。\n2. 教育業務の効率化: AIは、採点、質問対応、教材作成などの教育業務を自動化し、教師の負担を軽減することで、教師が生徒との対話や指導に集中できる環境を創出します。\n3. アクセス格差の是正: AIは、地理的要因や経済的理由で教育機会に恵まれない生徒に対して、オンライン学習プラットフォームなどを通じて、質の高い教育へのアクセスを提供し、教育格差の是正に貢献します。\n')], usage=RequestUsage(input_tokens=45, output_tokens=172, details={'text_prompt_tokens': 45, 'text_candidates_tokens': 172}), model_name='gemini-2.0-flash-lite', timestamp=datetime.datetime(2025, 10, 27, 2, 23, 49, 618336, tzinfo=datetime.timezone.utc), provider_name='google-gla', provider_details={'finish_reason': 'STOP'}, provider_response_id='s9f-aIfONbee1e8P6aHFsAE', finish_reason='stop')
all_messages_json
all_messages と同じ情報をJSON形式で取得します。
ログ保存や外部可視化ツールとの連携に便利です。
import json
import pprint
all_messages_json = json.loads(collected.all_messages_json())
pprint.pprint(all_messages_json[:200])
出力例:
[{'instructions': '与えられたトピックについて、分析エージェントに渡すための要約を作成してください。客観的で簡潔に、重要な情報のみを3点程度にまとめてください。',
'kind': 'request',
'parts': [{'content': 'AIによる教育支援 に関する情報をまとめて',
'part_kind': 'user-prompt',
'timestamp': '2025-10-27T02:23:47.750978Z'}]},
{'finish_reason': 'stop',
'kind': 'response',
'model_name': 'gemini-2.0-flash-lite',
'parts': [{'content': 'AIによる教育支援 に関する要約は以下の通りです。\n'
'\n'
'1. 個別最適化された学習: '
'AIは、生徒の学習進捗や理解度を分析し、個々のニーズに合わせた学習コンテンツや学習方法を提示することで、学習効果の最大化を目指します。\n'
'2. 教育業務の効率化: '
'AIは、採点、質問対応、教材作成などの教育業務を自動化し、教師の負担を軽減することで、教師が生徒との対話や指導に集中できる環境を創出します。\n'
'3. アクセス格差の是正: '
'AIは、地理的要因や経済的理由で教育機会に恵まれない生徒に対して、オンライン学習プラットフォームなどを通じて、質の高い教育へのアクセスを提供し、教育格差の是正に貢献します。\n',
'id': None,
'part_kind': 'text'}],
'provider_details': {'finish_reason': 'STOP'},
'provider_name': 'google-gla',
'provider_response_id': 's9f-aIfONbee1e8P6aHFsAE',
'timestamp': '2025-10-27T02:23:49.618336Z',
'usage': {'cache_audio_read_tokens': 0,
'cache_read_tokens': 0,
'cache_write_tokens': 0,
'details': {'text_candidates_tokens': 172,
'text_prompt_tokens': 45},
'input_audio_tokens': 0,
'input_tokens': 45,
'output_audio_tokens': 0,
'output_tokens': 172}}]
response
エージェントがモデルから受け取った生のレスポンスオブジェクトです。
プロバイダ固有のメタデータ(モデル名、トークン数、実行ID など)を含みます。
これを使うと、LLMプロバイダレベルでの挙動分析が可能です。
print(collected.response)
出力例:
ModelResponse(parts=[TextPart(content='AIによる教育支援 に関する要約は以下の通りです。\n\n1. 個別最適化された学習: AIは、生徒の学習進捗や理解度を分析し、個々のニーズに合わせた学習コンテンツや学習方法を提示することで、学習効果の最大化を目指します。\n2. 教育業務の効率化: AIは、採点、質問対応、教材作成などの教育業務を自動化し、教師の負担を軽減することで、教師が生徒との対話や指導に集中できる環境を創出します。\n3. アクセス格差の是正: AIは、地理的要因や経済的理由で教育機会に恵まれない生徒に対して、オンライン学習プラットフォームなどを通じて、質の高い教育へのアクセスを提供し、教育格差の是正に貢献します。\n')], usage=RequestUsage(input_tokens=45, output_tokens=172, details={'text_prompt_tokens': 45, 'text_candidates_tokens': 172}), model_name='gemini-2.0-flash-lite', timestamp=datetime.datetime(2025, 10, 27, 2, 23, 49, 618336, tzinfo=datetime.timezone.utc), provider_name='google-gla', provider_details={'finish_reason': 'STOP'}, provider_response_id='s9f-aIfONbee1e8P6aHFsAE', finish_reason='stop')
usage
トークン使用量の統計情報を格納します。
input_tokens, output_tokens, total_tokens の3項目が含まれ、コスト分析やリソース最適化に活用できます。
print(collected.usage())
出力例:
RunUsage(input_tokens=45, output_tokens=172, details={'text_prompt_tokens': 45, 'text_candidates_tokens': 172}, requests=1)
timestamp
エージェント実行が完了した日時(UTC)を示します。
ログ管理や、複数実行の時間比較などに利用できます。
print(collected.timestamp())
出力例:
2025-10-27 02:23:49.618336+00:00
まとめ
本記事では、Pydantic AIを用いた 複数エージェントの連携を通して、AI パイプラインの全体像とエージェント間のデータの流れを確認しました。
Pydantic AIでは次のようなフローが簡潔なコードで実装できます。
- 各エージェントが明確な役割を持ち、順に処理を担当し、1つのLLMに頼るよりも安定した結果を得られる
-
AgentRunResultを調べることで、内部でどのようなデータがやり取りされているかを可視化する - Pydantic AI の仕組みが、単なるプロンプト制御ではなく「構造化された情報パイプライン」を実現している
多分、次回に続きます。
Discussion