コンテンツにスキップ

リアルタイムトランスポート

セッションがどこで実行されるか、またどの程度まで元のメディアやイベント制御が必要かに応じて、トランスポートを選択してください。

シナリオ推奨トランスポート理由
ブラウザーの speech-to-speech アプリOpenAIRealtimeWebRTC最も手軽な方法です。 SDK がマイク入力、再生、WebRTC 接続を管理します
サーバーサイドの音声ループまたはカスタム音声パイプラインOpenAIRealtimeWebSocketすでに音声の録音 / 再生を制御しており、イベントへ直接アクセスしたい場合に適しています
SIP または電話ブリッジOpenAIRealtimeSIPcallId により、既存の SIP 開始 Realtime 通話に RealtimeSession を接続します
Cloudflare Workers / workerdCloudflare 拡張トランスポートworkerd では、グローバルな WebSocket コンストラクターで外向き WebSocket を開けません
Twilio 上のプロバイダー固有の電話フローTwilio 拡張トランスポートTwilio の音声転送と割り込み動作を SDK が処理します

デフォルトのトランスポート層

Section titled “デフォルトのトランスポート層”

WebRTC はブラウザー向けのデフォルトの選択肢

Section titled “WebRTC はブラウザー向けのデフォルトの選択肢”

デフォルトのブラウザートランスポートは WebRTC を使用します。音声はマイクから自動的に取得され、自動的に再生されるため、クイックスタート ではエフェメラルトークンと session.connect(...) だけで接続できます。

この経路では、session.connect() は初期セッション設定が session.updated で確認されるまで待機しようとしてから resolve するため、音声の送受信が始まる前に instructions と tools が適用されます。その確認が届かない場合に備えて、タイムアウトによるフォールバックもあります。

独自のメディアストリームや音声要素を使用するには、セッション作成時に OpenAIRealtimeWebRTC インスタンスを渡してください。

import {
RealtimeAgent,
RealtimeSession,
OpenAIRealtimeWebRTC,
} from '@openai/agents/realtime';
const agent = new RealtimeAgent({
name: 'Greeter',
instructions: 'Greet the user with cheer and answer questions.',
});
async function main() {
const transport = new OpenAIRealtimeWebRTC({
mediaStream: await navigator.mediaDevices.getUserMedia({ audio: true }),
audioElement: document.createElement('audio'),
});
const customSession = new RealtimeSession(agent, { transport });
}

より低レベルなカスタマイズ向けに、OpenAIRealtimeWebRTCchangePeerConnection も受け付けます。これにより、offer が生成される前に、新しく作成された RTCPeerConnection を確認または置き換えできます。

WebSocket はサーバー向けのデフォルトの選択肢

Section titled “WebSocket はサーバー向けのデフォルトの選択肢”

WebRTC の代わりに WebSocket 接続を使用するには、セッション作成時に transport: 'websocket' または OpenAIRealtimeWebSocket のインスタンスを渡します。これはサーバーサイドのユースケース、電話ブリッジ、カスタム音声パイプラインに適しています。

WebSocket 経路では、session.connect() はソケットが開き、初期設定が送信されると resolve します。対応する session.updated イベントは少し遅れて届く可能性があるため、connect() が返った時点でその更新がすでに反映済みだとは想定しないでください。

import { RealtimeAgent, RealtimeSession } from '@openai/agents/realtime';
const agent = new RealtimeAgent({
name: 'Greeter',
instructions: 'Greet the user with cheer and answer questions.',
});
const myRecordedArrayBuffer = new ArrayBuffer(0);
const wsSession = new RealtimeSession(agent, {
transport: 'websocket',
model: 'gpt-realtime-1.5',
});
await wsSession.connect({ apiKey: process.env.OPENAI_API_KEY! });
wsSession.on('audio', (event) => {
// event.data is a chunk of PCM16 audio
});
wsSession.sendAudio(myRecordedArrayBuffer);

元の PCM16 音声バイトの処理には、任意の録音 / 再生ライブラリを使用してください。

高度な連携では、OpenAIRealtimeWebSocketcreateWebSocket() を受け付けるため、独自のソケット実装を渡せます。また、カスタムコネクター側がソケットを接続済み状態へ遷移させる責務を持つ場合は、skipOpenEventListeners も使用できます。@openai/agents-extensions の Cloudflare トランスポートは、これらのフックを基に構築されています。

SIP は通話プロバイダーと電話ブリッジ向け

Section titled “SIP は通話プロバイダーと電話ブリッジ向け”

既存の SIP 開始 Realtime 通話に RealtimeSession を接続したい場合は、OpenAIRealtimeSIP を使用してください。これは SIP 対応の薄いトランスポートです。音声は SIP 通話自体で処理され、SDK セッションは callId で接続されます。

  1. OpenAIRealtimeSIP.buildInitialConfig() を使って初期セッション設定を生成し、着信を受け付けます。これにより、SIP 招待と後続の SDK セッションが同じデフォルト設定から開始されます
  2. OpenAIRealtimeSIP トランスポートを使う RealtimeSession を接続し、プロバイダー webhook が発行した callId で connect します
  3. プロバイダー固有のメディア転送やイベントブリッジが必要な場合は、Twilio 拡張などの連携トランスポートを使用してください
import OpenAI from 'openai';
import {
OpenAIRealtimeSIP,
RealtimeAgent,
RealtimeSession,
type RealtimeSessionOptions,
} from '@openai/agents/realtime';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY!,
webhookSecret: process.env.OPENAI_WEBHOOK_SECRET!,
});
const agent = new RealtimeAgent({
name: 'Receptionist',
instructions:
'Welcome the caller, answer scheduling questions, and hand off if the caller requests a human.',
});
const sessionOptions: Partial<RealtimeSessionOptions> = {
model: 'gpt-realtime-1.5',
config: {
audio: {
input: {
turnDetection: { type: 'semantic_vad', interruptResponse: true },
},
},
},
};
export async function acceptIncomingCall(callId: string): Promise<void> {
const initialConfig = await OpenAIRealtimeSIP.buildInitialConfig(
agent,
sessionOptions,
);
await openai.realtime.calls.accept(callId, initialConfig);
}
export async function attachRealtimeSession(
callId: string,
): Promise<RealtimeSession> {
const session = new RealtimeSession(agent, {
transport: new OpenAIRealtimeSIP(),
...sessionOptions,
});
session.on('history_added', (item) => {
console.log('Realtime update:', item.type);
});
await session.connect({
apiKey: process.env.OPENAI_API_KEY!,
callId,
});
return session;
}

Cloudflare Workers やその他の workerd ランタイムでは、グローバルな WebSocket コンストラクターを使って外向き WebSocket を開けません。拡張パッケージの Cloudflare トランスポートを使用してください。内部で fetch() ベースの upgrade を実行します。

import { CloudflareRealtimeTransportLayer } from '@openai/agents-extensions';
import { RealtimeAgent, RealtimeSession } from '@openai/agents/realtime';
const agent = new RealtimeAgent({
name: 'My Agent',
});
// Create a transport that connects to OpenAI Realtime via Cloudflare/workerd's fetch-based upgrade.
const cfTransport = new CloudflareRealtimeTransportLayer({
url: 'wss://api.openai.com/v1/realtime?model=gpt-realtime',
});
const session = new RealtimeSession(agent, {
// Set your own transport.
transport: cfTransport,
});

完全なセットアップについては、Cloudflare 上の Realtime Agent を参照してください。

RealtimeSession は、生の WebSocket または @openai/agents-extensions の専用 Twilio トランスポートのいずれかを使って Twilio に接続できます。Twilio Media Streams に対して SDK に割り込みタイミングや音声転送を処理させたい場合は、専用トランスポートをデフォルトの選択肢として使うのが適しています。

完全なセットアップについては、Twilio 上の Realtime Agent を参照してください。

別の speech-to-speech API を使用したい場合や、独自のカスタムトランスポート機構がある場合は、RealtimeTransportLayer インターフェースを実装し、RealtimeTransportEventTypes イベントを自分で emit できます。

必要に応じた元の Realtime イベントへのアクセス

Section titled “必要に応じた元の Realtime イベントへのアクセス”

基盤となる Realtime API により直接アクセスしたい場合は、2 つの方法があります。

方法 1 - トランスポート層へのアクセス

Section titled “方法 1 - トランスポート層へのアクセス”

RealtimeSession のすべての機能の恩恵を受けつつ利用したい場合は、session.transport を通じてトランスポート層にアクセスできます。

トランスポート層は、受信したすべてのイベントを * イベントで emit し、sendEvent() を使って元のイベントを送信できます。これは session.updateresponse.createresponse.cancel などの低レベル操作のためのエスケープハッチです。

import { RealtimeAgent, RealtimeSession } from '@openai/agents/realtime';
const agent = new RealtimeAgent({
name: 'Greeter',
instructions: 'Greet the user with cheer and answer questions.',
});
const session = new RealtimeSession(agent, {
model: 'gpt-realtime-1.5',
});
session.transport.on('*', (event) => {
// JSON parsed version of the event received on the connection
});
// Send any valid event as JSON. For example triggering a new response
session.transport.sendEvent({
type: 'response.create',
// ...
});

方法 2 - トランスポート層のみの使用

Section titled “方法 2 - トランスポート層のみの使用”

自動ツール実行、ガードレール、ローカル履歴管理が不要な場合は、接続と割り込みだけを管理する「薄い」クライアントとしてトランスポート層だけを使うこともできます。

import { OpenAIRealtimeWebRTC } from '@openai/agents/realtime';
const client = new OpenAIRealtimeWebRTC();
const audioBuffer = new ArrayBuffer(0);
await client.connect({
apiKey: '<api key>',
model: 'gpt-realtime-1.5',
initialSessionConfig: {
instructions: 'Speak like a pirate',
outputModalities: ['audio'],
audio: {
input: {
format: 'pcm16',
},
output: {
format: 'pcm16',
voice: 'ash',
},
},
},
});
// optionally for WebSockets
client.on('audio', (newAudio) => {});
client.sendAudio(audioBuffer);