Elige la API que usa tu aplicación. Cada API tiene sus propios mecanismos de autenticación y creación de sesiones, y su propio contrato de eventos.
Controla una sesión de GPT-Live desde tu servidor
Conecta el servidor de tu aplicación a una sesión existente de GPT-Live por WebRTC o SIP cuando el servidor necesite recibir eventos de la conversación, ejecutar herramientas privadas o actualizar la conversación. Esta segunda conexión se denomina WebSocket de canal lateral. Ambas conexiones comparten una sesión mientras WebRTC o SIP transporta el audio principal.
El canal lateral transporta eventos y comandos. Tu aplicación se encarga de la ejecución de herramientas, las comprobaciones de autorización y las reglas de negocio. Mantén las claves de API y las credenciales de las herramientas en tu servidor.
Decide si necesitas un canal lateral
En las aplicaciones de navegador, usa el canal de datos de WebRTC para los subtítulos y las actualizaciones locales de la interfaz. Usa un canal lateral cuando el procesamiento de transcripciones se ejecute en tu servidor, por ejemplo, para realizar comprobaciones de las medidas de protección, análisis de sentimiento o llamadas especulativas a herramientas. Tu servidor puede recibir eventos y dirigir la misma sesión de forma directa mientras el audio del navegador sigue transportándose por WebRTC. Consulta Reacciona a los fragmentos de transcripción para ver ejemplos.
Si tu backend ya administra la conexión WebSocket principal, ya recibe los eventos de la sesión y puede enviar comandos.
La delegación a Responses también funciona sin un canal lateral. El navegador puede reenviar eventos de llamada a funciones desde su canal de datos a un backend autenticado para su ejecución. Las herramientas alojadas por OpenAI se ejecutan a través del backend delegado, sin un ejecutor de herramientas de la aplicación.
Conéctate a la sesión existente
-
Guarda el ID de la sesión que controlará tu backend. Para WebRTC, usa
session.idde la respuesta JSON aPOST /v1/live/sessions. Para SIP, primero acepta la llamada entrante y luego usadata.session_idde su webhook. Guarda el ID junto con el registro del usuario y de la conversación de la aplicación. -
Abre un WebSocket desde tu servidor en la siguiente URL y sustituye el ID por el valor guardado sin modificarlo. Autentícate con
Authorization: Bearer $OPENAI_API_KEYusando la autenticación del proyecto con la que se creó o aceptó la sesión. Incluye los mismos encabezados de conexión que se requieren al crear la sesión.wss://api.openai.com/v1/live/sessions/{session_id}/attach -
Recibe eventos y envía comandos por el socket conectado. La sesión ya está en ejecución; no vuelvas a enviar
session.start.
Trata el ID de sesión como un valor opaco. Conserva su prefijo y úsalo solo para la sesión a la que tu aplicación tiene acceso autorizado. Lee el ID de la respuesta JSON de Live, en lugar de obtenerlo de un encabezado Location de Realtime o de un parámetro call_id de la URL.
Observa eventos y envía comandos
| Tarea | Eventos o comandos |
|---|---|
| Sigue la conversación | Recibe deltas de transcripción del usuario y del asistente, eventos de delegación y eventos anidados de Responses. |
| Actualiza la configuración del backend | Usa session.update para cambiar los ajustes compatibles dentro del modo de delegación existente. Los ajustes de inicio, como el modelo del frontend y la configuración de audio, permanecen fijos. |
| Proporciona contexto | Usa session.instructions.append para las instrucciones, session.thinking.append para el contexto que no se expresa en voz alta y session.commentary.append para las actualizaciones que pueden expresarse en voz alta. |
| Devuelve los resultados de las herramientas | Con la delegación a Responses, envía response.item.create y luego response.create para continuar el trabajo del backend. |
| Controla la entrada del micrófono | Usa session.input_audio.mute y session.input_audio.unmute. Silenciar la entrada no detiene la salida del asistente. |
| Finaliza la sesión | Envía session.close y recibe session.closed antes de desconectarte. |
Los comandos siguen las mismas reglas de validación y delegación que en la conexión principal. Al agregar contexto, usa delegation_id: null para el contexto general de la sesión; un ID no nulo debe identificar una delegación de cliente existente. Consulta Delegación y herramientas para obtener información sobre la configuración, la ejecución de funciones y los ejemplos de cómo agregar contexto.
Para las sesiones de navegador, mantén la entrada del micrófono y la salida de los altavoces en la pista multimedia de WebRTC negociada. Usa el canal lateral para los eventos y el control de la conversación. Un evento de transcripción o una confirmación de recepción de un comando no demuestra que el audio se haya reproducido ni que el usuario lo haya escuchado.
Recibe copias del audio
Un canal lateral también recibe copias del audio de entrada y salida posterior a la conexión, mientras la conexión principal transporta el contenido multimedia en vivo:
| Evento | Campo de audio | Información temporal |
|---|---|---|
session.input_audio.append | audio | Sin marcas de tiempo. |
session.output_audio.delta | delta | start_ms y end_ms describen el intervalo de la salida en la línea de tiempo de la sesión. |
Ambas cargas útiles contienen audio PCM16LE mono sin procesar a 24 kHz, codificado en base64, independientemente del formato de audio del transporte principal. Ninguno de los eventos tiene un event_id. La copia de la entrada contiene el audio recibido antes de aplicar el silenciamiento de entrada; no confirma que el modelo haya consumido esas muestras. Los intervalos de las copias de salida pueden tener huecos por tramas descartadas y no indican cuándo escuchó el audio la persona que llama.
Estos son eventos del servidor, no un permiso para enviar audio por el canal lateral. Envía el audio del micrófono por el transporte principal; no envíes session.input_audio.append por el socket conectado.
Asigna un único responsable para cada acción
Elige si el navegador o el backend se encarga de cada acción. Si ambas conexiones reciben un evento de llamada a una función, ejecuta la función una sola vez. Aplica la misma regla de responsabilidad a las actualizaciones de contexto y a las solicitudes para continuar el trabajo del backend.
Almacena las transcripciones y el estado de las herramientas en tu aplicación. Establece la conexión con anticipación si el backend necesita observar la conversación desde el inicio, y conserva todo el historial recopilado antes de conectarse. No dependas de la conexión para reconstruir transcripciones o resultados de herramientas anteriores.
Un canal lateral no oculta por sí solo los eventos de la sesión al navegador. Mantén las credenciales sensibles de las herramientas y las decisiones de autorización en tu backend, y devuelve solo el contexto necesario para la conversación.
Aplica medidas de protección a la conversación
Usa la conexión de tu servidor para monitorear la conversación, comprobar que las solicitudes cumplan las políticas de tu aplicación e intervenir cuando una comprobación detecte un problema. Un canal lateral permite a tu servidor acceder a los eventos y comandos de la sesión; tu aplicación ejecuta las comprobaciones y aplica las acciones que correspondan según sus resultados. El mismo flujo de trabajo se aplica cuando tu servidor ya administra la conexión WebSocket principal.
Ejecuta comprobaciones durante la conversación
Las medidas de protección son uno de los usos del procesamiento de fragmentos de transcripción a medida que llegan. Ese mismo flujo puede iniciar una consulta especulativa o actualizar la interfaz a la par de estas comprobaciones.
- Monitorea las transcripciones. Acumula fragmentos de
session.input_transcript.deltapara detectar intentos de jailbreak, información sensible o infracciones de las políticas en las solicitudes de los usuarios. Usasession.output_transcript.deltapara detectar afirmaciones sin fundamento o respuestas fuera del alcance de tu aplicación en lo que dice el asistente. Mantén cada comprobación asociada con la transcripción y la solicitud de la aplicación que evaluó. - Ejecuta comprobaciones de forma concurrente. Un modelo rápido y ligero puede evaluar las solicitudes mientras continúa la conversación. Devuelve un resultado estructurado pequeño, como
{"triggered": true}, que tu aplicación pueda usar para actuar. Mantén bloqueadas las acciones que requieren aprobación hasta que pasen sus comprobaciones; un tiempo de espera agotado o una comprobación fallida no constituyen una aprobación. - Bloquea las acciones afectadas. Cuando una comprobación detecte un problema, marca la solicitud como bloqueada en el estado de la aplicación. Consulta ese estado antes de ejecutar una herramienta o confirmar un cambio, incluso para el trabajo que ya esté en cola. Una negativa verbal no impide que se ejecute una herramienta.
- Detén el trabajo relacionado. Cancela los trabajos administrados por la aplicación cuando tu backend admita la cancelación y descarta los resultados tardíos de solicitudes bloqueadas o reemplazadas. Con la delegación a Responses, deja de ejecutar las funciones personalizadas afectadas y no envíes
response.createpara continuar el trabajo bloqueado. Esto no cancela una respuesta alojada que ya esté en ejecución ni detiene el habla del frontend. - Registra y redirige. Registra la decisión junto con los ID de la solicitud y de la delegación afectadas, y luego envía una instrucción correctiva. Un nombre de evento como
guardrail.triggeredpertenece a la telemetría de tu aplicación; no es un evento de la API de GPT-Live.
Consulta Deltas de transcripción para recopilar fragmentos y Delegación y herramientas para mantener los resultados del backend alineados con la tarea actual.
Redirige la conversación
Usa session.instructions.append para orientar la conversación según las medidas de protección. Puede interrumpir el habla en curso y aplicar una nueva instrucción. Por ejemplo, después de que tu aplicación bloquee una solicitud, envía:
export function sendUpdate(connection) {
connection.send({
type: "session.instructions.append",
event_id: "guardrail_block_17",
delegation_id: null,
content:
"Stop speaking immediately. Do not continue or act on the last request. Refuse briefly, then wait.",
});
}Asegúrate de que la instrucción esté redactada por la aplicación. No copies en ella texto no confiable del usuario como si fuera una instrucción. Usa delegation_id: null para esta corrección que abarca toda la sesión y limita content a 500 tokens.
Asocia session.instructions.appended con tu comando mediante client_event_id. La confirmación llega después del momento estimado de la inyección de contexto; no demuestra que el asistente haya dejado de hablar ni que se haya detenido la reproducción del audio en cola. Las instrucciones correctivas no pueden retirar el audio que el usuario ya escuchó.
Para los avisos que deban comunicarse oralmente con una redacción específica, usa también instrucciones. Consulta Comunicar un aviso para ver un ejemplo y consideraciones sobre la reproducción.
Controla la reproducción cuando sea necesario
Primero prueba las instrucciones correctivas y el bloqueo de acciones. Si tu aplicación también necesita bloquear el audio del modelo, controla la salida en el cliente o en el retransmisor multimedia: silencia o descarta temporalmente la salida, descarta el audio en cola local, envía la instrucción correctiva y reanuda la reproducción según la política de recuperación de tu aplicación. Elimina el audio desactualizado antes de reanudarla. Un canal auxiliar por sí solo no controla la ruta del contenido multimedia, y la confirmación de una instrucción no es una señal para reanudar la reproducción.
session.input_audio.mute controla la entrada del micrófono de quien llama. No silencia la salida del modelo ni cancela el trabajo delegado.
GPT-Live transmite fragmentos de transcripción mientras habla. Si una comprobación debe terminar antes de que el usuario escuche el audio, tu aplicación debe almacenar el audio en un búfer y aprobarlo antes de reproducirlo. Esto agrega latencia. El audio suprimido también puede hacer que el contexto de conversación del modelo se adelante a lo que el usuario escuchó, así que prueba cómo se reanuda la conversación.
Prueba la intervención
Prueba solicitudes permitidas y bloqueadas, falsos positivos, comprobaciones lentas o fallidas, la activación de una comprobación durante el habla o mientras se ejecuta una herramienta, y resultados tardíos de trabajos cancelados. Verifica por separado el bloqueo de acciones, el estado de la aplicación, la respuesta oral correctiva y la reproducción real. Si controlas la salida, incluye el audio en cola y la recuperación en la prueba. Usa el Cookbook de evaluación de agentes de voz para comparar el éxito de las tareas y el tiempo de respuesta oral.
Finaliza correctamente
Sigue recibiendo eventos mientras el backend esté a cargo de la ejecución de herramientas o de la recopilación de los datos finales de uso. Registra el controlador de session.closed antes de enviar session.close y mantén abiertos la conexión WebRTC, el canal de datos y el canal auxiliar mientras termina el trabajo pendiente. Guarda los datos finales de uso de la sesión y cualquier dato de uso del backend recibido en eventos de Responses antes de liberar los recursos. Si la conexión falla antes de que llegue el evento final, registra la finalización como incompleta. Consulta Administración de sesiones para conocer la secuencia de cierre.
La Realtime API permite que los clientes se conecten directamente al servidor de la API mediante WebRTC o SIP. Sin embargo, lo más probable es que quieras mantener el uso de herramientas y el resto de la lógica de negocio en el servidor de tu aplicación para que esta lógica sea privada e independiente del cliente.
Mantén seguros el uso de herramientas, la lógica de negocio y otros detalles en el servidor mediante una conexión a través de un canal de control “auxiliar”. Ahora ofrecemos opciones de canales auxiliares tanto para conexiones SIP como WebRTC.
Una conexión auxiliar implica que hay dos conexiones activas a la misma sesión de Realtime: una desde el cliente del usuario y otra desde el servidor de tu aplicación. La conexión del servidor se puede usar para monitorear la sesión, actualizar instrucciones y responder a llamadas a herramientas.
Con WebRTC
- Al establecer una conexión entre pares, solicitas y recibes una respuesta SDP de la Realtime API para configurar la conexión. Si usaste el código de ejemplo de la guía de WebRTC, será similar a esto:
const baseUrl = "https://api.openai.com/v1/realtime/calls";
const sdpResponse = await fetch(baseUrl, {
method: "POST",
body: offer.sdp,
headers: {
Authorization: `Bearer ${EPHEMERAL_KEY}`,
"Content-Type": "application/sdp",
},
});- La respuesta a la solicitud contendrá un encabezado
Locationcon un ID de llamada único que se puede usar en el servidor para establecer una conexión WebSocket a esa misma sesión de Realtime.
// Location: /v1/realtime/calls/rtc_123456
const location = sdpResponse.headers.get("Location");
const callId = location?.split("/").pop();
console.log(callId);- Luego, en un servidor, puedes escuchar eventos y configurar la sesión como lo harías desde una conexión WebSocket típica de la Realtime API, usando ese ID de llamada con la URL
wss://api.openai.com/v1/realtime?call_id=rtc_xxxxx, como se muestra a continuación:
import WebSocket from "ws";
const callId = "rtc_u1_9c6574da8b8a41a18da9308f4ad974ce";
// Connect to a WebSocket for the in-progress call
const url = "wss://api.openai.com/v1/realtime?call_id=" + callId;
const ws = new WebSocket(url, {
headers: {
Authorization: "Bearer " + process.env.OPENAI_API_KEY,
},
});
ws.on("open", function open() {
console.log("Connected to server.");
// Send client events over the WebSocket once connected
ws.send(
JSON.stringify({
type: "session.update",
session: {
type: "realtime",
instructions: "Be extra nice today!",
},
})
);
});
// Listen for and parse server events
ws.on("message", function incoming(message) {
console.log(JSON.parse(message.toString()));
});De esta manera, puedes agregar herramientas, monitorear sesiones y ejecutar lógica de negocio en el servidor sin tener que configurar esas acciones en el cliente.
Con SIP
- Un usuario se conecta a OpenAI por teléfono mediante SIP.
- OpenAI envía un webhook a la URL de webhook del servidor de tu aplicación para notificarle el estado de la sesión. El webhook será similar a esto:
POST https://my_website.com/webhook_endpoint
user-agent: OpenAI/1.0 (+https://platform.openai.com/docs/webhooks)
content-type: application/json
webhook-id: wh_685342e6c53c8190a1be43f081506c52 # unique id for idempotency
webhook-timestamp: 1750287078 # timestamp of delivery attempt
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4= # signature to verify authenticity from OpenAI
{
"object": "event",
"id": "evt_685343a1381c819085d44c354e1b330e",
"type": "realtime.call.incoming",
"created_at": 1750287018, // Unix timestamp
"data": {
"call_id": "some_unique_id",
"sip_headers": [
{ "name": "From", "value": "sip:+142555512112@sip.example.com" },
{ "name": "To", "value": "sip:+18005551212@sip.example.com" },
{ "name": "Call-ID", "value": "03782086-4ce9-44bf-8b0d-4e303d2cc590"}
]
}
}
- El servidor de la aplicación abre una conexión WebSocket a la Realtime API con el valor
call_idproporcionado en el webhook, mediante una URL como esta:wss://api.openai.com/v1/realtime?call_id={callId}. La conexión WebSocket permanecerá activa mientras dure la llamada SIP.
La conexión WebSocket se puede usar entonces para enviar y recibir eventos que permitan controlar la llamada, tal como lo harías si la sesión se hubiera iniciado con una conexión WebSocket. Esto incluye monitorear la llamada, actualizar instrucciones de forma dinámica y responder a llamadas a herramientas.