Configura llamadas de voz en OpenClaw: Guía rápida
¿Alguna vez has intentado integrar llamadas de voz en una aplicación y has terminado perdido entre documentación de webhooks y configuraciones de red imposibles? Todos hemos pasado por ese dolor de cabeza donde algo tan “simple” como hacer que el sistema hable por teléfono se convierte en un proyecto de semanas.
Con el plugin de Voice Call para OpenClaw, puedes gestionar notificaciones salientes y conversaciones multi-turno de forma directa. Actualmente soporta Twilio, Telnyx, Plivo y un modo mock para que hagas pruebas en local sin gastar ni un céntimo ni configurar redes.
Dónde se ejecuta (local vs remoto)
Sección titulada «Dónde se ejecuta (local vs remoto)»El plugin Voice Call se ejecuta dentro del proceso del Gateway.
Si utilizas un Gateway remoto, debes instalar y configurar el plugin en la máquina que ejecuta el Gateway. Después, reinicia el Gateway para que cargue los cambios.
Instalación
Sección titulada «Instalación»Opción A: instalar desde npm (recomendado)
Sección titulada «Opción A: instalar desde npm (recomendado)»openclaw plugins install @openclaw/voice-callReinicia el Gateway al terminar.
Opción B: instalar desde una carpeta local (desarrollo)
Sección titulada «Opción B: instalar desde una carpeta local (desarrollo)»PLUGIN_SRC=./path/to/local/voice-call-pluginopenclaw plugins install "$PLUGIN_SRC"cd "$PLUGIN_SRC" && pnpm installReinicia el Gateway al terminar.
Configuración
Sección titulada «Configuración»Define la configuración bajo plugins.entries.voice-call.config:
{ plugins: { entries: { "voice-call": { enabled: true, config: { provider: "twilio", // or "telnyx" | "plivo" | "mock" fromNumber: "+15550001234", toNumber: "+15550005678",
twilio: { accountSid: "ACxxxxxxxx", authToken: "...", },
telnyx: { apiKey: "...", connectionId: "...", // Telnyx webhook public key from the Telnyx Mission Control Portal // (Base64 string; can also be set via TELNYX_PUBLIC_KEY). publicKey: "...", },
plivo: { authId: "MAxxxxxxxxxxxxxxxxxxxx", authToken: "...", },
// Webhook server serve: { port: 3334, path: "/voice/webhook", },
// Webhook security (recommended for tunnels/proxies) webhookSecurity: { allowedHosts: ["voice.example.com"], trustedProxyIPs: ["100.64.0.1"], },
// Public exposure (pick one) // publicUrl: "https://example.ngrok.app/voice/webhook", // tunnel: { provider: "ngrok" }, // tailscale: { mode: "funnel", path: "/voice/webhook" }
outbound: { defaultMode: "notify", // notify | conversation },
streaming: { enabled: true, streamPath: "/voice/stream", preStartTimeoutMs: 5000, maxPendingConnections: 32, maxPendingConnectionsPerIp: 4, maxConnections: 128, }, }, }, }, },}Notas importantes:
- Twilio, Telnyx y Plivo requieren una URL de webhook accesible públicamente.
mockes un proveedor para desarrollo local que no realiza llamadas de red.- Telnyx necesita
telnyx.publicKey(o la variableTELNYX_PUBLIC_KEY) a menos queskipSignatureVerificationsea true. - Si usas el plan gratuito de ngrok, configura
publicUrlcon la URL exacta; la verificación de firma es obligatoria. - Para producción, te recomiendo usar un dominio estable o Tailscale funnel en lugar de URLs temporales.
- La seguridad del streaming incluye límites de conexiones por IP y tiempos de espera para proteger tu Gateway.
Limpieza de llamadas inactivas (Stale call reaper)
Sección titulada «Limpieza de llamadas inactivas (Stale call reaper)»Usa staleCallReaperSeconds para finalizar llamadas que nunca reciben un webhook de terminación. Por defecto está en 0 (desactivado).
Configuraciones recomendadas:
- Producción: entre
120y300segundos para flujos de notificación. - Mantén este valor por encima de
maxDurationSecondspara que las llamadas normales terminen correctamente. Un buen punto de partida esmaxDurationSeconds + 30–60segundos.
Ejemplo:
{ plugins: { entries: { "voice-call": { config: { maxDurationSeconds: 300, staleCallReaperSeconds: 360, }, }, }, },}Seguridad de los Webhooks
Sección titulada «Seguridad de los Webhooks»Cuando usas un proxy o túnel frente al Gateway, el plugin reconstruye la URL pública para verificar la firma. Estas opciones controlan en qué cabeceras confiamos.
webhookSecurity.allowedHosts define una lista de hosts permitidos.
webhookSecurity.trustForwardingHeaders confía en las cabeceras reenviadas sin lista de permitidos.
webhookSecurity.trustedProxyIPs solo confía en las cabeceras si la IP remota coincide con la lista.
El plugin incluye protección contra ataques de replicación (replay protection) para Twilio y Plivo. Además, las peticiones de webhook no autenticadas se rechazan antes de leer el cuerpo si faltan las firmas requeridas.
Ejemplo con un host público estable:
{ plugins: { entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", webhookSecurity: { allowedHosts: ["voice.example.com"], }, }, }, }, },}TTS para llamadas
Sección titulada «TTS para llamadas»Voice Call utiliza la configuración messages.tts del núcleo para el streaming de voz. Puedes sobrescribirla dentro de la configuración del plugin y se fusionará (deep-merge) con la global.
{ tts: { provider: "elevenlabs", providers: { elevenlabs: { voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, },}Notas:
- Ignora las voces de Microsoft para llamadas de voz, ya que la telefonía requiere PCM y el transporte actual de Microsoft no lo soporta.
- Si el streaming de Twilio está activo, se usa el TTS del núcleo; de lo contrario, se vuelve a las voces nativas del proveedor.
- Cuando el TTS falla y pasa a un proveedor secundario, verás un aviso en los logs con la cadena de intentos para facilitar el debugging.
Más ejemplos
Sección titulada «Más ejemplos»Usar solo el TTS del núcleo (sin sobrescribir):
{ messages: { tts: { provider: "openai", providers: { openai: { voice: "alloy" }, }, }, },}Sobrescribir con ElevenLabs solo para llamadas:
{ plugins: { entries: { "voice-call": { config: { tts: { provider: "elevenlabs", providers: { elevenlabs: { apiKey: "elevenlabs_key", voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }, }, }, }, },}Sobrescribir solo el modelo de OpenAI para llamadas:
{ plugins: { entries: { "voice-call": { config: { tts: { providers: { openai: { model: "gpt-4o-mini-tts", voice: "marin", }, }, }, }, }, }, },}Llamadas entrantes
Sección titulada «Llamadas entrantes»Por defecto, la política de entrada está en disabled. Para activarla, configura lo siguiente:
{ inboundPolicy: "allowlist", allowFrom: ["+15550001234"], inboundGreeting: "Hello! How can I help?",}La política allowlist filtra por el ID del llamante. Ten en cuenta que esto es un filtrado básico y no una prueba de identidad fuerte. Las respuestas automáticas usan el sistema de agentes, que puedes ajustar con responseModel y responseTimeoutMs.
Contrato de salida de voz
Sección titulada «Contrato de salida de voz»Para las respuestas automáticas, Voice Call añade una instrucción estricta al prompt del sistema:
{"spoken":"..."}
El plugin extrae el texto de forma defensiva, ignorando contenido de razonamiento o errores, y eliminando párrafos de planificación para que el usuario solo escuche lo que debe escuchar.
Comportamiento al inicio de la conversación
Sección titulada «Comportamiento al inicio de la conversación»En llamadas salientes de tipo conversation, el manejo del primer mensaje depende del estado de reproducción:
- Si el saludo inicial falla, la llamada vuelve a estado
listeningy reintenta el mensaje. - El streaming de Twilio comienza en cuanto se conecta el stream, sin retrasos extra.
Gracia por desconexión de stream en Twilio
Sección titulada «Gracia por desconexión de stream en Twilio»Si un stream de Twilio se desconecta, Voice Call espera 2000ms antes de colgar:
- Si el stream se reconecta en ese tiempo, se cancela el cierre.
- Si no hay reconexión, la llamada termina para evitar sesiones fantasma activas.
openclaw voicecall call --to "+15555550123" --message "Hello from OpenClaw"openclaw voicecall start --to "+15555550123" # alias for callopenclaw voicecall continue --call-id <id> --message "Any questions?"openclaw voicecall speak --call-id <id> --message "One moment"openclaw voicecall end --call-id <id>openclaw voicecall status --call-id <id>openclaw voicecall tailopenclaw voicecall latency # summarize turn latency from logsopenclaw voicecall expose --mode funnelEl comando latency analiza el archivo calls.jsonl. Puedes usar --last <n> para limitar el análisis a los últimos registros. Obtendrás métricas p50/p90/p99 sobre la latencia de respuesta y tiempos de espera.
Herramienta de Agente
Sección titulada «Herramienta de Agente»Nombre de la herramienta: voice_call
Acciones disponibles:
initiate_call(message, to?, mode?)continue_call(callId, message)speak_to_user(callId, message)end_call(callId)get_status(callId)
Puedes encontrar la documentación de la skill en skills/voice-call/SKILL.md.
Gateway RPC
Sección titulada «Gateway RPC»voicecall.initiate(to?,message,mode?)voicecall.continue(callId,message)voicecall.speak(callId,message)voicecall.end(callId)voicecall.status(callId)
Siguientes pasos
Sección titulada «Siguientes pasos»¿Necesitas ayuda para configurar tu proveedor de voz? Prueba nuestro AI Setup Assistant.
OpenClaw Expert
Sigues atascado?
Si esta pagina no resolvio tu caso, pregunta a OpenClaw Expert para pasos concretos.