# Chat Completions と Responses API の違い：URL変更では終わらない

> OpenAIの2つのAPIを、リクエスト、output Item、会話状態、ツール呼び出し、構造化出力、streamingの実装境界から比較します。

- Source: https://www.aifreeapi.com/ja/posts/chat-completions-vs-responses-api
- Language: ja
- Published: 2026-08-25
- Updated: 2026-08-25
- Publisher: AI Free API (https://www.aifreeapi.com)

新規プロジェクトなら、基本線は Responses API です。既存の Chat Completions が単純なテキスト生成を安定して処理しているなら、移行は段階的で構いません。OpenAI の現行[移行ガイド](https://developers.openai.com/api/docs/guides/migrate-to-responses)は、Responses を新規プロジェクトに推奨しつつ、Chat Completions は引き続きサポートされると明記しています。

違いは endpoint 名だけではありません。Chat Completions は Messages を入力し、`choices` 内の assistant message を返します。Responses は message、reasoning、function call、tool result を別々の型付き **Item** として扱います。このデータモデルの差が、出力解析、会話状態、ツール、streaming の実装に波及します。

![Chat Completions と Responses API で変わる入力、出力、会話状態、ツール、構造化出力、ストリーミングの契約](https://www.aifreeapi.com/posts/ja/chat-completions-vs-responses-api/img/cover.webp)

## 最小コードが同じに見える理由

単発テキストでは移行は簡単に見えます。

```js
const completion = await client.chat.completions.create({
  model: "gpt-5.6",
  messages: [{ role: "user", content: "問い合わせを分類して" }],
});
const chatText = completion.choices[0].message.content;

const response = await client.responses.create({
  model: "gpt-5.6",
  input: "問い合わせを分類して",
});
const responseText = response.output_text;
```

`output_text` は最終テキストを取り出す SDK の便利機能です。tool call、reasoning summary、引用、個別ステータスが必要なら、`response.output` の Item を型ごとに処理します。

| 実装上の契約 | Chat Completions | Responses API |
|---|---|---|
| endpoint | `/v1/chat/completions` | `/v1/responses` |
| 入力 | `messages` | `input` と任意の `instructions` |
| 出力 | `choices[].message` | 型付き `output[]` Items |
| 複数候補 | `n` で複数 choice | 1 response につき1 generation |
| 会話継続 | 履歴を再送 | `previous_response_id`、Conversations、手動 replay |
| Structured Outputs | `response_format` | `text.format` |
| streaming | chunk の `choices[].delta` | 型付きイベント |

単純な role/content 配列は Responses の `input` に再利用できます。しかし、これは最小入力の互換性であり、両 endpoint の request body や response body を混ぜてよいという意味ではありません。

## 会話状態は明示的に選ぶ

Chat Completions では、アプリが必要な履歴を保持し、次の `messages` に入れ直すのが一般的です。Responses では `previous_response_id` で前回とつなげられます。

```js
const first = await client.responses.create({
  model: "gpt-5.6",
  instructions: "障害対応者として簡潔に答える。",
  input: "アラートを原因別にまとめて。",
});

const next = await client.responses.create({
  model: "gpt-5.6",
  previous_response_id: first.id,
  instructions: "障害対応者として簡潔に答える。",
  input: "最優先のグループだけ残して。",
});
```

`instructions` を再指定しているのは意図的です。[Responses API reference](https://developers.openai.com/api/reference/resources/responses/methods/create)によれば、`previous_response_id` を渡しても前回の instructions は自動継承されません。継続すべきポリシーはアプリ側で保持します。

また、会話をつなげやすいこととデータ保持は別問題です。OpenAI の[データ管理ドキュメント](https://developers.openai.com/api/docs/guides/your-data)は、`store`、Zero Data Retention、background mode、prompt cache、hosted tools を別々に説明しています。現在、保存される Responses application state には少なくとも30日の保持が記載されていますが、組織設定や例外で挙動が変わります。実際の利用面を確認してください。

## ツール呼び出しは往復形式が変わる

Chat Completions では、assistant message 内の `tool_calls` を読み、`tool_call_id` を持つ `role: "tool"` message を追加します。Responses では `function_call` Item を受け取り、同じ `call_id` を持つ `function_call_output` Item を返します。

```js
const outputs = response.output
  .filter((item) => item.type === "function_call")
  .map((call) => ({
    type: "function_call_output",
    call_id: call.call_id,
    output: JSON.stringify(runTool(call.name, call.arguments)),
  }));
```

最初の call だけを処理してはいけません。並列 call、引数不正、timeout、tool error、結果後の再 call をテストします。現行の対応形式は OpenAI の[function calling ガイド](https://developers.openai.com/api/docs/guides/function-calling)で確認できます。

Responses は web search、file search、code interpreter、remote MCP などの hosted tools も型付き Item として扱えるため、agentic workflow では有力です。ただし、実際の tool 対応はモデルごとに確認が必要です。

## streaming は終了条件まで作り直す

Chat Completions の UI は `choices[0].delta.content` を順に足す実装が一般的です。Responses はテキスト delta、function arguments、Item 完了、response 完了などの型付きイベントを返します。[公式 streaming ガイド](https://developers.openai.com/api/docs/guides/streaming-responses)に沿ってイベントを分岐してください。

HTTP 200 や最初の文字列到着だけを成功にすると、`incomplete` や途中失敗を見落とします。response ID、最終 status、Item type、usage、error または incomplete reason をログ対象にします。ユーザーキャンセルとネットワーク切断も別の終了状態です。

Structured Outputs も `response_format` から `text.format` へ設定位置が変わります。[Structured Outputs ガイド](https://developers.openai.com/api/docs/guides/structured-outputs)を基に、JSON Schema だけでなく refusal、モデル対応、parse failure を確認します。

![用途別のAPI選択と第三者サービスのResponses互換性を確認するマトリクス](https://www.aifreeapi.com/posts/ja/chat-completions-vs-responses-api/img/workload-choice-matrix.webp)

## 移行は adapter の後ろで証明する

Responses が向くのは、新規開発、reasoning context、hosted tools、複数段の function call、マルチモーダル入力、長い処理です。成熟した単発テキストサービスで利益が小さいなら、Chat Completions を維持する判断も成立します。Assistants API の終了予定を Chat Completions に適用してはいけません。

![Chat Completions から Responses API へ段階移行する順序と受け入れ判定の境界](https://www.aifreeapi.com/posts/ja/chat-completions-vs-responses-api/img/migration-acceptance.webp)

安全な移行では、まず `choices[0]` への直接依存を内部 adapter に閉じ込めます。同じ代表入力を両経路へ流し、文章の完全一致ではなく、構造化結果、refusal、切り詰め、tool intent、usage を比較します。その後、状態、全 tool call、streaming、データ管理を順番に切り替えます。

第三者 endpoint の「OpenAI compatible」は、多くの場合 Chat Completions 形式を指します。Responses の endpoint、Item、イベント、tool envelope、状態、error object は、その provider の最新ドキュメントで別途検証します。サンプルが一度返答したことではなく、会話が復元でき、call が欠落せず、schema が parse でき、stream が正しく閉じ、失敗原因が追えることを移行完了条件にしてください。
