For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
メインナビゲーション

GPT-Live セッションの管理

セッションを構成し、コンテキストを維持して、会話のライフサイクルを管理します。

GPT-Live に接続したら、セッションイベントを使ってコンテキストを更新し、文字起こしを表示して、接続のライフサイクルを管理します。モデルは聞きながら同時に話せるため、アプリケーションでは受信イベント、音声再生、バックエンドのタスク状態をそれぞれ別に管理してください。

このガイドは、接続で session.started が発行済みであることを前提としています。接続のセットアップと音声ストリーミングについては接続を、バックエンドの処理については委任とツールを参照してください。

セッションの構成

セッションの作成時に、モデル、音声、委任モードを選択します。会話に関する指示をモデルに与え、関連する履歴を含めます。会話が長くなると、GPT-Live がコンテキストを自動的に管理します。

構成フィールド

設定項目開始時の設定セッション中の変更
モデル必須項目の model を設定します。変更するには、新しいセッションを開始します。
指示会話中の振る舞いを指定する instructions を、最大 16,384 トークンで設定します。session.instructions.append で指示を追加します。
履歴input に関連する過去のテキストメッセージを設定します。デフォルトは [] です。開始時の履歴を置き換えずに、コンテキストを追加します。
音声audio.output.voice に、サポートされている音声または使用許可のあるカスタム音声を設定します。デフォルトは marin です。変更するには、新しいセッションを開始します。
委任delegation.typeclient または responses に設定します。委任の設定を省略するか null にすると、クライアントモードが選択されます。現在のモードのまま Responses の設定を更新します。
保存セッションをフォークできるようにするには、storetrue に設定します。デフォルトは false です。開始時に選択します。

音声の選択肢

セッションの作成時に音声を選択します。audio.output.voice"quartz" などの API 名を設定します。GPT-Live には、次の音声も用意されています。

音声API 名言語地域的な特徴声の印象音声の由来
Quartzquartz英語オーストラリア女性的生成音声
Rippleripple英語オーストラリア男性的自然音声
Vespervesper英語イギリス男性的自然音声
Willowwillow英語アイルランド女性的自然音声
Stonestone英語アイルランド男性的自然音声
Gleamgleam英語北米女性的自然音声
Meridianmeridian英語北米男性的自然音声
Bossabossaポルトガル語ブラジル女性的自然音声
Tempotempoポルトガル語ブラジル男性的自然音声
Beaconbeacon英語フィリピン男性的生成音声
Deltadelta英語米国南部女性的生成音声
Cindercinder英語米国南部男性的生成音声

地域的な特徴は音声の話し方を表すもので、アクセントの忠実な再現を保証するものではありません。ご自身の録音から作成する承認済みの音声については、カスタム音声をご覧ください。

WebSocket では、共通の audio.format を起動時に選択します。セッション中は変更できません。WebRTC では、接続時に音声形式がネゴシエーションされるため、このフィールドを省略します。形式とストリーミングの詳細については、WebSocket の音声形式をご覧ください。

ライブセッションの更新

すでに Responses への委譲を使用しているセッションで session.delegation.responses を変更するには、session.update を使用します。変更する設定だけを送信してください。省略した設定は現在の値を保持します。設定と更新のワークフローについては、Responses への委譲の構成をご覧ください。

起動後に委譲モードを変更することはできません。特に、delegationnull に設定するとクライアントモードが選択されます。Responses セッションがリセットされるわけではありません。起動時のフィールドである modelinstructionsinputaudiostore は、更新対象として受け付けられません。未知の構成フィールドは拒否されます。

更新が成功すると、解決済みのセッション構成全体を含む session.updated が発行されます。event_id を指定した場合、確認応答ではその値が client_event_id として返されます。確認応答だけでなく、コマンドの拒否も確認してください。受け付けられたことから確認できるのは構成の更新です。バックエンドのタスクが実行されたことや、モデルが発話したことを示すものではありません。

履歴とコンテキストの提供

起動時に履歴を渡して以前の話題を再開し、会話の進行に合わせて関連するコンテキストを追加します。信頼できるアプリケーションの指示は、ユーザーメッセージや事実としての結果とは分けてください。

過去の会話によるセッションの初期化

セッションの作成時に、過去のテキストメッセージを session.input に含めます。たとえば、次の input フィールドをセッション作成時の構成に追加します。

export const session = {
  model: "gpt-live-1",
  input: [
    {
      type: "message",
      role: "user",
      content: [
        {
          type: "input_text",
          text: "I need help with my recent order.",
        },
      ],
    },
    {
      type: "message",
      role: "assistant",
      content: [
        {
          type: "output_text",
          text: "What is the order number?",
        },
      ],
    },
  ],
};

このリストには、最大 128 件のメッセージ、合計 8,192 トークンまで指定できます。対応するロールは developeruserassistant で、それぞれにテキストパートを 1 つ含めます。開発者メッセージとユーザーメッセージには input_text を、アシスタントメッセージには text または output_text を使用します。信頼できるアプリケーションの指示は、instructions または開発者メッセージに記述してください。このリストは system ロールを受け付けません。

次のやり取りに必要な履歴を選択してください。input は起動時のフィールドであり、実行中のセッションの履歴を置き換えるためのものではありません。また、Responses への委譲で使用するバックエンド入力項目のすべてに対応しているわけではありません。

コンテキストがモデルに届くタイミング

セッション作成時に指定した input の全内容は、セッション開始時からモデルが利用できます。最初からモデルに必要なコンテキストは、このフィールドに含めてください。

セッションの実行中、session.instructions.appendsession.thinking.appendsession.commentary.append イベントは、時間の経過とともにコンテンツをモデルに渡します。これらの確認応答は、フレームの進行がコンテキスト注入の推定終了点に達するまで待機します。返される start_msend_ms は、セッションのタイムライン上の推定範囲を示すもので、発話や再生の完了を示すものではありません。モデルが更新内容のすべてを取り込んだことを証明するものでもありません。次の発話に更新内容全体が反映されるとは想定しないでください。

フレームの進行が止まると、確認応答が保留されたままになることがあります。セッションを閉じると、保留中の追加処理についてエラーが報告されます。client_event_id を使って各確認応答を送信した event_id と対応付け、待機中もエラー処理を続けてください。

会話中のコンテキストの追加

更新内容をモデルにどう使わせたいかに応じて、イベントを選択します。

  • session.instructions.append:振る舞いや発話に影響する、信頼できるアプリケーションの指示を追加
  • session.thinking.append:モデルにすぐ発話するよう求めずに、事実に関するコンテキストを追加
  • session.commentary.append:モデルが声に出して伝える情報を提供。モデルが言い換える場合もあります

各イベントには、最大 500 トークンのプレーン文字列である content と、必須の delegation_id を指定します。セッション全体に適用するコンテキストには null を使用します。たとえば、アプリケーションがユーザーの同意を確認し、検索を開始した後に、次のイベントを送信します。

export function sendUpdate(connection) {
  connection.send({
    type: "session.thinking.append",
    event_id: "context_1",
    delegation_id: null,
    content:
      "The user has already accepted the terms. The account lookup is still running.",
  });
}

client_event_id: "context_1" を含む session.thinking.appended を待ち、エラーが発生した場合は処理します。確認応答は、コンテキストが受け付けられたことを示します。発話、再生、外部アクションの完了を確認するものではありません。

すぐに発話させないコンテキストも、後の発話に影響する可能性があり、プライバシーを保護する境界にはなりません。認証情報、シークレット、モデルが決して開示してはいけないテキストは、3 種類のイベントのいずれにも含めないでください。指示用のイベントには、アプリケーション側で記述した振る舞いを指定し、信頼できないツール出力を渡さないでください。権限の制御や必須の確認は、アプリケーション側で確実に実施してください。

ページ移動、選択、その他の UI の変更については、UI コンテキストの共有をご覧ください。ユーザーが何を指しているかを GPT-Live が理解できるように、簡潔な更新情報を送る方法を説明しています。

バックエンドのタスクにひも付く結果には、既知のクライアント委譲 ID を使用し、適切な種類の更新の送信に従ってください。この ID は、Responses のレスポンス ID やツール呼び出し ID とは異なります。

アプリケーションのチェックが作動したら、指示を使って会話を誘導します。サーバーはイベントを監視し、既存のセッションに接続したサイドバンド WebSocket、またはプライマリ WebSocket を通じて修正指示を送信できます。並行したチェック、アクションのブロック、再生の制御については、会話へのガードレールの適用をご覧ください。

会話インターフェースの構築

文字起こしとマイクの状態は、バックエンドの進捗とは独立して表示します。アシスタントのテキストを受信しただけでは、ユーザーが音声をどこまで聞いたかはわかりません。

文字起こしの差分

ユーザーの発話については session.input_transcript.delta を、アシスタントの発話については session.output_transcript.delta を受信するようにします。各イベントには、テキストの断片と、セッションのタイムライン上でその断片に対応する区間が含まれます。

{
  "type": "session.input_transcript.delta",
  "event_id": "event_transcript_1",
  "delta": "What is",
  "start_ms": 1000,
  "end_ms": 1200
}

start_msend_ms を保持しながら、話者ごとに断片を順番に追加します。これらの値はセッションのタイムライン上のミリ秒を表し、区間には開始点を含み、終了点を含みません。実際の時刻を示すタイムスタンプ、パケットの到着時刻、単語と時間の厳密な対応を示すものではありません。

イベントが発生するのは、文字起こしのテキストを含む区間だけです。また、ネットワーク経由での配信間隔は不均一になる場合があります。イベントがないことから無音と判断したり、断片をユーザーの完全なターンとして扱ったりしないでください。文字起こしの差分には、項目 ID も、ターンの完了を確定するイベントもありません。

文字起こしの断片の処理は任意です。会話を続けながら、断片を使って UI を更新したり、チェックを実行したり、作業に早めに着手したりできます。軽量なチェックには、gpt-5.6-luna などの小規模モデルを低い推論強度で使用することを検討してください。例や接続方法については、文字起こしの断片への対応をご覧ください。

会話のガードレールを設ける場合は、ユーザーとアシスタントのテキストを受信するたびに、蓄積した内容をチェックします。文字起こしの配信では、再生前に発話を承認するための先行バッファは提供されません。必要に応じた再生の制御をご覧ください。

インターフェースでテキストをターンごとにまとめる場合は、そのグループ分けを後から修正できるようにしてください。元の断片を保持し、ユーザーとアシスタントの区間が重なることを許容します。また、発話間隔に基づくタイムアウトは、録音した会話を使って調整してください。相手の短い相づちは、進行中のやり取りの一部である場合があります。断片のグループ分けだけを理由に、ツールを実行したり、バックエンドの作業をキャンセルしたりしてはいけません。

文字起こしのタイミングは、音声の再生とは分けて扱います。WebSocket の session.output_audio.delta イベントにはタイミングのフィールドがなく、音声出力の完了を示すイベントもありません。WebRTC ではメディアトラックを通じて音声が配信されます。音声の扱いについては、接続をご覧ください。

字幕の表示

両方の話者が話している間もテキストを追加できる字幕行を作成します。

  1. テキストをそのまま保持します。 話者ごとに、元の deltastart_msend_ms を保存します。スペースや繰り返された単語も含め、受信したとおりにテキストを連結してください。断片の前後の空白を削除したり、断片の間にスペースを挿入したりしないでください。
  2. 話者ごとに独立して更新します。 発話が重なっている間も、ユーザーとアシスタントの両方の行にテキストを追加できるようにします。割り込みがあっても、それまでのアシスタントのテキストは表示したままにし、アシスタントが発話を再開したら新しい行を開始します。
  3. 行の識別と順序を維持します。 アプリケーションで表示用 ID を割り当て、テキストが増えても行の順序を保ちます。変化するテキストや終了タイムスタンプを行の識別に使ったり、断片を受信するたびに行を最下部に移動したりしないでください。
  4. 遅れて届いた断片に応じてグループ分けを見直します。 文字起こしのタイムスタンプを使って、同じ話者の時間的に近い断片をまとめます。元の断片を保持しながら、遅れて届いたテキストで以前の行を更新し、断片の割り当てを修正できるようにしてください。これらの表示上のグループは、意味的に完結したターンではありません。間隔のしきい値はアプリケーション側で決め、テストする必要があります。
  5. 字幕を読む人がスクロールを操作できるようにします。 最下部を表示している間は、新しいテキストに追従します。上にスクロールしたら自動スクロールを一時停止し、最新の字幕に戻る方法を用意してください。
  6. ツールの進捗はステータス領域に表示します。 発話の字幕には、アシスタントの文字起こしイベントを使用します。ツールの動作状況やバックエンドの結果は字幕とは別に表示してください。結果を受信しても、アシスタントがその内容を話したとは限りません。

発話の重なり、短い相づち、割り込み、長い沈黙、2 人の話者のテキストが異なるペースで届く翻訳などの状況で、表示をテストします。

マイク入力の制御

セッションを終了せずに入力をミュートするには、session.input_audio.mute を送信します。

export function sendUpdate(connection) {
  connection.send({
    type: "session.input_audio.mute",
    event_id: "mute_1",
  });
}

client_event_id: "mute_1" を持つ session.input_audio.muted を受信してから、コマンドが受け付けられたと判断します。入力を再開するには、session.input_audio.unmute を送信し、session.input_audio.unmuted を待ちます。どちらのコマンドについても、エラーを処理します。

入力をミュートしても、推論、委任した作業、生成される音声は停止しません。マイクからの音声取得や音声再生を制御する必要がある場合は、アプリケーション側でそれぞれ制御します。

発信者が話し始める前の挨拶

session.started の後に挨拶をリクエストする手順は次のとおりです。

  1. delegation_id: null を指定した新しい session.instructions.append を 1 件送信します。挨拶の文言と使用する言語に加え、発信者を待たずにすぐ挨拶し、その後は話を止めて相手の発話を聞くよう明示的に指示します。既存の開始時の指示は保持します。
  2. 送信したコマンドと client_event_id が一致する session.instructions.appended を待ちます。コマンドが拒否された場合は、処理してから次に進みます。
  3. 発信者が話し始める前の無音も含め、音声入力を継続します。WebSocket では session.input_audio.append の送信を続け、WebRTC ではネゴシエーション済みの入力音声トラックをアクティブな状態に保ちます。出力の文字起こしと音声で挨拶を確認します。

発信者が話し始めるまでは、アプリケーションで指定した言語を使用します。名前、電話番号、所在地から言語を推測しないでください。プロンプトの設計については、音声モデルのプロンプトを参照してください。

アプリケーションの指示に従った挨拶が必要な場合は、session.instructions.append でその指示を送信し、続いて短い session.commentary.append でアシスタントに開始を促します。たとえば、「Begin the conversation now, following the instructions provided.」と伝えます。発信者が話し始める前の無音も含め、音声入力を継続します。

指示は挨拶をリクエストするものであり、指定どおりの文言や、中断のない再生を保証するものではありません。API は冒頭の挨拶の完了を示すイベントを出力しません。また、受領確認があっても、挨拶が相手に聞こえたとは限りません。一字一句指定どおりに音声を流す必要がある場合は、アプリケーション側で再生を制御します。アプリケーションでサポートする言語や割り込みの状況で、挨拶をテストします。

告知の読み上げ

告知を特定の文言で読み上げるようリクエストするには、session.instructions.append を使用します。session.commentary.append では文言が言い換えられる場合があります。たとえば、session.started の後に次を送信します。

export function sendUpdate(connection) {
  connection.send({
    type: "session.instructions.append",
    event_id: "disclosure_1",
    delegation_id: null,
    content:
      "Immediately say the following disclosure exactly and in full before responding to the caller: This call may be recorded for quality and training purposes.",
  });
}

発信者が話し始める前の挨拶の説明に従って、音声入力を継続します。会話中に送信した指示は、進行中の発話を中断する可能性があるため、告知のタイミングは慎重に選びます。

これは文言を指定してリクエストするものであり、そのとおりに告知が行われることを保証するものではありません。告知済みと記録する前に、告知全文の読み上げ内容と実際の再生を確認します。session.instructions.appended が示すのは、指示が受け付けられたことだけです。指定どおりの音声を確実に流す必要がある場合は、確認済みの録音または生成済みの音声クリップをアプリケーションで再生し、その間は GPT-Live の出力を制御します。必要に応じた再生の制御を参照してください。

長い会話の管理

GPT-Live は長い会話のコンテキストを自動的に管理するため、設定パラメーターは不要です。セッション開始時に指定した指示は、コンパクションを経ても保持されます。再送信する必要はありません。

デフォルトのコンテキストウィンドウには 128,000 トークンが収まります。これには、指示、会話のテキスト、文字起こしには表示されない音声トークンが含まれます。

GPT-Live はバックグラウンドで古い会話履歴を要約します。コンテキスト使用率が 90% を超えると、同じセッション内で切り替え先の音声エンジンを起動します。切り替え先のエンジンには、元の指示と、最大 8,192 トークンの会話履歴が渡されます。この履歴には、最近のメッセージと、利用可能な場合は古いメッセージの要約が含まれます。要約を準備した時点で、稼働中のエンジンのコンテキストがすぐに変わるわけではありません。

古い会話の詳細は、要約または省略される場合があります。重要な事実、確認済みのアクション、現在のタスクの状態はアプリケーションで保持し、必要に応じて関連するコンテキストを提供します。

セッションの保存とフォーク

後でダウンロードやフォークに使用する録音を保存するには、セッション作成時の設定で storetrue にします。保存設定のデフォルトは false であり、プロジェクトで保存を有効にする必要があります。ダウンロードとフォークには、録音が完了して保存されていることと、データポリシーで永続化が許可されていることが必要です。録音は 30 日後に期限切れになります。ゼロデータ保持では、storefalse として扱われ、録音のダウンロードとフォークは利用できません。GPT-Live のデータ制御を参照してください。

たとえば、WebSocket の session.start イベントまたは WebRTC の作成リクエストに含まれる session オブジェクトに、次のフィールドを追加します。

{
  "store": true
}

session.started または WebRTC の作成レスポンスから、フォーク元のセッション ID を保存します。フォークでは、保存済みのセッション状態から新しい ID を持つ新しいセッションを開始します。元の接続を再開したり、フォーク元のセッション ID を再利用したりするものではありません。

アプリケーションで使用するトランスポート経由でフォークを開始します。

トランスポートフォークの開始方法
WebSocketwss://api.openai.com/v1/live/sessions/{source_session_id}/fork に接続します。
WebRTC新しい SDP オファーを POST /v1/live/sessions/{source_session_id}/fork に送信します。返された transport.sdp のアンサーを、新しいピア接続に適用します。

フォークは、以下のトランスポートのルールに従って、保存済みのセッション設定を継承します。WebSocket でフォークする場合は、必須の session オブジェクトを含めて session.start を送信します。{} を指定した場合、設定は上書きされません。新しいモデルを指定したり、元の指示や入力を繰り返し送信したりしないでください。store、Responses の委任設定、新しい WebSocket の音声形式は上書きできます。WebRTC でのフォークでは、store、Responses の委任設定、フロントエンドクライアントの権限を上書きできます。フォーク時に store を省略すると、フォーク元のセッションの設定が継承されます。

WebSocket でのフォークでは、フォーク元の音声形式は継承されませんaudio.format を明示的に設定するか、デフォルトの 24 kHz の PCM16 を使用します。また、継承したフロントエンドのデータチャネル権限も破棄されます。WebRTC でのフォークでは音声形式をネゴシエーションするため、audio.format は受け付けられません。フロントエンドの権限設定は、上書きしない限り保持されます。

追加の WebSocket コマンドを送信する前に、session.started を待ちます。WebRTC は HTTP リクエストによって開始されるため、データチャネルで 2 回目の session.start を送信してはいけません。

WebSocket でのフォークの開始

OPENAI_API_KEY を設定します。以下の例では、アプリケーションで保存した、保存済みのフォーク元セッションの ID を使用します。これらの例は、起動を確認した後、フォークしたセッションを閉じます。会話を続けるには、session.started の後にWebSocket 接続のフローに従って音声を送受信します。起動時のフィールドとイベントについては、フォーク用 WebSocket のリファレンスを参照してください。

import OpenAI from "openai";
import { ForksWS } from "openai/resources/live/forks/ws";

async function forkSession(sourceSessionId) {
  const ws = new ForksWS(new OpenAI(), { session_id: sourceSessionId });
  let finalized = false;
  try {
    for await (const event of ws) {
      if (event.type === "open") {
        ws.send({ type: "session.start", session: {} });
      } else if (event.type === "error") {
        throw event.error;
      } else if (event.type === "message") {
        if (event.message.type === "session.started") {
          console.log("Fork ready:", event.message.session.id);
          // This startup example closes the fork after confirming it is ready.
          ws.send({ type: "session.close" });
        } else if (event.message.type === "session.closed") {
          console.log("Final usage:", event.message.usage);
          finalized = true;
          break;
        }
      }
    }
    if (!finalized) throw new Error("Connection closed before session.closed");
  } finally {
    ws.close();
  }
}

WebRTC でのフォークの開始

フロントエンドで新しい SDP オファーを作成し、バックエンドに送信します。以下のバックエンドの例では、そのオファーと、アプリケーションで保持している保存済みのフォーク元セッションの ID を使用します。

import OpenAI from "openai";

async function forkSession(sourceSessionId, offerSdp) {
  const client = new OpenAI();
  const fork = await client.live.sessions.fork(sourceSessionId, {
    transport: { type: "webrtc", sdp: offerSdp },
  });
  console.log(JSON.stringify(fork));
}

レスポンスをフロントエンドに返し、transport.sdp を新しいピア接続のアンサーとして適用し、新しい session.id を保持します。API キーはバックエンドで保持します。

以降のサイドバンド接続とセッション制御には、新しいセッション ID を使用します。会話の状態を復元しても、保留中のバックエンドのアクションが完了したことは確認できないため、アプリケーションのタスクの状態は別途保持します。アクションを再試行する前に、不確かな結果を照合して確定します。フォークできる保存済みセッションがない場合は、保存した履歴を使って新しいセッションを初期化します

録音のダウンロード

保存した録音の確定処理が完了したら、GET /v1/live/sessions/{session_id}/content で音声をダウンロードします。レスポンスはステレオ WAV のバイナリデータで、左チャネルに入力音声、右チャネルに出力音声が含まれます。以下の例では、アプリケーションで保持している保存済みセッションの ID を使用し、レスポンスを recording.wav にストリーミングで書き込みます。

import OpenAI from "openai";
import { createWriteStream } from "node:fs";
import { pipeline } from "node:stream/promises";

async function downloadRecording(sessionId) {
  const client = new OpenAI();
  const response = await client.live.sessions.downloadRecording(sessionId);
  if (!response.body) throw new Error("Recording response has no body");
  await pipeline(response.body, createWriteStream("recording.wav"));
}

エラー処理とセッションの終了

セッションの終了処理が完了するまで、セッションイベントの読み取りを続けます。アプリケーションで適切に復旧できるよう、コマンドの拒否、接続の失敗、セッションの完了を区別します。

拒否されたコマンドの処理

受領確認とあわせて error イベントを読み取ります。error.client_event_id が含まれている場合は、その値で失敗した送信コマンドを特定できます。

{
  "type": "error",
  "event_id": "event_error",
  "error": {
    "type": "invalid_request_error",
    "code": "immutable_field_update",
    "message": "The delegation type cannot change after session startup.",
    "param": "session.delegation.type",
    "client_event_id": "event_update"
  }
}

エラーコードが null であったり、エラーにクライアントイベント ID が含まれていなかったりする場合があります。その場合も、コマンドが成功したと決めつけずに処理します。変更不可のフィールドに関するエラーの場合は、現在の設定を維持するか、目的の設定で新しいセッションを作成します。

モデレーションへの対応

モデレーションがセッションに及ぼす影響には、次の 2 種類があります。

  • 一部のモデレーションイベントは、セッションを終了させます。
  • それ以外のイベントは、セッションを終了せずに、アシスタントの現在の発話の残りの音声を打ち切り、error イベントを出力します。

音声の再生中も error イベントを読み取ります。すべてのモデレーションエラーでセッションが閉じると決めつけたり、音声の中断を接続の失敗とみなしたりしないでください。アプリケーションの状態をセッションのライフサイクルと一致させ、中断された音声メッセージを全文伝達済みとして記録しないようにします。アプリケーションレベルの会話のガードレールは、この組み込みのモデレーション動作とは別のものです。

使用量と正常終了

session.usage.updated は、音声の累積時間を秒単位で報告します。

{
  "type": "session.usage.updated",
  "event_id": "event_usage_1",
  "usage": { "seconds": 12 },
  "context_window": { "usage_ratio": 0.42 }
}

これらの値はスナップショットであり、合算するための増分値ではありません。バックエンドのトークン使用量は別に扱われるため、ネストされた Responses の完了イベントから取得して保持してください。使用量の集計については、コストの最適化を参照してください。

正常に終了するには、次の手順に従います。

  1. 処理待ちの関数の結果やレスポンスの継続処理を含め、委任された Responses の処理のうち、アプリケーションに必要なものを完了します。
  2. session.close を送信する前に、session.closed のリスナーを登録します。
  3. session.close を送信し、セッションへの新しい処理の送信を停止します。保留中のセッションイベントがすべて届くまで、WebSocket または WebRTC 接続、データチャネル、および接続されているサイドバンド受信側を維持します。
  4. session.closed から最終的な usage.secondsreason、セッションのスナップショットを読み取ります。response.event を通じてすでに受信した委任処理の使用量も保持します。
  5. そのイベントを受信した後で、トランスポートと音声デバイスのリソースを解放します。終了処理に失敗した場合や、アプリケーションで設定したタイムアウトを超えた場合は、終了処理が未完了であることを報告し、リソースを解放します。

session.close を送信すると、キュー内の Responses がキャンセルされ、以降のコマンドは拒否されます。実行中のレスポンスは完了できますが、関数の結果を待っているレスポンスは、終了処理の開始後は継続できません。クライアントへの委任によってアプリケーションが実行する処理を完了するか、キャンセルするかは、別途判断してください。

session.closed イベントによって終了処理の完了が確定します。イベントに含まれるセッションは、構成のスナップショットです。ソケットが閉じただけでは成功したとは判断できません。また、有効な最終イベントの後にトランスポートのクローズコードを受信しても、終了処理の完了が無効になるわけではありません。コマンドの送信直後に WebRTC を閉じると、最終イベントが届かない場合があります。

最終イベントの reason は、セッションが終了した理由を示します。

理由意味
close_requestedアプリケーションが session.close を送信したか、hangup エンドポイントを呼び出しました。
expiredセッションが制限時間に達しました。
content安全性フィルターによってセッションが終了しました。
remote_hangupリモート側のプライマリ接続が正常に終了しました。
connection_lostプライマリ接続または上流の接続が予期せず失われました。

終了理由が接続の切断や安全上の理由による終了であっても、session.closed イベントによって終了処理の完了を確認できます。このイベントがなければ、最終的な使用量は未確認のままです。保存対象のセッションでは、録音の保存によって終了処理に時間がかかる場合があります。保存にかかる時間を考慮して、アプリケーションのタイムアウトを設定してください。

接続障害からの復旧

HTTP のセッション作成エラーは、セッションが session.started に到達しなかったことを意味します。起動時のエラーは、実行中のセッションで発生するエラーとは分けて処理してください。session.closed の前に使用中の接続で障害が発生した場合は、最後に確認できた使用量を保持し、最終的な使用量を未確認として記録してください。

保存済みのセッションが利用できる場合は、そのセッションをフォークして、保存された状態から新しいセッションを開始します。利用できない場合は、関連する保存済みの履歴を使って代わりのセッションを作成します。保留中のアクションは、再試行する前にバックエンドの状態と照合し、前のセッションから届く古い結果は反映しないようにします。新しい接続によって前のセッションやその保留中の処理が再開されると想定せず、アプリケーションの状態を明示的に復元してください。