Plugin guides
Spraakoproepplugin
Spraakoproepen voor OpenClaw via een plugin: uitgaande meldingen, gesprekken met meerdere beurten, full-duplex realtime spraak, streaming transcriptie en inkomende oproepen met beleid op basis van toelatingslijsten.
Providers: mock (ontwikkeling, geen netwerk), plivo (Voice API + XML-overdracht +
GetInput-spraak), telnyx (Call Control v2), twilio (Programmable Voice +
Media Streams).
Snel aan de slag
Installeer de plugin
Van npm
openclaw plugins install @openclaw/voice-callVanuit een lokale map (ontwikkeling)
PLUGIN_SRC=./path/to/local/voice-call-pluginopenclaw plugins install "$PLUGIN_SRC"cd "$PLUGIN_SRC" && pnpm installGebruik het kale pakket om de huidige releasetag te volgen. Zet alleen een exacte versie vast wanneer je een reproduceerbare installatie nodig hebt. Start daarna de Gateway opnieuw zodat de plugin wordt geladen.
Configureer provider en webhook
Stel de configuratie in onder plugins.entries.voice-call.config (zie
Configuratie hieronder). Minimaal vereist: provider,
providerreferenties, fromNumber en een openbaar bereikbare webhook-URL.
Controleer de configuratie
openclaw voicecall setupopenclaw voicecall setup --jsonControleert of de plugin is ingeschakeld, de providerreferenties, de
bereikbaarheid van de webhook en of slechts één audiomodus
(streaming of realtime) actief is.
Voer een rooktest uit
openclaw voicecall smokeopenclaw voicecall smoke --to "+15555550123"Beide zijn standaard proefruns. Voeg --yes toe om een korte
uitgaande meldingsoproep te plaatsen:
openclaw voicecall smoke --to "+15555550123" --yesConfiguratie
Als enabled: true maar de geselecteerde provider geen referenties heeft,
registreert het opstarten van de Gateway een waarschuwing dat de configuratie
onvolledig is, met de ontbrekende sleutels, en wordt de runtime niet gestart.
Opdrachten, RPC-aanroepen en agenttools retourneren bij gebruik nog steeds de
exact ontbrekende configuratie.
{ plugins: { entries: { "voice-call": { enabled: true, config: { provider: "twilio", // of "telnyx" | "plivo" | "mock" fromNumber: "+15550001234", // of TWILIO_FROM_NUMBER voor Twilio toNumber: "+15550005678", sessionScope: "per-phone", // per-phone | per-call numbers: { "+15550009999": { inboundGreeting: "Silver Fox Cards, hoe kan ik helpen?", responseSystemPrompt: "Je bent een beknopte specialist in honkbalkaarten.", tts: { providers: { openai: { speakerVoice: "alloy" }, }, }, }, }, twilio: { accountSid: "ACxxxxxxxx", authToken: "...", // region: "ie1", // optioneel: us1 | ie1 | au1; standaard us1 }, telnyx: { apiKey: "...", connectionId: "...", // Openbare sleutel voor Telnyx-webhooks uit het Mission Control Portal // (Base64; kan ook via TELNYX_PUBLIC_KEY worden ingesteld). publicKey: "...", }, plivo: { authId: "MAxxxxxxxxxxxxxxxxxxxx", authToken: "...", }, // Webhookserver serve: { port: 3334, path: "/voice/webhook", }, // Webhookbeveiliging (aanbevolen voor tunnels/proxy's) webhookSecurity: { allowedHosts: ["voice.example.com"], trustedProxyIPs: ["100.64.0.1"], }, // Openbare beschikbaarstelling (kies er één) // publicUrl: "https://example.ngrok.app/voice/webhook", // tunnel: { provider: "ngrok" }, // tailscale: { mode: "funnel", path: "/voice/webhook" }, outbound: { defaultMode: "notify", // notify | conversation }, streaming: { enabled: true /* alleen Twilio; zie Streaming transcriptie */ }, realtime: { enabled: false /* zie Realtime spraakgesprekken */ }, }, }, }, },}Configuratiereferentie
Sleutels op het hoogste niveau onder plugins.entries.voice-call.config die hierboven niet worden weergegeven:
| Sleutel | Standaard | Opmerkingen |
|---|---|---|
enabled |
false |
Hoofdschakelaar voor aan/uit. |
inboundPolicy |
"disabled" |
disabled | allowlist | pairing | open. Zie Inkomende oproepen. |
allowFrom |
[] |
E.164-toelatingslijst voor inboundPolicy: "allowlist". |
maxDurationSeconds |
300 |
Harde maximale duur per oproep, ongeacht of de oproep is beantwoord. |
staleCallReaperSeconds |
120 |
Zie Opruimer voor verouderde oproepen. 0 schakelt deze uit. |
silenceTimeoutMs |
800 |
Detectie van stilte aan het einde van spraak voor de klassieke (niet-realtime) flow. |
transcriptTimeoutMs |
180000 |
Maximale wachttijd op een transcript van de beller voordat een beurt wordt opgegeven. |
ringTimeoutMs |
30000 |
Time-out voor overgaan bij uitgaande oproepen. |
maxConcurrentCalls |
1 |
Uitgaande oproepen boven deze limiet worden geweigerd. |
outbound.notifyHangupDelaySec |
3 |
Aantal seconden na TTS voordat in meldingsmodus automatisch wordt opgehangen. |
skipSignatureVerification |
false |
Alleen voor lokaal testen; nooit inschakelen in productie. |
store |
niet ingesteld | Overschrijft het standaardpad $OPENCLAW_STATE_DIR/voice-calls (normaal ~/.openclaw/voice-calls). |
agentId |
"main" |
Agent die wordt gebruikt voor het genereren van antwoorden en de opslag van sessies. |
responseModel |
niet ingesteld | Overschrijft het standaardmodel voor klassieke (niet-realtime) antwoorden. |
responseSystemPrompt |
gegenereerd | Aangepaste systeemprompt voor klassieke antwoorden. |
responseTimeoutMs |
30000 |
Time-out voor het genereren van klassieke antwoorden (ms). |
Twilio gebruikt standaard het Amerikaanse US1 REST-eindpunt. Om oproepen in
een ondersteunde niet-Amerikaanse regio te verwerken, stel je twilio.region
in op ie1 of au1 en gebruik je referenties uit die
regio. Zie
Twilio's handleiding voor de niet-Amerikaanse REST API.
Opmerkingen over beschikbaarstelling en beveiliging van providers
- Twilio, Telnyx en Plivo vereisen allemaal een openbaar bereikbare webhook-URL.
mockis een lokale ontwikkelprovider (geen netwerkaanroepen).- Telnyx vereist
telnyx.publicKey(ofTELNYX_PUBLIC_KEY), tenzijskipSignatureVerificationwaar is. skipSignatureVerificationis alleen bedoeld voor lokaal testen.- Stel bij de gratis laag van ngrok
publicUrlin op de exacte ngrok-URL; handtekeningverificatie wordt altijd afgedwongen. tunnel.allowNgrokFreeTierLoopbackBypass: truestaat Twilio-webhooks met ongeldige handtekeningen alleen toe wanneertunnel.provider="ngrok"enserve.bindloopback is (lokale ngrok-agent). Alleen voor lokale ontwikkeling.- URL's van de gratis ngrok-laag kunnen wijzigen of interstitialgedrag toevoegen; als
publicUrlafwijkt, mislukken Twilio-handtekeningen. Productie: geef de voorkeur aan een stabiel domein of een Tailscale-funnel.
Limieten voor streamingverbindingen
streaming.preStartTimeoutMs(standaard5000) sluit sockets die nooit een geldigstart-frame verzenden.streaming.maxPendingConnections(standaard32) beperkt het totale aantal niet-geverifieerde sockets vóór de start.streaming.maxPendingConnectionsPerIp(standaard4) beperkt niet-geverifieerde sockets vóór de start per bron-IP.streaming.maxConnections(standaard128) beperkt alle open mediastreamsockets (wachtend + actief).
Migraties van verouderde configuratie
Bij het verwerken van de configuratie worden deze verouderde sleutels
automatisch genormaliseerd en wordt een waarschuwing met het vervangende
pad geregistreerd; de compatibiliteitslaag wordt in een toekomstige
release verwijderd (2026.6.0), dus voer openclaw doctor --fix uit om
vastgelegde configuratie naar de canonieke vorm te herschrijven:
provider: "log"→provider: "mock"twilio.from→fromNumberstreaming.sttProvider→streaming.providerstreaming.openaiApiKey→streaming.providers.openai.apiKeystreaming.sttModel→streaming.providers.openai.modelstreaming.silenceDurationMs→streaming.providers.openai.silenceDurationMsstreaming.vadThreshold→streaming.providers.openai.vadThresholdrealtime.agentContext.includeSystemPromptis verwijderd (realtimecontext gebruikt nu de gegenereerde agentprompt)
Sessiebereik
Voice Call gebruikt standaard sessionScope: "per-phone", zodat herhaalde oproepen
van dezelfde beller het gespreksgeheugen behouden. Stel sessionScope: "per-call" in
wanneer elke carrieroproep met nieuwe context moet beginnen, bijvoorbeeld voor
receptie-, boekings-, IVR- of Google Meet-bridgeflows waarbij hetzelfde
telefoonnummer verschillende vergaderingen kan vertegenwoordigen.
Voice Call slaat gegenereerde sessiesleutels op onder de geconfigureerde
agentnaamruimte (agent:<agentId>:voice:*). Expliciete onbewerkte integratiesleutels
worden naar dezelfde naamruimte omgezet: een canonieke agent:<configuredAgentId>:*-sleutel
behoudt die eigenaar en respecteert de kernaliasing voor
session.mainKey/globaal bereik; vreemde of onjuist gevormde
agent:*-invoer krijgt als opake sleutel een bereik onder de
geconfigureerde agent; global en unknown blijven globale
sentinels.
Realtime spraakgesprekken
realtime selecteert een full-duplex realtime spraakprovider voor live
oproepaudio. Dit staat los van streaming, dat audio alleen doorstuurt
naar providers voor realtime transcriptie.
Huidig runtimegedrag:
realtime.enabledwordt ondersteund voor Twilio en Telnyx.realtime.provideris optioneel. Als dit niet is ingesteld, gebruikt Voice Call de eerste geregistreerde realtime-spraakprovider.- Gebundelde realtime-spraakproviders: Google Gemini Live (
google) en OpenAI (openai), geregistreerd door hun providerplugins. - Door de provider beheerde onbewerkte configuratie staat onder
realtime.providers.<providerId>. - Voice Call stelt standaard de gedeelde realtime-tool
openclaw_agent_consultbeschikbaar. Het realtime-model kan deze aanroepen wanneer de beller om diepgaandere redenering, actuele informatie of normale OpenClaw-tools vraagt. realtime.consultPolicyvoegt optioneel richtlijnen toe voor wanneer het realtime-modelopenclaw_agent_consultmoet aanroepen.realtime.agentContext.enabledis standaard uitgeschakeld. Wanneer dit is ingeschakeld, voegt Voice Call tijdens het instellen van de sessie een begrensde agentidentiteit en een geselecteerde capsule met werkruimtebestanden toe aan de instructies voor de realtime-provider.realtime.fastContext.enabledis standaard uitgeschakeld. Wanneer dit is ingeschakeld, doorzoekt Voice Call eerst de geïndexeerde geheugen-/sessiecontext voor de consultatievraag en retourneert die fragmenten binnenrealtime.fastContext.timeoutMsaan het realtime-model, voordat alleen op de volledige consultatieagent wordt teruggevallen alsrealtime.fastContext.fallbackToConsultwaar is.- Als
realtime.providernaar een niet-geregistreerde provider verwijst, of er helemaal geen realtime-spraakprovider is geregistreerd, registreert Voice Call een waarschuwing en slaat het realtime-media over in plaats van de hele plugin te laten mislukken. inboundPolicymag niet"disabled"zijn wanneerrealtime.enabledwaar is;validateProviderConfigwijst die combinatie af.- Consultatiesessiesleutels gebruiken waar mogelijk de opgeslagen oproepsessie opnieuw en vallen daarna terug op de geconfigureerde
sessionScope(standaardper-phone, ofper-callvoor geïsoleerde oproepen).
Toolbeleid
realtime.toolPolicy beheert de consultatierun:
| Beleid | Gedrag |
|---|---|
safe-read-only |
Stel de consultatietool beschikbaar en beperk de reguliere agent tot read, web_search, web_fetch, x_search, memory_search en memory_get. |
owner |
Stel de consultatietool beschikbaar en laat de reguliere agent het normale agenttoolbeleid gebruiken. |
none |
Stel de consultatietool niet beschikbaar. Aangepaste realtime.tools worden nog steeds doorgegeven aan de realtime-provider. |
realtime.consultPolicy beheert alleen de instructies voor het realtime-model:
| Beleid | Richtlijn |
|---|---|
auto |
Behoud de standaardprompt en laat de provider bepalen wanneer de consultatietool wordt aangeroepen. |
substantive |
Beantwoord eenvoudige verbindende gesprekszinnen rechtstreeks en consulteer vóór feiten, geheugen, tools of context. |
always |
Consulteer vóór elk inhoudelijk antwoord. |
Spraakcontext van de agent
Schakel realtime.agentContext in wanneer de spraakbrug moet klinken als de
geconfigureerde OpenClaw-agent zonder voor gewone beurten een volledige
heen-en-terugoproep naar de consultatieagent uit te voeren. De contextcapsule
wordt eenmaal toegevoegd wanneer de realtime-sessie wordt gemaakt en voegt
dus geen latentie per beurt toe. Aanroepen van openclaw_agent_consult voeren nog
steeds de volledige OpenClaw-agent uit en moeten worden gebruikt voor
toolwerk, actuele informatie, geheugenzoekopdrachten of de werkruimtestatus.
{ 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, includeWorkspaceFiles: true, files: ["SOUL.md", "IDENTITY.md", "USER.md"], }, }, }, }, }, },}Voorbeelden van realtime-providers
Google Gemini Live
Standaardwaarden: API-sleutel uit realtime.providers.google.apiKey, GEMINI_API_KEY
of GOOGLE_API_KEY; model gemini-3.1-flash-live-preview;
stem Kore. sessionResumption en contextWindowCompression zijn standaard
ingeschakeld voor langere oproepen waarmee opnieuw verbinding kan worden gemaakt. Gebruik silenceDurationMs,
startSensitivity en endSensitivity om snellere beurtwisseling af te stemmen
voor telefonieaudio.
{ plugins: { entries: { "voice-call": { config: { provider: "twilio", inboundPolicy: "allowlist", allowFrom: ["+15550005678"], realtime: { enabled: true, provider: "google", instructions: "Spreek kort. Roep openclaw_agent_consult aan voordat je diepgaandere tools gebruikt.", toolPolicy: "safe-read-only", consultPolicy: "substantive", consultThinkingLevel: "low", consultFastMode: true, agentContext: { enabled: true }, providers: { google: { apiKey: "${GEMINI_API_KEY}", model: "gemini-3.1-flash-live-preview", speakerVoice: "Kore", silenceDurationMs: 500, startSensitivity: "high", }, }, }, }, }, }, },}OpenAI
{ plugins: { entries: { "voice-call": { config: { realtime: { enabled: true, provider: "openai", providers: { openai: { apiKey: "${OPENAI_API_KEY}" }, }, }, }, }, }, },}Zie Google-provider en OpenAI-provider voor providerspecifieke opties voor realtime-spraak.
Streamingtranscriptie
streaming verbindt Twilio Media Streams met een realtime-transcriptieprovider.
Het klassieke streamingpad vereist provider: "twilio"; configuratie met
Telnyx, Plivo of mock wordt afgewezen. Live-audio van Telnyx gebruikt in plaats
daarvan het afzonderlijk geauthenticeerde pad realtime.enabled.
Huidig runtimegedrag:
streaming.provideris optioneel. Als dit niet is ingesteld, gebruikt Voice Call de eerste geregistreerde realtime-transcriptieprovider.- Gebundelde realtime-transcriptieproviders: Deepgram (
deepgram), ElevenLabs (elevenlabs), Mistral (mistral), OpenAI (openai) en xAI (xai), geregistreerd door hun providerplugins. - Door de provider beheerde onbewerkte configuratie staat onder
streaming.providers.<providerId>. - Nadat Twilio een geaccepteerd streambericht
startverzendt, registreert Voice Call de stream onmiddellijk, plaatst het binnenkomende media via de transcriptieprovider in de wachtrij terwijl de provider verbinding maakt en start het de eerste begroeting pas wanneer realtime-transcriptie gereed is. - Als
streaming.providernaar een niet-geregistreerde provider verwijst, of er geen is geregistreerd, registreert Voice Call een waarschuwing en slaat het mediastreaming over in plaats van de hele plugin te laten mislukken.
Voorbeelden van streamingproviders
OpenAI
Standaardwaarden: API-sleutel streaming.providers.openai.apiKey of
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-...", // optioneel als OPENAI_API_KEY is ingesteld model: "gpt-4o-transcribe", silenceDurationMs: 800, vadThreshold: 0.5, }, }, }, }, }, }, },}xAI
Standaardwaarden: API-sleutel streaming.providers.xai.apiKey of XAI_API_KEY (valt
terug op een xAI OAuth-authenticatieprofiel als geen van beide is ingesteld); eindpunt
wss://api.x.ai/v1/stt; codering mulaw; samplefrequentie 8000;
endpointingMs: 800; interimResults: true.
{ plugins: { entries: { "voice-call": { config: { streaming: { enabled: true, provider: "xai", streamPath: "/voice/stream", providers: { xai: { apiKey: "${XAI_API_KEY}", // optioneel als XAI_API_KEY is ingesteld endpointingMs: 800, language: "en", }, }, }, }, }, }, },}TTS voor oproepen
Voice Call gebruikt de kernconfiguratie tts voor streaming-spraak tijdens
oproepen. Je kunt deze onder de pluginconfiguratie overschrijven met dezelfde structuur —
deze wordt diep samengevoegd met tts.
{ tts: { provider: "elevenlabs", providers: { elevenlabs: { speakerVoiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, },}Opmerkingen over gedrag:
- Verouderde
tts.<provider>-sleutels binnen de pluginconfiguratie (openai,elevenlabs,microsoft,edge) worden hersteld dooropenclaw doctor --fix; vastgelegde configuratie moettts.providers.<provider>gebruiken. - Kern-TTS wordt gebruikt wanneer Twilio-mediastreaming is ingeschakeld; anders vallen oproepen terug op providerspecifieke stemmen.
- Als er al een Twilio-mediastream actief is, valt Voice Call niet terug op TwiML
OPENCLAW_DOCS_MARKER:calloutOpen:U2F5. Als telefonie-TTS in die toestand niet beschikbaar is, mislukt het afspeelverzoek in plaats van twee afspeelpaden te combineren. - Wanneer telefonie-TTS terugvalt op een secundaire provider, registreert Voice Call voor foutopsporing een waarschuwing met de providerketen (
from,to,attempts). - Wanneer Twilio-barge-in of het afbreken van de stream de wachtende TTS-wachtrij wist, worden in de wachtrij geplaatste afspeelverzoeken afgehandeld in plaats van bellers die op voltooiing van het afspelen wachten te laten hangen.
TTS-voorbeelden
Alleen kern-TTS
{tts: {provider: "openai",providers: {openai: { speakerVoice: "alloy" },},},}Overschrijven met ElevenLabs (alleen oproepen)
{plugins: {entries: {"voice-call": { config: { tts: { provider: "elevenlabs", providers: { elevenlabs: { apiKey: "elevenlabs_key", speakerVoiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }, },},},},}OpenAI-model overschrijven (diep samenvoegen)
{plugins: {entries: {"voice-call": { config: { tts: { providers: { openai: { model: "gpt-4o-mini-tts", speakerVoice: "marin", }, }, }, },},},},}Inkomende oproepen
Het beleid voor inkomende oproepen is standaard disabled. Stel het volgende in om inkomende oproepen in te schakelen:
{inboundPolicy: "allowlist",allowFrom: ["+15550001234"],inboundGreeting: "Hallo! Hoe kan ik helpen?",}Automatische antwoorden gebruiken het agentsysteem. Stem dit af met responseModel,
responseSystemPrompt en responseTimeoutMs.
Routering per nummer
Gebruik numbers wanneer één Voice Call-plugin oproepen voor meerdere telefoon-
nummers ontvangt en elk nummer zich als een afzonderlijke lijn moet gedragen. Het ene
nummer kan bijvoorbeeld een informele persoonlijke assistent gebruiken, terwijl een ander een zakelijke
persona, een andere antwoordagent en een andere TTS-stem gebruikt.
Routes worden geselecteerd op basis van het door de provider geleverde, gebelde nummer To. Sleutels moeten
E.164-nummers zijn. Wanneer een oproep binnenkomt, bepaalt Voice Call eenmaal de overeenkomende
route, slaat de gevonden route op in de oproeprecord en hergebruikt die
effectieve configuratie voor de begroeting, het klassieke pad voor automatische antwoorden, het realtime
consultatiepad en TTS-weergave. Als geen route overeenkomt, wordt de algemene Voice Call-
configuratie gebruikt. Uitgaande oproepen gebruiken numbers niet; geef het uitgaande
doel, het bericht en de sessie expliciet door wanneer je de oproep start.
Routeoverschrijvingen ondersteunen momenteel:
inboundGreetingttsagentIdresponseModelresponseSystemPromptresponseTimeoutMs
De routewaarde tts wordt diep samengevoegd boven op de algemene Voice Call-configuratie tts, zodat
je doorgaans alleen de providerstem hoeft te overschrijven:
{inboundGreeting: "Hallo vanaf de hoofdlijn.",responseSystemPrompt: "Je bent de standaard spraakassistent.",tts: { provider: "openai", providers: { openai: { speakerVoice: "coral" }, },},numbers: { "+15550001111": { inboundGreeting: "Silver Fox Cards, hoe kan ik helpen?", responseSystemPrompt: "Je bent een beknopte specialist in honkbalkaarten.", tts: { providers: { openai: { speakerVoice: "alloy" }, }, }, },},}Contract voor gesproken uitvoer
Voor automatische antwoorden voegt Voice Call een strikt contract voor gesproken uitvoer toe aan
de systeemprompt, dat een JSON-antwoord van het type {"spoken":"..."} vereist. Voice Call
extraheert de gesproken tekst defensief:
- Negeert payloads die als redeneer-/foutinhoud zijn gemarkeerd.
- Parseert rechtstreekse JSON, JSON in een codeblok of inline sleutels van het type
"spoken". - Valt terug op platte tekst en verwijdert waarschijnlijke inleidende alinea's met planning/metatekst.
Hierdoor blijft de gesproken weergave gericht op tekst voor de beller en wordt voorkomen dat planningstekst in de audio terechtkomt.
Gedrag bij het starten van een gesprek
Voor uitgaande oproepen van het type conversation is de verwerking van het eerste bericht gekoppeld aan de actuele
afspeelstatus:
- Het wissen van de wachtrij bij onderbreken en automatisch antwoorden worden alleen onderdrukt zolang de eerste begroeting actief wordt uitgesproken.
- Als de eerste weergave mislukt, keert de oproep terug naar
listeningen blijft het eerste bericht in de wachtrij staan om opnieuw te proberen. - De eerste weergave voor Twilio-streaming begint zonder extra vertraging zodra de stream verbinding maakt.
- Onderbreken breekt actieve weergave af en wist Twilio TTS-items die in de wachtrij staan maar nog niet worden afgespeeld. Gewiste items worden als overgeslagen afgehandeld, zodat de vervolglogica voor antwoorden kan doorgaan zonder te wachten op audio die nooit zal worden afgespeeld.
- Realtime spraakgesprekken gebruiken de eigen openingsbeurt van de realtime stream. Voice Call plaatst geen verouderde TwiML-update van het type
OPENCLAW_DOCS_MARKER:calloutOpen:U2F5voor dat eerste bericht, zodat uitgaande sessies van het type<Connect><Stream>verbonden blijven.
Respijtperiode bij verbreken van Twilio-stream
Wanneer de verbinding met een Twilio-mediastream wordt verbroken, wacht Voice Call 2000 ms voordat de oproep automatisch wordt beëindigd:
- Als de stream binnen die periode opnieuw verbinding maakt, wordt het automatisch beëindigen geannuleerd.
- Als na de respijtperiode geen stream opnieuw wordt geregistreerd, wordt de oproep beëindigd om vastgelopen actieve oproepen te voorkomen.
Opruimer voor verouderde oproepen
Gebruik staleCallReaperSeconds (standaard 120) om oproepen te beëindigen die nooit worden
beantwoord en nooit een actieve gespreksstatus bereiken, bijvoorbeeld oproepen in meldingsmodus
waarbij de provider nooit een afsluitende Webhook levert. Stel dit in op 0 om
het uit te schakelen.
De opruimer wordt elke 30 seconden uitgevoerd en beëindigt alleen oproepen zonder
tijdstempel answeredAt die nog niet de eindstatus of actieve
status (speaking/listening) hebben. Beantwoorde gesprekken worden dus nooit door deze timer
opgeruimd; maxDurationSeconds (standaard 300) is de afzonderlijke limiet die
beantwoorde oproepen beëindigt wanneer ze te lang duren.
Voor meldingsachtige flows waarbij providers traag kunnen zijn met het leveren van Webhooks
voor overgaan/beantwoorden, verhoog je staleCallReaperSeconds boven de standaardwaarde, zodat trage maar normale
oproepen niet voortijdig worden opgeruimd; 120-300 seconden is een redelijk bereik voor productie.
{plugins: {entries: { "voice-call": { config: { maxDurationSeconds: 300, staleCallReaperSeconds: 120, }, },},},}Webhook-beveiliging
Wanneer een proxy of tunnel vóór de Gateway staat, reconstrueert de plugin de openbare URL voor handtekeningverificatie. Deze opties bepalen welke doorgestuurde headers worden vertrouwd:
webhookSecurity.allowedHostsstring[]Hosts uit doorstuurheaders op de toelatingslijst.
webhookSecurity.trustForwardingHeadersbooleanVertrouw doorgestuurde headers zonder toelatingslijst.
webhookSecurity.trustedProxyIPsstring[]Vertrouw doorgestuurde headers alleen wanneer het externe IP-adres van het verzoek overeenkomt met de lijst.
Aanvullende beveiligingen:
- Webhook-beveiliging tegen herhaling is ingeschakeld voor Twilio, Telnyx en Plivo. Herhaalde geldige Webhook-verzoeken worden bevestigd, maar bijwerkingen worden overgeslagen.
- Twilio-gespreksbeurten bevatten een token per beurt in callbacks van het type
<Gather>, zodat verouderde/herhaalde spraakcallbacks niet kunnen voldoen aan een nieuwere wachtende transcriptiebeurt. - Niet-geverifieerde Webhook-verzoeken worden vóór het lezen van de body geweigerd wanneer de vereiste handtekeningheaders van de provider ontbreken.
- De voice-call-Webhook gebruikt vóór handtekeningverificatie het gedeelde profiel voor het lezen van de body vóór authenticatie (maximale body van 64 KB, leestime-out van 5 seconden), plus een limiet per sleutel voor gelijktijdig verwerkte verzoeken (standaard 8 gelijktijdige verzoeken per sleutel).
Voorbeeld met een stabiele openbare host:
{plugins: {entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", webhookSecurity: { allowedHosts: ["voice.example.com"], }, }, },},},}CLI
openclaw voicecall call --to "+15555550123" --message "Hallo van OpenClaw"openclaw voicecall start --to "+15555550123" # alias voor callopenclaw voicecall continue --call-id <id> --message "Nog vragen?"openclaw voicecall speak --call-id <id> --message "Een ogenblik"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 # vat de latentie per beurt samen op basis van logboekenopenclaw voicecall expose --mode funnelWanneer de Gateway al actief is, delegeren operationele opdrachten van het type voicecall
naar de door de Gateway beheerde voice-call-runtime, zodat de CLI geen
tweede Webhook-server bindt. Als er geen Gateway bereikbaar is, vallen de opdrachten terug op
een zelfstandige CLI-runtime.
latency leest calls.jsonl uit het standaardopslagpad voor voice-call. Gebruik
--file <path> om naar een ander logboek te verwijzen en --last <n> om
de analyse te beperken tot de laatste N records (standaard 200). De uitvoer bevat min/max/gem,
p50 en p95 voor de latentie per beurt en de wachttijden voor luisteren.
Agenttool
Toolnaam: voice_call.
| Actie | Argumenten |
|---|---|
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 |
De voice-call-plugin levert een bijpassende agentskill.
Gateway-RPC
| Methode | Argumenten | Opmerkingen |
|---|---|---|
voicecall.initiate |
to?, message, mode?, sessionKey?, requesterSessionKey? |
Valt terug op de configuratie van toNumber wanneer to is weggelaten. |
voicecall.start |
to, message?, mode?, dtmfSequence?, sessionKey? |
Hetzelfde als initiate, maar accepteert ook dtmfSequence vóór de verbinding. |
voicecall.continue |
callId, message |
Blokkeert totdat de beurt is afgehandeld en retourneert het transcript. |
voicecall.continue.start |
callId, message |
Asynchrone variant: retourneert onmiddellijk een operationId. |
voicecall.continue.result |
operationId |
Vraagt het resultaat van een wachtende voicecall.continue.start-bewerking op. |
voicecall.speak |
callId, message |
Spreekt zonder te wachten en gebruikt de realtime-bridge wanneer realtime.enabled. |
voicecall.dtmf |
callId, digits |
|
voicecall.end |
callId |
|
voicecall.status |
callId? |
Laat callId weg om alle actieve gesprekken weer te geven. |
dtmfSequence is alleen geldig met mode: "conversation"; gesprekken in meldingsmodus
moeten voicecall.dtmf gebruiken nadat het gesprek bestaat als ze cijfers
na het verbinden nodig hebben.
Probleemoplossing
Instellen van webhooktoegang mislukt
Voer de instelling uit vanuit dezelfde omgeving waarin de Gateway wordt uitgevoerd:
openclaw voicecall setupopenclaw voicecall setup --jsonVoor twilio, telnyx en plivo moet webhook-exposure groen zijn. Een
geconfigureerde publicUrl mislukt nog steeds wanneer deze naar lokale of privé-
netwerkruimte verwijst, omdat de telecomprovider die adressen niet kan terugbellen.
Gebruik 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, fd00::/8 of andere carrier-grade-NAT-
bereiken niet als publicUrl.
Uitgaande Twilio-gesprekken in meldingsmodus sturen hun initiële OPENCLAW_DOCS_MARKER:calloutOpen:U2F5-TwiML rechtstreeks
mee in het verzoek om een gesprek te starten, zodat het eerste gesproken bericht niet afhankelijk is
van het ophalen van webhook-TwiML door Twilio. Een openbare webhook blijft vereist voor status-
callbacks, conversatiegesprekken, DTMF vóór het verbinden, realtime-streams en
gespreksbesturing na het verbinden.
Gebruik één openbaar toegangspad:
{plugins: {entries: {"voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", // of tunnel: { provider: "ngrok" }, // of tailscale: { mode: "funnel", path: "/voice/webhook" }, },},},},}Start na een configuratiewijziging de Gateway opnieuw of laad deze opnieuw en voer daarna uit:
openclaw voicecall setupopenclaw voicecall smokevoicecall smoke is een proefuitvoering, tenzij je --yes meegeeft.
Providerreferenties mislukken
Controleer de geselecteerde provider en de vereiste referentievelden:
- Twilio:
twilio.accountSid,twilio.authTokenenfromNumber, ofTWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKENenTWILIO_FROM_NUMBER. - Telnyx:
telnyx.apiKey,telnyx.connectionId,telnyx.publicKeyenfromNumber, ofTELNYX_API_KEY,TELNYX_CONNECTION_IDenTELNYX_PUBLIC_KEY. - Plivo:
plivo.authId,plivo.authTokenenfromNumber, ofPLIVO_AUTH_IDenPLIVO_AUTH_TOKEN.
De referenties moeten op de Gateway-host aanwezig zijn. Het bewerken van een lokaal shellprofiel heeft geen invloed op een Gateway die al wordt uitgevoerd, totdat deze opnieuw wordt gestart of zijn omgeving opnieuw laadt.
Gesprekken starten, maar providerwebhooks komen niet aan
Controleer of de providerconsole naar de exacte openbare webhook-URL verwijst:
https://voice.example.com/voice/webhookInspecteer daarna de runtimestatus:
openclaw voicecall status --call-id <id>openclaw voicecall tailopenclaw logs --followVeelvoorkomende oorzaken:
publicUrlverwijst naar een ander pad danserve.path.- De tunnel-URL is gewijzigd nadat de Gateway is gestart.
- Een proxy stuurt het verzoek door, maar verwijdert of herschrijft host-/protoheaders.
- De firewall of DNS routeert de openbare hostnaam naar een andere locatie dan de Gateway.
- De Gateway is opnieuw gestart zonder dat de Voice Call-plugin was ingeschakeld.
Wanneer zich een reverse proxy of tunnel vóór de Gateway bevindt, stel je
webhookSecurity.allowedHosts in op de openbare hostnaam of gebruik je
webhookSecurity.trustedProxyIPs voor een bekend proxyadres. Gebruik
webhookSecurity.trustForwardingHeaders alleen wanneer je de proxygrens
zelf beheert.
Handtekeningverificatie mislukt
Providerhandtekeningen worden gecontroleerd aan de hand van de openbare URL die OpenClaw reconstrueert uit het binnenkomende verzoek. Als handtekeningen mislukken:
- Controleer of de webhook-URL van de provider exact overeenkomt met
publicUrl, inclusief schema, host en pad. - Werk bij gratis ngrok-URL's
publicUrlbij wanneer de tunnelhostnaam verandert. - Zorg dat de proxy de oorspronkelijke host- en protoheaders behoudt of configureer
webhookSecurity.allowedHosts. - Schakel
skipSignatureVerificationniet in buiten lokale tests.
Deelname aan Google Meet via Twilio mislukt
Google Meet gebruikt deze Plugin voor deelname via Twilio-inbellen. Controleer eerst Voice Call:
openclaw voicecall setupopenclaw voicecall smoke --to "+15555550123"Controleer daarna expliciet het Google Meet-transport:
openclaw googlemeet setup --transport twilioAls Voice Call groen is, maar de Meet-deelnemer nooit deelneemt, controleer dan het Meet-
inbelnummer, de pincode en --dtmf-sequence. Het telefoongesprek kan correct werken,
terwijl de vergadering een onjuiste DTMF-reeks weigert of negeert.
Google Meet start het Twilio-telefoongedeelte via voicecall.start met een
DTMF-reeks vóór het verbinden. Van pincodes afgeleide reeksen bevatten de
voiceCall.dtmfDelayMs van de Google Meet-plugin (standaard 12000 ms) als voorloop-
wachtcijfers voor Twilio, omdat Meet-inbelprompts laat kunnen verschijnen. Voice Call leidt
daarna terug naar realtime-afhandeling voordat om de introductiebegroeting wordt gevraagd.
Gebruik openclaw logs --follow voor de live fasetracering. Een geslaagde Twilio Meet-
deelname registreert deze volgorde:
- Google Meet delegeert de Twilio-deelname aan Voice Call.
- Voice Call slaat DTMF-TwiML voor het verbinden op.
- De initiële TwiML van Twilio wordt verwerkt en aangeboden vóór de realtime-afhandeling.
- Voice Call biedt realtime-TwiML aan voor het Twilio-gesprek.
- Google Meet vraagt na de vertraging na DTMF om introductiespraak met
voicecall.speak.
openclaw voicecall tail toont nog steeds opgeslagen gespreksrecords; nuttig voor
gespreksstatus en transcripties, maar niet elke webhook-/realtime-overgang
verschijnt daar.
Realtime-gesprek heeft geen spraak
Controleer of slechts één audiomodus is ingeschakeld: realtime.enabled en
streaming.enabled kunnen niet beide waar zijn.
Controleer voor realtime Twilio-/Telnyx-gesprekken ook het volgende:
- Er is een realtime-providerplugin geladen en geregistreerd.
realtime.provideris niet ingesteld of noemt een geregistreerde provider.- De API-sleutel van de provider is beschikbaar voor het Gateway-proces.
openclaw logs --followtoont dat realtime-TwiML is aangeboden, de realtime-bridge is gestart en de initiële begroeting in de wachtrij is geplaatst.