コンテンツにスキップ

Realtime Agent を Twilio に接続

Twilio は、電話通話の元音声を WebSocket サーバーへ送信する Media Streams API を提供しています。このセットアップを利用して、あなたの 音声エージェント を Twilio に接続できます。websocket モードの既定の Realtime Session transport を使って、Twilio から送られてくるイベントを Realtime Session に接続することもできます。しかし、電話通話は Web ベースの会話よりも遅延が大きくなるため、正しいオーディオ形式を設定し、割り込みタイミングを調整する必要があります。

セットアップ体験を向上させるために、Twilio への接続、割り込み処理、オーディオ転送をすべて自動で行う専用のトランスポートレイヤーを用意しました。

  1. Twilio アカウントと Twilio 電話番号を用意します。

  2. Twilio からのイベントを受信できる WebSocket サーバーを設定します。

    ローカル開発の場合、Twilio からアクセスできるように ngrok
    Cloudflare Tunnel などでローカルトンネルを構成する必要があります。TwilioRealtimeTransportLayer を使用して Twilio に接続できます。

  3. extensions パッケージをインストールして Twilio アダプターを追加します:

    Terminal window
    npm install @openai/agents-extensions
  4. アダプターとモデルをインポートして RealtimeSession に接続します:

    import { TwilioRealtimeTransportLayer } from '@openai/agents-extensions';
    import { RealtimeAgent, RealtimeSession } from '@openai/agents/realtime';
    const agent = new RealtimeAgent({
    name: 'My Agent',
    });
    // Create a new transport mechanism that will bridge the connection between Twilio and
    // the OpenAI Realtime API.
    const twilioTransport = new TwilioRealtimeTransportLayer({
    twilioWebSocket: websocketConnection,
    });
    const session = new RealtimeSession(agent, {
    // set your own transport
    transport: twilioTransport,
    });
  5. RealtimeSession を Twilio に接続します:

    session.connect({ apiKey: 'your-openai-api-key' });

RealtimeSession から期待できるイベントや動作は、ツール呼び出しやガードレールなどを含め、すべてそのまま利用できます。RealtimeSession を音声エージェントで使用する方法については、音声エージェント ガイドを参照してください。

  1. 速度が最重要です。
    Twilio から必要なすべてのイベントとオーディオを受け取るために、WebSocket 接続の参照を取得したらすぐに TwilioRealtimeTransportLayer インスタンスを作成し、その直後に session.connect() を呼び出すようにしてください。

  2. Twilio の元イベントへアクセスする。
    Twilio から送信される生のイベントにアクセスしたい場合、RealtimeSession インスタンスの transport_event をリッスンできます。Twilio のすべてのイベントは twilio_message タイプと、生のイベントデータを含む message プロパティを持っています。

  3. デバッグログを確認する。
    何が起こっているかを詳しく知りたい場合があります。環境変数 DEBUG=openai-agents* を使用すると、Agents SDK のすべてのデバッグログが表示されます。あるいは DEBUG=openai-agents:extensions:twilio* を使って Twilio アダプターのデバッグログだけを有効にできます。

以下は、Twilio からのリクエストを受け取り、それを RealtimeSession に転送する WebSocket サーバーのエンドツーエンド例です。

Fastify を使用した例示サーバー
import Fastify from 'fastify';
import dotenv from 'dotenv';
import fastifyFormBody from '@fastify/formbody';
import fastifyWs from '@fastify/websocket';
import { RealtimeAgent, RealtimeSession } from '@openai/agents/realtime';
import { TwilioRealtimeTransportLayer } from '@openai/agents-extensions';
// Load environment variables from .env file
dotenv.config();
// Retrieve the OpenAI API key from environment variables. You must have OpenAI Realtime API access.
const { OPENAI_API_KEY } = process.env;
if (!OPENAI_API_KEY) {
console.error('Missing OpenAI API key. Please set it in the .env file.');
process.exit(1);
}
const PORT = +(process.env.PORT || 5050);
// Initialize Fastify
const fastify = Fastify();
fastify.register(fastifyFormBody);
fastify.register(fastifyWs);
const agent = new RealtimeAgent({
name: 'Triage Agent',
instructions:
'You are a helpful assistant that starts every conversation with a creative greeting.',
});
// Root Route
fastify.get('/', async (request, reply) => {
reply.send({ message: 'Twilio Media Stream Server is running!' });
});
// Route for Twilio to handle incoming and outgoing calls
// <Say> punctuation to improve text-to-speech translation
fastify.all('/incoming-call', async (request, reply) => {
const twimlResponse = `
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>O.K. you can start talking!</Say>
<Connect>
<Stream url="wss://${request.headers.host}/media-stream" />
</Connect>
</Response>`.trim();
reply.type('text/xml').send(twimlResponse);
});
// WebSocket route for media-stream
fastify.register(async (fastify) => {
fastify.get('/media-stream', { websocket: true }, async (connection) => {
const twilioTransportLayer = new TwilioRealtimeTransportLayer({
twilioWebSocket: connection,
});
const session = new RealtimeSession(agent, {
transport: twilioTransportLayer,
});
await session.connect({
apiKey: OPENAI_API_KEY,
});
console.log('Connected to the OpenAI Realtime API');
});
});
fastify.listen({ port: PORT }, (err) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log(`Server is listening on port ${PORT}`);
});
process.on('SIGINT', () => {
fastify.close();
process.exit(0);
});