TL;DR
OpenAI propose deux modes d'API WebSocket pour différents cas d'utilisation : le mode WebSocket de l'API de réponses pour les workflows agentiques avec de nombreux appels d'outils (jusqu'à 40 % plus rapide pour plus de 20 appels d'outils), et l'API en temps réel pour les applications vocales et audio à faible latence. Les deux utilisent des connexions WebSocket persistantes au lieu de requêtes HTTP sans état, ce qui réduit la latence en éliminant les frais généraux de connexion répétés et permet des interactions événementielles et avec état.
Introduction
L'API d'OpenAI a évolué au-delà des simples modèles de requête-réponse. Pour les applications nécessitant des appels d'outils rapides ou le streaming audio en temps réel, le modèle HTTP traditionnel génère une surcharge inutile. Chaque nouvelle requête nécessite la mise en place d'une connexion, une authentification et la transmission de l'état — même lorsque vous poursuivez la même conversation.
L'API WebSocket d'OpenAI résout ce problème en maintenant une connexion persistante et bidirectionnelle. Pour les workflows agentiques avec plus de 20 appels d'outils séquentiels, cela se traduit par une exécution de bout en bout environ 40 % plus rapide. Pour les applications vocales, cela permet des conversations naturelles et interruptibles avec des latences inférieures à 500 ms.
Ce guide couvre les deux modes WebSocket d'OpenAI : l'API de réponses pour les workflows d'agents à forte utilisation d'outils, et l'API en temps réel pour le streaming audio. Vous apprendrez quand utiliser chacun d'eux, comment les implémenter et comment les tester efficacement.
Qu'est-ce que l'API WebSocket d'OpenAI ?
L'API WebSocket d'OpenAI offre un mécanisme de transport alternatif à HTTP pour interagir avec les modèles linguistiques d'OpenAI. Au lieu de créer une nouvelle connexion pour chaque appel d'API, WebSocket établit une connexion unique et durable qui reste ouverte pendant toute la durée de votre session.
Caractéristiques Clés
- Connexion Persistante : Une fois établie, la connexion WebSocket reste ouverte jusqu'à ce qu'elle soit explicitement fermée, éliminant ainsi les frais généraux de connexion par requête.
- Communication Bidirectionnelle : Le client et le serveur peuvent envoyer des messages à tout moment, permettant de véritables architectures événementielles.
- Sessions avec État : Le serveur maintient le contexte de la connexion actuelle, vous permettant de référencer les réponses précédentes sans renvoyer l'historique complet de la conversation.
- Modèle Événementiel : La communication se fait par le biais d'événements discrets (messages JSON) plutôt que par paires requête-réponse.
Principes de Base du Protocole WebSocket
Les connexions WebSocket commencent par une requête de mise à niveau HTTP, puis passent au protocole WebSocket. Pour OpenAI, vous vous connecterez à des points d'accès comme :
- API de Réponses :
wss://api.openai.com/v1/responses - API en Temps Réel :
wss://api.openai.com/v1/realtime?model=gpt-realtime
Le schéma wss:// indique une connexion WebSocket sécurisée (analogue à HTTPS pour HTTP).
Deux Modes WebSocket Expliqués
OpenAI propose deux modes WebSocket distincts, chacun optimisé pour des cas d'utilisation différents.
Mode WebSocket de l'API de Réponses
L'API de Réponses prend en charge les connexions WebSocket pour les workflows agentiques où vous devez effectuer de nombreux appels d'outils séquentiels. Ce mode est conçu pour les assistants de codage, les systèmes d'orchestration et les agents autonomes qui appellent à plusieurs reprises des outils pour accomplir des tâches complexes.
Comment ça Fonctionne :
Sur une connexion WebSocket active, le service maintient un état de réponse précédente dans un cache en mémoire local à la connexion (la réponse la plus récente). Lorsque vous continuez un tour, vous n'envoyez que :
previous_response_id(référence à la dernière réponse)- Nouveaux éléments d'entrée (messages utilisateur, résultats d'outils, etc.)
Le serveur réutilise l'état mis en cache au lieu de retraiter l'historique complet de la conversation.
Avantages en Termes de Performance :
Pour les workflows avec plus de 20 appels d'outils, OpenAI rapporte jusqu'à 40 % d'exécution de bout en bout plus rapide par rapport à HTTP. Cela provient de :
- Pas de configuration de connexion par requête
- Pas de surcharge d'authentification répétée
- L'état mis en cache réduit le temps de traitement
- Latence réseau plus faible pour les petits messages de continuation
Compatibilité :
Le mode WebSocket fonctionne avec les options Zero Data Retention (ZDR) et store=false, le rendant adapté aux applications soucieuses de la confidentialité.
Mode WebSocket de l'API en Temps Réel
L'API en Temps Réel offre des capacités audio en streaming à faible latence pour les applications vocales. Elle permet des interactions parole-à-parole où le modèle peut répondre à une entrée audio avec une sortie audio, gérant les interruptions naturellement.
Comment ça Fonctionne :
L'API en Temps Réel utilise WebSocket pour créer une session avec état, axée sur les événements. Vous diffusez des fragments audio vers l'API, et elle renvoie en streaming à la fois les transcriptions et les réponses audio générées. La connexion prend en charge :
- Streaming d'entrée audio (envoyer des fragments audio au fur et à mesure qu'ils sont capturés)
- Streaming de sortie audio (recevoir l'audio généré en temps réel)
- Entrée/sortie de texte (pour les interactions hybrides texte+voix)
- Gestion automatique des interruptions (arrêter la génération lorsque l'utilisateur parle)
Fonctionnalités Clés :
Détection d'Activité Vocale (VAD) : L'API inclut une VAD sémantique qui comprend quand un utilisateur a fini de parler par opposition à une simple pause. Cela crée un flux de conversation plus naturel.
Capacités Multimodales : Accès direct aux capacités multimodales natives de GPT-4o, traitant à la fois l'audio et le texte dans un modèle unifié.
Faible Latence : Conçu pour des latences inférieures à 500 ms pour les interactions vocales, adapté aux conversations en temps réel.
WebSocket vs HTTP : Comparaison des Performances
Le choix entre WebSocket et HTTP dépend des caractéristiques de votre application. Voici quand chaque protocole excelle.

Quand WebSocket Surpasse HTTP
Volume Élevé d'Appels d'Outils :
Si votre workflow effectue plus de 10 appels d'outils séquentiels, la connexion persistante de WebSocket élimine la surcharge de configuration répétée. Chaque requête HTTP nécessite :
- Résolution DNS (si non mise en cache)
- Poignée de main TCP (à 3 voies)
- Poignée de main TLS (2 allers-retours pour TLS 1.3)
- En-têtes de requête/réponse HTTP
WebSocket le fait une fois, puis réutilise la connexion.
Applications Sensibles à la Latence :
Pour les applications vocales ou de chat en temps réel où chaque milliseconde compte, la connexion persistante de WebSocket et ses capacités de streaming réduisent considérablement la latence perçue.
Mises à Jour Initiées par le Serveur :
WebSocket permet au serveur de pousser des données aux clients sans interrogation. Pour les tâches d'agent de longue durée, le serveur peut envoyer des mises à jour de progression à mesure que les événements se produisent.
Quand HTTP est Suffisant
Requête-Réponse Simple :
Pour les appels d'API ponctuels ou les workflows avec 1 à 2 appels d'outils, HTTP est plus simple à implémenter et à déboguer. La plupart des développeurs sont familiers avec les clients HTTP, et l'infrastructure (répartiteurs de charge, proxys) gère bien HTTP.
Opérations Sans État :
Si vous n'avez pas besoin de maintenir l'état de session entre les requêtes, la nature sans état de HTTP est en fait un avantage — aucune gestion de connexion n'est requise.
Contraintes d'Infrastructure :
Certains environnements de déploiement (fonctions sans serveur, certains proxys) ne prennent pas en charge les connexions WebSocket de longue durée. HTTP fonctionne universellement.
Métriques de Performance
Basé sur la documentation d'OpenAI et les tests de la communauté :
| Métriques | HTTP | WebSocket (API de Réponses) | WebSocket (API en Temps Réel) |
|---|---|---|---|
| Établissement de la Connexion | Chaque requête (~100-300ms) | Une fois (~100-300ms) | Une fois (~100-300ms) |
| Workflow avec 20+ Appels d'Outils | Référence | ~40% plus rapide | N/A |
| Latence Aller-Retour Vocale | N/A (non conçu pour cela) | N/A | <500ms |
| Surcharge Mémoire | Faible (sans état) | Moyenne (état mis en cache) | Moyenne-Élevée (état de session) |
| Complexité d'Implémentation | Faible | Moyenne | Moyenne-Élevée |
Comment Utiliser le Mode WebSocket de l'API de Réponses
Implémentons une connexion WebSocket à l'API de Réponses pour un workflow agentique.
Prérequis
- Clé API OpenAI avec accès à l'API de Réponses
- Bibliothèque client WebSocket (
wspour Node.js ouwebsocket-clientpour Python) - Compréhension des appels d'outils dans l'API OpenAI
Configuration de la Connexion
Exemple Node.js :
const WebSocket = require('ws');
// Se connecter au point d'accès WebSocket de l'API de Réponses
const ws = new WebSocket('wss://api.openai.com/v1/responses', {
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'OpenAI-Beta': 'responses-api=v1'
}
});
ws.on('open', () => {
console.log('Connected to OpenAI Responses API');
// Envoyer la requête initiale
const initialMessage = {
model: 'gpt-4o',
messages: [
{ role: 'user', content: 'Help me analyze this codebase and suggest improvements.' }
],
tools: [
{
type: 'function',
function: {
name: 'read_file',
description: 'Read contents of a file',
parameters: {
type: 'object',
properties: {
path: { type: 'string', description: 'File path to read' }
},
required: ['path']
}
}
},
{
type: 'function',
function: {
name: 'search_code',
description: 'Search for code patterns',
parameters: {
type: 'object',
properties: {
pattern: { type: 'string', description: 'Regex pattern to search' }
},
required: ['pattern']
}
}
}
]
};
ws.send(JSON.stringify(initialMessage));
});
ws.on('message', (data) => {
const response = JSON.parse(data);
console.log('Received:', response);
// Vérifier si le modèle veut appeler des outils
if (response.choices[0].finish_reason === 'tool_calls') {
const toolCalls = response.choices[0].message.tool_calls;
// Exécuter les outils (simplifié)
const toolResults = toolCalls.map(call => ({
tool_call_id: call.id,
output: executeToolLocally(call.function.name, call.function.arguments)
}));
// Continuer la conversation avec les résultats des outils
const continuation = {
previous_response_id: response.id, // Référence la réponse précédente
input: toolResults
};
ws.send(JSON.stringify(continuation));
}
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
ws.on('close', () => {
console.log('Connection closed');
});
function executeToolLocally(name, args) {
// Votre logique d'exécution d'outil
if (name === 'read_file') {
const { path } = JSON.parse(args);
return fs.readFileSync(path, 'utf-8');
}
// ... autres outils
}
Exemple Python :
import websocket
import json
import os
def on_message(ws, message):
response = json.loads(message)
print(f"Received: {response}")
# Gérer les appels d'outils
if response['choices'][0]['finish_reason'] == 'tool_calls':
tool_calls = response['choices'][0]['message']['tool_calls']
# Exécuter les outils
tool_results = []
for call in tool_calls:
result = execute_tool(call['function']['name'],
json.loads(call['function']['arguments']))
tool_results.append({
'tool_call_id': call['id'],
'output': result
})
# Envoyer la continuation avec seulement la nouvelle entrée + previous_response_id
continuation = {
'previous_response_id': response['id'],
'input': tool_results
}
ws.send(json.dumps(continuation))
def on_error(ws, error):
print(f"Error: {error}")
def on_close(ws, close_status_code, close_msg):
print("Connection closed")
def on_open(ws):
print("Connected to OpenAI Responses API")
# Envoyer la requête initiale
initial_message = {
'model': 'gpt-4o',
'messages': [
{'role': 'user', 'content': 'Analyze this codebase and suggest improvements.'}
],
'tools': [
{
'type': 'function',
'function': {
'name': 'read_file',
'description': 'Read file contents',
'parameters': {
'type': 'object',
'properties': {
'path': {'type': 'string'}
},
'required': ['path']
}
}
}
]
}
ws.send(json.dumps(initial_message))
def execute_tool(name, args):
if name == 'read_file':
with open(args['path'], 'r') as f:
return f.read()
# ... autres outils
# Créer la connexion WebSocket
ws = websocket.WebSocketApp(
"wss://api.openai.com/v1/responses",
header={
"Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}",
"OpenAI-Beta": "responses-api=v1"
},
on_open=on_open,
on_message=on_message,
on_error=on_error,
on_close=on_close
)
ws.run_forever()
Détails Clés de l'Implémentation
Gestion de l'État :
La différence essentielle par rapport à HTTP est l'utilisation de previous_response_id dans les continuations. Cela indique à l'API de réutiliser l'état mis en cache de la dernière réponse.
Continuations Uniquement d'Entrée :
Lors de la continuation d'un tour, n'envoyez que :
previous_response_id: Référence la réponse mise en cacheinput: Nouvelles données (résultats d'outils, messages utilisateur, etc.)
Ne renvoyez pas le tableau messages complet — le serveur a déjà ce contexte.
Rétention Zéro Données :
Pour utiliser le ZDR avec le mode WebSocket, incluez store: false dans votre requête initiale.
Comment Utiliser le Mode WebSocket de l'API en Temps Réel
L'API en Temps Réel permet des interactions vocales à faible latence. Voici comment l'implémenter.
Prérequis
- Clé API OpenAI avec accès à l'API en Temps Réel
- Capacités de capture/lecture audio
- Bibliothèque client WebSocket
- Encodage audio (PCM mono 24 kHz, 16 bits pour de meilleurs résultats)
Configuration de la Connexion
Exemple JavaScript (Navigateur) :
// Se connecter à l'API en Temps Réel
const ws = new WebSocket(
`wss://api.openai.com/v1/realtime?model=gpt-realtime`,
['realtime', 'openai-insecure-api-key.' + process.env.OPENAI_API_KEY]
);
ws.addEventListener('open', () => {
console.log('Connected to Realtime API');
// Configurer la session
ws.send(JSON.stringify({
type: 'session.update',
session: {
modalities: ['text', 'audio'],
voice: 'alloy',
input_audio_format: 'pcm16',
output_audio_format: 'pcm16',
turn_detection: {
type: 'server_vad', // or 'semantic_vad' for smarter detection
threshold: 0.5,
prefix_padding_ms: 300,
silence_duration_ms: 500
}
}
}));
});
ws.addEventListener('message', (event) => {
const message = JSON.parse(event.data);
switch (message.type) {
case 'session.created':
console.log('Session created:', message.session);
break;
case 'conversation.item.created':
console.log('New item:', message.item);
break;
case 'response.audio.delta':
// Fragment audio reçu - le lire
const audioChunk = base64ToArrayBuffer(message.delta);
playAudioChunk(audioChunk);
break;
case 'response.audio_transcript.delta':
// Fragment de transcription reçu
console.log('Transcript:', message.delta);
break;
case 'input_audio_buffer.speech_started':
console.log('User started speaking'); // L'utilisateur a commencé à parler
break;
case 'input_audio_buffer.speech_stopped':
console.log('User stopped speaking'); // L'utilisateur a arrêté de parler
break;
case 'error':
console.error('API error:', message.error); // Erreur API
break;
}
});
// Envoyer l'audio du microphone
async function streamMicrophoneToAPI() {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const audioContext = new AudioContext({ sampleRate: 24000 });
const source = audioContext.createMediaStreamSource(stream);
const processor = audioContext.createScriptProcessor(4096, 1, 1);
processor.onaudioprocess = (e) => {
const inputData = e.inputBuffer.getChannelData(0);
// Convertir Float32 en Int16 PCM
const pcmData = new Int16Array(inputData.length);
for (let i = 0; i < inputData.length; i++) {
pcmData[i] = Math.max(-32768, Math.min(32767, inputData[i] * 32768));
}
// Envoyer à l'API
ws.send(JSON.stringify({
type: 'input_audio_buffer.append',
audio: arrayBufferToBase64(pcmData.buffer)
}));
};
source.connect(processor);
processor.connect(audioContext.destination);
}
// Envoyer l'entrée texte
function sendTextMessage(text) {
ws.send(JSON.stringify({
type: 'conversation.item.create',
item: {
type: 'message',
role: 'user',
content: [
{ type: 'input_text', text: text }
]
}
}));
// Demander la génération de réponse
ws.send(JSON.stringify({
type: 'response.create'
}));
}
function playAudioChunk(arrayBuffer) {
const audioContext = new AudioContext({ sampleRate: 24000 });
audioContext.decodeAudioData(arrayBuffer, (buffer) => {
const source = audioContext.createBufferSource();
source.buffer = buffer;
source.connect(audioContext.destination);
source.start();
});
}
Exemple Python :
import websocket
import json
import base64
import pyaudio
# Configuration audio
RATE = 24000
CHUNK = 4096
FORMAT = pyaudio.paInt16
CHANNELS = 1
audio = pyaudio.PyAudio()
def on_open(ws):
print("Connected to Realtime API")
# Configurer la session
ws.send(json.dumps({
'type': 'session.update',
'session': {
'modalities': ['text', 'audio'],
'voice': 'alloy',
'input_audio_format': 'pcm16',
'output_audio_format': 'pcm16',
'turn_detection': {
'type': 'server_vad',
'threshold': 0.5,
'silence_duration_ms': 500
}
}
}))
# Commencer le streaming du microphone
stream_microphone(ws)
def on_message(ws, message):
data = json.loads(message)
if data['type'] == 'response.audio.delta':
# Décoder et lire l'audio
audio_chunk = base64.b64decode(data['delta'])
play_audio(audio_chunk)
elif data['type'] == 'response.audio_transcript.delta':
print(f"Transcript: {data['delta']}", end='', flush=True)
elif data['type'] == 'input_audio_buffer.speech_started':
print("\n[User speaking...]") # L'utilisateur parle...
elif data['type'] == 'error':
print(f"Error: {data['error']}")
def stream_microphone(ws):
stream = audio.open(
format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK
)
def audio_thread():
while True:
audio_data = stream.read(CHUNK)
ws.send(json.dumps({
'type': 'input_audio_buffer.append',
'audio': base64.b64encode(audio_data).decode('utf-8')
}))
import threading
threading.Thread(target=audio_thread, daemon=True).start()
def play_audio(audio_chunk):
stream = audio.open(
format=FORMAT,
channels=CHANNELS,
rate=RATE,
output=True
)
stream.write(audio_chunk)
stream.stop_stream()
stream.close()
# Créer la connexion WebSocket
ws = websocket.WebSocketApp(
f"wss://api.openai.com/v1/realtime?model=gpt-realtime",
header={
"Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}"
},
on_open=on_open,
on_message=on_message
)
ws.run_forever()
Détails Clés de l'Implémentation
Types d'Événements :
L'API en Temps Réel utilise une communication événementielle. Événements courants :
Client → Serveur :
session.update- Configurer les paramètres de sessioninput_audio_buffer.append- Envoyer des fragments audioconversation.item.create- Ajouter des messages texteresponse.create- Demander une réponse de l'IA
Serveur → Client :
session.created- Confirme la configuration de la sessionresponse.audio.delta- Fragment audio de l'IAresponse.audio_transcript.delta- Transcription de l'audio de l'IAinput_audio_buffer.speech_started/stopped- Événements VADerror- Notifications d'erreur
Détection d'Activité Vocale :
Choisissez entre deux modes VAD :
server_vad : Détection d'activité vocale de base basée sur le volume audio et la durée du silence.
semantic_vad : Détection plus intelligente qui comprend les pauses naturelles par opposition à la fin du tour. Utilisez-la pour des conversations plus naturelles où les utilisateurs pourraient faire une pause en pleine réflexion.
Tester les Connexions WebSocket avec Apidog
Tester les API WebSocket diffère du test HTTP — vous devez maintenir une connexion, envoyer des événements et surveiller le flux de messages bidirectionnel. Apidog offre des capacités spécialisées de test WebSocket.

Configuration des Tests WebSocket dans Apidog
Étape 1 : Créer une Requête WebSocket
Dans Apidog, créez une nouvelle requête et sélectionnez "WebSocket" comme protocole. Entrez votre URL de connexion :

wss://api.openai.com/v1/responses
Étape 2 : Configurer les En-têtes
Ajoutez les en-têtes d'authentification :
Authorization: Bearer YOUR_OPENAI_API_KEY
OpenAI-Beta: responses-api=v1
Pour l'API en temps réel, vous pouvez également utiliser l'authentification basée sur l'URL :
wss://api.openai.com/v1/realtime?model=gpt-realtime
Avec la clé API dans l'en-tête du sous-protocole.
Étape 3 : Établir la Connexion
Cliquez sur "Connecter" pour établir la connexion WebSocket. Apidog affiche :
- Statut de la connexion (connecté/déconnecté)
- Métriques de latence
- Durée de la connexion
Étape 4 : Envoyer des Événements
Utilisez le composeur de messages d'Apidog pour envoyer des événements JSON. Pour l'API de Réponses :
{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": "What's the weather in San Francisco?"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string" }
}
}
}
}
]
}
Étape 5 : Surveiller les Réponses
Apidog affiche :
- Tous les messages reçus par ordre chronologique
- Horodatages et tailles des messages
- Formatage JSON et coloration syntaxique
- Capacités de copie/exportation pour le débogage
Tester les Continuations
Pour tester le modèle de continuation avec previous_response_id :
- Envoyez le message initial, notez le
response.iddans la réponse - Envoyez la continuation avec seulement la nouvelle entrée :
{
"previous_response_id": "resp_abc123",
"input": [
{
"tool_call_id": "call_xyz789",
"output": "{\"temperature\": 72, \"conditions\": \"sunny\"}"
}
]
}
- Observez la latence réduite par rapport à la réexpédition du contexte complet
Tester l'API en Temps Réel
Pour l'API en temps réel, Apidog vous permet de :
- Envoyer des fragments audio encodés en base64
- Surveiller les événements
session.update - Suivre les événements VAD (début/fin de la parole)
- Visualiser les deltas de transcription en temps réel
Ceci est particulièrement utile pour déboguer pourquoi votre assistant vocal pourrait couper les utilisateurs ou ne pas détecter correctement la parole.
Variables d'Environnement
Stockez les clés API en toute sécurité en utilisant les variables d'environnement d'Apidog :
{{OPENAI_API_KEY}}
Cela vous permet de basculer entre les clés de développement et de production sans modifier les requêtes.
Cas d'Utilisation Réels
Explorons des scénarios pratiques où les modes WebSocket d'OpenAI excellent.
Cas d'Utilisation 1 : Agent de Codage Autonome
Scénario : Un assistant de codage qui analyse les bases de code, identifie les problèmes et apporte des améliorations de manière autonome.
Pourquoi l'API de Réponses WebSocket :
- Workflow typique : Lire le fichier → Analyser → Rechercher des motifs similaires → Lire d'autres fichiers → Suggérer des modifications
- Cela génère 15 à 30 appels d'outils par tâche
- Le mode WebSocket réduit le temps d'exécution total d'environ 40 %
- La connexion persistante maintient le contexte pour tous les appels d'outils
Modèle d'Implémentation :
// Tâche initiale
ws.send({ messages: [{ role: 'user', content: 'Audit security vulnerabilities' }], tools: [...] })
// Première réponse : le modèle appelle read_file
ws.on('message', (resp1) => {
ws.send({ previous_response_id: resp1.id, input: [tool_result_1] })
})
// Deuxième réponse : le modèle appelle search_code
ws.on('message', (resp2) => {
ws.send({ previous_response_id: resp2.id, input: [tool_result_2] })
})
// Continuer pour plus de 20 itérations...
Cas d'Utilisation 2 : Bot de Service Client Vocal
Scénario : Un bot de support téléphonique qui gère les demandes des clients avec un flux de conversation naturel.
Pourquoi l'API en Temps Réel WebSocket :
- Faible latence critique (<500ms pour une conversation naturelle)
- Doit gérer les interruptions (le client parle par-dessus le bot)
- Traite l'entrée vocale directement sans transcription séparée
- Diffuse les réponses en temps réel (n'attend pas la phrase complète)
Modèle d'Implémentation :
// Diffuser l'audio du téléphone vers l'API
phoneSystem.on('audio', (chunk) => {
ws.send({
type: 'input_audio_buffer.append',
audio: base64Encode(chunk)
})
})
// Lire les réponses de l'IA immédiatement
ws.on('message', (event) => {
if (event.type === 'response.audio.delta') {
phoneSystem.playAudio(base64Decode(event.delta))
}
})
Dépannage des Problèmes Courants
La Connexion ne S'établit Pas
Symptômes : La connexion WebSocket ne s'ouvre jamais, événement de fermeture immédiat.
Causes Courantes :
- Clé API invalide - Vérifiez votre en-tête
Authorization - En-tête bêta manquant - L'API de Réponses requiert
OpenAI-Beta: responses-api=v1 - Restrictions réseau - Certains réseaux d'entreprise bloquent WebSocket
- URL incorrecte - Vérifiez
wss://(pasws://) et le chemin du point d'accès
Solution :
Utilisez Apidog pour tester la connexion avec des messages d'erreur détaillés. L'inspecteur de requêtes montre exactement quels en-têtes sont envoyés, ce qui facilite la détection des clés API manquantes ou incorrectes.
Code de Débogage :
ws.on('error', (error) => {
console.error('Connection error:', error);
});
ws.on('close', (code, reason) => {
console.log(`Closed with code ${code}: ${reason}`);
// Codes courants :
// 1006 : Fermeture anormale (souvent des problèmes d'authentification)
// 1008 : Violation de politique (en-têtes invalides)
});
Latence Élevée Malgré WebSocket
Symptômes : La connexion WebSocket fonctionne mais n'est pas plus rapide que HTTP.
Causes Courantes :
- Non-utilisation de
previous_response_id- Vous renvoyez le contexte complet - Démarrage à froid - La première requête sur une nouvelle connexion est plus lente
- Latence réseau - Distance géographique aux serveurs API
- Charges utiles volumineuses - Envoi de données inutiles dans les continuations
Solution :
Vérifiez que vous n'envoyez que de nouvelles entrées dans les continuations :
// FAUX - envoie le contexte complet à chaque fois
ws.send({
messages: [...allPreviousMessages, newMessage],
tools: [...]
})
// CORRECT - référence l'état mis en cache
ws.send({
previous_response_id: lastResponse.id,
input: [newMessage]
})
Fuites de Mémoire dans les Connexions Longue Durée
Symptômes : La mémoire de l'application augmente avec le temps avec une connexion persistante.
Causes Courantes :
- Écouteurs d'événements non supprimés - Accumulation d'écouteurs lors de la reconnexion
- Tampons audio non libérés - Conservation des références à l'audio lu
- Historique des messages croissant - Stockage de tous les messages reçus
Solution :
// Nettoyer les écouteurs d'événements lors de la reconnexion
function cleanupAndReconnect(ws) {
ws.removeAllListeners();
ws.close();
const newWs = createConnection();
return newWs;
}
// Libérer les tampons audio après la lecture
function playAndRelease(audioBuffer) {
const audioContext = new AudioContext({ sampleRate: 24000 });
audioContext.decodeAudioData(audioBuffer, (buffer) => {
const source = audioContext.createBufferSource();
source.buffer = buffer;
source.connect(audioContext.destination);
source.start();
source.onended = () => {
source.disconnect();
// Le tampon sera collecté par le ramasse-miettes
};
});
}
// Limiter l'historique des messages
const messageHistory = [];
const MAX_HISTORY = 100;
ws.on('message', (data) => {
messageHistory.push(data);
if (messageHistory.length > MAX_HISTORY) {
messageHistory.shift(); // Supprimer le plus ancien
}
});
Conclusion
Les modes API WebSocket d'OpenAI ouvrent de nouvelles possibilités pour les applications d'IA. Le mode WebSocket de l'API de Réponses offre une exécution jusqu'à 40 % plus rapide pour les workflows agentiques avec de nombreux appels d'outils, ce qui le rend idéal pour les assistants de codage autonomes et les systèmes d'orchestration. L'API en Temps Réel offre une latence inférieure à 500 ms pour les applications vocales, permettant des conversations naturelles et interruptibles.
Le choix du bon mode dépend de votre cas d'utilisation :
- WebSocket de l'API de Réponses : Agents à forte utilisation d'outils, assistants de codage, outils de recherche (plus de 10 appels d'outils)
- WebSocket de l'API en Temps Réel : Assistants vocaux, bots téléphoniques, tuteurs de langues (streaming audio)
- HTTP : Requêtes simples, environnements sans serveur, 1-5 appels d'API
La nature persistante et événementielle des connexions WebSocket nécessite des approches de test différentes de celles de HTTP. Testez les API WebSocket d'OpenAI avec le client WebSocket en temps réel d'Apidog — importez votre clé API, établissez des connexions, envoyez des événements et surveillez les réponses avec une journalisation détaillée. Essayez-le gratuitement pour valider vos intégrations avant le déploiement en production.
