DEV Community

Cover image for OpenAI 関数呼び出しの使い方
Akira
Akira

Posted on • Originally published at apidog.com

OpenAI 関数呼び出しの使い方

このガイドでは、ツールを定義し、OpenAIに送信し、モデルが返すツールコールを読み取り、構造化された引数で独自の関数を実行する手順を実装ベースで確認します。さらに、厳格モードと並列呼び出しを設定し、Apidog を使ってツール側の入力をアサートし、ダウンストリームAPIをモックすることで、本番投入前に出力の信頼性を確認します。仕様の詳細はOpenAIの関数呼び出しドキュメントを参照し、より上位の概要はOpenAI Agents SDKでエージェントを構築するの記事を確認してください。

今すぐApidogを試す

始める前に必要なもの

関数呼び出し(ツール呼び出し)は、モデルをあなたのコードや外部システムに接続する仕組みです。

基本の役割分担は次のとおりです。

  • モデル: ユーザーの意図を読み取り、呼び出す関数名と引数を生成する
  • あなたのアプリ: 引数を検証し、実際の関数やAPIを実行する
  • モデル: 実行結果を受け取り、最終回答を生成する

たとえば、ユーザーが「パリの天気は?」と聞いた場合、モデルは自然文を直接処理する代わりに、次のような構造化された呼び出しを返します。

get_weather({ location: "Paris, France" })
Enter fullscreen mode Exit fullscreen mode

このガイドを試すには、次のものが必要です。

  • OpenAI APIキー
  • モデルに呼び出させたいアプリケーション側の関数
  • Chat Completions APIまたはResponses APIのどちらを使うかの方針

関数呼び出しは、Chat Completions APIとResponses APIの両方で利用できます。形式は少し異なりますが、実装ループは同じです。

ステップ1:ツールを定義する

ツールは、モデルに公開する関数定義です。主に次の情報を含めます。

  • name: 関数名
  • description: いつ使うべきかの説明
  • parameters: 引数のJSONスキーマ
  • strict: スキーマ準拠を強制するかどうか

description は単なるラベルではなく、モデルへの指示として書きます。

Chat Completions APIのツール定義

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Get the current weather for a city. Use when the user asks about temperature or conditions.",
    "parameters": {
      "type": "object",
      "properties": {
        "location": {
          "type": "string",
          "description": "City and country, e.g. Bogotá, Colombia"
        },
        "unit": {
          "type": "string",
          "enum": ["celsius", "fahrenheit"]
        }
      },
      "required": ["location"],
      "additionalProperties": false
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Responses APIのツール定義

Responses APIでは、namedescriptionparametersstrict をツールオブジェクトのトップレベルに置きます。

{
  "type": "function",
  "name": "get_weather",
  "description": "Get the current weather for a city. Use when the user asks about temperature or conditions.",
  "parameters": {
    "type": "object",
    "properties": {
      "location": {
        "type": "string",
        "description": "City and country, e.g. Bogotá, Colombia"
      },
      "unit": {
        "type": "string",
        "enum": ["celsius", "fahrenheit"]
      }
    },
    "required": ["location"],
    "additionalProperties": false
  }
}
Enter fullscreen mode Exit fullscreen mode

すでにOpenAPI仕様を管理している場合、パラメータ定義は関数呼び出しのスキーマにも流用しやすくなります。OpenAPI仕様からテストコレクションを生成する方法を使うと、API定義をテストにも再利用できます。

ステップ2:最初のリクエストを作成する

ユーザーのメッセージとツール定義を一緒にモデルへ送信します。

Chat Completions APIでは次のようになります。

curl https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4.1",
    "messages": [
      {
        "role": "user",
        "content": "What is the weather in Paris right now?"
      }
    ],
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "get_weather",
          "description": "Get the current weather for a city.",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string"
              }
            },
            "required": ["location"],
            "additionalProperties": false
          }
        }
      }
    ]
  }'
Enter fullscreen mode Exit fullscreen mode

tools 配列には、このターンでモデルに公開する関数をすべて入れます。モデルがツールを使うべきだと判断すると、通常の文章ではなくツールコールを返します。

ステップ3:モデルが返すツールコールを読み取る

モデルが関数呼び出しを選択した場合、レスポンスには関数名と引数が含まれます。

Chat Completions APIの場合

Chat Completions APIでは、アシスタントメッセージの tool_calls 配列にツールコールが入ります。

{
  "id": "call_12345xyz",
  "type": "function",
  "function": {
    "name": "get_weather",
    "arguments": "{\"location\":\"Paris, France\"}"
  }
}
Enter fullscreen mode Exit fullscreen mode

Responses APIの場合

Responses APIでは、output 配列に function_call として返されます。

{
  "type": "function_call",
  "call_id": "call_12345xyz",
  "name": "get_weather",
  "arguments": "{\"location\":\"Paris, France\"}"
}
Enter fullscreen mode Exit fullscreen mode

重要なのは、arguments がオブジェクトではなくJSONエンコードされた文字列で返る点です。必ずアプリケーション側でパースしてから使います。

const args = JSON.parse(toolCall.function.arguments)

const result = await getWeather({
  location: args.location,
  unit: args.unit
})
Enter fullscreen mode Exit fullscreen mode

ステップ4:関数を実行して結果をモデルに返す

関数を実行したら、その結果をモデルに返します。これにより、モデルはユーザー向けの最終回答を生成できます。

実装ループは次の流れです。

  1. ユーザーの入力をモデルへ送る
  2. モデルがツールコールを返す
  3. アプリ側で arguments をパースする
  4. 対応する関数を実行する
  5. 実行結果をモデルに返す
  6. モデルが最終回答を返す

Chat Completions APIでは、tool_call_id に対応する tool ロールのメッセージを追加します。

{
  "role": "tool",
  "tool_call_id": "call_12345xyz",
  "content": "{\"temperature\": 18, \"unit\": \"celsius\", \"condition\": \"Cloudy\"}"
}
Enter fullscreen mode Exit fullscreen mode

Responses APIでは、call_id に対応する function_call_output を送信します。

{
  "type": "function_call_output",
  "call_id": "call_12345xyz",
  "output": "{\"temperature\": 18, \"unit\": \"celsius\", \"condition\": \"Cloudy\"}"
}
Enter fullscreen mode Exit fullscreen mode

ステップ5:並列呼び出しと厳格モードを設定する

基本ループが動いたら、信頼性と実行制御のために次の設定を確認します。

設定 制御するもの デフォルト 変更するタイミング
parallel_tool_calls 1回のターンで複数のツール呼び出しを返せるか true 呼び出し順序が重要な場合や、依存関係がある場合は false
strict 引数がJSONスキーマに一致することを強制するか 未設定時はベストエフォート 本番相当の処理では有効化を推奨
tool_choice モデルがツールを呼ぶか、どのツールを呼ぶか auto 強制するなら required、無効化するなら none、特定関数を指定するなら関数名

並列ツール呼び出し

デフォルトでは、モデルは1回のターンで複数のツールコールを返すことがあります。

たとえば、ユーザーが「東京、パリ、ニューヨークの天気を教えて」と聞いた場合、3つの get_weather 呼び出しが返る可能性があります。

並列実行できる処理なら高速化できますが、順序が重要な処理では無効化します。

{
  "parallel_tool_calls": false
}
Enter fullscreen mode Exit fullscreen mode

厳格モード

strict: true を設定すると、モデルが返す引数がJSONスキーマに一致するようになります。

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Get the current weather for a city.",
    "strict": true,
    "parameters": {
      "type": "object",
      "properties": {
        "location": {
          "type": "string"
        },
        "unit": {
          "type": ["string", "null"],
          "enum": ["celsius", "fahrenheit", null]
        }
      },
      "required": ["location", "unit"],
      "additionalProperties": false
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

厳格モードでは、次の点に注意します。

  • すべてのオブジェクトに additionalProperties: false を設定する
  • properties 内のフィールドは required に含める
  • オプション扱いにしたいフィールドは、省略ではなく null を許可する

たとえば unit を任意にしたい場合でも、キー自体は必須にし、値として null を許可します。これにより、アプリ側のパース処理は毎回同じキー構造を期待できます。

ただし、厳格モードは「構造」を保証するだけです。location が実在する都市か、サービス対象エリアか、APIが成功するかまでは保証しません。そこはアプリ側の検証とテストが必要です。

Apidogでテストする方法

モデルはツールコールを返しますが、それを実際の関数に接続する前に確認すべきことが2つあります。

  1. モデルが返した引数が期待するスキーマに一致しているか
  2. 関数が呼び出すダウンストリームAPIが想定どおりに動作するか

Apidog は、このAPI契約の検証とモックに使えます。

Apidogは、あなたのアプリケーション内の関数そのものを実行するわけではありません。主に次の2つを担当します。

1. ツールコールの引数をアサートする

OpenAIから返された arguments 文字列を取得し、リクエストボディとして扱います。

確認する項目の例です。

  • location が存在する
  • location が文字列である
  • unit が許可された enum のいずれかである
  • 必須フィールドが欠けていない
  • 余分なプロパティが含まれていない

特定フィールドの抽出にはJSONPath式を使えます。より厳密にチェックする場合は、OpenAIに渡したものと同じスキーマを使ってJSONスキーマに対するバリデーションを行います。

2. ダウンストリームAPIをモックする

get_weather 関数は、おそらく外部の天気APIを呼び出します。

しかし開発中は、次のような問題が起こりがちです。

  • 外部APIにレート制限がある
  • APIが有料である
  • まだ本物のAPIが完成していない
  • エラーケースを再現しにくい

この場合、Apidogで現実的な天気レスポンスを返すモックAPIを作成し、get_weather 関数の接続先をそのモックに向けます。

これにより、次のケースを本番APIなしで検証できます。

  • 正常レスポンス
  • タイムアウト
  • 429 Too Many Requests
  • 不正なレスポンス形式
  • 空の結果
  • サービス対象外の都市

おすすめのテストフローは次のとおりです。

  1. OpenAIからツールコールを取得する
  2. arguments をJSONとしてパースする
  3. Apidogでスキーマに対してアサートする
  4. アプリ側の関数を実行する
  5. 関数からApidogのモックAPIを呼び出す
  6. 正常系と異常系の両方を確認する

これにより、モデル出力の契約と外部APIの契約を、本番呼び出しを消費せずに検証できます。

よくある質問

関数呼び出しはChat Completions APIとResponses APIの両方で使えますか?

はい。両方でサポートされています。

主な違いは形式です。

  • Chat Completions API: function キーの下に関数定義をネストし、tool_calls を返す
  • Responses API: フラットなツール定義を使い、output 配列に function_call を返す

なぜ arguments はオブジェクトではなく文字列で返るのですか?

arguments はJSONエンコードされた文字列として返ります。使う前に必ずアプリ側でパースしてください。

const args = JSON.parse(toolCall.function.arguments)
Enter fullscreen mode Exit fullscreen mode

そのまま信頼せず、JSONスキーマ検証に通してから関数に渡すのが安全です。

厳格モードを使えば関数の成功は保証されますか?

いいえ。

厳格モードが保証するのは、引数の構造がJSONスキーマに一致することです。値がビジネスロジック上正しいか、外部APIが成功するか、関数が例外を出さないかは保証しません。

そのため、次の処理は引き続きアプリ側で必要です。

  • 値の検証
  • 権限チェック
  • サービス対象範囲の確認
  • タイムアウト処理
  • リトライ処理
  • エラーハンドリング

Apidogは実際の関数を実行できますか?

いいえ。Apidogはアプリケーション内の関数そのものを実行するツールではありません。

Apidogは主に次を担当します。

  • モデルが生成した引数の検証
  • 関数が依存するAPIのモック
  • API契約の確認
  • 正常系と異常系レスポンスのテスト

実際の関数実行は、あなたのアプリケーション側で行います。

まとめ

OpenAIの関数呼び出しは、次のループで実装します。

  1. ツールをJSONスキーマ付きで定義する
  2. ユーザーメッセージと一緒にモデルへ送る
  3. tool_calls または function_call を読み取る
  4. arguments をパースして検証する
  5. アプリ側の関数を実行する
  6. 結果をモデルに返す
  7. モデルに最終回答を生成させる

本番向けには、strict: true を有効化し、parallel_tool_callstool_choice を用途に合わせて設定します。

さらに、Apidogでツールコールの引数をスキーマに対してアサートし、関数が依存するAPIをモックすれば、実際の外部APIを消費せずに入力と依存関係の契約を検証できます。

テスト側を試す場合は、Apidogをダウンロードして、ツールコールの引数検証とAPIモックを一箇所で管理できます。

Top comments (0)