Plugin guides
Voice call troubleshooting
Fixes for setup, webhook exposure, credentials, signature verification, Google Meet dial-in, and silent realtime calls. Part of the Voice call plugin guide.
Troubleshooting
Call placement fails to save its initial record
Voice Call saves the initial record before reserving a concurrency slot or
contacting the carrier. If that write fails, the placement reports the storage
error without dialing. Restore access to the state directory, then retry; the
failed placement does not consume maxConcurrentCalls capacity.
Setup fails webhook exposure
Run setup from the same environment that runs the Gateway:
openclaw voicecall setupopenclaw voicecall setup --jsonFor twilio, telnyx, and plivo, webhook-exposure must be green. A
configured publicUrl still fails when it points at local or private
network space, because the carrier cannot call back into those addresses.
Do not use 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, or other carrier-grade-NAT
ranges as publicUrl.
Twilio notify-mode outbound calls send their initial <Say> TwiML directly
in the create-call request, so the first spoken message does not depend on
Twilio fetching webhook TwiML. A public webhook is still required for status
callbacks, conversation calls, pre-connect DTMF, realtime streams, and
post-connect call control.
Use one public exposure path:
{ plugins: { entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", // or tunnel: { provider: "ngrok" }, // or tailscale: { mode: "funnel", port: 8443, path: "/voice/webhook" }, }, }, }, },}After changing config, restart or reload the Gateway, then run:
openclaw voicecall setupopenclaw voicecall smokevoicecall smoke is a dry run unless you pass --yes.
Provider credentials fail
Check the selected provider and the required credential fields:
- Twilio:
twilio.accountSid,twilio.authToken, andfromNumber, orTWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN, andTWILIO_FROM_NUMBER. - Telnyx:
telnyx.apiKey,telnyx.connectionId,telnyx.publicKey, andfromNumber, orTELNYX_API_KEY,TELNYX_CONNECTION_ID, andTELNYX_PUBLIC_KEY. - Plivo:
plivo.authId,plivo.authToken, andfromNumber, orPLIVO_AUTH_IDandPLIVO_AUTH_TOKEN.
Credentials must exist on the Gateway host. Editing a local shell profile does not affect an already running Gateway until it restarts or reloads its environment.
Calls start but provider webhooks do not arrive
Confirm the provider console points at the exact public webhook URL:
https://voice.example.com/voice/webhookFor a Twilio inbound number, configure both number-level callbacks in the Twilio Console:
- Voice webhook:
https://voice.example.com/voice/webhookusingPOST. - Status Callback:
https://voice.example.com/voice/webhook?type=statususingPOST.
Media Streams stop/WebSocket close handling is the primary auto-end path and
does not depend on the HTTP status callback. Twilio's optional <Stream statusCallback> is a separate stream-diagnostic signal and is not required for
teardown. openclaw voicecall setup validates local configuration and webhook
exposure; it cannot inspect or change Twilio Console settings.
Then inspect runtime state:
openclaw voicecall status --call-id <id>openclaw voicecall tailopenclaw logs --followCommon causes:
publicUrldoes not match the public webhook URL configured with the provider. A reverse proxy may map that public path to a differentserve.path, butpublicUrlmust remain the provider-facing URL.- The tunnel URL changed after the Gateway started.
- A proxy forwards the request but strips or rewrites host/proto headers.
- Firewall or DNS routes the public hostname somewhere other than the Gateway.
- The Gateway was restarted without the Voice Call plugin enabled.
When a reverse proxy or tunnel is in front of the Gateway, set
webhookSecurity.allowedHosts to the public hostname, or use
webhookSecurity.trustedProxyIPs for a known proxy address. Use
webhookSecurity.trustForwardingHeaders only when the proxy boundary is
under your control.
Signature verification fails
Twilio and Plivo URL signatures use publicUrl when it is configured: its
scheme, host, and path are preserved, while the request query is applied.
Without publicUrl, OpenClaw reconstructs the URL from the request. Telnyx
signatures do not include the request URL. If signatures fail:
- Confirm the provider webhook URL exactly matches
publicUrl, including scheme, host, and path. - For ngrok free-tier URLs, update
publicUrlwhen the tunnel hostname changes. - Ensure the proxy preserves the original host and proto headers, or configure
webhookSecurity.allowedHosts. - Do not enable
skipSignatureVerificationoutside local testing.
Google Meet Twilio joins fail
Google Meet uses this plugin for Twilio dial-in joins. First verify Voice Call:
openclaw voicecall setupopenclaw voicecall smoke --to "+15555550123"Then verify the Google Meet transport explicitly:
openclaw googlemeet setup --transport twilioIf Voice Call is green but the Meet participant never joins, check the Meet
dial-in number, PIN, and --dtmf-sequence. The phone call can be healthy
while the meeting rejects or ignores an incorrect DTMF sequence.
Google Meet starts the Twilio phone leg through voicecall.start with a
pre-connect DTMF sequence. PIN-derived sequences include the Google Meet
plugin's voiceCall.dtmfDelayMs (default 12000 ms) as leading Twilio
wait digits, because Meet dial-in prompts can arrive late. Voice Call then
redirects back to realtime handling before the intro greeting is requested.
Use openclaw logs --follow for the live phase trace. A healthy Twilio Meet
join logs this order:
- Google Meet delegates the Twilio join to Voice Call.
- Voice Call stores pre-connect DTMF TwiML.
- Twilio initial TwiML is consumed and served before realtime handling.
- Voice Call serves realtime TwiML for the Twilio call.
- Google Meet requests intro speech with
voicecall.speakafter the post-DTMF delay.
openclaw voicecall tail still shows persisted call records; useful for
call state and transcripts, but not every webhook/realtime transition
appears there.
Realtime call has no speech
Confirm only one audio mode is enabled: realtime.enabled and
streaming.enabled cannot both be true.
For realtime Twilio/Telnyx calls, also verify:
- A realtime provider plugin is loaded and registered.
realtime.provideris unset or names a registered provider.- The provider API key is available to the Gateway process.
openclaw logs --followshows realtime TwiML served, the realtime bridge started, and the initial greeting queued.