openai-responses について
OpenAI Responses APIでエージェント型アプリケーションを構築するためのスキルです。状態管理付き会話、ホスト型ツール、MCP接続を扱います。
主な機能
- 01会話状態の自動管理
- 02ターンをまたぐ推論状態の保持
- 03コード・ファイル・ウェブ・画像のホスト型ツール
- 04長時間タスクのバックグラウンド処理
活用シーン
- 01複数ターンのエージェント型アプリ構築
- 02アップロード済みファイルの検索
- 03Pythonによるデータ分析
- 04MCP経由での外部ツール接続
MCP 対応
Responses APIを介したMCPサーバーの接続方法を説明します。サーバーラベル、URL、認証トークンを扱います。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ovachiever/ droid-tings --skill openai-responsesインストール後、Claude Code で/openai-responsesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.md.claude-plugin/plugin.jsonreferences/built-in-tools-guide.mdmcp-integration-guide.mdmigration-guide.mdreasoning-preservation.mdresponses-vs-chat-completions.mdstateful-conversations.mdtop-errors.mdscripts/check-versions.shtemplates/background-mode.tsbasic-response.tscloudflare-worker.tscode-interpreter.tsfile-search.tsimage-generation.tsmcp-integration.tspackage.jsonstateful-conversation.tsweb-search.ts詳細
OpenAI Responses API
ステータス:本番環境対応 最終更新日:2025-10-25 API リリース:2025 年 3 月 依存関係:[email protected]+(Node.js)または fetch API(Cloudflare Workers)
Responses API とは?
Responses API(/v1/responses)は、エージェント型アプリケーションを構築するための OpenAI の統合インターフェースで、2025 年 3 月にリリースされました。ステートフルな会話と推論および実行のための構造化されたループを提供することで、OpenAI モデルとのやり取りを根本的に変えます。
主な革新:推論状態の保持
ターン間で推論が破棄される Chat Completions とは異なり、Responses ではノートブックを開いたままにできます。モデルの段階的な思考プロセスが次のターンにも引き継がれ、パフォーマンスが約5%向上し、TAUBench での複数ターンのやり取りも改善されます。
Chat Completions ではなく Responses を使う理由
| 機能 | Chat Completions | Responses API | 利点 |
|---|---|---|---|
| 状態管理 | 手動(履歴を追跡) | 自動(会話 ID) | コードがシンプルになり、エラーも減少 |
| 推論 | ターン間で破棄 | ターン間で保持 | 複数ターンのパフォーマンスが向上 |
| ツール | クライアント側の往復処理 | サーバー側でホスト | レイテンシの低減、コードの簡素化 |
| 出力形式 | 単一のメッセージ | 多態型(メッセージ、推論、ツール呼び出し) | デバッグ機能の強化、UX の向上 |
| キャッシュ利用率 | ベースライン | 40~80%向上 | コスト低減、応答の高速化 |
| MCP サポート | 手動で統合 | 組み込み | 外部ツールに簡単に接続 |
クイックスタート(5 分)
1. API キーを取得
# Sign up at https://platform.openai.com/
# Navigate to API Keys section
# Create new key and save securely
export OPENAI_API_KEY="sk-proj-..."
重要な理由:
- すべてのリクエストで API キーが必要です
- 安全に管理してください(git にコミットしないでください)
- 環境変数を使用してください
2. SDK をインストール(Node.js)
npm install openai
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const response = await openai.responses.create({
model: 'gpt-5',
input: 'What are the 5 Ds of dodgeball?',
});
console.log(response.output_text);
重要:
- 必ずサーバー側で使用してください(クライアントコードで API キーを公開しないでください)
- モデルのデフォルトは
gpt-5です(gpt-5-mini、gpt-4oなども使用できます) inputは文字列またはメッセージの配列にできます
3. または直接 API を使用(Cloudflare Workers)
// No SDK needed - use fetch()
const response = await fetch('https://api.openai.com/v1/responses', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-5',
input: 'Hello, world!',
}),
});
const data = await response.json();
console.log(data.output_text);
fetch を使う理由
- エッジ環境で依存関係が不要です
- リクエストとレスポンスを完全に制御できます
- Cloudflare Workers、Deno、Bun で動作します
Responses と Chat Completions の完全比較
使い分け
Responses API を使うケース:
- ✅ エージェント型アプリケーション(推論+アクション)を構築する
- ✅ ターン間で推論状態を保持する必要がある
- ✅ 組み込みツール(Code Interpreter、File Search、Web Search)を使いたい
- ✅ 外部連携に MCP サーバーを使用する
- ✅ 自動状態管理による会話型 AI を実装する
- ✅ 長時間実行されるタスクをバックグラウンド処理する
- ✅ 多態型の出力(メッセージ、推論、ツール呼び出し)が必要
Chat Completions を使うケース:
- ✅ 単発のシンプルなテキスト生成
- ✅ 完全にステートレスなやり取り(会話の継続性が不要)
- ✅ 既存の Chat Completions コードなど、レガシーな連携
- ✅ ツールを使わない非常にシンプルなユースケース
アーキテクチャの違い
Chat Completions のフロー:
User Input → Model → Single Message → Done
(Reasoning discarded, state lost)
Responses API のフロー:
User Input → Model (preserved reasoning) → Polymorphic Outputs
↓ (server-side tools)
Tool Call → Tool Result → Model → Final Response
(Reasoning preserved, state maintained)
パフォーマンス上の利点
キャッシュ利用率:
- Chat Completions:ベースラインのパフォーマンス
- Responses API:キャッシュ利用率が 40~80%向上
- 結果:レイテンシとコストを削減
推論パフォーマンス:
- Chat Completions:ターン間で推論が破棄されます
- Responses API:ターン間で推論が保持されます
- 結果:TAUBench で 5%向上(Responses を使用した GPT-5 と Chat Completions の比較)
ステートフルな会話
自動状態管理
Responses API は、会話 IDを使用して会話の状態を自動的に管理できます。
会話の作成
// Create conversation with initial message
const conversation = await openai.conversations.create({
metadata: { user_id: 'user_123' },
items: [
{
type: 'message',
role: 'user',
content: 'Hello!',
},
],
});
console.log(conversation.id); // "conv_abc123..."
会話 ID の使用
// First turn
const response1 = await openai.responses.create({
model: 'gpt-5',
conversation: 'conv_abc123',
input: 'What are the 5 Ds of dodgeball?',
});
console.log(response1.output_text);
// Second turn - model remembers previous context
const response2 = await openai.responses.create({
model: 'gpt-5',
conversation: 'conv_abc123',
input: 'Tell me more about the first one',
});
console.log(response2.output_text);
// Model automatically knows "first one" refers to first D from previous turn
重要な理由:
- 履歴を手動で追跡する必要がありません
- 推論状態がターン間で保持されます
- コンテキストが自動で管理されます
- コンテキストエラーのリスクが低減します
手動での状態管理(代替方法)
完全に制御する必要がある場合は、履歴を手動で管理できます。
let history = [
{ role: 'user', content: 'Tell me a joke' },
];
const response = await openai.responses.create({
model: 'gpt-5',
input: history,
store: true, // Optional: store for retrieval later
});
// Add response to history
history = [
...history,
...response.output.map(el => ({
role: el.role,
content: el.content,
})),
];
// Next turn
history.push({ role: 'user', content: 'Tell me another' });
const secondResponse = await openai.responses.create({
model: 'gpt-5',
input: history,
});
手動管理を使用する場合:
- 履歴の削除に独自のロジックが必要な場合
- 会話履歴をプログラムで変更したい場合
- 独自のキャッシュ戦略を実装する場合
組み込みツール(サーバー側)
Responses API には、コストのかかるバックエンドへの往復をなくすサーバー側ホスト型ツールが含まれています。
利用可能なツール
| ツール | 目的 | 使用例 |
|---|---|---|
| Code Interpreter | Python コードを実行します | データ分析、計算、グラフ作成 |
| File Search | ベクトルストアなしで RAG を利用します | アップロードしたファイルから回答を検索します |
| Web Search | ウェブのリアルタイム情報を取得します | 時事情報、ファクトチェック |
| Image Generation | DALL-E と連携します | 説明から画像を作成します |
| MCP | 外部ツールに接続します | Stripe、データベース、カスタム API |
Code Interpreter
サーバー側で Python コードを実行し、データ分析、計算、可視化を行います。
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Calculate the mean, median, and mode of: 10, 20, 30, 40, 50',
tools: [{ type: 'code_interpreter' }],
});
console.log(response.output_text);
// Model writes and executes Python code, returns results
応用例:データ分析
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Analyze this sales data and create a bar chart showing monthly revenue: [data here]',
tools: [{ type: 'code_interpreter' }],
});
// Check output for code execution results
response.output.forEach(item => {
if (item.type === 'code_interpreter_call') {
console.log('Code executed:', item.input);
console.log('Result:', item.output);
}
});
これが重要な理由:
- ローカルで Python を実行する必要がありません
- サンドボックス化された実行環境です
- グラフが自動生成されます
- アップロードしたファイルを処理できます
File Search(ベクトルストアなしの RAG)
独自の RAG パイプラインを構築せずに、アップロードしたファイルを検索できます。
// 1. Upload files first (one-time setup)
const file = await openai.files.create({
file: fs.createReadStream('knowledge-base.pdf'),
purpose: 'assistants',
});
// 2. Use file search
const response = await openai.responses.create({
model: 'gpt-5',
input: 'What does the document say about pricing?',
tools: [
{
type: 'file_search',
file_ids: [file.id],
},
],
});
console.log(response.output_text);
// Model searches file and provides answer with citations
対応ファイル形式:
- PDF、Word 文書、テキストファイル
- Markdown、HTML
- コードファイル(Python、JavaScript など)
- 最大サイズ:1 ファイルあたり 512MB
Web Search
ウェブからリアルタイム情報を取得します。
const response = await openai.responses.create({
model: 'gpt-5',
input: 'What are the latest updates on GPT-5?',
tools: [{ type: 'web_search' }],
});
console.log(response.output_text);
// Model searches web and provides current information with sources
これが重要な理由:
- 知識のカットオフ日の制限がありません
- 出典が自動的に引用されます
- リアルタイムのデータにアクセスできます
- 外部の検索 API が不要です
Image Generation(DALL-E)
Responses API 内で直接画像を生成します。
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Create an image of a futuristic cityscape at sunset',
tools: [{ type: 'image_generation' }],
});
// Find image in output
response.output.forEach(item => {
if (item.type === 'image_generation_call') {
console.log('Image URL:', item.output.url);
}
});
利用可能なモデル:
- DALL-E 3(デフォルト)
- さまざまなサイズと品質のオプション
MCP サーバーとの統合
Responses API は Model Context Protocol(MCP) サーバーを標準でサポートしており、外部ツールに接続できます。
MCP とは
MCP は、アプリケーションが LLM にコンテキストを提供する方法を標準化するオープンプロトコルです。以下のことができます。
- 外部 API(Stripe、データベース、CRM)に接続する
- ホスト型 MCP サーバーを使用する
- カスタムツール連携を構築する
MCP の基本的な統合
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Roll 2d6 dice',
tools: [
{
type: 'mcp',
server_label: 'dice',
server_url: 'https://example.com/mcp',
},
],
});
// Model discovers available tools on MCP server and uses them
console.log(response.output_text);
認証付き MCP(OAuth)
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Create a $20 payment link',
tools: [
{
type: 'mcp',
server_label: 'stripe',
server_url: 'https://mcp.stripe.com',
authorization: process.env.STRIPE_OAUTH_TOKEN,
},
],
});
console.log(response.output_text);
// Model uses Stripe MCP server to create payment link
重要:
- API は認証トークンを保存しません
- リクエストごとにトークンを指定する必要があります
- セキュリティのために環境変数を使用してください
多相出力:MCP ツール呼び出し
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Roll 2d4+1',
tools: [
{
type: 'mcp',
server_label: 'dice',
server_url: 'https://dmcp.example.com',
},
],
});
// Inspect tool calls
response.output.forEach(item => {
if (item.type === 'mcp_call') {
console.log('Tool:', item.name);
console.log('Arguments:', item.arguments);
console.log('Output:', item.output);
}
if (item.type === 'mcp_list_tools') {
console.log('Available tools:', item.tools);
}
});
出力の種類:
mcp_list_tools- サーバー上で検出されたツールmcp_call- ツールの呼び出しと結果message- ユーザーへの最終応答
推論の保持
仕組み
Responses API は、Chat Completions とは異なり、ターンをまたいでモデルの内部推論状態を保持します。Chat Completions ではこの状態が破棄されます。
視覚的なたとえ:
- Chat Completions:モデルはメモ用紙に推論を書き、応答する前にそのページを破り取ります
- Responses API:モデルはメモ用紙を開いたままにし、次のターンでも前の推論を確認できます
パフォーマンスへの影響
TAUBench の結果(GPT-5):
- Chat Completions:ベースラインスコア
- Responses API:5% 向上(推論の保持のみで実現)
これが重要な理由:
- 複数ターンにわたる問題解決が向上します
- 長い会話の一貫性が高まります
- 段階的な推論が改善されます
- コンテキストの誤りが減少します
推論の要約(無料!)
Responses API は、追加料金なしで推論の要約を提供します。
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Solve this complex math problem: [problem]',
});
// Inspect reasoning
response.output.forEach(item => {
if (item.type === 'reasoning') {
console.log('Model reasoning:', item.summary[0].text);
}
if (item.type === 'message') {
console.log('Final answer:', item.content[0].text);
}
});
使用例:
- モデルの判断のデバッグ
- コンプライアンス対応の監査証跡
- モデルの思考プロセスの理解
- 透明性の高い AI システムの構築
バックグラウンドモード(長時間実行タスク)
標準のタイムアウト制限を超えるタスクには、バックグラウンドモードを使用してください。
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Analyze this 500-page document and summarize key findings',
background: true,
tools: [{ type: 'file_search', file_ids: [fileId] }],
});
// Returns immediately with status
console.log(response.status); // "in_progress"
console.log(response.id); // Use to check status later
// Poll for completion
const checkStatus = async (responseId) => {
const result = await openai.responses.retrieve(responseId);
if (result.status === 'completed') {
console.log(result.output_text);
} else if (result.status === 'failed') {
console.error('Task failed:', result.error);
} else {
// Still running, check again later
setTimeout(() => checkStatus(responseId), 5000);
}
};
checkStatus(response.id);
使用する場面:
- 大きなファイルの処理
- 複雑な計算
- 複数ステップの調査タスク
- 大規模なデータセットのデータ分析
タイムアウト制限:
- 標準モード:60 秒
- バックグラウンドモード:最大 10 分
多相出力
Responses API は、単一のメッセージではなく、複数の出力タイプを返します。
出力タイプ
| タイプ | 説明 | 例 |
|---|---|---|
message | ユーザーへのテキスト応答 | 最終回答、説明 |
reasoning | モデルの内部思考プロセス | ステップごとの推論の要約 |
code_interpreter_call | コードの実行 | Python コードと結果 |
mcp_call | ツールの呼び出し | ツール名、引数、出力 |
mcp_list_tools | 使用可能なツール | MCP サーバーのツール定義 |
file_search_call | ファイル検索結果 | 一致したチャンク、引用 |
web_search_call | ウェブ検索結果 | URL、スニペット |
image_generation_call | 画像の生成 | 画像 URL |
多相出力の処理
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Search the web for the latest AI news and summarize',
tools: [{ type: 'web_search' }],
});
// Process different output types
response.output.forEach(item => {
switch (item.type) {
case 'reasoning':
console.log('Reasoning:', item.summary[0].text);
break;
case 'web_search_call':
console.log('Searched:', item.query);
console.log('Sources:', item.results);
break;
case 'message':
console.log('Response:', item.content[0].text);
break;
}
});
// Or use helper for text-only
console.log(response.output_text);
重要な理由:
- デバッグの改善(すべてのステップを確認できます)
- 監査証跡(すべてのツール呼び出しを追跡できます)
- より豊かな UX(ユーザーに進捗を表示できます)
- コンプライアンス(すべての操作を記録できます)
Chat Completions からの移行
互換性を破る変更
| 機能 | Chat Completions | Responses API | 移行 |
|---|---|---|---|
| エンドポイント | /v1/chat/completions | /v1/responses | URL を更新 |
| パラメーター | messages | input | パラメーター名を変更 |
| 状態 | 手動(messages 配列) | 自動(conversation ID) | conversation ID を使用 |
| ツール | 関数を含む tools 配列 | 組み込み型 + MCP | ツール定義を更新 |
| 出力 | choices[0].message.content | output_text または output 配列 | レスポンスの解析を更新 |
| ストリーミング | data: {"choices":[...]} | 複数のアイテムタイプを含む SSE | ストリームパーサーを更新 |
移行例
移行前(Chat Completions):
const response = await openai.chat.completions.create({
model: 'gpt-5',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello!' },
],
});
console.log(response.choices[0].message.content);
移行後(Responses):
const response = await openai.responses.create({
model: 'gpt-5',
input: [
{ role: 'developer', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello!' },
],
});
console.log(response.output_text);
主な違い:
chat.completions.create→responses.createmessages→inputsystemロール →developerロールchoices[0].message.content→output_text
移行するタイミング
今すぐ移行するケース:
- ✅ 新しいアプリケーションを構築する
- ✅ 状態を保持する会話が必要
- ✅ エージェント型のパターン(推論 + ツール)を使用する
- ✅ パフォーマンスの向上(推論の保持)を求める
Chat Completions を使い続けるケース:
- ✅ 単純な単発の生成
- ✅ レガシーな統合
- ✅ 状態管理が不要
エラー処理
よくあるエラーと解決方法
1. セッション状態が保持されない
エラー:
Conversation state not maintained between turns
原因:
- conversation ID を使用していない
- ターンごとに異なる conversation ID を使用している
解決方法:
// Create conversation once
const conv = await openai.conversations.create();
// Reuse conversation ID for all turns
const response1 = await openai.responses.create({
model: 'gpt-5',
conversation: conv.id, // ✅ Same ID
input: 'First message',
});
const response2 = await openai.responses.create({
model: 'gpt-5',
conversation: conv.id, // ✅ Same ID
input: 'Follow-up message',
});
2. MCP サーバーへの接続に失敗する
エラー:
{
"error": {
"type": "mcp_connection_error",
"message": "Failed to connect to MCP server"
}
}
原因:
- サーバー URL が無効
- 認証トークンがない、または期限切れ
- サーバーが応答しない
解決方法:
// 1. Verify URL is correct
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Test MCP',
tools: [
{
type: 'mcp',
server_label: 'test',
server_url: 'https://api.example.com/mcp', // ✅ Full URL
authorization: process.env.AUTH_TOKEN, // ✅ Valid token
},
],
});
// 2. Test server URL manually
const testResponse = await fetch('https://api.example.com/mcp');
console.log(testResponse.status); // Should be 200
// 3. Check token expiration
console.log('Token expires:', parseJWT(token).exp);
3. コードインタープリターのタイムアウト
エラー:
{
"error": {
"type": "code_interpreter_timeout",
"message": "Code execution exceeded time limit"
}
}
原因:
- コードの実行に 30 秒以上かかる
解決方法:
// Use background mode for long-running code
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Process this large dataset',
background: true, // ✅ Extended timeout
tools: [{ type: 'code_interpreter' }],
});
// Poll for results
const result = await openai.responses.retrieve(response.id);
4. 画像生成のレート制限
エラー:
{
"error": {
"type": "rate_limit_error",
"message": "DALL-E rate limit exceeded"
}
}
原因:
- 画像生成リクエストが多すぎる
解決方法:
// Implement retry with exponential backoff
const generateImage = async (prompt, retries = 3) => {
try {
return await openai.responses.create({
model: 'gpt-5',
input: prompt,
tools: [{ type: 'image_generation' }],
});
} catch (error) {
if (error.type === 'rate_limit_error' && retries > 0) {
const delay = (4 - retries) * 1000; // 1s, 2s, 3s
await new Promise(resolve => setTimeout(resolve, delay));
return generateImage(prompt, retries - 1);
}
throw error;
}
};
5. ファイル検索の関連性に関する問題
問題:
- ファイル検索で関連性のない結果が返される
解決方法:
// Use more specific queries
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Find sections about pricing in Q4 2024 specifically', // ✅ Specific
// NOT: 'Find pricing' (too vague)
tools: [{ type: 'file_search', file_ids: [fileId] }],
});
// Or filter results manually
response.output.forEach(item => {
if (item.type === 'file_search_call') {
const relevantChunks = item.results.filter(
chunk => chunk.score > 0.7 // ✅ Only high-confidence matches
);
}
});
6. コストの追跡に関する混乱
問題:
- 請求額が予想と異なる
説明:
- Responses API の請求対象:入力トークン + 出力トークン + ツールの使用 + 保存された会話
- Chat Completions の請求対象:入力トークン + 出力トークンのみ
解決方法:
// Monitor usage
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Hello',
store: false, // ✅ Don't store if not needed
});
console.log('Usage:', response.usage);
// {
// prompt_tokens: 10,
// completion_tokens: 20,
// tool_tokens: 5,
// total_tokens: 35
// }
7. 会話が見つからない
エラー:
{
"error": {
"type": "invalid_request_error",
"message": "Conversation conv_xyz not found"
}
}
原因:
- conversation ID の入力ミス
- 会話が削除された
- 会話の有効期限が切れた(90 日)
解決方法:
// Verify conversation exists before using
const conversations = await openai.conversations.list();
const exists = conversations.data.some(c => c.id === 'conv_xyz');
if (!exists) {
// Create new conversation
const newConv = await openai.conversations.create();
// Use newConv.id
}
8. ツール出力の解析に失敗する
問題:
- ツールの出力に正しくアクセスできない
解決方法:
// Use helper methods
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Search for AI news',
tools: [{ type: 'web_search' }],
});
// Helper: Get text-only output
console.log(response.output_text);
// Manual: Inspect all outputs
response.output.forEach(item => {
console.log('Type:', item.type);
console.log('Content:', item);
});
本番環境でのパターン
コスト最適化
1. 会話 ID を使用する(キャッシュのメリット)
// ✅ GOOD: Reuse conversation ID
const conv = await openai.conversations.create();
const response1 = await openai.responses.create({
model: 'gpt-5',
conversation: conv.id,
input: 'Question 1',
});
// 40-80% better cache utilization
// ❌ BAD: New manual history each time
const response2 = await openai.responses.create({
model: 'gpt-5',
input: [...previousHistory, newMessage],
});
// No cache benefits
2. 不要な場合はストレージを無効にする
// For one-off requests
const response = await openai.responses.create({
model: 'gpt-5',
input: 'Quick question',
store: false, // ✅ Don't store conversation
});
3. 可能な場合は小さいモデルを使用する
// For simple tasks
const response = await openai.responses.create({
model: 'gpt-5-mini', // ✅ 50% cheaper
input: 'Summarize this paragraph',
});
レート制限への対処
const createResponseWithRetry = async (params, maxRetries = 3) => {
for (let i = 0; i < maxRetries; i++) {
try {
return await openai.responses.create(params);
} catch (error) {
if (error.type === 'rate_limit_error' && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // Exponential backoff
console.log(`Rate limited, retrying in ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
};
監視とログ記録
const monitoredResponse = async (input) => {
const startTime = Date.now();
try {
const response = await openai.responses.create({
model: 'gpt-5',
input,
});
// Log success metrics
console.log({
status: 'success',
latency: Date.now() - startTime,
tokens: response.usage.total_tokens,
model: response.model,
conversation: response.conversation_id,
});
return response;
} catch (error) {
// Log error metrics
console.error({
status: 'error',
latency: Date.now() - startTime,
error: error.message,
type: error.type,
});
throw error;
}
};
Node.js と Cloudflare Workers の比較
Node.js の実装
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export async function handleRequest(input: string) {
const response = await openai.responses.create({
model: 'gpt-5',
input,
tools: [{ type: 'web_search' }],
});
return response.output_text;
}
メリット:
- SDK の完全なサポート
- 型安全性
- ストリーミング用ヘルパー
デメリット:
- Node.js ランタイムが必要
- バンドルサイズが大きい
Cloudflare Workers の実装
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { input } = await request.json();
const response = await fetch('https://api.openai.com/v1/responses', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-5',
input,
tools: [{ type: 'web_search' }],
}),
});
const data = await response.json();
return new Response(data.output_text, {
headers: { 'Content-Type': 'text/plain' },
});
},
};
メリット:
- 依存関係なし
- エッジへのデプロイ
- コールドスタートの高速化
デメリット:
- リクエストを手動で構築
- カスタム型がなければ型安全性がない
必ず行うこと/絶対に行わないこと
✅ 必ず行うこと
-
複数ターンのやり取りには会話 ID を使用する
const conv = await openai.conversations.create(); // Reuse conv.id for all related turns -
多相レスポンスのすべての出力タイプを処理する
response.output.forEach(item => { if (item.type === 'reasoning') { /* log */ } if (item.type === 'message') { /* display */ } }); -
長時間実行されるタスクにはバックグラウンドモードを使用する
const response = await openai.responses.create({ background: true, // ✅ For tasks >30s ... }); -
MCP サーバーに認証トークンを提供する
tools: [{ type: 'mcp', authorization: process.env.TOKEN, // ✅ Required }] -
コスト管理のためにトークン使用量を監視する
console.log(response.usage.total_tokens);
❌ 絶対に行わないこと
-
API キーをクライアント側のコードで公開しない
// ❌ DANGER: API key in browser const response = await fetch('https://api.openai.com/v1/responses', { headers: { 'Authorization': 'Bearer sk-proj-...' } }); -
出力が単一のメッセージだと決めつけない
// ❌ BAD: Ignores reasoning, tool calls console.log(response.output[0].content); // ✅ GOOD: Use helper or check all types console.log(response.output_text); -
ユーザー間で会話 ID を再利用しない
// ❌ DANGER: User A sees User B's conversation const sharedConv = 'conv_123'; -
エラータイプを無視しない
// ❌ BAD: Generic error handling try { ... } catch (e) { console.log('error'); } // ✅ GOOD: Type-specific handling catch (e) { if (e.type === 'rate_limit_error') { /* retry */ } if (e.type === 'mcp_connection_error') { /* alert */ } } -
バックグラウンドタスクのポーリング間隔を 1 秒未満にしない
// ❌ BAD: Too frequent setInterval(() => checkStatus(), 100); // ✅ GOOD: Reasonable interval setInterval(() => checkStatus(), 5000);
参考資料
公式ドキュメント
- Responses API ガイド:https://platform.openai.com/docs/guides/responses
- API リファレンス:https://platform.openai.com/docs/api-reference/responses
- MCP 統合:https://platform.openai.com/docs/guides/tools-connectors-mcp
- ブログ記事(Responses API の理由):https://developers.openai.com/blog/responses-api/
- スターターアプリ:https://github.com/openai/openai-responses-starter-app
スキルのリソース
templates/- 動作するコード例references/responses-vs-chat-completions.md- 機能の比較references/mcp-integration-guide.md- MCP サーバーのセットアップreferences/built-in-tools-guide.md- ツールの使用パターンreferences/stateful-conversations.md- 会話の管理references/migration-guide.md- Chat Completions → Responsesreferences/top-errors.md- よくあるエラーと解決策
次のステップ
- ✅
templates/basic-response.tsを読む - 簡単な例 - ✅
templates/stateful-conversation.tsを試す - 複数ターンのチャット - ✅
templates/mcp-integration.tsを確認する - 外部ツール - ✅
references/top-errors.mdを確認する - よくある落とし穴を回避 - ✅
references/migration-guide.mdを確認する - Chat Completions から移行する場合
Responses API での開発をお楽しみください! 🚀