{
  "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": []
}