クイックスタート
/access-token エンドポイント からアクセストークンを取得します。詳細は クライアントアプリの認証 を参照してください。
接続
WebSocket エンドポイントに接続します:プロトコル概要
WebSocket 接続は、制御イベントには JSON メッセージ、メディアには Base64 エンコードされた音声を使用します。新しいサーバーイベントの種類は今後追加される可能性があります。前方互換性を保つため、認識できないイベントはエラーとして扱わずに無視してください。 セッションは 4 つのフェーズを経て進行します:- Start(開始)。 音声設定を含む
startイベントを送信します。 - Ready(準備完了)。 エージェントのパイプラインが準備できると、サーバーは
ackで応答します。 - Converse(会話)。 ユーザー音声を
media_inputとしてストリーミングし、media_outputからエージェント音声を再生します。並行して、サーバーは会話の進行を表す会話イベント(turn_started、turn_output_text_delta、turn_ended)をプッシュします。 - End(終了)。 クライアントまたはサーバーのいずれからでも接続を閉じることができます。サーバーのクローズ理由は通話が終了した理由を伝えます(接続の管理を参照)。
call_id を使って通話 APIからセッションの完全なレコードを取得できます。
クライアントイベント
セッションの開始(start)
音声ストリームの構成を初期化します。
configはエージェントのデフォルトの入力音声設定を上書きしますstream_idは任意です。指定されない場合、サーバーが生成してackイベントで返します
stream_id(任意): ストリーム識別子。指定されない場合はサーバーが生成config.input_format: クライアント音声入力の音声形式(mulaw_8000、pcm_16000、pcm_24000、pcm_44100)config.output_audio_delivery(任意): サーバーがエージェント音声を配信する方法。speaking_pace(デフォルト)は再生速度に合わせて音声をペーシングします。as_availableはモデルが生成し次第送信するため、ローカルでバッファリングするクライアントは独自のクロックで再生でき、低遅延を実現できます。エージェントがバックグラウンド音声を使用する場合はサポートされません。config.voice_id(任意): エージェントのデフォルト TTS 音声を上書きagent(任意): API 経由で個別のエージェント通話を構成し、本番環境に公開せずに introduction やプロンプトの変更をプレビュー可能metadata(任意): カスタムメタデータオブジェクト。これらはエージェントコードに渡されますが、次のように利用できる特別なフィールドもあります:to(任意): コールルーティング用の宛先識別子(デフォルトはエージェント ID)from(任意): 通話の発信元識別子(デフォルトは「websocket」)
ユーザー音声のストリーミング(media_input)
クライアントからサーバーに送信される音声データです。payload の音声データは Base64 エンコードする必要があります。
stream_id: ack レスポンスから取得したストリームの一意の識別子media.payload: start イベントで指定された形式の Base64 エンコードされた音声データ
DTMF トーンの送信(dtmf)
DTMF(デュアルトーン多重周波数)トーンを送信します。
stream_id: ストリーム識別子dtmf: DTMF 桁(0〜9、*、#)
カスタムメタデータの送信(custom)
エージェントにカスタムメタデータを送信します。
stream_id: ストリーム識別子metadata: カスタムデータのキーと値のペアを含むオブジェクト
サーバーイベント
セッションの準備完了(ack)
エージェントのパイプラインが音声を受信できる状態になると start に応答して送信されます。ストリーム構成を確認し、start イベントで指定されなかった場合はサーバー生成の stream_id を返します。
call_id: このセッションに対して作成された通話レコードの識別子。通話 API と組み合わせて、通話終了後に録音とトランスクリプトを取得できます
エージェント音声の受信(media_output)
エージェントの発話です。payload は start イベントの config.input_format で指定された形式の Base64 エンコード音声です。
会話イベント
会話そのものを表す 3 つのイベントがあります:turn_started、turn_output_text_delta、turn_ended。すべてのターンは、両ロールで共有される単一のカウンターから id を受け取ります。この id は 1 から始まり、通話全体を通じて厳密に単調増加するため、id だけでターンを一意に特定できます。
1 つのターンに関するイベントは、常に次の順序で到着します:turn_started、続いてゼロ個以上の turn_output_text_delta、最後に turn_ended。サーバーは会話の進行に合わせてこれらをプッシュし、音声の配信タイミングとは独立しています。これらのイベントを使ってトランスクリプトや発話中インジケーターを制御できます。コード例は ライブトランスクリプトを構築する を参照してください。
ターンの開始時(turn_started)
ユーザーが話し始めた、またはエージェントが応答を開始したときに送信されます。
stream_id: ストリーム識別子turn_started.id: ターンのインデックス。通話全体を通じて一意turn_started.role:userまたはassistantturn_started.start_timestamp: 通話開始からの経過秒数(おおよそクライアントがackを受信した時点)
エージェントテキストのストリーミング(turn_output_text_delta)
エージェントが発話する各単語ごとに、発話とほぼ同時に送信されます。エージェント側のトランスクリプトを 1 単語ずつ描画するために使用します。
stream_id: ストリーム識別子turn_output_text_delta.id: このテキストが属するターンのidと一致turn_output_text_delta.role: 常にassistantturn_output_text_delta.text: 追加する厳密な部分文字列。区切りのスペースも含まれるため、buffer[id] += textの形で連結してテキストを構築してください
turn_ended イベントの確定テキストとして届きます。
ターンの終了時(turn_ended)
ターンが終了したときに送信されます。ターンの完全な確定テキストを含み、ターン終了後に保存・表示すべきバージョンです。
stream_id: ストリーム識別子turn_ended.id: 対応するturn_startedイベントのidと一致turn_ended.role:userまたはassistantturn_ended.text: ターンの確定テキスト。ユーザーのターンでは書き起こされた発話、アシスタントのターンではエージェントが実際に発話したテキストturn_ended.was_interrupted: アシスタントのターンでは、ユーザーがターンを中断したときにtrue。ユーザーのターンでは、ターンの途中で通話が終了したときにのみtrueturn_ended.start_timestamp、turn_ended.end_timestamp: 通話開始からの経過秒数turn_ended.tool_calls: ターン中に行われたツール呼び出し。各エントリはname、arguments、および任意でresultとidを持ちます
turn_ended を送信せずに接続が閉じられます。接続が閉じたときは、開いているターンが終了したものとして扱ってください。
中断の処理(clear)
エージェントが現在の音声ストリームをクリア/中断したいことを示します。
通話の転送(transfer_call)
エージェントが通話を電話番号に転送したいことを示します。クライアントは自身のテレフォニー側で転送を開始する責任があります。
stream_id: ストリーム識別子transfer.target_phone_number: 通話を転送する E.164 形式の電話番号
ライブトランスクリプトを構築する
ライブトランスクリプトは、進行中の会話を UI に表示する機能で、エージェントの発話がライブキャプションのように 1 語ずつ現れます。turn_ended が届いた時点でテキストを埋めます。エージェントのターンでは、各単語をデルタが届くたびに表示し、発話ペースに合わせて応答が積み上がるようにします。
接続の管理
無操作タイムアウト
サーバーは 180 秒 後にアイドル接続を閉じます。クライアントからのメッセージがあるたびにタイマーがリセットされます:- アプリケーションメッセージ(media_input、dtmf、custom イベント)
- 標準の WebSocket ping フレーム
- その他の有効な WebSocket メッセージ
- コード: 1000(Normal Closure)
- 理由:
"connection idle timeout"
Ping/Pong キープアライブ
無音期間中の無操作タイムアウトを防ぐため、定期的なキープアライブとして標準の WebSocket ping フレームを使用します:接続の終了
接続はクライアントまたはサーバーのどちらからでも WebSocket クローズフレームを使って閉じることができます。 クライアント開始のクローズ:- コード: 1000(Normal Closure)
- 理由:
"call ended by agent"、または追加のコンテキストが利用可能な場合は"call ended by agent, reason: {specific_reason}"
ベストプラクティス
- 最初に
startを送信 —startより前に他のイベントが送信されると接続は閉じられます。 - 適切な音声形式を選択 — ソースに合わせて形式を選択してください:テレフォニーには
mulaw_8000、Web クライアントにはpcm_44100。 - クローズを適切に処理 — デバッグやリカバリのため、常にクローズコードと理由をキャプチャしてください。
- 接続を維持 — 180 秒の無操作タイムアウトを回避するため、60〜90 秒ごとに WebSocket ping フレームを送信してください。
- ストリーム ID を管理 — システム全体のオブザーバビリティ(可観測性)を高めるため、独自の
stream_id値を指定してください。 - アイドルタイムアウトから復旧 —
1000 / connection idle timeoutの場合、再接続してstartイベントを再送してください。