Voice Call Plugin
このコンテンツはまだ日本語訳がありません。
Voice Call (plugin)
Section titled “Voice Call (plugin)”Voice calls for CoderClaw via a plugin. Supports outbound notifications and multi-turn conversations with inbound policies.
Current providers:
twilio(Programmable Voice + Media Streams)telnyx(Call Control v2)plivo(Voice API + XML transfer + GetInput speech)mock(dev/no network)
Quick mental model:
- Install plugin
- Restart Gateway
- Configure under
plugins.entries.voice-call.config - Use
coderclaw voicecall ...or thevoice_calltool
Where it runs (local vs remote)
Section titled “Where it runs (local vs remote)”The Voice Call plugin runs inside the Gateway process.
If you use a remote Gateway, install/configure the plugin on the machine running the Gateway, then restart the Gateway to load it.
Install
Section titled “Install”Option A: install from npm (recommended)
Section titled “Option A: install from npm (recommended)”coderclaw plugins install @coderclaw/voice-callRestart the Gateway afterwards.
Option B: install from a local folder (dev, no copying)
Section titled “Option B: install from a local folder (dev, no copying)”coderclaw plugins install ./extensions/voice-callcd ./extensions/voice-call && pnpm installRestart the Gateway afterwards.
Config
Section titled “Config”Set config under plugins.entries.voice-call.config:
{ plugins: { entries: { "voice-call": { enabled: true, config: { provider: "twilio", // or "telnyx" | "plivo" | "mock" fromNumber: "+15550001234", toNumber: "+15550005678",
twilio: { accountSid: "ACxxxxxxxx", authToken: "...", },
telnyx: { apiKey: "...", connectionId: "...", // Telnyx webhook public key from the Telnyx Mission Control Portal // (Base64 string; 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, streamPath: "/voice/stream", }, }, }, }, },}Notes:
- Twilio/Telnyx require a publicly reachable webhook URL.
- Plivo requires a publicly reachable webhook URL.
mockis a local dev provider (no network calls).- Telnyx requires
telnyx.publicKey(orTELNYX_PUBLIC_KEY) unlessskipSignatureVerificationis true. skipSignatureVerificationis for local testing only.- If you use ngrok free tier, set
publicUrlto the exact ngrok URL; signature verification is always enforced. tunnel.allowNgrokFreeTierLoopbackBypass: trueallows Twilio webhooks with invalid signatures only whentunnel.provider="ngrok"andserve.bindis loopback (ngrok local agent). Use for local dev only.- Ngrok free tier URLs can change or add interstitial behavior; if
publicUrldrifts, Twilio signatures will fail. For production, prefer a stable domain or Tailscale funnel.
Stale call reaper
Section titled “Stale call reaper”Use staleCallReaperSeconds to end calls that never receive a terminal webhook
(for example, notify-mode calls that never complete). The default is 0
(disabled).
Recommended ranges:
- Production:
120–300seconds for notify-style flows. - Keep this value higher than
maxDurationSecondsso normal calls can finish. A good starting point ismaxDurationSeconds + 30–60seconds.
Example:
{ plugins: { entries: { "voice-call": { config: { maxDurationSeconds: 300, staleCallReaperSeconds: 360, }, }, }, },}Webhook Security
Section titled “Webhook Security”When a proxy or tunnel sits in front of the Gateway, the plugin reconstructs the public URL for signature verification. These options control which forwarded headers are trusted.
webhookSecurity.allowedHosts allowlists hosts from forwarding headers.
webhookSecurity.trustForwardingHeaders trusts forwarded headers without an allowlist.
webhookSecurity.trustedProxyIPs only trusts forwarded headers when the request
remote IP matches the list.
Example with a stable public host:
{ plugins: { entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", webhookSecurity: { allowedHosts: ["voice.example.com"], }, }, }, }, },}TTS for calls
Section titled “TTS for calls”Voice Call uses the core messages.tts configuration (OpenAI or ElevenLabs) for
streaming speech on calls. You can override it under the plugin config with the
same shape — it deep‑merges with messages.tts.
{ tts: { provider: "elevenlabs", elevenlabs: { voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, },}Notes:
- Edge TTS is ignored for voice calls (telephony audio needs PCM; Edge output is unreliable).
- Core TTS is used when Twilio media streaming is enabled; otherwise calls fall back to provider native voices.
More examples
Section titled “More examples”Use core TTS only (no override):
{ messages: { tts: { provider: "openai", openai: { voice: "alloy" }, }, },}Override to ElevenLabs just for calls (keep core default elsewhere):
{ plugins: { entries: { "voice-call": { config: { tts: { provider: "elevenlabs", elevenlabs: { apiKey: "elevenlabs_key", voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }, }, }, },}Override only the OpenAI model for calls (deep‑merge example):
{ plugins: { entries: { "voice-call": { config: { tts: { openai: { model: "gpt-4o-mini-tts", voice: "marin", }, }, }, }, }, },}Inbound calls
Section titled “Inbound calls”Inbound policy defaults to disabled. To enable inbound calls, set:
{ inboundPolicy: "allowlist", allowFrom: ["+15550001234"], inboundGreeting: "Hello! How can I help?",}Auto-responses use the agent system. Tune with:
responseModelresponseSystemPromptresponseTimeoutMs
coderclaw voicecall call --to "+15555550123" --message "Hello from CoderClaw"coderclaw voicecall continue --call-id <id> --message "Any questions?"coderclaw voicecall speak --call-id <id> --message "One moment"coderclaw voicecall end --call-id <id>coderclaw voicecall status --call-id <id>coderclaw voicecall tailcoderclaw voicecall expose --mode funnelAgent tool
Section titled “Agent tool”Tool name: voice_call
Actions:
initiate_call(message, to?, mode?)continue_call(callId, message)speak_to_user(callId, message)end_call(callId)get_status(callId)
This repo ships a matching skill doc at skills/voice-call/SKILL.md.
Gateway RPC
Section titled “Gateway RPC”voicecall.initiate(to?,message,mode?)voicecall.continue(callId,message)voicecall.speak(callId,message)voicecall.end(callId)voicecall.status(callId)