Agents SDKにおけるツールの設計と実装

OpenAI Agents SDKを用いた開発において、ツールは単なる拡張機能ではなく、エージェントの知能を現実世界に接続するための最重要要素である。この記事では、ツールがどのように定義され、エージェントによっていかに選択・実行されるのか、その仕組みを解説する。

1.エージェントにおけるツールの位置付け

OpenAI Agents SDKにおけるツールとは、エージェントが文章生成以外の行動を選択するための手段である。ツールが存在しない場合、エージェントは学習データに基づいた自然言語による応答しか返せない。しかし、ツールを追加することで外部情報の検索、複雑な計算、API連携による外部ロジックの実行といった具体的な行為が可能になる。

2.ツールは単なるPython関数である

ツールの実体は標準的なPython関数であり、特別なクラスを継承する必要はない。重要なのは、引数の型ヒント、戻り値の型、そして関数の役割を説明するdocstringが明確であることだ。これにより、エージェントは「どのような入力を与えればよいか」「このツールで何が得られるか」を正確に理解できる。

# 注文IDに応じて状態を返す関数の例
def lookup_delivery_status(order_id: int) -> str:
    """注文IDを受け取り、現在の配送ステータスを返します。"""
    if order_id < 200:
        return "配送済み"
    elif order_id < 300:
        return "遅延中"
    else:
        return "キャンセル済み"

3.ツールが使える選択肢になる仕組み

関数がツールとして登録されると、エージェントはそれを利用可能な行動候補として認識する。ここで重要なのは、ツールが登録された時点で自動的に実行されるわけではない点である。ツールはあくまで選択肢であり、使うかどうかはエージェント自身が判断する。

(1) ツールを使える選択肢にするコード例

エージェントがツールを使える選択肢として認識するために必要な要素は、①ツールとなる関数の定義、②その関数をエージェント生成時に明示的に渡すこと、の2点である。

from agents import Agent, Runner

# 1. ツールとなる関数の定義
def lookup_delivery_status(order_id: int) -> str:
    if order_id < 200:
        return "配送済み"
    elif order_id < 300:
        return "遅延中"
    else:
        return "キャンセル済み"

# 2. エージェント生成時にツールを登録
agent = Agent(
    name="Delivery Support Agent",
    instructions="あなたは注文状況に関する質問に対応するAIエージェントである。",
    model="gpt-4o",
    tools=[lookup_delivery_status]
)

# 実行例
result = Runner.run_sync(
    agent,
    "注文IDが250の注文はどうなっている?"
)

この構成では、ツールを登録しただけで即座に実行されることはない。エージェントは、質問が注文状況に関するものであり、かつ具体的な注文IDが含まれているという文脈を踏まえ、ツールを使うのが適切だと判断した場合にのみ関数を呼び出す。

(2) 条件分岐ではなく推論による選択

開発者は「注文IDが含まれていたら必ずツールを呼ぶ」といったif文を書く必要がない。それにもかかわらず、エージェントは必要に応じてツールを利用する。この判断は固定ロジックではなく、LLMによる推論に委ねられており、ここにエージェント型AIの本質がある。

(3) ツールを登録しても使われない例

同じエージェントに対して、次の入力を与えた場合を考える。

result = Runner.run_sync(
    agent,
    "パスワードの変更方法を教えてほしい"
)

この場合、注文状況を調べるツールは文脈上不要であるため、エージェントはツールを呼び出さず、自然言語のみで回答を生成する。ツールは常に実行される処理ではなく、状況に応じて選ばれるオプションとして扱われている。

4.ツール選択は非決定的である

エージェントは、ユーザー入力とシステムプロンプトを踏まえ、ツールを呼び出すか、直接回答するかを判断する。この判断は決定論的(1対1の固定対応)ではない。同じツールが存在していても、質問のニュアンスや文脈が異なれば、エージェントが「今はツールを使わずに回答すべきだ」と判断することがあり得る。

5.ツール実行とinput_contextの更新

ツールが選択されると、その関数が実行され、戻り値が得られる。この結果はそのままユーザーに返されるのではなく、input_context(エージェントが把握している文脈)に追加される。その上で、エージェントは元のユーザー入力とツールの実行結果の両方を材料として再推論を行い、最終的な自然言語の回答を生成する。

6.ツールは推論の材料であり、答えそのものではない

ツールの戻り値は、エージェントにとって事実情報や計算結果の提供にすぎない。ユーザーに最終的に返される文章は、その情報を踏まえてLLMが再構成したものである。この設計により、ツールの実行結果をそのまま出力するのではなく、ユーザーの口調に合わせたり、補足説明を加えたりといった柔軟な対応が可能になる。

7.トレースで確認できるツール利用の実態

SDKのトレース機能を用いると、LLM呼び出し、ツール選択、ツール実行、再推論という一連の流れを時系列で確認できる。なぜそのツールが選ばれたのか、どの時点で最終出力に至ったのかを検証することは、ツール設計や指示文(instructions)の改善に直結する。

8.ツール設計で意識すべきポイント

①いつ使うべきかが文脈から自然に判断できること、②ツールを増やすこと自体を目的化せず必要最小限に絞ること、③関数の名前や引数名をLLMが理解しやすいセマンティックな名称にすることから、ツールは単機能で役割が明確であることが望ましい。

9.まとめ

ツールは、エージェントを「話すだけの存在」から「状況に応じて行動を選択する存在」へ進化させる中核要素である。重要なのは単なる関数の登録ではなく、エージェントが文脈に応じてツールを道具として使いこなし、その結果を次の推論に活かす構造にある。この考え方は、handoff(エージェント間の権限委譲)やマルチエージェント設計を理解する上での強固な基礎となる。