Los restaurantes pierden un promedio de 150 llamadas telefónicas por ubicación cada mes, y alrededor del 60 por ciento de ellas son clientes que intentan hacer un pedido o reservar una mesa. La mayoría de estas llamadas llegan durante el servicio de cena, exactamente cuando el anfitrión está sentando a los invitados, los camareros están girando las mesas y el teléfono se convierte en una ocurrencia de último momento. Sacar a alguien del suelo para que responda no soluciona el problema. Sólo empeora dos experiencias. Agregar una aplicación o un sitio web ayuda a los clientes que prefieren realizar pedidos en línea, pero no sirve de nada para la persona que solo quiere llamar.
En esta publicación, le mostramos cómo construir un sistema de pedidos por voz que responda a un número de teléfono y lleve el pedido desde el saludo hasta la confirmación. El sistema utiliza Amazon Bedrock AgentCore para alojar y ejecutar el agente y Amazon Nova 2 Sonic para voz en tiempo real, conectado al backend de un restaurante a través del protocolo de contexto modelo (MCP). El tutorial cubre la implementación de la pila completa con AWS Cloud Development Kit (AWS CDK) y la conexión de una llamada telefónica al agente a través de una puerta de enlace del Protocolo de inicio de sesión (SIP) en Amazon Elastic Container Service (Amazon ECS) y AWS Fargate. También calienta la sesión del agente mientras el teléfono sigue sonando, por lo que la persona que llama nunca escucha el silencio.
Descripción general de la solución
El sistema tiene tres capas. La capa de telefonía maneja inquietudes específicas del teléfono. El audio llega a través de la red telefónica en lugar de a través de un navegador, y el sistema identifica a la persona que llama por el número de teléfono en lugar de por un inicio de sesión. Una puerta de enlace SIP transmite ese audio a la capa del agente a través de una conexión WebSocket firmada, donde el agente ejecuta la conversación con Amazon Nova 2 Sonic. El agente llega a la capa backend a través de herramientas MCP. El backend contiene el menú, los carritos, los pedidos y las ubicaciones. Mantener estas capas separadas significa que la lógica de pedido permanece independiente del canal que la llama. Un nuevo canal, como una aplicación móvil o un quiosco, puede conectarse al mismo agente sin tener que reescribir el backend. Y como MCP es un estándar abierto para conectar un agente a herramientas externas, el backend puede cambiar sin tocar al agente. El agente admite texto y audio como entrada y salida, manejando la transcripción, los turnos y las interrupciones en una única secuencia bidireccional.
La solución implementa lo siguiente:
En el lado de la telefonía, Amazon Chime SDK Voice Connector proporciona la troncal SIP y el número gratuito que acepta llamadas entrantes. Amazon ECS en AWS Fargate ejecuta la puerta de enlace SIP detrás de un balanceador de carga de red. Para la capa de agente, AgentCore Runtime aloja la lógica de conversación, y cada llamada se ejecuta en su propia microVM para su aislamiento. Amazon Nova 2 Sonic maneja la interacción de voz a voz. AgentCore Gateway expone las API de backend como herramientas MCP que el agente puede descubrir y llamar por su nombre. La capa backend utiliza Amazon API Gateway para los puntos finales REST protegidos por AWS Identity and Access Management (IAM). AWS Lambda ejecuta la lógica empresarial para menús, carritos, pedidos y búsquedas de ubicaciones. Amazon DynamoDB almacena los datos y Amazon Location Service maneja la codificación geográfica y el cálculo de rutas. Amazon Elastic Container Registry (Amazon ECR), AWS CodeBuild y Amazon Simple Storage Service (Amazon S3) crean y almacenan la imagen del contenedor del agente.
Diagrama de arquitectura
El siguiente diagrama muestra la solución, que está organizada en cuatro secciones.
La infraestructura backend del restaurante se implementa primero en la Sección A. Amazon DynamoDB contiene los datos del cliente, el pedido, el menú, el carrito y la ubicación, y Amazon Location Service maneja las direcciones y las rutas. AWS Lambda ejecuta la lógica empresarial y Amazon API Gateway la expone externamente con autorización de IAM. Los recursos se implementan en orden de dependencia.
La sección B crea la puerta de enlace AgentCore, configura sus permisos de IAM y configura la puerta de enlace para exponer los puntos finales de backend como herramientas MCP accesibles al agente. Esta es la capa que desacopla al agente del backend. Sin él, agregar o cambiar una herramienta requeriría volver a implementar el agente.
La Sección C aprovisiona al agente. Crea el repositorio de Amazon ECR y utiliza Amazon S3 y AWS CodeBuild para crear y enviar la imagen del contenedor. Luego implementa AgentCore Runtime. También implementa las piezas de soporte que permiten al agente personalizar cada llamada, incluida una función Lambda de procesamiento de mensajes y un conjunto de entradas del almacén de parámetros de AWS Systems Manager que contienen las plantillas de mensajes y un secreto utilizado para la identificación de la persona que llama.
La sección D proporciona la ruta telefónica. Configura el conector de voz del SDK de Amazon Chime y un número gratuito, una aplicación Lambda de medios SIP que decide qué hacer con una llamada entrante, una nube privada virtual de Amazon compartida (Amazon VPC) y la puerta de enlace SIP (servidor drachtio), que se ejecuta en Amazon ECS en AWS Fargate detrás de un balanceador de carga de red. La puerta de enlace conecta las llamadas entre Chime SDK Voice Connector y AgentCore Runtime.
Las leyendas numeradas en el diagrama anterior trazan la solución de principio a fin:
Se inicia una llamada al número de teléfono proporcionado por Amazon Chime SDK, ya sea por un cliente o reenviada desde otra línea. Amazon Chime SDK responde a la llamada e invoca AWS Lambda para configurar el puente. Lambda crea un identificador de sesión y abre una conexión a AgentCore Runtime para calentar la microVM, lo que evita un inicio en frío cuando comienza la transmisión de medios. Después de una respuesta exitosa de Lambda, el SDK de Amazon Chime inicia una acción de puente contra el balanceador de carga de red enviando una invitación SIP a través del puerto TCP 5060. El servicio SIP que se ejecuta en AWS Fargate acepta la invitación y asigna un puerto libre en el servicio de protocolo de transporte en tiempo real (RTP) en el mismo contenedor para recibir medios en la dirección IP pública asignada. El servicio RTP recibe los medios en el puerto UDP desde Voice Connector y se conecta al AgentCore Runtime WebSocket para comenzar la traducción de medios, utilizando el mismo identificador de sesión creado por el controlador de la aplicación de medios SIP. AgentCore Runtime invoca una función de AWS Lambda para crear el indicador del sistema, almacenado en AWS Systems Manager Parameter Store, en función del identificador de sesión y el registro de Amazon DynamoDB del cliente. AgentCore Runtime crea una sesión con Amazon Nova 2 Sonic y saluda al cliente a través de la conexión establecida, siguiendo las instrucciones del sistema. AgentCore Runtime enumera y llama a las herramientas disponibles desde AgentCore Gateway utilizando el protocolo MCP. AWS CDK implementa la solución en Amazon S3, lo que activa AWS CodeBuild para crear las imágenes del contenedor y almacenarlas en Amazon ECR. AgentCore Runtime y AWS Fargate utilizan estas imágenes para implementar el agente y los servidores SIP y RTP. Amazon CloudWatch proporciona monitoreo, registro y alertas centralizados en todos los servicios, y todos los datos en reposo se cifran mediante AWS Key Management Service (AWS KMS).
Los puntos 1 a 9 ocurren durante una sola llamada telefónica, el punto 10 cubre cómo la solución implementa el servidor SIP y AgentCore Runtime, y el punto 11 cubre cómo se monitorea y protege. La siguiente sección deja de lado el despliegue y las operaciones y se acerca más a la llamada en sí.
Flujo de llamadas entrantes
Esta sección sigue una llamada del lado de la persona que llama desde el primer timbre hasta la respuesta hablada. Es la misma ruta de ejecución que las llamadas 1 a 9 en el diagrama de arquitectura anterior. El siguiente diagrama lo muestra como una secuencia para que el orden de los eventos sea más sencillo de ver.
Los pasos numerados en el diagrama anterior corresponden a estas etapas de la convocatoria:
La persona que llama marca el número gratuito y Amazon Chime SDK Voice Connector responde. Voice Connector invoca la aplicación Lambda de medios SIP, que calcula un identificador de sesión para la llamada. Lambda envía una solicitud de preparación a AgentCore Runtime, para que el agente prepare su sesión mientras el teléfono sigue sonando. Lambda le indica al conector de voz que conecte la llamada a la puerta de enlace SIP en Amazon ECS en AWS Fargate, pasando el identificador de sesión. La puerta de enlace SIP abre un WebSocket firmado por SigV4 en AgentCore Runtime utilizando ese mismo identificador de sesión. La llamada se adjunta a la sesión preparada, el audio de la persona que llama fluye al agente y el audio del agente regresa a la persona que llama. El agente ejecuta la conversación con Amazon Nova 2 Sonic y llama a las herramientas de backend a través de AgentCore Gateway cuando necesita datos de menú, carrito, pedido o ubicación.
Requisitos previos
Antes de comenzar, verifique que tenga lo siguiente en su lugar:
Una cuenta de AWS. Acceso al modelo de Amazon Bedrock para Amazon Nova 2 Sonic en la región de AWS donde realiza la implementación, solicitado en la página de acceso al modelo en la consola de Amazon Bedrock. Acceso de audio PSTN de Amazon Chime SDK, con un aumento de cuota de número de teléfono solicitado en la consola de Amazon Chime SDK si nunca ha solicitado un número en esta cuenta. Node.js 24.x o posterior. Interfaz de línea de comandos de AWS (AWS CLI) 2.x configurada con credenciales. git para clonar el repositorio. AWS CDK arranca en su cuenta y región de destino (npx cdk bootstrap aws:///).
El contenedor del agente está creado con Python, pero la compilación se ejecuta dentro de AWS CodeBuild, por lo que no necesita Python en su propia máquina. Implemente en una región donde Amazon Nova 2 Sonic, Amazon Chime SDK PSTN Audio y AgentCore Runtime estén disponibles. US East (N. Virginia), us-east-1, es un buen lugar para comenzar.
Implemente la solución con AWS CDK
La solución completa está disponible en el repositorio de muestra en GitHub. Clona el repositorio y cambia al directorio del proyecto.
Ejecute la verificación previa. Confirma que Node.js, AWS CLI, git, el arranque de AWS CDK y el acceso al modelo de Amazon Bedrock están en su lugar e informa cualquier cosa que falte.
Luego ejecute el script de implementación con un prefijo de implementación. El prefijo se agrega a cada nombre de recurso, que puede usar para implementar la solución más de una vez en la misma cuenta.
El script implementa cada pila de AWS CDK en orden y pasa las salidas de una pila a la siguiente. Primero construye el backend y luego agrega AgentCore Gateway delante de las API del backend. A continuación, crea y envía la imagen del contenedor del agente con AWS CodeBuild e implementa el agente en AgentCore Runtime. Finalmente, abre la puerta de enlace SIP en Amazon ECS en AWS Fargate y aprovisiona el conector de voz del SDK de Amazon Chime y el número gratuito. También genera datos de ubicación y menú de muestra para que puedas realizar un pedido real tan pronto como finalice. La compilación del contenedor del agente tarda varios minutos la primera vez, por lo que se espera que la ejecución se detenga mientras AWS CodeBuild funciona.
Cuando se completa el script, imprime el número a marcar:
Cómo funciona la puerta de enlace SIP
La capa de telefonía tiene una función. Convierte una llamada telefónica en un flujo multimedia que el agente puede leer y escribir. Esto es importante porque la red telefónica y el agente utilizan protocolos diferentes. El teléfono entrega audio como paquetes RTP a través de UDP. El agente espera un WebSocket que lleve marcos en el formato que entiende Amazon Nova 2 Sonic. Sin una capa de traducción intermedia, el agente necesitaría conocimientos sobre SIP, negociación de códec y enrutamiento de medios a nivel de red, todo lo cual lo acoplaría a un solo canal. Dos componentes manejan esa traducción.
El conector de voz del SDK de Amazon Chime acepta la llamada entrante e invoca la aplicación Lambda de medios SIP. Esa Lambda es hacia donde se dirige la llamada. Devuelve una instrucción para conectar la llamada a la puerta de enlace SIP y lleva el identificador de sesión para que el siguiente salto sepa a qué sesión pertenece esta llamada.
La puerta de enlace SIP se ejecuta en Amazon ECS en AWS Fargate. Utiliza drachtio-server para la señalización SIP, con un puente Node.js para el audio. La puerta de enlace responde a la llamada y convierte entre el formato de audio que utiliza la red telefónica y el formato que espera Amazon Nova 2 Sonic. Para alta disponibilidad (HA), se ejecuta como dos tareas en dos zonas de disponibilidad (AZ), lo que le brinda redundancia y un lugar para publicar una métrica de recuento de llamadas en Amazon CloudWatch para escalar. La señalización de la llamada pasa a través del balanceador de carga de red, pero el audio en sí fluye directamente entre el conector de voz y la tarea Fargate, lo que mantiene el balanceador de carga fuera de la ruta de los medios.
Calentando al agente mientras suena el teléfono
Una llamada de voz no perdona el silencio. Si una persona que llama se conecta y no escucha nada durante unos segundos, la llamada se siente interrumpida aunque el sistema esté funcionando. La parte lenta de iniciar una llamada es la configuración única. El agente debe resolver el mensaje del sistema para esta persona que llama, abrir la transmisión de Amazon Nova 2 Sonic y descubrir las herramientas MCP disponibles.
En lugar de hacer que la persona que llama espere, la aplicación SIP Media Lambda la inicia mientras el teléfono sigue sonando. Tan pronto como llega la llamada, Lambda envía una solicitud de preparación a AgentCore Runtime con un identificador de sesión para la llamada. AgentCore Runtime asigna una microVM y ejecuta la configuración durante la ventana de timbre. Un momento después, cuando la puerta de enlace SIP abre su conexión WebSocket usando el mismo identificador de sesión, AgentCore Runtime la enruta a esa microVM que ya está caliente y el agente está listo para hablar.
El identificador de sesión es lo que conecta las dos solicitudes. Lambda lo calcula a partir de la llamada misma, por lo que la solicitud de preparación y la conexión de audio posterior se resuelven en el mismo microVM sin ningún estado adicional que rastrear. El siguiente diagrama muestra cómo esto se superpone con la ventana de timbre para que el agente esté listo cuando se conecte la llamada.
Almacenamiento de menús, carritos y pedidos.
Cinco tablas de Amazon DynamoDB cubren el flujo de trabajo de pedidos. La tabla Clientes almacena perfiles, incluido el nombre, el teléfono y la información de lealtad, que el agente utiliza para reconocer a una persona que regresa. La tabla de Pedidos mantiene el historial de pedidos junto con el lugar de recogida. La tabla Menú contiene artículos, precios y disponibilidad, que pueden variar según la ubicación. La tabla Carros contiene carros en progreso y utiliza un valor de tiempo de vida para que los carros abandonados se limpien solos. La tabla Ubicaciones contiene detalles del restaurante, como coordenadas, horarios y tasas impositivas que el agente utiliza para los totales y las recomendaciones. La capacidad bajo demanda de DynamoDB aumenta con el tráfico, por lo que no hay rendimiento que administrar.
Encontrar un lugar de recogida
El servicio de ubicación de Amazon ayuda a la persona que llama a encontrar un lugar de recogida conveniente sin tener que escribir nada. Una persona que llama por teléfono no tiene un navegador para compartir una ubicación, por lo que el agente solicita un código postal o un cruce de calles y utiliza el Servicio de ubicación de Amazon para convertirlo en coordenadas. A partir de ahí, el backend puede hacer algunas cosas con esas coordenadas. Puede encontrar los restaurantes más cercanos, clasificarlos por tiempo de conducción en lugar de distancia en línea recta para favorecer un desvío corto a lo largo de la ruta de la persona que llama, o geocodificar una dirección específica. Eso le permite al agente decir algo que la persona que llama puede actuar, como "la ubicación más cercana está en Main Street, a unos cinco minutos de distancia", en lugar de leer un código interno.
Procesamiento de voz con Amazon Bedrock AgentCore y Amazon Nova 2 Sonic
El agente se ejecuta en AgentCore Runtime. Cada llamada se ejecuta en su propia microVM, por lo que la sesión de una persona que llama no puede afectar la de otra. AgentCore Runtime maneja el escalado y proporciona la conexión WebSocket que transporta audio en ambos sentidos.
Dentro del agente, el marco del agente define el aviso del sistema, las herramientas que puede llamar y el flujo de la conversación. Amazon Nova 2 Sonic hace el trabajo de voz dentro de la llamada. Reconoce el habla en una variedad de acentos y maneja la variada calidad de audio que viene con una línea telefónica. Transmite audio en ambas direcciones con baja latencia y llama a herramientas de forma asíncrona sin detener la conversación (consulte Llamadas de herramientas asíncronas en Amazon Nova Sonic), para que la persona que llama no tenga que esperar mientras se recuperan los datos. También maneja las interrupciones, de modo que la persona que llama puede hablar con el agente como lo hacen las personas en llamadas de persona a persona.
Un detalle es específico de las llamadas telefónicas. Una búsqueda de backend puede tardar unos segundos y Amazon Nova 2 Sonic finaliza una sesión que permanece inactiva en el lado del servidor durante demasiado tiempo. Para mantener abierta la sesión durante una llamada lenta a la herramienta, el agente envía una trama silenciosa en un breve intervalo. La sesión permanece activa y la persona que llama no escucha nada inusual.
El agente nunca llama directamente a las funciones Lambda del backend. AgentCore Gateway se ubica en el medio y presenta los puntos finales de backend como herramientas MCP que el agente descubre y llama por nombre, cubriendo búsquedas de menú, operaciones de carrito, realización de pedidos, historial de pedidos y clientes, codificación geográfica y búsqueda de ubicación. Esto significa que el agente no necesita saber qué función Lambda se encuentra detrás de una operación determinada o cómo autenticarse en ella.
Esa capa es la que mantiene el diseño ligeramente acoplado. Cuando el agente llama a una herramienta como PlaceOrder, la puerta de enlace la convierte en una solicitud REST a Amazon API Gateway, que la enruta a la función AWS Lambda correspondiente. Debido a que el agente se comunica con herramientas nombradas en lugar de funciones específicas, puede cambiar un controlador de backend o agregar una herramienta sin cambiar el agente. El mismo backend también puede servir a otros canales, porque todos realizan pedidos con las mismas herramientas y datos.
El siguiente diagrama muestra cómo una única llamada a una herramienta viaja desde el agente hasta el backend.
Reconocer a una persona que llama sin iniciar sesión
La persona que llama no inicia sesión, por lo que el sistema utiliza el número de teléfono de la persona que llama como base para su identidad. El sistema codifica el número con un valor secreto guardado en el almacén de parámetros de AWS Systems Manager y el resultado se convierte en el identificador de la sesión. El número de teléfono sin formato no aparece en los registros ni en el estado de la sesión. Este enfoque de hash ayuda a cumplir con los requisitos de manejo de información de identificación personal (PII) al garantizar que la información confidencial de la persona que llama nunca se almacene ni se transmita en texto sin formato.
Si ese identificador coincide con un cliente conocido, el agente saluda a la persona que llama por su nombre y puede ofrecerle su último pedido. Si no coincide, la persona que llama realiza el pedido como invitado y el pedido aún se realiza y almacena. Cada pedido registra el canal de donde proviene y si la persona que llama era un invitado, para que puedas identificar los pedidos de telefonía más adelante.
Esto reconoce a una persona que llama sin solicitar un inicio de sesión, pero no es una verificación de identidad, y el hash del número de teléfono no debe tratarse como prueba de quién está llamando. Cualquiera que tenga acceso al mismo teléfono puede realizar un pedido con esa identidad. Una implementación de producción que necesita una identidad verificada puede agregar un paso como un código de acceso único enviado a través de SMS antes de que el agente abra el historial de la cuenta de la persona que llama.
Tutorial de pedidos
Marque el número que aparece en la salida de implementación. El agente te saluda y te pregunta qué te gustaría. Puedes hablar con naturalidad, preguntar sobre el menú, dar un código postal para recoger y confirmar el pedido, todo por voz. Mientras la persona que llama habla, el agente llama a las herramientas de backend en segundo plano, por lo que no hay pausas mientras se cargan los datos. El siguiente vídeo muestra un orden típico desde el saludo hasta la confirmación.
Una vez finalizada la llamada, puede rastrear la ruta completa en Amazon CloudWatch Logs. Los registros de la puerta de enlace SIP muestran cómo se configuró y puenteó la llamada al agente. Los registros de los agentes muestran cada evento del agente y llamada a la herramienta a medida que avanza la conversación. Una vez que se confirma el pedido, aparece en la tabla Pedidos de DynamoDB con su tiempo total y estimado de preparación.
Costo
Usted paga por los servicios de AWS que utiliza el sistema. El cargo por minuto gratuito y las tareas siempre activas de Fargate son las dos partidas más importantes. Puedes bajar ambos si se ajusta a tus necesidades. Un número de marcación interna directa local cuesta menos por minuto que un número gratuito, y reducir las tareas de Fargate fuera del horario comercial reduce el cargo de cómputo una vez que conoce su tráfico. Consulte la página de precios de cada servicio para conocer las tarifas actuales y configure un presupuesto en AWS Cost Explorer para realizar un seguimiento del gasto.
Limpiar
Para evitar cargos continuos, elimine los recursos cuando haya terminado. Las tareas siempre activas de Fargate y el número gratuito continúan acumulando costos independientemente de que entren o no llamadas. El script de limpieza elimina las pilas en orden inverso, por lo que cada pila se elimina antes que aquellas de las que depende.
La limpieza es destructiva. Libera el número gratuito, elimina el historial de pedidos en Amazon DynamoDB, elimina el secreto en AWS Systems Manager Parameter Store y elimina las imágenes del contenedor en Amazon ECR. Haga una copia de seguridad de todo lo que desee conservar primero. Cuando finalice el script, confirme en la consola de AWS CloudFormation que las pilas han desaparecido (consulte Visualización de datos y recursos de la pila de AWS CloudFormation en la consola de administración de AWS) y en la consola de Amazon Chime SDK que se ha liberado el número gratuito (consulte Administración de números de teléfono en Amazon Chime SDK).
Conclusión
En esta publicación, analizamos un sistema de pedidos de telefonía por voz desde la implementación hasta el pedido completo. La arquitectura mantiene la telefonía, el agente y el backend independientes para que cada pieza pueda evolucionar por sí sola. Esa separación es lo que hace que el sistema sea práctico de operar, porque puede actualizar los datos del menú, intercambiar un nuevo modelo de voz o agregar un canal sin coordinar los cambios en toda la pila.
Para el restaurante, esto significa que los pedidos telefónicos fluyen sin tener que alejar al personal del mostrador. Las personas que llaman reciben un saludo inmediato en lugar de música en espera, el agente confirma cada elemento en voz alta para reducir errores y el sistema maneja las horas pico sin personal adicional. Debido a que el agente se conecta al backend a través de herramientas MCP, puede agregar capacidades como reservas o puntos de fidelidad registrando nuevas herramientas sin cambiar el agente o la capa de telefonía.
Para comenzar, clone el repositorio de muestra en GitHub y ejecute la verificación previa para confirmar que su entorno esté listo. A partir de ahí, reemplace los datos iniciales en las definiciones de la tabla de DynamoDB con sus propios elementos de menú, ubicaciones y precios. Actualice las plantillas de mensajes del sistema en las entradas de la Tienda de parámetros para reflejar el nombre de su restaurante, el estilo de saludo y las reglas de pedido. Luego ejecute el script de implementación para activar el sistema en su propio número gratuito.