OpenAI Agents SDKのhandoff — 専門エージェントへの引き渡し
ChatGPTクローンを作るうえで、1つのエージェントにすべてを任せるのは限界があります。天気、経済、地理……領域ごとに専門性が違います。
OpenAI Agents SDK の handoff を使うと、ユーザー向けの Main Agent が質問内容に応じて 専門エージェントに処理を委譲 できます。
handoff とは
handoff(ハンドオフ) = エージェント A が、自分では答えにくい質問を エージェント B に引き渡す 仕組みです。
ユーザー → Main Agent → (質問を判断)→ 専門 Agent → 回答
ツール(function_tool)が「外部APIを呼ぶ」のに対し、handoff は 別のエージェントに会話を渡す イメージです。
専門エージェントの定義
それぞれの専門エージェントに instructions と handoff_description を設定します。
handoff_description は、他のエージェント(Main Agent)が「いつこのエージェントに渡すか」 を判断するための説明です。
from agents import Agent, Runner, SQLiteSession
session = SQLiteSession("user_1", "ai-memory.db")
geography_agent = Agent(
name="Geography Expert Agent",
instructions="You are a geography expert. Answer questions about the world and its countries.",
handoff_description="Transfer to the economics expert if the user's question is about economics.",
)
economics_agent = Agent(
name="Economics Expert Agent",
instructions="You are an economics expert. Answer questions about economics and finance.",
handoff_description="Transfer to the geography expert if the user's question is about geography.",
)
| プロパティ | 役割 |
|---|---|
instructions |
そのエージェント自身の振る舞い |
handoff_description |
他のエージェント向け の「いつ渡すか」の説明 |
Main Agent — handoffs で専門家を登録
ユーザーと直接やり取りする Main Agent の handoffs リストに、専門エージェントを渡します。
main_agent = Agent(
name="Main Agent",
instructions="You are a user-facing agent. Transfer to the agent most capable of answering the user's question.",
handoffs=[
geography_agent,
economics_agent,
],
)
Main Agent は ルーター(受付) の役割。自分で全部答えるのではなく、適切な専門家に 委譲 します。
実行 — 質問内容で handoff 先が変わる
同じ Main Agent でも、質問の分野によって委譲先が変わります。
例1:経済の質問 → Economics Expert Agent
result = await Runner.run(
main_agent,
"韓国のウォン安の要因は?",
session=session,
)
print(result.last_agent.name)
print(result.final_output)
出力:
Economics Expert Agent
韓国ウォン安の主な要因は、だいたい次の通りです。
- **米ドル高**:米国の金利が高いとドルに資金が集まり、ウォンが売られやすい
- **韓国の輸出環境悪化**:半導体などの輸出が弱いと、外貨収入が減る
- **中国景気の減速**:韓国の輸出先である中国の需要が落ちるとウォン安要因
...
$\small{全然下がらない....}$
経済に関する質問なので、Economics Expert Agent に handoff しました。
例2:地理の質問 → Geography Expert Agent
result = await Runner.run(
main_agent,
"モンゴルの2番目に大きい都市はどこですか?",
session=session,
)
print(result.last_agent.name)
print(result.final_output)
出力:
Geography Expert Agent
モンゴルで2番目に大きい都市は **エルデネト** です。
地理に関する質問なので、今度は Geography Expert Agent に handoff しました。
比較
| 質問 | handoff 先 | 回答 |
|---|---|---|
| 韓国のウォン安の要因は? | Economics Expert Agent | ウォン安の経済要因 |
| モンゴルの2番目に大きい都市は? | Geography Expert Agent | エルデネト |
Main Agent は自分で答えず、質問内容を見て適切な専門家に渡す — これが handoff の核心です。
result.last_agent.name で 最終的に回答したエージェント を確認できます。UI では「Geography Expert が回答中…」のような表示に使えます。
handoff と tool の違い
function_tool |
handoff |
|
|---|---|---|
| 委譲先 | 関数(API・DBなど) | 別の Agent |
| 向いている用途 | 天気取得、計算、検索 | 専門分野ごとの回答 |
| 会話の文脈 | ツール結果を返す | エージェントが引き継いで回答 |
両方を組み合わせることもできます。例:Geography Agent が get_weather ツールを持ち、Economics Agent は経済データだけを扱う、など。
SQLiteSession との組み合わせ
Runner.run(..., session=session) に handoff を組み合わせると、委譲前後の会話履歴も DB に保存 されます。
- ユーザー発言
- handoff の記録
- 専門エージェントの回答
が同じセッションに残るため、次の質問でも文脈を引き継げます。
まとめ
- handoff = Main Agent から専門 Agent への 委譲(経済 → Economics、地理 → Geography)
-
handoff_description= 「いつこの Agent に渡すか」の説明(他 Agent 向け) -
handoffs=[...]= Main Agent に渡せる専門 Agent の一覧 -
result.last_agent.name= 最終的に回答した Agent を確認
ChatGPTクローンでは、1つのチャット UI の裏側に 複数の専門エージェント を置き、handoff でルーティングする構成が現実的です。