mcpField
O
openai-responses

openai-responses

github.com/ovachieverエージェントワークフロー5658 回インストール48 週間前に更新
リポジトリ

openai-responses について

OpenAI Responses APIでエージェント型アプリケーションを構築するためのスキルです。状態管理付き会話、ホスト型ツール、MCP接続を扱います。

主な機能

  1. 01会話状態の自動管理
  2. 02ターンをまたぐ推論状態の保持
  3. 03コード・ファイル・ウェブ・画像のホスト型ツール
  4. 04長時間タスクのバックグラウンド処理

活用シーン

  1. 01複数ターンのエージェント型アプリ構築
  2. 02アップロード済みファイルの検索
  3. 03Pythonによるデータ分析
  4. 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.json
references/
built-in-tools-guide.md
mcp-integration-guide.md
migration-guide.md
reasoning-preservation.md
responses-vs-chat-completions.md
stateful-conversations.md
top-errors.md
scripts/
check-versions.sh
templates/
background-mode.ts
basic-response.ts
cloudflare-worker.ts
code-interpreter.ts
file-search.ts
image-generation.ts
mcp-integration.ts
package.json
stateful-conversation.ts
web-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 CompletionsResponses 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 InterpreterPython コードを実行しますデータ分析、計算、グラフ作成
File Searchベクトルストアなしで RAG を利用しますアップロードしたファイルから回答を検索します
Web Searchウェブのリアルタイム情報を取得します時事情報、ファクトチェック
Image GenerationDALL-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 CompletionsResponses API移行
エンドポイント/v1/chat/completions/v1/responsesURL を更新
パラメーターmessagesinputパラメーター名を変更
状態手動(messages 配列)自動(conversation ID)conversation ID を使用
ツール関数を含む tools 配列組み込み型 + MCPツール定義を更新
出力choices[0].message.contentoutput_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);

主な違い:

  1. chat.completions.create → responses.create
  2. messages → input
  3. system ロール → developer ロール
  4. 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' },
    });
  },
};

メリット:

  • 依存関係なし
  • エッジへのデプロイ
  • コールドスタートの高速化

デメリット:

  • リクエストを手動で構築
  • カスタム型がなければ型安全性がない

必ず行うこと/絶対に行わないこと

✅ 必ず行うこと
  1. 複数ターンのやり取りには会話 ID を使用する

    const conv = await openai.conversations.create();
    // Reuse conv.id for all related turns
    
  2. 多相レスポンスのすべての出力タイプを処理する

    response.output.forEach(item => {
      if (item.type === 'reasoning') { /* log */ }
      if (item.type === 'message') { /* display */ }
    });
    
  3. 長時間実行されるタスクにはバックグラウンドモードを使用する

    const response = await openai.responses.create({
      background: true, // ✅ For tasks >30s
      ...
    });
    
  4. MCP サーバーに認証トークンを提供する

    tools: [{
      type: 'mcp',
      authorization: process.env.TOKEN, // ✅ Required
    }]
    
  5. コスト管理のためにトークン使用量を監視する

    console.log(response.usage.total_tokens);
    
❌ 絶対に行わないこと
  1. API キーをクライアント側のコードで公開しない

    // ❌ DANGER: API key in browser
    const response = await fetch('https://api.openai.com/v1/responses', {
      headers: { 'Authorization': 'Bearer sk-proj-...' }
    });
    
  2. 出力が単一のメッセージだと決めつけない

    // ❌ BAD: Ignores reasoning, tool calls
    console.log(response.output[0].content);
    
    // ✅ GOOD: Use helper or check all types
    console.log(response.output_text);
    
  3. ユーザー間で会話 ID を再利用しない

    // ❌ DANGER: User A sees User B's conversation
    const sharedConv = 'conv_123';
    
  4. エラータイプを無視しない

    // ❌ 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 */ }
    }
    
  5. バックグラウンドタスクのポーリング間隔を 1 秒未満にしない

    // ❌ BAD: Too frequent
    setInterval(() => checkStatus(), 100);
    
    // ✅ GOOD: Reasonable interval
    setInterval(() => checkStatus(), 5000);
    

参考資料

公式ドキュメント
スキルのリソース
  • 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 → Responses
  • references/top-errors.md - よくあるエラーと解決策

次のステップ

  1. ✅ templates/basic-response.ts を読む - 簡単な例
  2. ✅ templates/stateful-conversation.ts を試す - 複数ターンのチャット
  3. ✅ templates/mcp-integration.ts を確認する - 外部ツール
  4. ✅ references/top-errors.md を確認する - よくある落とし穴を回避
  5. ✅ references/migration-guide.md を確認する - Chat Completions から移行する場合

Responses API での開発をお楽しみください! 🚀

コメント