Voice Call (plugin)
Chiamate vocali per Mayros tramite plugin. Supporta notifiche in uscita e conversazioni multi-turno con policy in entrata.
Provider attuali:
twilio(Programmable Voice + Media Streams)telnyx(Call Control v2)plivo(Voice API + trasferimento XML + speech GetInput)mock(dev/nessuna rete)
Modello mentale rapido:
- Installa plugin
- Riavvia Gateway
- Configura in
plugins.entries.voice-call.config - Usa
mayros voicecall ...o lo strumentovoice_call
Dove gira (locale vs remoto)
Il plugin Voice Call gira dentro il processo Gateway.
Se usi un Gateway remoto, installa/configura il plugin sulla macchina che esegue il Gateway, poi riavvia il Gateway per caricarlo.
Installazione
Opzione A: installa da npm (consigliato)
bashmayros plugins install @apilium/mayros-voice-call
Riavvia il Gateway dopo.
Opzione B: installa da una cartella locale (dev, senza copia)
bashmayros plugins install ./extensions/voice-call cd ./extensions/voice-call && pnpm install
Riavvia il Gateway dopo.
Configurazione
Imposta la configurazione in plugins.entries.voice-call.config:
json5{ plugins: { entries: { "voice-call": { enabled: true, config: { provider: "twilio", // o "telnyx" | "plivo" | "mock" fromNumber: "+15550001234", toNumber: "+15550005678", twilio: { accountSid: "ACxxxxxxxx", authToken: "...", }, telnyx: { apiKey: "...", connectionId: "...", // Chiave pubblica webhook Telnyx dal Mission Control Portal Telnyx // (stringa Base64; può anche essere impostata via TELNYX_PUBLIC_KEY). publicKey: "...", }, plivo: { authId: "MAxxxxxxxxxxxxxxxxxxxx", authToken: "...", }, // Server webhook serve: { port: 3334, path: "/voice/webhook", }, // Sicurezza webhook (consigliato per tunnel/proxy) webhookSecurity: { allowedHosts: ["voice.example.com"], trustedProxyIPs: ["100.64.0.1"], }, // Esposizione pubblica (scegline una) // 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", }, }, }, }, }, }
Note:
- Twilio/Telnyx richiedono un URL webhook raggiungibile pubblicamente.
- Plivo richiede un URL webhook raggiungibile pubblicamente.
mockè un provider dev locale (nessuna chiamata rete).- Telnyx richiede
telnyx.publicKey(oTELNYX_PUBLIC_KEY) a meno cheskipSignatureVerificationnon sia true. skipSignatureVerificationè solo per test locali.- Se usi ngrok tier gratuito, imposta
publicUrlall'URL ngrok esatto; la verifica firma è sempre applicata. tunnel.allowNgrokFreeTierLoopbackBypass: truepermette webhook Twilio con firme non valide solo quandotunnel.provider="ngrok"eserve.bindè loopback (agente locale ngrok). Usa solo per dev locale.- Gli URL ngrok tier gratuito possono cambiare o aggiungere comportamento interstitial; se
publicUrlderiva, le firme Twilio falliranno. Per produzione, preferisci un dominio stabile o Tailscale funnel.
Reaper chiamate stantie
Usa staleCallReaperSeconds per terminare chiamate che non ricevono mai un webhook terminale (es. chiamate modalità notify che non si completano mai). Il default è 0 (disabilitato).
Range consigliati:
- Produzione:
120–300secondi per flussi stile notify. - Mantieni questo valore più alto di
maxDurationSecondscosì le chiamate normali possono finire. Un buon punto di partenza èmaxDurationSeconds + 30–60secondi.
Esempio:
json5{ plugins: { entries: { "voice-call": { config: { maxDurationSeconds: 300, staleCallReaperSeconds: 360, }, }, }, }, }
Sicurezza Webhook
Quando un proxy o tunnel sta davanti al Gateway, il plugin ricostruisce l'URL pubblico per la verifica firma. Queste opzioni controllano quali header inoltrati sono fidati.
webhookSecurity.allowedHosts allowlist host da header inoltro.
webhookSecurity.trustForwardingHeaders fida header inoltrati senza allowlist.
webhookSecurity.trustedProxyIPs fida solo header inoltrati quando l'IP remoto richiesta corrisponde alla lista.
Esempio con host pubblico stabile:
json5{ plugins: { entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", webhookSecurity: { allowedHosts: ["voice.example.com"], }, }, }, }, }, }
TTS per chiamate
Voice Call usa la configurazione core messages.tts (OpenAI o ElevenLabs) per speech streaming sulle chiamate. Puoi sovrascriverla nella configurazione plugin con la stessa forma — si fonde in profondità con messages.tts.
json5{ tts: { provider: "elevenlabs", elevenlabs: { voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }
Note:
- Edge TTS è ignorato per chiamate vocali (l'audio telefonia necessita PCM; output Edge è inaffidabile).
- Il TTS core è usato quando lo streaming media Twilio è abilitato; altrimenti le chiamate fallback a voci native provider.
Altri esempi
Usa solo TTS core (nessun override):
json5{ messages: { tts: { provider: "openai", openai: { voice: "alloy" }, }, }, }
Override a ElevenLabs solo per chiamate (mantieni default core altrove):
json5{ plugins: { entries: { "voice-call": { config: { tts: { provider: "elevenlabs", elevenlabs: { apiKey: "elevenlabs_key", voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }, }, }, }, }
Override solo il modello OpenAI per chiamate (esempio deep-merge):
json5{ plugins: { entries: { "voice-call": { config: { tts: { openai: { model: "gpt-4o-mini-tts", voice: "marin", }, }, }, }, }, }, }
Chiamate in entrata
La policy in entrata è disabled per default. Per abilitare chiamate in entrata, imposta:
json5{ inboundPolicy: "allowlist", allowFrom: ["+15550001234"], inboundGreeting: "Ciao! Come posso aiutarti?", }
Le risposte automatiche usano il sistema agente. Regola con:
responseModelresponseSystemPromptresponseTimeoutMs
CLI
bashmayros voicecall call --to "+15555550123" --message "Ciao da Mayros" mayros voicecall continue --call-id <id> --message "Domande?" mayros voicecall speak --call-id <id> --message "Un momento" mayros voicecall end --call-id <id> mayros voicecall status --call-id <id> mayros voicecall tail mayros voicecall expose --mode funnel
Strumento agente
Nome strumento: voice_call
Azioni:
initiate_call(message, to?, mode?)continue_call(callId, message)speak_to_user(callId, message)end_call(callId)get_status(callId)
Questo repo fornisce una documentazione skill corrispondente in skills/voice-call/SKILL.md.
RPC Gateway
voicecall.initiate(to?,message,mode?)voicecall.continue(callId,message)voicecall.speak(callId,message)voicecall.end(callId)voicecall.status(callId)