{ "title": "Voice Call (plugin)", "content": "Voice calls for OpenClaw via a plugin. Supports outbound notifications and\nmulti-turn conversations with inbound policies.\n\n* `twilio` (Programmable Voice + Media Streams)\n* `telnyx` (Call Control v2)\n* `plivo` (Voice API + XML transfer + GetInput speech)\n* `mock` (dev/no network)\n\n* Install plugin\n* Restart Gateway\n* Configure under `plugins.entries.voice-call.config`\n* Use `openclaw voicecall ...` or the `voice_call` tool\n\n## Where it runs (local vs remote)\n\nThe Voice Call plugin runs **inside the Gateway process**.\n\nIf you use a remote Gateway, install/configure the plugin on the **machine running the Gateway**, then restart the Gateway to load it.\n\n### Option A: install from npm (recommended)\n\nRestart the Gateway afterwards.\n\n### Option B: install from a local folder (dev, no copying)\n\nRestart the Gateway afterwards.\n\nSet config under `plugins.entries.voice-call.config`:\n\n* Twilio/Telnyx require a **publicly reachable** webhook URL.\n* Plivo requires a **publicly reachable** webhook URL.\n* `mock` is a local dev provider (no network calls).\n* `skipSignatureVerification` is for local testing only.\n* If you use ngrok free tier, set `publicUrl` to the exact ngrok URL; signature verification is always enforced.\n* `tunnel.allowNgrokFreeTierLoopbackBypass: true` allows Twilio webhooks with invalid signatures **only** when `tunnel.provider=\"ngrok\"` and `serve.bind` is loopback (ngrok local agent). Use for local dev only.\n* Ngrok free tier URLs can change or add interstitial behavior; if `publicUrl` drifts, Twilio signatures will fail. For production, prefer a stable domain or Tailscale funnel.\n\nWhen a proxy or tunnel sits in front of the Gateway, the plugin reconstructs the\npublic URL for signature verification. These options control which forwarded\nheaders are trusted.\n\n`webhookSecurity.allowedHosts` allowlists hosts from forwarding headers.\n\n`webhookSecurity.trustForwardingHeaders` trusts forwarded headers without an allowlist.\n\n`webhookSecurity.trustedProxyIPs` only trusts forwarded headers when the request\nremote IP matches the list.\n\nExample with a stable public host:\n\nVoice Call uses the core `messages.tts` configuration (OpenAI or ElevenLabs) for\nstreaming speech on calls. You can override it under the plugin config with the\n**same shape** — it deep‑merges with `messages.tts`.\n\n* **Edge TTS is ignored for voice calls** (telephony audio needs PCM; Edge output is unreliable).\n* Core TTS is used when Twilio media streaming is enabled; otherwise calls fall back to provider native voices.\n\nUse core TTS only (no override):\n\nOverride to ElevenLabs just for calls (keep core default elsewhere):\n\nOverride only the OpenAI model for calls (deep‑merge example):\n\nInbound policy defaults to `disabled`. To enable inbound calls, set:\n\nAuto-responses use the agent system. Tune with:\n\n* `responseModel`\n* `responseSystemPrompt`\n* `responseTimeoutMs`\n\nTool name: `voice_call`\n\n* `initiate_call` (message, to?, mode?)\n* `continue_call` (callId, message)\n* `speak_to_user` (callId, message)\n* `end_call` (callId)\n* `get_status` (callId)\n\nThis repo ships a matching skill doc at `skills/voice-call/SKILL.md`.\n\n* `voicecall.initiate` (`to?`, `message`, `mode?`)\n* `voicecall.continue` (`callId`, `message`)\n* `voicecall.speak` (`callId`, `message`)\n* `voicecall.end` (`callId`)\n* `voicecall.status` (`callId`)", "code_samples": [ { "code": "Restart the Gateway afterwards.\n\n### Option B: install from a local folder (dev, no copying)", "language": "unknown" }, { "code": "Restart the Gateway afterwards.\n\n## Config\n\nSet config under `plugins.entries.voice-call.config`:", "language": "unknown" }, { "code": "Notes:\n\n* Twilio/Telnyx require a **publicly reachable** webhook URL.\n* Plivo requires a **publicly reachable** webhook URL.\n* `mock` is a local dev provider (no network calls).\n* `skipSignatureVerification` is for local testing only.\n* If you use ngrok free tier, set `publicUrl` to the exact ngrok URL; signature verification is always enforced.\n* `tunnel.allowNgrokFreeTierLoopbackBypass: true` allows Twilio webhooks with invalid signatures **only** when `tunnel.provider=\"ngrok\"` and `serve.bind` is loopback (ngrok local agent). Use for local dev only.\n* Ngrok free tier URLs can change or add interstitial behavior; if `publicUrl` drifts, Twilio signatures will fail. For production, prefer a stable domain or Tailscale funnel.\n\n## Webhook Security\n\nWhen a proxy or tunnel sits in front of the Gateway, the plugin reconstructs the\npublic URL for signature verification. These options control which forwarded\nheaders are trusted.\n\n`webhookSecurity.allowedHosts` allowlists hosts from forwarding headers.\n\n`webhookSecurity.trustForwardingHeaders` trusts forwarded headers without an allowlist.\n\n`webhookSecurity.trustedProxyIPs` only trusts forwarded headers when the request\nremote IP matches the list.\n\nExample with a stable public host:", "language": "unknown" }, { "code": "## TTS for calls\n\nVoice Call uses the core `messages.tts` configuration (OpenAI or ElevenLabs) for\nstreaming speech on calls. You can override it under the plugin config with the\n**same shape** — it deep‑merges with `messages.tts`.", "language": "unknown" }, { "code": "Notes:\n\n* **Edge TTS is ignored for voice calls** (telephony audio needs PCM; Edge output is unreliable).\n* Core TTS is used when Twilio media streaming is enabled; otherwise calls fall back to provider native voices.\n\n### More examples\n\nUse core TTS only (no override):", "language": "unknown" }, { "code": "Override to ElevenLabs just for calls (keep core default elsewhere):", "language": "unknown" }, { "code": "Override only the OpenAI model for calls (deep‑merge example):", "language": "unknown" }, { "code": "## Inbound calls\n\nInbound policy defaults to `disabled`. To enable inbound calls, set:", "language": "unknown" }, { "code": "Auto-responses use the agent system. Tune with:\n\n* `responseModel`\n* `responseSystemPrompt`\n* `responseTimeoutMs`\n\n## CLI", "language": "unknown" } ], "headings": [ { "level": "h2", "text": "Where it runs (local vs remote)", "id": "where-it-runs-(local-vs-remote)" }, { "level": "h2", "text": "Install", "id": "install" }, { "level": "h3", "text": "Option A: install from npm (recommended)", "id": "option-a:-install-from-npm-(recommended)" }, { "level": "h3", "text": "Option B: install from a local folder (dev, no copying)", "id": "option-b:-install-from-a-local-folder-(dev,-no-copying)" }, { "level": "h2", "text": "Config", "id": "config" }, { "level": "h2", "text": "Webhook Security", "id": "webhook-security" }, { "level": "h2", "text": "TTS for calls", "id": "tts-for-calls" }, { "level": "h3", "text": "More examples", "id": "more-examples" }, { "level": "h2", "text": "Inbound calls", "id": "inbound-calls" }, { "level": "h2", "text": "CLI", "id": "cli" }, { "level": "h2", "text": "Agent tool", "id": "agent-tool" }, { "level": "h2", "text": "Gateway RPC", "id": "gateway-rpc" } ], "url": "llms-txt#voice-call-(plugin)", "links": [] }