39
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

15分でわかる!AIエージェント開発の最新フレームワーク OpenAI Agents SDK

Last updated at Posted at 2025-03-13

はじめに

こんにちは!KIYOラーニングでスタディングの開発を担当している @Kumacchiino です!
今回は、先日OpenAIが新たに公開したAIエージェントのフレームワークOpenAI Agents SDKについてご紹介します。

本フレームワークを使うと、AIエージェントの活動をオーケストレーションできるようになり、複数のエージェントが連携して複雑な課題に取り組むことができるようになります。

この記事では、OpenAI Agents SDKのコアとなる4つの概念を取り入れ、Pythonでシンプルなアプリを作成し、フレームワークの使い方やエージェントシステムの基本的な動きを解説します。

記事の最後には、完成したプログラム全体を掲載しています。

エージェントシステムの全体像

今回作成するエージェントシステムの全体像と仕様は、以下のようになります。

AIエージェント全体像2.png

ユーザーは以下のようなタスクをエージェントに依頼してくる想定で構築しております。

  1. 住宅ローンの計算
  2. 旅費の計算
  3. 上記以外のタスク

マネージャーエージェントは、依頼されたタスクを分類および評価し、専門のエージェントへ委譲します。
各エージェントは、ツール自律的に使用してタスクを処理し、その結果を返す仕組みです。
また、想定外のタスクが依頼された場合には、タスクの実行を拒否するガードレール機能も備えています。

この記事を読むとわかること

この記事では、OpenAI Agents SDKのコアとなる4つの概念(以下の項目)の役割使い方を解説します。

  • Agents(エージェント)
  • Handoffs(ハンドオフ)
  • Guardrails(ガードレール)
  • Tracing(トレーシング)

また、プログラムの実行例や全体のコードを通して、実際の動作イメージや実用例についても解説します。

前提条件

  • OpenAIのAPIキーを発行し、環境変数に設定していること(プログラムを実際に動かす場合)
  • Pythonの基本的な知識があること

環境構築

まずは、ローカル環境にPythonの仮想環境を作成します。

python -m venv env
source env/bin/activate

その後、OpenAI Agents SDKをpipでインストールします。

pip install openai-agents

必要に応じて、.envファイルからAPIキーを読み込むためのpython-dotenvもインストールしてください。

pip install python-dotenv

Agents(エージェント)

まずは、エージェントについてです。
エージェントはフレームワークの中核となるコンポーネントであり、名前、役割、使用するモデル、利用するツールなどを設定して定義します。

例として、旅費計算エージェントは以下のように定義します。

travel_expense_agent = Agent(
    name="旅費計算エージェント",
    instructions=(
        "旅費の計算を頼まれたら、ツールを使って回答すること。"
        "計算には、旅行日数と1日あたりの基本費用、任意で追加費用を使用する。"
        "内部計算では、土日の割増、長期旅行割引、消費税加算などを実施する。"
    ),
    model="gpt-4o-mini",
    tools=[travel_expense_calculator],
)

エージェントが使用する旅費計算ツールは、以下のように関数として定義します。

@function_tool
def travel_expense_calculator(days: int, base_daily_cost: float, other: float = 0) -> str:
    """
    旅費計算ツール(複雑な計算):
    旅行日数(days)と1日あたりの基本費用(base_daily_cost)、任意の追加費用(other)から、
    以下の計算を行い、最終的な旅費を求める。
    
    計算内容:
    1. 旅行日数のうち約2/7を土日と仮定し、土日は基本費用の10%増しとする。
    2. 平日は残りの日数とする。
    3. 7日を超える場合は、超過日数に対して基本費用の5%を割引する。
    4. 最終的な小計に10%の消費税を加算する。
    """
    weekend_days = int(days * 2 / 7)
    weekday_days = days - weekend_days
    weekday_cost = weekday_days * base_daily_cost
    weekend_cost = weekend_days * base_daily_cost * 1.10
    discount_days = max(0, days - 7)
    discount = discount_days * base_daily_cost * 0.05
    subtotal = weekday_cost + weekend_cost - discount + other
    total = subtotal * 1.1

    return f"最終的な旅費は {total:.2f} 円です"

これで、旅費計算エージェントの定義が完了しました。
直感的で分かりやすいコードにより、エージェントの定義が容易に行えます。

Handoffs(ハンドオフ)

ハンドオフ機能を利用すると、エージェントは他のエージェントへタスクを委譲することができます。
例えば、専門性の高いエージェントを複数用意し、マネージャーエージェントがユーザーの質問を評価・分類した上で、適切なエージェントへタスクを振り分ける仕組みです。

今回のプログラムでは、住宅ローン計算エージェントと旅費計算エージェントを用意し、マネージャーエージェントがユーザーの質問を受け取り、各エージェントにタスクを委譲します。
プログラム上では、エージェントの定義時にhandoffs引数を使用して、委譲先のエージェントをリスト形式で指定します。

manager_agent = Agent(
    name="マネージャーエージェント",
    instructions=(
        "ユーザーからの質問を受け取り、適切なエージェントに回答を依頼する。"
    ),
    handoffs=[loan_calculator_agent, travel_expense_agent]
)

Guardrails(ガードレール)

ガードレールは、エージェントの実行と並行して動作し、ユーザーの入力をチェックおよび検証する機能です。
今回のケースでは、旅費計算や住宅ローン計算以外のタスクが依頼された場合に、ガードレールを用いてその遂行を拒否する仕組みを実装しています。
この仕組みにより、安全なエージェントシステムの構築が可能になります。

まず、ガードレール用のエージェントを定義し、このエージェントを利用してガードレール機能を構築します。
ガードレールは、@input_guardrailデコレータを用いて関数として定義し、定義したガードレール関数をマネージャーエージェントのinput_guardrails引数にリスト形式で指定します。

class IntendedTaskOutput(BaseModel):
    # タスクが不適切かどうかの判定結果を保持するクラス
    is_inappropriate_task: bool  # 不適切なタスクかどうかのフラグ
    reasoning: str  # 判定の理由

# ガードレールチェックを行うエージェントの定義
guardrail_agent = Agent( 
    name="ガードレールチェックエージェント",
    instructions="旅費計算やローン計算以外のタスクをチェックして、不適切なタスクかどうかを判定する。",
    model="gpt-4o-mini",
    output_type=IntendedTaskOutput,
)

@input_guardrail
async def task_guardrail( 
    ctx: RunContextWrapper[None], agent: Agent, input: str | list[TResponseInputItem]
) -> GuardrailFunctionOutput:
    # ガードレールエージェントを実行し、タスクの適切性を判定する
    result = await Runner.run(guardrail_agent, input, context=ctx.context)

    return GuardrailFunctionOutput(
        output_info=result.final_output, 
        tripwire_triggered=result.final_output.is_inappropriate_task,
    )

# ユーザーのタスクを適切なエージェントに振り分けるエージェントの定義
manager_agent = Agent(
    name="マネージャーエージェント",
    instructions=(
        "ユーザーからの質問を受け取り、適切なエージェントに回答を依頼する。"
    ),
    model="gpt-4o-mini",
    handoffs=[loan_calculator_agent, travel_expense_agent],  # 振り分け対象のエージェント
    input_guardrails=[task_guardrail],  # タスクの適切性をチェックするガードレール
)

Tracing(トレーシング)

OpenAI Agents SDKには組み込みのトレース機能があり、エージェント実行中にLLMの生成、ツール呼び出し、ハンドオフ、ガードレール、さらにはカスタムイベントなど各種イベントを自動的に記録して可視化します。
これにより、OpenAIのTracesダッシュボードを使用して、開発中や運用中のワークフローのデバッグ、可視化、監視が可能になります。
エージェントシステムがブラックボックスにならないよう、トレース機能を活用してエージェントの動作を可視化することは非常に重要です。

以下の図は、マネージャーエージェントがユーザーからの住宅ローンの計算の質問を受け、ガードレールによるチェックを経て、ハンドオフ機能で適切なエージェントにタスクを委譲しているフローを可視化しています。

トレース1.png

実行例

作成したプログラムを実行してみます。
コマンドライン上で、pythonコマンドを使って実行します。
第一引数に依頼するタスク・質問を渡します。

住宅ローン計算の例

住宅ローン計算の質問を入力すると、住宅ローン計算エージェントから以下のような回答が得られます。

$ python app.py 35年の金利0.88%で5550万円のローンを返すには月々いくらの支払いになるか計算してください。
エージェントの回答: 35年の金利0.88%で5550万円のローンを返済する場合、毎月の支払い額は約153,584円になります。

旅費計算の例

旅費計算の質問を入力すると、旅費計算エージェントから以下の回答が返されます。

$ python app.py 10日間の旅行を計算している。人数は4人で、1日の予算は20000円。総額でいくらになるか計算してください。
エージェントの回答: 10日間の旅行の総額は884,400円です。

トレースを見ると、ツールを使用して回答していることがわかります。

トレース2.png

上記以外のタスクの例

住宅ローン計算や旅費計算以外のタスクが依頼されると、ガードレールが作動し、以下のようなメッセージが返されます。

$ python app.py 1+1は?
ガードレール: 不適切なタスク依頼です。

このように、ガードレールが適切に作動し、不適切なタスクを拒否していることが確認できます。
また、トレースを確認すると、ガードレールが発火し、不適切なタスクとして認識されている様子が記録されています。

ガードレール1.png
ガードレール2.png


完成したプログラム

以下が、今回作成したプログラム全体です。

OpenAI Agents SDKのv0.0.3を使用したコードであり、今後バージョンが更新されると下記のコードは動作しなくなる可能性もありますので、ご注意ください。

app.py
import asyncio
import sys
from pydantic import BaseModel
from agents import (
    Agent,
    GuardrailFunctionOutput,
    InputGuardrailTripwireTriggered,
    RunContextWrapper,
    Runner,
    TResponseInputItem,
    input_guardrail,
    trace,
    function_tool
)
from dotenv import load_dotenv


# .envファイルからAPIキーを読み込む
load_dotenv(override=True)

@function_tool
def loan_calculator(principal: float, annual_rate: float, term_years: int) -> str:
    """
    住宅ローン計算ツール:
    元本(principal)、年利(annual_rate、パーセント)と返済期間(term_years)から、
    毎月の返済額を複利計算を用いて求める。
    """
    monthly_rate = annual_rate / 100 / 12
    months = term_years * 12
    if monthly_rate == 0:
        payment = principal / months
    else:
        payment = principal * monthly_rate * (1 + monthly_rate) ** months / ((1 + monthly_rate) ** months - 1)
    return f"毎月の返済額は {payment:.2f} 円です"

@function_tool
def travel_expense_calculator(days: int, base_daily_cost: float, num_people: int) -> str:
    """
    旅費計算ツール:
    旅行日数(days)、1日あたりの基本費用(base_daily_cost)、人数(num_people)を元に
    総旅費を計算する。
    
    計算内容:
    1. 旅行日数のうち約2/7を土日と仮定し、土日は基本費用の10%増しとする。
    2. 平日は残りの日数とする。
    3. 7日を超える場合は、超過日数に対して基本費用の5%を割引する。
    4. 最終的な小計に10%の消費税を加算する。
    5. 総額は人数分を乗算して算出する。
    """
    # 土日の推定日数(小数点以下切り捨て)
    weekend_days = int(days * 2 / 7)
    weekday_days = days - weekend_days

    # 平日と土日の基本費用
    weekday_cost = weekday_days * base_daily_cost
    weekend_cost = weekend_days * base_daily_cost * 1.10  # 土日は10%増し

    # 長期旅行割引:7日を超える日数には基本費用の5%割引を適用
    discount_days = max(0, days - 7)
    discount = discount_days * base_daily_cost * 0.05

    # 小計
    subtotal = weekday_cost + weekend_cost - discount

    # 消費税10%を加算
    total_per_person = subtotal * 1.1

    # 人数分の総額
    total = total_per_person * num_people

    return f"最終的な旅費は {total:.2f} 円です"

loan_calculator_agent = Agent(
    name="住宅ローン計算エージェント",
    instructions="ローンの計算を頼まれたら、ツールを使って回答すること",
    model="gpt-4o-mini",
    tools=[loan_calculator],
)

travel_expense_agent = Agent(
    name="旅費計算エージェント",
    instructions=(
        "旅費の計算を頼まれたら、ツールを使って回答すること。"
    ),
    model="gpt-4o-mini",
    tools=[travel_expense_calculator],
)

class IntendedTaskOutput(BaseModel):
    is_inappropriate_task: bool
    reasoning: str

guardrail_agent = Agent( 
    name="ガードレールチェックエージェント",
    instructions="旅費計算やローン計算以外のタスクかをチェックして、不適切なタスクかどうかを判定する。",
    model="gpt-4o-mini",
    output_type=IntendedTaskOutput,
)

@input_guardrail
async def task_guardrail( 
    ctx: RunContextWrapper[None], agent: Agent, input: str | list[TResponseInputItem]
) -> GuardrailFunctionOutput:
    result = await Runner.run(guardrail_agent, input, context=ctx.context)

    return GuardrailFunctionOutput(
        output_info=result.final_output, 
        tripwire_triggered=result.final_output.is_inappropriate_task,
    )
    
manager_agent = Agent(
    name="マネージャーエージェント",
    instructions=(
        "ユーザーからの質問を受け取り、適切なエージェントに回答を依頼する。"
    ),
    model="gpt-4o-mini",
    handoffs=[loan_calculator_agent, travel_expense_agent],
    input_guardrails=[task_guardrail],
)

async def main():
    if len(sys.argv) > 1:
        user_input = sys.argv[1]
    else:
        user_input = input("質問を入力してください: ")
    with trace(workflow_name="計算ワークフロー"):
        try:
            result = await Runner.run(manager_agent, input=user_input)
            print("エージェントの回答: " + result.final_output)

        except InputGuardrailTripwireTriggered:
            print("ガードレール: 不適切なタスク依頼です。")

if __name__ == "__main__":
    asyncio.run(main())

まとめ・感想

今回は、OpenAI Agents SDKのコアとなる4つの概念を盛り込んだプログラムをPythonで作成し、その使い方や動作をコードを通して解説しました。
AIエージェントのフレームワークとしては、LangGraphCrewAIなど、さまざまな選択肢がありますが、それらと比較しても、OpenAIのAgents SDKフレームワークは十分に使いやすいと感じました。今後もアップデートがあると思うので、キャッチアップ出来ればと思います。


スタディングでは、AIを活用し、利用者が効率的に新たな知識を習得できるよう、日々サービス向上に努めています。
ご興味のある方は、ぜひ下記のリンクをご覧ください。
最後までお読みいただき、ありがとうございました!


KIYOラーニング株式会社について

当社のビジョンは『世界一「学びやすく、分かりやすく、続けやすい」学習手段を提供する』ことです。革新的な教育サービスを作り成長させていく事で、オンライン教育分野でナンバーワンの存在となり、世界に展開していくことを目指しています。

プロダクト

  • スタディング:「学びやすく・わかりやすく・続けやすい」オンライン資格対策講座
  • スタディングキャリア:資格取得者の仕事探しやキャリア形成を支援する転職サービス
  • AirCourse:受け放題の動画研修がついたeラーニングシステム(LMS)

KIYOラーニング株式会社では一緒に働く仲間を募集しています

39
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?