OpenAI Agents SDK のコア・ビルディングブロック – エージェントの機能の説明です。エージェントは指示とツールで構成された、大規模言語モデル (LLM) です。
OpenAI Agents SDK 0.3 : エージェント
作成 : クラスキャット・セールスインフォメーション
作成日時 : 10/15/2025
バージョン : v0.3.3
* 本記事は以下のページを参考にしています :
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
OpenAI Agents SDK 0.3 : エージェント
エージェントはアプリケーションのはコア・ビルディングブロックです。エージェントは指示 (instructions) とツールで構成された、大規模言語モデル (LLM) です。
基本的な構成設定
構成設定するエージェントの最も一般的なプロパティは以下です :
- name : エージェントを識別する必須の文字列。
- instructions: 開発者メッセージやシステムプロンプトとも呼ばれます。
- model: どの LLM を使用するか、そして temperature, top_p のようなモデル調整パラメータを設定するオプションの model_settings。
- tools: エージェントがタスクを遂行するために使用できるツール。
from agents import Agent, ModelSettings, function_tool
@function_tool
def get_weather(city: str) -> str:
"""returns weather info for the specified city."""
return f"The weather in {city} is sunny"
agent = Agent(
name="Haiku agent",
instructions="Always respond in haiku form",
model="gpt-5-nano",
tools=[get_weather],
)
コンテキスト
エージェントはコンテキスト型について汎用的 (generic) です (i.e. 型パラメータ化されています)。またコンテキストは依存性注入 (dependency-injection) ツールです : それはユーザが作成して Runner.run() に渡すオブジェクトで、すべてのエージェント、ツール、ハンドオフ等に渡され、そしてエージェント実行の依存性と状態の詰め合わせ (grab bag) として機能します。任意の Python オブジェクトをコンテキストとして提供できます。
@dataclass
class UserContext:
name: str
uid: str
is_pro_user: bool
async def fetch_purchases() -> list[Purchase]:
return ...
agent = Agent[UserContext](
...,
)
出力タイプ
デフォルトでは、エージェントは plain テキスト (i.e. str) 出力を生成します。エージェントに特定のタイプの出力を生成することを望む場合、output_type パラメータを使用できます。一般的な選択は Pydantic オブジェクトを使用することですが、Pydantic TypeAdapter – dataclasses, lists, TypedDict 等でラップできる任意のタイプをサポートします。
from pydantic import BaseModel
from agents import Agent
class CalendarEvent(BaseModel):
name: str
date: str
participants: list[str]
agent = Agent(
name="Calendar extractor",
instructions="Extract calendar events from text",
output_type=CalendarEvent,
)
Note : output_type を渡す場合、通常の plain テキスト応答ではなく、構造化出力 を使用するようにモデルに指示します。
マルチエージェントシステム・デザインパターン
マルチエージェントシステムの設計方法は数多くありますが、一般的には広く適用可能な 2 つのパターンがあります :
- マネージャ (ツールとしてのエージェント) : 中心的なマネージャ/オーケストレーターが専門のサブエージェントをツールとして呼び出し、会話の制御を維持します。
- ハンドオフ : peer エージェントが会話を引き継ぐ専門エージェントに制御をハンドオフします。これは分散型 (decentralized) です。
See our practical guide to building agents for more details.
マネージャ (ツールとしてのエージェント)
customer_facing_agent はすべてのユーザ・インタラクションを処理し、ツールとして公開されている、専門のサブエージェントをツールとして呼び出します。Read more in the tools documentation.
from agents import Agent
booking_agent = Agent(...)
refund_agent = Agent(...)
customer_facing_agent = Agent(
name="Customer-facing agent",
instructions=(
"Handle all direct user communication. "
"Call the relevant tools when specialized expertise is needed."
),
tools=[
booking_agent.as_tool(
tool_name="booking_expert",
tool_description="Handles booking questions and requests.",
),
refund_agent.as_tool(
tool_name="refund_expert",
tool_description="Handles refund questions and requests.",
)
],
)
ハンドオフ
ハンドオフはエージェントが委任できるサブエージェントです。ハンドオフが発生すると、委任されたエージェントは会話履歴を受け取り、会話を引き継ぎます。このパターンは、単一のタスクに優れた、モジュール型の専門エージェントの実現を可能にします。Read more in the handoffs documentation.
from agents import Agent
booking_agent = Agent(...)
refund_agent = Agent(...)
triage_agent = Agent(
name="Triage agent",
instructions=(
"Help the user with their questions. "
"If they ask about booking, hand off to the booking agent. "
"If they ask about refunds, hand off to the refund agent."
),
handoffs=[booking_agent, refund_agent],
)
動的な指示 (instructions)
殆どの場合、エージェントを作成するときに指示を提供できます。但し関数を通して動的な指示を提供することもできます。関数はエージェントとコンテキストを受け取り、プロンプトを返す必要があります。通常の関数と async 関数の両方が受け入れられます。
def dynamic_instructions(
context: RunContextWrapper[UserContext], agent: Agent[UserContext]
) -> str:
return f"The user's name is {context.context.name}. Help them with their questions."
agent = Agent[UserContext](
name="Triage agent",
instructions=dynamic_instructions,
)
ライフサイクル・イベント (フック)
エージェントのライフサイクルを観察したい場合があります。例えば、イベントをログ記録したり、特定のイベントが発生するときデータを事前取得したい場合があるかもしれません。hooks プロパティを使用してエージェントのライフサイクルをフックできます。AgentHooks クラスをサブクラス化して、関心のあるメソッドをオーバライドします。
ガードレール
ガードレールは、エージェントの実行と並行して、ユーザ入力と (生成後に) エージェントの出力をチェック/検証を実行することを可能にします。例えば、関連性の観点からユーザの入力とエージェントの出力をスクリーニングできるでしょう。Read more in the guardrails documentation.
エージェントのクローニング (複製) /コピー
エージェントの clone() メソッドを使用して、エージェントを複製し、オプションで好みのプロパティを変更することができます。
pirate_agent = Agent(
name="Pirate",
instructions="Write like a pirate",
model="gpt-4.1",
)
robot_agent = pirate_agent.clone(
name="Robot",
instructions="Write like a robot",
)
ツール使用の強制
ツールのリストの供給は、LLM がツールを使用することを意味しているとは限りません。ModelSettings.tool_choice を設定することで、ツール使用を強制できます。有効な値は :
- auto, LLM がツールを使用するか否か決定することができます。
- required, LLM がツールを使用することを必須にします (ただしどのツールを使用するかはインテリジェントに決定できます)。
- none, LLM がツールを使用しないことを必須にします。
- 特定の文字列 e.g. my_tool を設定すると、 LLM がその特定のツールを使用することを必須にします。
from agents import Agent, Runner, function_tool, ModelSettings
@function_tool
def get_weather(city: str) -> str:
"""Returns weather info for the specified city."""
return f"The weather in {city} is sunny"
agent = Agent(
name="Weather Agent",
instructions="Retrieve weather details.",
tools=[get_weather],
model_settings=ModelSettings(tool_choice="get_weather")
)
ツール使用時の動作
エージェント設定の tool_use_behavior パラメータはツール出力の処理方法を制御します :
- “run_llm_again”: デフォルト。ツールが実行され、LLM は結果を処理して最終的な応答を生成します。
- “stop_on_first_tool”: 最初のツール呼び出しの出力が最終的な応答として使用され、それ以上の LLM により処理は行われません。
from agents import Agent, Runner, function_tool, ModelSettings @function_tool def get_weather(city: str) -> str: """Returns weather info for the specified city.""" return f"The weather in {city} is sunny" agent = Agent( name="Weather Agent", instructions="Retrieve weather details.", tools=[get_weather], tool_use_behavior="stop_on_first_tool" )
- StopAtTools(stop_at_tool_names=[…]): 指定したツールが呼び出された場合には停止し、その出力を最終的な応答として使用します。
from agents import Agent, Runner, function_tool from agents.agent import StopAtTools @function_tool def get_weather(city: str) -> str: """Returns weather info for the specified city.""" return f"The weather in {city} is sunny" @function_tool def sum_numbers(a: int, b: int) -> int: """Adds two numbers.""" return a + b agent = Agent( name="Stop At Stock Agent", instructions="Get weather or sum numbers.", tools=[get_weather, sum_numbers], tool_use_behavior=StopAtTools(stop_at_tool_names=["get_weather"]) )
- ToolsToFinalOutputFunction: ツールの結果を処理して、LLM を停止するか続行するかを決定するカスタム関数。
from agents import Agent, Runner, function_tool, FunctionToolResult, RunContextWrapper from agents.agent import ToolsToFinalOutputResult from typing import List, Any @function_tool def get_weather(city: str) -> str: """Returns weather info for the specified city.""" return f"The weather in {city} is sunny" def custom_tool_handler( context: RunContextWrapper[Any], tool_results: List[FunctionToolResult] ) -> ToolsToFinalOutputResult: """Processes tool results to decide final output.""" for result in tool_results: if result.output and "sunny" in result.output: return ToolsToFinalOutputResult( is_final_output=True, final_output=f"Final weather: {result.output}" ) return ToolsToFinalOutputResult( is_final_output=False, final_output=None ) agent = Agent( name="Weather Agent", instructions="Retrieve weather details.", tools=[get_weather], tool_use_behavior=custom_tool_handler )
Note : 無限ループを防ぐために、フレームワークはツール呼び出し後に tool_choice を “auto” に自動的にリセットします。この動作は agent.reset_tool_choice で設定可能です。無限ループが発生するのは、ツールの結果が LLM に送信され、これが tool_choice ゆえに別のツール呼び出しを無限に生成するためです。
以上