OpenAI Responses APIは、テキスト生成、会話状態、組み込みツール、独自関数を1つのAPIで扱うための中心的なインターフェースです。JavaScriptでは client.responses.create() にモデルと入力を渡し、通常のテキストは response.output_text から取得できます。
従来のChat Completions APIに慣れていると、messages と choices が見当たらず戸惑うかもしれません。Responses APIでは、入力と出力を複数種類の項目として扱い、前のレスポンスIDを使って会話をつなげられます。
この記事では、Node.jsの最小コード、出力配列の読み方、previous_response_id、ツール利用、Chat Completionsからの移行ポイントを順に解説します。
情報確認日:2026年7月18日(日本時間)
結論:新規実装はResponses APIを基準に考える
Responses APIで押さえる項目
inputへ文字列または入力項目を渡す- 簡単なテキストは
output_textから取得する - 詳細処理では
outputの項目種別を確認する previous_response_idで前の応答へ接続する- 会話状態、保存期間、個人情報、料金を別々に検討する
- 外部処理はツール呼び出しをアプリ側で検証して実行する
OpenAI API自体が初めての場合は、先にOpenAI APIをJavaScriptから使う方法でSDKとAPIキーの準備を確認してください。APIキーはブラウザへ埋め込まず、サーバー側の環境変数で管理します。
Chat Completions APIとの違い
| 項目 | Chat Completions | Responses API |
|---|---|---|
| 呼び出し | chat.completions.create() |
responses.create() |
| 主な入力 | messages |
input と instructions |
| テキスト取得 | choices[0].message.content |
output_text |
| 会話の接続 | 履歴を自分で再送する方式が中心 | previous_response_id または会話項目 |
| ツール | 関数呼び出しを利用可能 | 関数と各種組み込みツールを統合 |
| 出力構造 | 選択肢中心 | メッセージ、ツール呼び出し等の項目配列 |
Chat Completions APIが直ちに使えなくなるという意味ではありません。既存実装はテストを保ちながら段階的に移行し、新規機能ではResponses APIの機能が要件に合うか確認します。
最小のリクエストをJavaScriptで送る
プロジェクトとSDKを準備する
mkdir responses-api-sample
cd responses-api-sample
npm init -y
npm pkg set type=module
npm install openai
APIキーと利用可能なモデルIDを環境変数へ設定します。
export OPENAI_API_KEY="your_api_key_here"
export OPENAI_MODEL="your_available_model_id"
テキストを送って出力する
import OpenAI from "openai";
const client = new OpenAI();
const model = process.env.OPENAI_MODEL;
if (!model) {
throw new Error("OPENAI_MODEL is not set");
}
const response = await client.responses.create({
model,
instructions:
"あなたはJavaScript初学者向けの講師です。",
input:
"Array.prototype.mapを80文字程度で説明してください。",
});
console.log(response.output_text);
instructions は応答全体の振る舞い、input は今回の依頼に使えます。SDKの便利な output_text は、出力内のテキストをまとめて取得したい場合に向いています。
output配列の構造を理解する
Responses APIの出力には、通常のメッセージだけでなく、ツール呼び出しやその他の項目が含まれる場合があります。処理を自動化する場合は、テキストだけを前提にせず output の型を確認します。
for (const item of response.output) {
if (item.type === "message") {
for (const content of item.content) {
if (content.type === "output_text") {
console.log(content.text);
}
}
}
}
画面へ文章を表示するだけなら output_text が簡単です。ツール実行、引用、拒否、構造化出力を扱うなら、項目の種別ごとに分岐します。存在しない型を黙って無視するのではなく、ログへ残すとSDK更新時の変化を検知できます。
previous_response_idで会話を続ける
const first = await client.responses.create({
model,
input: "変数名をuserDisplayNameにしました。覚えてください。",
store: true,
});
const second = await client.responses.create({
model,
previous_response_id: first.id,
input: "先ほどの変数名を使ったconst宣言を書いてください。",
store: true,
});
console.log(second.output_text);
previous_response_id を指定すると、前のレスポンスにつながる会話として処理できます。公式ドキュメントでは、レスポンスオブジェクトは既定で一定期間保存され、store: false で保存を無効にできることが案内されています。保持条件は最新の公式情報と契約条件を確認してください。
料金の注意:previous_response_id を使っても、会話で参照される過去の入力トークンが無料になるわけではありません。会話が長くなるほど使用量が増えるため、要約、履歴の切り替え、上限を設計します。
会話IDとレスポンスIDを混同しない
アプリ側では、利用者の会話IDとOpenAIのレスポンスIDを別に保存します。複数タブや再送があると、単一のグローバル変数だけでは会話が混線します。
{
"app_conversation_id": "conv_local_123",
"user_id": "user_456",
"last_response_id": "resp_from_api",
"updated_at": "2026-07-18T05:00:00Z"
}
ログアウト、削除依頼、保持期限に応じて、アプリ側データとAPI側の保存データをどう扱うか決めてください。機密情報を入力する前に、組織のデータ方針を確認します。
組み込みツールと独自関数を使う
Responses APIでは、対応モデル・環境で組み込みツールを指定できるほか、アプリ独自の関数を定義できます。利用可能なツール名とパラメータは更新されるため、実装時の公式ガイドを確認してください。
const responseWithTool = await client.responses.create({
model,
input: "注文番号A-100の配送状況を確認してください。",
tools: [
{
type: "function",
name: "get_delivery_status",
description: "注文番号から配送状況を取得する",
parameters: {
type: "object",
properties: {
orderId: { type: "string" },
},
required: ["orderId"],
additionalProperties: false,
},
strict: true,
},
],
});
モデルは関数の実行要求を返しますが、外部APIを実行するのは自分のアプリです。関数名を許可リストで確認し、引数を検証し、利用者がその注文へアクセスできるか認可してから実行します。詳しい流れはTool Callingの基本を参照してください。
モデルの関数要求
↓ 関数名と引数を検証
アプリが外部処理
↓ 実行結果を関数出力として返す
モデルが利用者向け回答を生成
構造化出力を使う場面
APIの結果をデータベース登録や画面部品に使う場合、自由文を正規表現で解析するより、JSON Schemaに沿う構造化出力を使うほうが安全です。ただし、スキーマ準拠は内容の事実性まで保証しません。
スキーマ設計、失敗時の扱い、検証方法はStructured Outputsの基本で確認できます。
Chat Completionsから移行するチェックリスト
- 現在の入出力、ストリーミング、関数、エラー処理をテストで固定する
chat.completions.create()をresponses.create()へ置き換えるmessagesをinputと必要な入力項目へ変換するchoices参照をoutput_textまたはoutput処理へ変える- 会話状態を履歴再送にするかレスポンスID接続にするか決める
- 関数呼び出しと関数結果の形式をResponses API向けに更新する
- 使用量、保存、エラー、タイムアウト、再試行を再確認する
- 同じ評価データで旧実装と品質・料金・遅延を比較する
移行のコツ:会話、ツール、ストリーミングを一度に変えず、まず単発テキスト、次に会話、最後にツールの順で移行すると原因を切り分けやすくなります。
よくあるエラー
| 症状 | 確認点 |
|---|---|
| 401 | APIキー、環境変数、プロジェクト権限 |
| 400 | モデル、入力形式、ツールスキーマ、未対応機能 |
| 429 | レート制限、利用上限、請求状態、再試行 |
| 会話がつながらない | 保存設定、前のレスポンスID、利用者ごとのID管理 |
| テキストが空 | output 内の項目種別、拒否、ツール要求、終了理由 |
よくある質問
previous_response_idを使えば履歴保存は不要ですか?
アプリの要件によります。画面表示、検索、削除、監査、複数デバイス同期にはアプリ側の会話管理が必要なことがあります。API側の保持だけへ依存せず、保存目的と期間を設計します。
inputには文字列しか渡せませんか?
文字列だけでなく、役割やコンテンツ種別を持つ入力項目も利用できます。画像やファイルなどの対応形式はモデルとAPIの最新ドキュメントを確認してください。
新規開発でChat Completionsを選ぶ理由はありますか?
既存ライブラリや互換性要件によって選ぶ場合はあります。ただし、必要なツール、状態管理、出力形式を比較し、Responses APIを含めて判断するのがよいでしょう。
まとめ
Responses APIは、入力、出力、会話状態、ツールを統一的に扱います。最初は responses.create() と output_text で単発の応答を成功させ、次に previous_response_id、最後にツールを追加すると理解しやすくなります。
会話をつなぐ機能と、データ保存、料金、認可は別の設計問題です。公式仕様を確認しながら、利用者ごとのID管理、保存方針、ツール引数の検証まで実装してください。