extensions/voice-call/README.md
Official Voice Call plugin for OpenClaw.
Providers:
Docs: https://docs.openclaw.ai/plugins/voice-call
Plugin system: https://docs.openclaw.ai/plugin
openclaw plugins install @openclaw/voice-call
Restart the Gateway afterwards.
PLUGIN_HOME=~/.openclaw/extensions
mkdir -p "$PLUGIN_HOME"
cp -R <local-plugin-checkout> "$PLUGIN_HOME/voice-call"
cd "$PLUGIN_HOME/voice-call" && pnpm install
Put under plugins.entries.voice-call.config:
{
provider: "twilio", // or "telnyx" | "plivo" | "mock"
fromNumber: "+15550001234",
toNumber: "+15550005678",
sessionScope: "per-phone", // or "per-call"
twilio: {
accountSid: "ACxxxxxxxx",
authToken: "your_token",
},
telnyx: {
apiKey: "KEYxxxx",
connectionId: "CONNxxxx",
// 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: "your_token",
},
// Webhook server
serve: {
port: 3334,
path: "/voice/webhook",
},
// Public exposure (pick one):
// publicUrl: "https://example.ngrok.app/voice/webhook",
// tunnel: { provider: "ngrok" },
// tailscale: { mode: "funnel", path: "/voice/webhook" }
outbound: {
defaultMode: "notify", // or "conversation"
},
// Optional response agent workspace. Defaults to "main".
agentId: "main",
streaming: {
enabled: true,
// optional; if omitted, Voice Call picks the first registered
// realtime-transcription provider by autoSelectOrder
provider: "<realtime-transcription-provider-id>",
streamPath: "/voice/stream",
providers: {
"<realtime-transcription-provider-id>": {
// provider-owned options
},
},
preStartTimeoutMs: 5000,
maxPendingConnections: 32,
maxPendingConnectionsPerIp: 4,
maxConnections: 128,
},
}
Notes:
mock is a local dev provider (no network calls).telnyx.publicKey (or TELNYX_PUBLIC_KEY) unless skipSignatureVerification is true.provider: "log", twilio.from, or legacy streaming.* OpenAI keys, run openclaw doctor --fix to rewrite them.https://docs.openclaw.ai/plugins/voice-callresponseModel is optional. When unset, voice responses use the runtime default model.sessionScope defaults to per-phone, preserving caller memory across calls. Use per-call for reception, booking, IVR, and bridge flows where each carrier call should start fresh.realtime.consultThinkingLevel is optional. When set, it overrides the thinking level used by the model behind realtime openclaw_agent_consult calls.realtime.consultFastMode is optional. When set, it toggles fast mode for realtime openclaw_agent_consult calls.See the plugin docs for recommended ranges and production examples:
https://docs.openclaw.ai/plugins/voice-call#stale-call-reaper
Voice Call uses the core messages.tts configuration for
streaming speech on calls. Override examples and provider caveats live here:
https://docs.openclaw.ai/plugins/voice-call#tts-for-calls
openclaw voicecall call --to "+15555550123" --message "Hello from OpenClaw"
openclaw voicecall continue --call-id <id> --message "Any questions?"
openclaw voicecall speak --call-id <id> --message "One moment"
openclaw voicecall end --call-id <id>
openclaw voicecall status --json
openclaw voicecall status --call-id <id>
openclaw voicecall tail
openclaw voicecall expose --mode funnel
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)voicecall.initiate (to?, message, mode?)voicecall.continue (callId, message)voicecall.speak (callId, message)voicecall.end (callId)voicecall.status (callId)responseModel / responseSystemPrompt control AI auto-responses.{"spoken":"..."}) and filter reasoning/meta output before playback.<Say>; stream-TTS failures fail the playback request.streaming.provider / realtime.provider and put provider-owned options under providers.<id>.