Plugin d'appel vocal
Appels vocaux pour OpenClaw via un plugin. Prend en charge les notifications sortantes, les conversations à tours multiples, la voix en temps réel duplex intégral, la transcription en flux et les appels entrants avec des stratégies de liste d’autorisation.
Fournisseurs actuels : twilio (Programmable Voice + Media Streams),
telnyx (Call Control v2), plivo (Voice API + XML transfer + GetInput
speech), mock (dev/no network).
Quick start
Section intitulée « Quick start »Installer le plugin
Fenêtre de terminal openclaw plugins install @openclaw/voice-callFenêtre de terminal PLUGIN_SRC=./path/to/local/voice-call-pluginopenclaw plugins install "$PLUGIN_SRC"cd "$PLUGIN_SRC" && pnpm installUtilisez le package nu pour suivre la balise de version officielle actuelle. N’épinglez une version exacte que lorsque vous avez besoin d’une installation reproductible.
Redémarrez ensuite la passerelle Gateway pour que le plugin se charge.
Configurer le fournisseur et le webhook
Définissez la configuration sous
plugins.entries.voice-call.config(voir Configuration ci-dessous pour la structure complète). Au minimum :provider, les identifiants du fournisseur,fromNumber, et une URL de webhook publiquement accessible.Vérifier l'installation
Fenêtre de terminal openclaw voicecall setupLa sortie par défaut est lisible dans les journaux de chat et les terminaux. Elle vérifie l’activation du plugin, les identifiants du fournisseur, l’exposition du webhook et qu’un seul mode audio (
streamingourealtime) est actif. Utilisez--jsonpour les scripts.Smoke test
Fenêtre de terminal openclaw voicecall smokeopenclaw voicecall smoke --to "+15555550123"Les deux sont des exécutions à blanc par défaut. Ajoutez
--yespour réellement passer un court appel de notification sortant :Fenêtre de terminal openclaw voicecall smoke --to "+15555550123" --yes
Configuration
Section intitulée « Configuration »Si enabled: true mais que le fournisseur sélectionné manque d’identifiants,
le démarrage du Gateway enregistre un avertissement de configuration incomplète avec les clés manquantes et
ignore le démarrage du runtime. Les commandes, les appels RPC et les outils de l’agent
renvoient toujours la configuration exacte du fournisseur manquant lors de leur utilisation.
{ plugins: { entries: { "voice-call": { enabled: true, config: { provider: "twilio", // or "telnyx" | "plivo" | "mock" fromNumber: "+15550001234", // or TWILIO_FROM_NUMBER for Twilio toNumber: "+15550005678", sessionScope: "per-phone", // per-phone | per-call numbers: { "+15550009999": { inboundGreeting: "Silver Fox Cards, how can I help?", responseSystemPrompt: "You are a concise baseball card specialist.", tts: { providers: { openai: { voice: "alloy" }, }, }, }, },
twilio: { accountSid: "ACxxxxxxxx", authToken: "...", }, telnyx: { apiKey: "...", connectionId: "...", // Telnyx webhook public key from the Mission Control Portal // (Base64; 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 /* see Streaming transcription */ }, realtime: { enabled: false /* see Realtime voice */ }, }, }, }, },}Exposition du provider et notes de sécurité
- Twilio, Telnyx et Plivo nécessitent tous une URL de webhook publiquement accessible.
mockest un provider de développement local (pas d’appels réseau).- Telnyx nécessite
telnyx.publicKey(ouTELNYX_PUBLIC_KEY) sauf siskipSignatureVerificationest vrai. skipSignatureVerificationest destiné uniquement aux tests locaux.- Sur le niveau gratuit de ngrok, définissez
publicUrlsur l’URL ngrok exacte ; la vérification de signature est toujours appliquée. tunnel.allowNgrokFreeTierLoopbackBypass: trueautorise les webhooks Twilio avec des signatures invalides uniquement lorsquetunnel.provider="ngrok"etserve.bindsont en boucle locale (agent local ngrok). Uniquement pour le développement local.- Les URL de niveau gratuit de Ngrok peuvent changer ou ajouter un comportement interstitiel ; si
publicUrldérive, les signatures Twilio échouent. Production : préférez un domaine stable ou un entonnoir Tailscale.
Limites de connexion de streaming
streaming.preStartTimeoutMsferme les sockets qui n’envoient jamais de tramestartvalide.streaming.maxPendingConnectionslimite le total des sockets non authentifiés avant démarrage.streaming.maxPendingConnectionsPerIplimite les sockets non authentifiés avant démarrage par IP source.streaming.maxConnectionslimite le total des sockets ouverts de flux multimédia (en attente + actifs).
Migrations de configuration héritées
Les anciennes configurations utilisant provider: "log", twilio.from``streaming.* ou des clés OpenAI héritées sont réécrites par openclaw doctor --fix.
Pour l’instant, le repli d’exécution accepte toujours les anciennes clés voice-call, mais
le chemin de réécriture est openclaw doctor --fix et la shim de compatibilité est
temporaire.
Clés de diffusion en continu migrées automatiquement :
streaming.sttProvider→streaming.providerstreaming.openaiApiKey→streaming.providers.openai.apiKeystreaming.sttModel→streaming.providers.openai.modelstreaming.silenceDurationMs→streaming.providers.openai.silenceDurationMsstreaming.vadThreshold→streaming.providers.openai.vadThreshold
Portée de la session
Section intitulée « Portée de la session »Par défaut, Voice Call utilise sessionScope: "per-phone" afin que les appels répétés du même appelant conservent la mémoire de la conversation. Définissez sessionScope: "per-call" lorsque chaque appel d’opérateur doit commencer avec un contexte frais, par exemple pour la réception, la réservation, les SVI ou les flux de pont Google Meet où le même numéro de téléphone peut représenter différentes réunions.
Conversations vocales en temps réel
Section intitulée « Conversations vocales en temps réel »realtime sélectionne un fournisseur vocal temps réel full-duplex pour l’audio des appels en direct. Il est distinct de streaming, qui ne transmet l’audio qu’aux fournisseurs de transcription temps réel.
Comportement d’exécution actuel :
realtime.enabledest pris en charge pour Twilio Media Streams.realtime.providerest facultatif. S’il n’est pas défini, Voice Call utilise le premier fournisseur vocal temps réel enregistré.- Fournisseurs vocaux temps réel inclus : Google Gemini Live (
google) et OpenAI (openai), enregistrés par leurs plugins de fournisseur. - La configuration brute détenue par le fournisseur se trouve sous
realtime.providers.<providerId>. - Voice Call expose l’outil partagé
openclaw_agent_consultde temps réel par défaut. Le modèle temps réel peut l’appeler lorsque l’appelant demande un raisonnement plus approfondi, des informations actuelles ou les outils normaux d’OpenClaw. realtime.consultPolicyajoute facultativement des conseils sur le moment où le modèle temps réel doit appeleropenclaw_agent_consult.realtime.agentContext.enabledest désactivé par défaut. Lorsqu’il est activé, Voice Call injecte une identité d’agent délimitée, une substitution de prompt système et une capsule de fichier d’espace de travail sélectionnée dans les instructions du fournisseur temps réel lors de la configuration de la session.realtime.fastContext.enabledest désactivé par défaut. Lorsqu’il est activé, Voice Call recherche d’abord dans la mémoire indexée/le contexte de session pour la question de consultation et renvoie ces extraits au modèle temps réel dansrealtime.fastContext.timeoutMsavant de revenir à l’agent de consultation complet uniquement sirealtime.fastContext.fallbackToConsultest vrai.- Si
realtime.providerpointe vers un fournisseur non enregistré, ou si aucun fournisseur de voix temps réel n’est enregistré du tout, Voice Call enregistre un avertissement et ignore les médias temps réel au lieu de faire échouer l’ensemble du plugin. - Les clés de session de consultation réutilisent la session d’appel stockée lorsqu’elle est disponible, puis reviennent au
sessionScopeconfiguré (per-phonepar défaut, ouper-callpour les appels isolés).
Stratégie d’outil
Section intitulée « Stratégie d’outil »realtime.toolPolicy contrôle l’exécution de la consultation :
| Stratégie | Comportement |
|---|---|
safe-read-only | Exposez l’outil de consultation et limitez l’agent normal à read, web_search, web_fetch, x_search, memory_search et memory_get. |
owner | Exposez l’outil de consultation et laissez l’agent normal utiliser la stratégie d’outil d’agent normal. |
none | N’exposez pas l’outil de consultation. Les realtime.tools personnalisés sont toujours transmis au fournisseur temps réel. |
realtime.consultPolicy contrôle uniquement les instructions du modèle temps réel :
| Stratégie | Conseils |
|---|---|
auto | Conservez le prompt par défaut et laissez le fournisseur décider quand appeler l’outil de consultation. |
substantive | Répondez directement aux éléments de conversation simples et consultez avant les faits, la mémoire, les outils ou le contexte. |
always | Consultez avant chaque réponse substantielle. |
Contexte vocal de l’agent
Section intitulée « Contexte vocal de l’agent »Activez realtime.agentContext lorsque le pont vocal doit sonner comme l’agent OpenClaw configuré sans payer un cycle complet de consultation de l’agent lors des tours ordinaires. La capsule de contexte est ajoutée une seule fois lors de la création de la session temps réel, elle n’ajoute donc pas de latence par tour. Les appels à openclaw_agent_consult exécutent toujours l’agent OpenClaw complet et doivent être utilisés pour le travail d’outil, les informations actuelles, les recherches en mémoire ou l’état de l’espace de travail.
{ plugins: { entries: { "voice-call": { config: { agentId: "main", realtime: { enabled: true, provider: "google", toolPolicy: "safe-read-only", consultPolicy: "substantive", agentContext: { enabled: true, maxChars: 6000, includeIdentity: true, includeSystemPrompt: true, includeWorkspaceFiles: true, files: ["SOUL.md", "IDENTITY.md", "USER.md"], }, }, }, }, }, },}Exemples de fournisseurs temps réel
Section intitulée « Exemples de fournisseurs temps réel »Valeurs par défaut : clé API issue de realtime.providers.google.apiKey,
GEMINI_API_KEY, ou GOOGLE_GENERATIVE_AI_API_KEY ; modèle
gemini-2.5-flash-native-audio-preview-12-2025 ; voix Kore.
sessionResumption et contextWindowCompression sont activés par défaut pour les appels plus longs
et reconnectables. Utilisez silenceDurationMs, startSensitivity et
endSensitivity pour régler l’échange de tours plus rapide sur l’audio téléphonique.
{ plugins: { entries: { "voice-call": { config: { provider: "twilio", inboundPolicy: "allowlist", allowFrom: ["+15550005678"], realtime: { enabled: true, provider: "google", instructions: "Speak briefly. Call openclaw_agent_consult before using deeper tools.", toolPolicy: "safe-read-only", consultPolicy: "substantive", consultThinkingLevel: "low", consultFastMode: true, agentContext: { enabled: true }, providers: { google: { apiKey: "${GEMINI_API_KEY}", model: "gemini-2.5-flash-native-audio-preview-12-2025", voice: "Kore", silenceDurationMs: 500, startSensitivity: "high", }, }, }, }, }, }, },}{ plugins: { entries: { "voice-call": { config: { realtime: { enabled: true, provider: "openai", providers: { openai: { apiKey: "${OPENAI_API_KEY}" }, }, }, }, }, }, },}Voir Google provider et OpenAI provider pour les options vocales en temps réel spécifiques au fournisseur.
Transcription en continu
Section intitulée « Transcription en continu »streaming sélectionne un fournisseur de transcription en temps réel pour l’audio des appels en direct.
Comportement d’exécution actuel :
streaming.providerest facultatif. S’il n’est pas défini, Voice Call utilise le premier fournisseur de transcription en temps réel enregistré.- Fournisseurs de transcription en temps réel inclus : Deepgram (Deepgram
deepgram), ElevenLabs (elevenlabs), Mistral (mistralOpenAI), OpenAI (openai) et xAI (xai), enregistrés par leurs plugins de fournisseur. - La configuration brute propriétaire au fournisseur se trouve sous
streaming.providers.<providerId>. - Une fois que Twilio a envoyé un message de flux accepté
start, Voice Call enregistre immédiatement le flux, met en file d’attente les médias entrants via le fournisseur de transcription pendant que le fournisseur se connecte, et ne lance le message d’accueil initial qu’une fois la transcription en temps réel prête. - Si
streaming.providerpointe vers un fournisseur non enregistré, ou si aucun n’est enregistré, Voice Call enregistre un avertissement et ignore le streaming média au lieu de faire échouer l’ensemble du plugin.
Exemples de fournisseurs de streaming
Section intitulée « Exemples de fournisseurs de streaming »Valeurs par défaut : clé API streaming.providers.openai.apiKey ou
OPENAI_API_KEY ; model gpt-4o-transcribe ; silenceDurationMs: 800 ;
vadThreshold: 0.5.
{ plugins: { entries: { "voice-call": { config: { streaming: { enabled: true, provider: "openai", streamPath: "/voice/stream", providers: { openai: { apiKey: "sk-...", // optional if OPENAI_API_KEY is set model: "gpt-4o-transcribe", silenceDurationMs: 800, vadThreshold: 0.5, }, }, }, }, }, }, },}Valeurs par défaut : clé API streaming.providers.xai.apiKey ou XAI_API_KEY ;
endpoint wss://api.x.ai/v1/stt ; encodage mulaw ; taux d’échantillonnage 8000 ;
endpointingMs: 800 ; interimResults: true.
{ plugins: { entries: { "voice-call": { config: { streaming: { enabled: true, provider: "xai", streamPath: "/voice/stream", providers: { xai: { apiKey: "${XAI_API_KEY}", // optional if XAI_API_KEY is set endpointingMs: 800, language: "en", }, }, }, }, }, }, },}TTS pour les appels
Section intitulée « TTS pour les appels »Voice Call utilise la configuration principale messages.tts pour la synthèse vocale en continu lors des appels. Vous pouvez la remplacer sous la configuration du plugin avec la même structure — elle fusionne en profondeur avec messages.tts.
{ tts: { provider: "elevenlabs", providers: { elevenlabs: { voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, },}Notes de comportement :
- Les clés
tts.<provider>héritées dans la configuration du plugin (openai,elevenlabs,microsoft,edge) sont réparées paropenclaw doctor --fix; la configuration validée doit utilisertts.providers.<provider>. - Le TTS Core est utilisé lorsque le streaming média Twilio est activé ; sinon, les appels reviennent aux voix natives du provider.
- Si un flux média Twilio est déjà actif, Voice Call ne revient pas au TwiML
<Say>. Si le TTS téléphonique n’est pas disponible dans cet état, la demande de lecture échoue au lieu de mélanger deux chemins de lecture. - Lorsque le TTS téléphonique revient à un provider secondaire, Voice Call enregistre un avertissement avec la chaîne de providers (
from,to,attempts) pour le débogage. - Lorsque l’interruption Twilio ou l’arrêt du flux vide la file d’attente TTS en attente, les demandes de lecture en file d’attente se règlent au lieu de mettre en attente les appelants en attendant la fin de la lecture.
Exemples TTS
Section intitulée « Exemples TTS »{ messages: { tts: { provider: "openai", providers: { openai: { voice: "alloy" }, }, }, },}{ plugins: { entries: { "voice-call": { config: { tts: { provider: "elevenlabs", providers: { elevenlabs: { apiKey: "elevenlabs_key", voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }, }, }, }, },}{ plugins: { entries: { "voice-call": { config: { tts: { providers: { openai: { model: "gpt-4o-mini-tts", voice: "marin", }, }, }, }, }, }, },}Appels entrants
Section intitulée « Appels entrants »La stratégie entrante par défaut est disabled. Pour activer les appels entrants, définissez :
{ inboundPolicy: "allowlist", allowFrom: ["+15550001234"], inboundGreeting: "Hello! How can I help?",}Les réponses automatiques utilisent le système d’agent. Ajustez avec responseModel,
responseSystemPrompt et responseTimeoutMs.
Routage par numéro
Section intitulée « Routage par numéro »Utilisez numbers lorsqu’un seul plugin Voice Call reçoit des appels pour plusieurs numéros de téléphone et que chaque numéro doit se comporter comme une ligne différente. Par exemple, un numéro peut utiliser un assistant personnel décontracté tandis qu’un autre utilise une persona professionnelle, un agent de réponse différent et une voix TTS différente.
Les itinéraires sont sélectionnés à partir du numéro composé To fourni par le provider. Les clés doivent être des numéros E.164. Lorsqu’un appel arrive, Voice Call résout l’itinéraire correspondant une seule fois, stocke l’itinéraire correspondant sur l’enregistrement de l’appel et réutilise cette configuration effective pour le message d’accueil, le chemin de réponse automatique classique, le chemin de consultation en temps réel et la lecture TTS. Si aucun itinéraire ne correspond, la configuration globale Voice Call est utilisée. Les appels sortants n’utilisent pas numbers ; transmettez la cible sortante, le message et la session explicitement lors de l’initiation de l’appel.
Les remplacements d’itinéraire prennent actuellement en charge :
inboundGreetingttsagentIdresponseModelresponseSystemPromptresponseTimeoutMs
La valeur d’itinéraire tts fusionne en profondeur avec la configuration tts globale de Voice Call, vous pouvez donc généralement remplacer uniquement la voix du provider :
{ inboundGreeting: "Hello from the main line.", responseSystemPrompt: "You are the default voice assistant.", tts: { provider: "openai", providers: { openai: { voice: "coral" }, }, }, numbers: { "+15550001111": { inboundGreeting: "Silver Fox Cards, how can I help?", responseSystemPrompt: "You are a concise baseball card specialist.", tts: { providers: { openai: { voice: "alloy" }, }, }, }, },}Contrat de sortie vocale
Section intitulée « Contrat de sortie vocale »Pour les réponses automatiques, Voice Call ajoute un contrat de sortie vocale strict au prompt système :
{"spoken":"..."}Voice Call extrait le texte de la parole de manière défensive :
- Ignore les charges utiles marquées comme contenu de raisonnement/erreur.
- Analyse le JSON direct, le JSON clôturé ou les clés
"spoken"en ligne. - Revient au texte brut et supprime les paragraphes d’introduction probables de planification/métadonnées.
Cela permet de maintenir la lecture vocale concentrée sur le texte destiné à l’appelant et d’éviter la fuite de texte de planification dans l’audio.
Comportement de démarrage de la conversation
Section intitulée « Comportement de démarrage de la conversation »Pour les appels conversation sortants, la gestion du premier message est liée à l’état de lecture en direct :
- Le vidage de la file d’attente et la réponse automatique en cas de coupure sont supprimés uniquement pendant que le message d’accueil initial parle activement.
- Si la lecture initiale échoue, l’appel revient à
listeninget le message initial reste en file d’attente pour une nouvelle tentative. - La lecture initiale pour le streaming Twilio commence lors de la connexion du flux sans délai supplémentaire.
- L’interrution (barge-in) interrompt la lecture active et efface les entrées TTS Twilio mises en file d’attente mais pas encore lues. Les entrées effacées sont résolues comme étant ignorées, ce qui permet à la logique de réponse de suite de continuer sans attendre l’audio qui ne sera jamais diffusé.
- Les conversations vocales en temps réel utilisent le tour d’ouverture propre au flux temps réel. Voice Call ne publie pas de mise à jour
<Say>TwiML héritée pour ce message initial, les sessions<Connect><Stream>sortantes restent donc attachées.
Délai de grâce de déconnexion du flux Twilio
Section intitulée « Délai de grâce de déconnexion du flux Twilio »Lorsqu’un flux média Twilio se déconnecte, Voice Call attend 2000 ms avant de mettre fin automatiquement à l’appel :
- Si le flux se reconnecte pendant cette fenêtre, la fin automatique est annulée.
- Si aucun flux ne s’enregistre à nouveau après la période de grâce, l’appel est terminé pour éviter d’avoir des appels actifs bloqués.
Nettoyeur d’appels périmés
Section intitulée « Nettoyeur d’appels périmés »Utilisez staleCallReaperSeconds pour terminer les appels qui ne reçoivent jamais de webhook terminal (par exemple, les appels en mode notification qui ne se terminent jamais). La valeur par défaut est 0 (désactivé).
Plages recommandées :
- Production :
120–300secondes pour les flux de type notification. - Gardez cette valeur supérieure à
maxDurationSecondsafin que les appels normaux puissent se terminer. Un bon point de départ estmaxDurationSeconds + 30–60secondes.
{ plugins: { entries: { "voice-call": { config: { maxDurationSeconds: 300, staleCallReaperSeconds: 360, }, }, }, },}Sécurité des webhooks
Section intitulée « Sécurité des webhooks »Lorsqu’un proxy ou un tunnel est placé devant le Gateway, le plugin reconstruit l’URL publique pour la vérification de signature. Ces options contrôlent quels en-têtes transférés sont fiables :
Protections supplémentaires :
- La protection contre la répétition (replay protection) des webhooks est activée pour Twilio et Plivo. Les demandes de webhook valides répétées sont accusées réception mais ignorées pour leurs effets secondaires.
- Les tours de conversation Twilio incluent un jeton par tour dans les rappels
<Gather>, de sorte que les rappels vocaux périmés/répétés ne peuvent pas satisfaire un tour de transcription en attente plus récent. - Les requêtes webhook non authentifiées sont rejetées avant la lecture du corps lorsque les en-têtes de signature requis par le fournisseur sont manquants.
- Le webhook d’appel vocal utilise le profil de corps de pré-authentification partagé (64 Ko / 5 secondes) plus une limite en vol par adresse IP avant la vérification de signature.
Exemple avec un hôte public stable :
{ plugins: { entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", webhookSecurity: { allowedHosts: ["voice.example.com"], }, }, }, }, },}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 dtmf --call-id <id> --digits "ww123456#"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 funnelLorsque le Gateway est déjà en cours d’exécution, les commandes opérationnelles voicecall délèguent
au runtime d’appel vocal propriétaire du Gateway de sorte que le CLI ne lie pas un second
serveur webhook. Si aucun Gateway n’est joignable, les commandes reviennent à un
runtime autonome CLI.
latency lit calls.jsonl à partir du chemin de stockage d’appel vocal par défaut.
Utilisez --file <path> pour pointer vers un journal différent et --last <n> pour limiter
l’analyse aux N derniers enregistrements (par défaut 200). La sortie inclut p50/p90/p99
pour la latence de tour et les temps d’écoute-attente.
Outil de l’agent
Section intitulée « Outil de l’agent »Nom de l’outil : voice_call.
| Action | Args |
|---|---|
initiate_call | message, to?, mode?, dtmfSequence? |
continue_call | callId, message |
speak_to_user | callId, message |
send_dtmf | callId, digits |
end_call | callId |
get_status | callId |
Ce dépôt fournit un document de compétence correspondant à skills/voice-call/SKILL.md.
Gateway RPC
Section intitulée « Gateway RPC »| Méthode | Args |
|---|---|
voicecall.initiate | to?, message, mode?, dtmfSequence? |
voicecall.continue | callId, message |
voicecall.speak | callId, message |
voicecall.dtmf | callId, digits |
voicecall.end | callId |
voicecall.status | callId |
dtmfSequence n’est valide qu’avec mode: "conversation". Les appels en mode de notification
devraient utiliser voicecall.dtmf après que l’appel existe s’ils ont besoin de chiffres
après connexion.
Dépannage
Section intitulée « Dépannage »L’échec de la configuration expose le webhook
Section intitulée « L’échec de la configuration expose le webhook »Exécutez la configuration à partir du même environnement que celui qui exécute le Gateway :
openclaw voicecall setupopenclaw voicecall setup --jsonPour twilio, telnyx et plivo, webhook-exposure doit être vert. Un
publicUrl configur échoue toujours lorsqu’il pointe vers un espace réseau local
ou privé, car le transporteur ne peut pas rappeler ces adresses. N’utilisez pas
localhost, 127.0.0.1, 0.0.0.0, 10.x, 172.16.x-172.31.x,
192.168.x, 169.254.x, fc00::/7 ou fd00::/8 comme publicUrl.
Les appels sortants en mode de notification Twilio envoient leur <Say> TwiML initial
directement dans la requête de création d’appel, de sorte que le premier message vocal ne d pas
de Twilio r cup rant le TwiML du webhook. Un webhook public est toujours requis pour les rappels
de statut, les appels de conversation, le DTMF pr -connexion, les flux en temps réel et le contrôle
d’appel post-connexion.
Utilisez un chemin d’exposition public :
{ plugins: { entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", // or tunnel: { provider: "ngrok" }, // or tailscale: { mode: "funnel", path: "/voice/webhook" }, }, }, }, },}Apr avoir modifi la configuration, red marrez ou rechargez le Gateway, puis ex cutez :
openclaw voicecall setupopenclaw voicecall smokevoicecall smoke est un essai vide (dry run) sauf si vous passez --yes.
Échec des informations d’identification du fournisseur
Section intitulée « Échec des informations d’identification du fournisseur »Vérifiez le fournisseur s lectionn et les champs d’identification requis :
- Twilio :
twilio.accountSid,twilio.authTokenetfromNumber, ouTWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKENetTWILIO_FROM_NUMBER. - Telnyx :
telnyx.apiKey,telnyx.connectionId,telnyx.publicKeyetfromNumber. - Plivo :
plivo.authId,plivo.authTokenetfromNumber.
Les identifiants doivent exister sur l’hôte du Gateway. La modification d’un profil de shell local n’a pas d’effet sur un Gateway déjà en cours d’exécution jusqu’à ce qu’il redémarre ou recharge son environnement.
Les appels commencent mais les webhooks du provider n’arrivent pas
Section intitulée « Les appels commencent mais les webhooks du provider n’arrivent pas »Confirmez que la console du provider pointe vers l’URL publique exacte du webhook :
https://voice.example.com/voice/webhookEnsuite, inspectez l’état d’exécution :
openclaw voicecall status --call-id <id>openclaw voicecall tailopenclaw logs --followCauses courantes :
publicUrlpointe vers un chemin différent deserve.path.- L’URL du tunnel a changé après le démarrage du Gateway.
- Un proxy transmet la demande mais supprime ou réécrit les en-têtes hôte/proto.
- Un pare-feu ou un DNS achemine le nom d’hôte public ailleurs que vers le Gateway.
- Le Gateway a été redémarré sans que le plugin Voice Call soit activé.
Lorsqu’un proxy inverse ou un tunnel est devant le Gateway, définissez
webhookSecurity.allowedHosts sur le nom d’hôte public, ou utilisez
webhookSecurity.trustedProxyIPs pour une adresse proxy connue. N’utilisez
webhookSecurity.trustForwardingHeaders que lorsque la limite du proxy est sous
votre contrôle.
La vérification de la signature échoue
Section intitulée « La vérification de la signature échoue »Les signatures du provider sont vérifiées par rapport à l’URL publique que OpenClaw reconstruit à partir de la demande entrante. Si les signatures échouent :
- Confirmez que l’URL du webhook du provider correspond exactement à
publicUrl, y compris le schéma, l’hôte et le chemin. - Pour les URL ngrok de niveau gratuit, mettez à jour
publicUrllorsque le nom d’hôte du tunnel change. - Assurez-vous que le proxy préserve les en-tètres hôte et proto d’origine, ou configurez
webhookSecurity.allowedHosts. - N’activez pas
skipSignatureVerificationen dehors des tests locaux.
Les jointures Google Meet Twilio échouent
Section intitulée « Les jointures Google Meet Twilio échouent »Google Meet utilise ce plugin pour les connexions Twilio par entrée d’appel. Vérifiez d’abord Voice Call :
openclaw voicecall setupopenclaw voicecall smoke --to "+15555550123"Vérifiez ensuite explicitement le transport Google Meet :
openclaw googlemeet setup --transport twilioSi Voice Call est vert mais que le participant Meet ne rejoint jamais, vérifiez le numéro d’appel Meet, le code PIN et --dtmf-sequence. L’appel téléphonique peut être sain alors que la réunion rejette ou ignore une séquence DTMF incorrecte.
Google Meet lance la phase téléphonique Twilio via voicecall.start avec une séquence DTMF de pré-connexion. Les séquences dérivées du code PIN incluent voiceCall.dtmfDelayMs du plugin Google Meet comme premiers chiffres d’attente Twilio. La valeur par défaut est de 12 secondes car les invites d’appel Meet peuvent arriver tardivement. Voice Call redirige ensuite vers le traitement en temps réel avant que la salutation d’introduction ne soit demandée.
Utilisez openclaw logs --follow pour la trace de phase en direct. Une jointure Meet Twilio saine enregistre cet ordre :
- Google Meet délègue la jointure Twilio à Voice Call.
- Voice Call stocke le TwiML DTMF de pré-connexion.
- Le TwiML initial Twilio est consommé et servi avant le traitement en temps réel.
- Voice Call sert le TwiML en temps réel pour l’appel Twilio.
- Google Meet demande le discours d’introduction avec
voicecall.speakaprès le délai post-DTMF.
openclaw voicecall tail affiche toujours les enregistrements d’appels persistants ; il est utile pour l’état de l’appel et les transcriptions, mais chaque transition webhook/temps réel n’y apparaît pas.
L’appel en temps réel n’a pas de parole
Section intitulée « L’appel en temps réel n’a pas de parole »Confirmez qu’un seul mode audio est activé. realtime.enabled et streaming.enabled ne peuvent pas tous deux être vrais.
Pour les appels Twilio en temps réel, vérifiez également :
- Un plugin de provider en temps réel est chargé et enregistré.
realtime.providerest non défini ou nomme un provider enregistré.- La clé API du provider est disponible pour le processus Gateway.
openclaw logs --followmontre le TwiML en temps réel servi, le pont en temps réel démarré et la salutation initiale mise en file d’attente.