Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los agentes hospedados en Foundry Agent Service admiten cargas de trabajo de voz en tiempo real a través del protocolo invocations_ws WebSocket. En este artículo se muestra cómo elegir un marco de voz, exponer el punto de conexión de WebSocket desde el contenedor y conectar un cliente.
Para obtener información sobre los agentes hospedados y los protocolos disponibles, consulte ¿Qué son los agentes hospedados?. Para conocer los pasos generales de empaquetado e implementación de contenedores, consulte Implementación de un agente hospedado.
Importante
Los agentes hospedados y el invocations_ws protocolo están en versión preliminar pública. El invocations_ws protocolo solo está disponible actualmente en centro-norte de EE. UU. Las características y los límites pueden cambiar.
Cuándo usar el protocolo WebSocket
Los agentes de voz en tiempo real necesitan streaming bidireccional: el cliente y el agente envían y reciben audio simultáneamente a través de una conexión persistente. El protocolo invocations_ws proporciona un único WebSocket de dúplex completo entre el autor de la llamada y el contenedor, con texto y tramas binarias transmitidas de extremo a extremo.
Use invocations_ws cuando necesite:
- Transmita audio del micrófono (por ejemplo, tramas PCM de 20 ms a 16 kHz) al agente y transmita voz sintetizada de vuelta.
- Ejecute una canalización de voz a voz o de voz en cascada (STT → LLM → TTS) dentro del contenedor.
- Transportar mensajes de control intercalados (JSON) y contenido multimedia (binario) en la misma conexión.
- Use la señalización de WebSocket para configurar una conexión multimedia de WebRTC que administra la aplicación.
- Conecte un proveedor de telefonía (por ejemplo, Twilio) que transmite el audio de las llamadas mediante WebSocket.
En el caso de las invocaciones de estilo de solicitud o respuesta, siga usando las rutas HTTP /invocations o /responses . Un único contenedor puede exponer los tres protocolos al mismo tiempo.
Semántica de puntos de conexión y tramas
El contenedor expone una ruta de WebSocket:
GET /invocations_ws
Upgrade: websocket
Connection: Upgrade
Punto de conexión público (ruta de acceso literal única; project_name, agent_namey agent_session_id se pasan como parámetros de cadena de consulta):
wss://<account>.services.ai.azure.com/api/projects/agents/endpoint/protocols/invocations_ws
?project_name=<project>
&agent_name=<agent>
&agent_session_id=<session-id>
&foundry_features=HostedAgents=V1Preview
La plataforma utiliza project_name, agent_name y foundry_features en las capas de APIM y Agents-service para dirigir la actualización y controlar el acceso a la versión preliminar. No aparecen en la actualización que recibe el contenedor. Cualquier otro parámetro de consulta que agregue se reenvía sin cambios.
La marca de vista previa es necesaria mientras el protocolo está en versión preliminar. Puede proporcionarlo como parámetro foundry_features=HostedAgents=V1Preview de consulta (mostrado anteriormente) o como Foundry-Features: HostedAgents=V1Preview encabezado de solicitud en la actualización, que es la misma marca que usa HTTP /invocations.
La plataforma actúa como proxy para la solicitud de actualización a WebSocket de forma transparente. Las tramas fluyen entre el autor de la llamada y el contenedor como bytes sin procesar; la plataforma no analiza, transforma ni almacena en búfer en la capa de aplicación.
| Tipo de marco | Soportado | Uso típico |
|---|---|---|
| Texto (UTF-8) | Sí | Mensajes de control JSON |
| Binary | Sí | Audio (PCM/Opus), imágenes, otras cargas sin texto |
| Continuación | Sí | RfC 6455 mensajes fragmentados retransmitidos sin cambios |
| Ping /Pong | Sí | Mantener conexión (el contenedor envía Pings; el proxy no genera los suyos) |
| Close | Sí | Códigos de cierre estándar de RFC 6455 |
Límite de tamaño de fotograma. El proxy de plataforma aplica un tamaño de trama máximo de 1 MB. Las tramas de más de 1 MB se rechazan con código de cierre de WebSocket 1009. En el caso del audio, los fotogramas PCM de 20 ms a 16 kHz mono (~640 bytes) están muy por debajo del límite.
Resolución de sesión. Quien realiza la llamada puede pasar ?agent_session_id=<id> en la dirección URL de actualización. Dentro del contenedor, lea FOUNDRY_AGENT_SESSION_ID del entorno o recurra al parámetro de consulta. Si no se establece ninguno, genere su propio UUID.
Autenticación. Los autores de llamadas presentan un token de portador de Microsoft Entra en el encabezado Authorization durante la actualización. APIM y el servicio Agentes validan el token; el contenedor no lo ve. No confíe en que una cabecera Authorization llegue a /invocations_ws, y no acepte un parámetro de consulta authorization.
Ciclo de vida de la conexión
Caller ──Upgrade──▶ Agents service (proxy) ──Upgrade──▶ Container /invocations_ws
◀─── 101 ─────────────────────────────────── 101 ───
◀══ frames (bidirectional, raw byte relay) ══▶
── Close ────────────────────────────────── Close ──▶
- Abrir. El autor de la llamada envía
GET /invocations_wscon encabezados de actualización de WebSocket. La plataforma resuelve la sesión y la versión, actúa como proxy para la actualización y el contenedor responde101 Switching Protocols. - Exchange. Las tramas fluyen en ambas direcciones hasta que una de las partes inicie el cierre.
- Cierre. Una de las partes envía una trama de cierre; el elemento del mismo nivel repite un trama de cierre y cierra su lado de envío.
- Cierre anómalo. Si se elimina la conexión TCP subyacente, el elemento del mismo nivel observa el código de cierre
1006sin trama de cierre.
Duración máxima de la conexión (versión preliminar)
La plataforma recicla la infraestructura de forma gradual con un período de gracia de cierre de 10 minutos. Las conexiones individuales de WebSocket en versión preliminar están limitadas a aproximadamente 10 minutos. Cuando la plataforma inicia el apagado, envía código 1001 de cierre (desconexión). Los clientes deben estar preparados para volver a conectarse a la misma agent_session_id; el entorno aislado (y cualquier estado del contenedor en curso) se mantiene entre reconexiones. La plataforma no vuelve a reproducir las tramas que faltan; el contenedor debe encargarse de cualquier protocolo de reanudación de nivel de aplicación.
Códigos de cierre
| Cerrar código | Meaning | Source |
|---|---|---|
1000 |
Cierre normal | Cualquiera de los lados |
1001 |
Va a desaparecer | Vaciado de cierre de plataforma |
1002 |
Error de protocolo | Cualquiera de los lados |
1003 |
Datos no compatibles | Cualquiera de los lados |
1006 |
Cierre anómalo (sin trama de cierre) | Eliminación de TCP |
1008 |
Infracción de directiva | Contenedor |
1009 |
Mensaje demasiado grande | Proxy de plataforma (la trama ha superado 1 MB) |
1011 |
Error interno del servidor | Contenedor |
Implementación del controlador de WebSocket
Agregue la /invocations_ws ruta al contenedor mediante el mismo azure-ai-agentserver-invocations host que sirve la ruta HTTP /invocations . El host expone dos decoradores:
| Decorador | Route | Purpose |
|---|---|---|
@app.invocation_handler |
POST /invocations |
Solicitud/respuesta (protocolo de invocaciones existente) |
@app.ws_handler |
GET /invocations_ws (Actualización de WebSocket) |
Streaming bidireccional (este artículo) |
Puede registrar uno o ambos en el mismo app objeto. El host llama a await websocket.accept() antes de invocar su @app.ws_handler, ejecuta mantener conexión Ping/Pong (30 s de forma predeterminada), asigna las excepciones no controladas al código de cierre 1011 y emite el evento de cierre estructurado y las métricas indicadas en Observabilidad.
from azure.ai.agentserver.invocations import InvocationsAgentServerHost
from starlette.websockets import WebSocket
app = InvocationsAgentServerHost()
@app.invocation_handler # POST /invocations
async def invoke(payload: dict) -> dict:
return {"echo": payload}
@app.ws_handler # GET /invocations_ws (WebSocket upgrade)
async def ws(websocket: WebSocket) -> None:
async for message in websocket.iter_text():
# JSON control message
await websocket.send_text(message)
app.run()
Para el audio en formato binario, lea las tramas en forma de bytes y páselas por su flujo de procesamiento STT/LLM/TTS:
@app.ws_handler
async def ws(websocket: WebSocket) -> None:
async for chunk in websocket.iter_bytes():
# chunk = e.g., 20 ms PCM @ 16 kHz mono = 640 bytes
response_audio = await process_audio(chunk)
await websocket.send_bytes(response_audio)
Para control mixto + medios, envíe el tipo de trama:
import json
@app.ws_handler
async def ws(websocket: WebSocket) -> None:
while True:
message = await websocket.receive()
if "text" in message:
event = json.loads(message["text"])
await handle_control(event, websocket)
elif "bytes" in message:
response = await process_audio(message["bytes"])
await websocket.send_bytes(response)
El punto de conexión /readiness, la exportación OTLP, el apagado controlado y el encabezado de identidad x-platform-server se heredan de azure-ai-agentserver-core; no necesita configurarlos manualmente.
El contenedor debe:
- Controle tramas de texto y binarias; respete las tramas de continuación de acuerdo con RFC 6455.
- Mantenga los fotogramas a 1 MB o por debajo.
- Conservar el estado relevante para la sesión para que un cliente pueda volver a asociarse a través de la misma
agent_session_id. - Propague
traceparent,tracestateybaggagedesde la solicitud de actualización como contexto principal para cualquier intervalo que emita la conexión.
Para ver ejemplos de voz de extremo a extremo que incluyen un portal de explorador, consulte los invocations_wsejemplos de agente de voz.
Elige un entorno de voz
Los agentes hospedados admiten cualquier marco de voz en contenedor. Los marcos siguientes han validado ejemplos:
| Marco de referencia | Descripción |
|---|---|
| Microsoft Voice Live | Interacción de voz en tiempo real con STT, LLM y TTS integrados. Admite canalizaciones en cascada y modelos de voz a voz, como GPT-4o Realtime. |
| Pipecat | Marco de canalización modular de código abierto para la inteligencia artificial de voz en tiempo real. Componer procesadores para STT, LLM y TTS. |
| Agentes de LiveKit | Plataforma de código abierto para audio y vídeo en tiempo real con administración de sesiones basadas en salas. |
Arquitecturas de canalización de voz
Puede ejecutar cualquier estilo de canalización dentro del contenedor:
- En cascada (STT → LLM → TTS). Separe los modelos de cada fase. Utiliza cualquier modelo de texto del catálogo de modelos de Foundry y cualquier voz de TTS. Lo mejor para la compatibilidad multilingüe y las voces personalizadas.
- Voz a voz. Los modelos en tiempo real, como GPT-4o Realtime, gestionan audio de entrada y de salida en un solo modelo. Lo mejor para la dinámica conversacional natural (interrupciones, canalización inversa) donde la latencia es crítica.
Implementación de un agente de voz
Los agentes de voz siguen el mismo flujo de implementación que cualquier agente hospedado. La única diferencia es declarar el invocations_ws protocolo en la versión del agente.
Declaración del protocolo
Al crear la versión del agente, incluya invocations_ws en container_protocol_versions. Puede declararlo solo o junto a responses y invocations.
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import (
AgentProtocol,
HostedAgentDefinition,
ProtocolVersionRecord,
)
from azure.identity import DefaultAzureCredential
project = AIProjectClient(
endpoint="https://<resource>.services.ai.azure.com/api/projects/<project>",
credential=DefaultAzureCredential(),
allow_preview=True,
)
agent = project.agents.create_version(
agent_name="my-voice-agent",
definition=HostedAgentDefinition(
container_protocol_versions=[
ProtocolVersionRecord(protocol=AgentProtocol.INVOCATIONS_WS, version="1.0.0"),
],
cpu="1",
memory="2Gi",
image="your-registry.azurecr.io/your-voice-agent:v1",
environment_variables={
"MODEL_DEPLOYMENT_NAME": "gpt-realtime",
},
),
)
Para obtener el flujo de implementación completo (compilación, inserción, RBAC y sondeo de estado), consulte Implementación de un agente hospedado.
Tip
En el caso de las cargas de trabajo de voz, se recomienda al menos 1 vCPU/2 GiB para el procesamiento de audio suave y la inferencia del modelo. Hay tamaños de sandbox de hasta 2 vCPU / 4 GiB; elige el que mejor se adapte a tu pipeline.
Conexión de un cliente
Los clientes del explorador usan la API webSocket de W3C. Otros autores de llamadas usan bibliotecas estándar, como Python websockets o aiohttp. No hay ningún SDK de cliente independiente.
import asyncio
import websockets
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
token = credential.get_token("https://ai.azure.com/.default").token
uri = (
"wss://<account>.services.ai.azure.com/api/projects/agents"
"/endpoint/protocols/invocations_ws"
"?project_name=<project>"
"&agent_name=my-voice-agent"
"&agent_session_id=demo-session-1"
"&foundry_features=HostedAgents=V1Preview"
)
async def main():
headers = {"Authorization": f"Bearer {token}"}
async with websockets.connect(uri, additional_headers=headers) as ws:
await ws.send("hello")
print(await ws.recv())
asyncio.run(main())
Usa contenido multimedia de WebRTC con señalización mediante WebSocket
Algunos agentes de voz usan WebRTC para medios de audio de explorador a agente porque WebRTC controla bien la pérdida de paquetes, el almacenamiento en búfer de vibración y el transporte de audio en tiempo real. Los agentes hospedados no proporcionan un servicio multimedia WebRTC administrado, servicio TURN, SFU ni protocolo de señalización webRTC. En su lugar, use invocations_ws como canal de señalización autenticado e implemente la ruta de acceso multimedia de WebRTC en el cliente y el contenedor.
Un patrón típico de WebRTC funciona de la siguiente manera:
- El explorador abre una conexión autenticada al agente hospedado
invocations_ws. - El explorador envía mensajes de señalización en forma de tramas de texto, como una solicitud de configuración de ICE, una oferta SDP y candidatos ICE.
- El contenedor crea o actualiza su conexión entre pares de WebRTC y responde con una respuesta SDP y mensajes de estado de candidatos.
- El audio se transmite a través de la conexión entre pares de WebRTC. WebSocket sigue estando disponible para la señalización, los eventos del ciclo de vida y los mensajes de control de aplicaciones.
- La aplicación proporciona la configuración del relé TURN y gestiona cualquier comportamiento de reconexión o reanudación específico de WebRTC.
Los ejemplos de WebRTC de referencia usan marcos de texto JSON en /invocations_ws para acciones como ice_config, offer, ice_candidatey disconnect. El medio de audio no usa el WebSocket en ese patrón; fluye a través de la conexión entre pares de WebRTC negociada a través del WebSocket.
Utilice este patrón cuando desee el comportamiento de medios de WebRTC en un explorador o cliente móvil y esté preparado para operar la pila de WebRTC del lado del cliente y del lado del servidor. Use streaming de audio de WebSocket directo cuando desee un transporte más sencillo, especialmente para prototipos, puentes de telefonía o redes controladas.
Para obtener una implementación completa, consulte el ejemplo webRTC de Pipecat.
Uso de modelos y herramientas de Foundry
Los agentes de voz tienen acceso nativo al ecosistema Foundry. El contenedor del agente se autentica con su identidad del agente de Microsoft Entra dedicada, sin claves de API ni cadenas de conexión en el código.
- Modelos en tiempo real. GPT-4o Realtime y GPT Realtime para flujos de voz a voz.
- Modelos de texto. GPT-4o, GPT-4.1 y la serie GPT-5 para canalizaciones en cascada.
- Modelos de voz. Voz de Azure AI para STT y TTS.
- Herramientas. Acceda a las herramientas administradas por Foundry (Búsqueda web, Búsqueda de archivos, Intérprete de código, Búsqueda de Azure AI, servidores MCP personalizados, A2A) a través del punto de conexión mcP del cuadro de herramientas en el proyecto Foundry. Consulte Mantener la caja de herramientas basada en intenciones en Foundry.
Observability
La /invocations_ws actualización y el ciclo de vida de cada conexión deben instrumentarse con tramos de trazas distribuidas, siguiendo las convenciones de OpenTelemetry GenAI utilizadas por el protocolo HTTP /invocations.
Propague traceparent, tracestatey baggage desde la solicitud de actualización como contexto principal para los intervalos emitidos durante la vigencia de la conexión.
Métricas recomendadas para emitir:
| Métrica | Tipo | Descripción |
|---|---|---|
websocket.connection.duration_ms |
Histograma | Duración de la conexión desde la actualización hasta su cierre. |
websocket.connection.close_code |
Contador | Distribución de códigos de cierre. |
websocket.frames.sent / websocket.frames.received |
Contador | Recuentos de tramas (texto + binario). |
websocket.frames.bytes_sent / websocket.frames.bytes_received |
Contador | Volumen de bytes en cada dirección. |
websocket.active_connections |
Medidor | Conexiones activas simultáneas. |
Las trazas y las métricas aparecen en el recurso vinculado de Application Insights junto con las trazas de invocación de modelos y herramientas.
Límites y consideraciones
| Limit | Value | Notas |
|---|---|---|
| Tamaño máximo de marco de WebSocket | 1 MB | Impuesto por el proxy de la plataforma (código de cierre 1009). |
| Duración máxima de la conexión | ~10 minutos (versión preliminar) | La plataforma envía el código de cierre 1001 durante el vaciado de cierre. Vuelva a conectarse con el mismo agent_session_id. |
| Recursos del entorno de pruebas | Hasta 2 vCPU / 4 GiB | Se recomienda al menos 1 vCPU / 2 GiB para voz. |
| Número máximo de sesiones simultáneas | 50 por suscripción por región | Se puede ajustar mediante una solicitud de cuota. |
| Tiempo de inactividad de la sesión | 15 minutos | Se desaprovisionan los recursos de cómputo; se conserva el estado de la sesión. |
La plataforma no reproduce fotogramas perdidos. El contenedor se encarga de cualquier protocolo de reanudación a nivel de aplicación.
Integración de telefonía
Para conectar un agente tradicional basado en telefonía, utilice un proveedor de telefonía (por ejemplo, Azure Communication Services o Twilio) que enlace las llamadas de la RTC con el punto de conexión invocations_ws del agente hospedado. El proveedor de telefonía controla la señalización SIP, la transcodificación multimedia y el procesamiento DTMF.