twilio (Programmable Voice + Media Streams),
telnyx (Call Control v2), plivo (Voice API + XML transfer + GetInput
speech), mock (dev/no network).
Voice Call Plugin Gateway प्रक्रिया के अंदर चलता है। यदि आप रिमोट
Gateway का उपयोग करते हैं, तो Gateway चलाने वाली मशीन पर Plugin इंस्टॉल
और कॉन्फ़िगर करें, फिर उसे लोड करने के लिए Gateway रीस्टार्ट करें।
त्वरित शुरुआत
Plugin इंस्टॉल करें
- npm से
- स्थानीय फ़ोल्डर से (dev)
प्रदाता और Webhook कॉन्फ़िगर करें
plugins.entries.voice-call.config के अंतर्गत config सेट करें (पूरा आकार
नीचे कॉन्फ़िगरेशन में देखें)। न्यूनतम रूप से:
provider, प्रदाता credentials, fromNumber, और सार्वजनिक रूप से
पहुंच योग्य Webhook URL चाहिए।सेटअप सत्यापित करें
streaming या realtime) सक्रिय है। scripts के
लिए --json का उपयोग करें।कॉन्फ़िगरेशन
यदिenabled: true है लेकिन चुने गए प्रदाता में credentials नहीं हैं, तो
Gateway startup missing keys के साथ setup-incomplete चेतावनी log करता है और
runtime शुरू करना छोड़ देता है। Commands, RPC calls, और agent tools उपयोग किए
जाने पर अब भी सटीक missing provider configuration लौटाते हैं।
Voice-call credentials SecretRefs स्वीकार करते हैं।
plugins.entries.voice-call.config.twilio.authToken, plugins.entries.voice-call.config.realtime.providers.*.apiKey, plugins.entries.voice-call.config.streaming.providers.*.apiKey, और plugins.entries.voice-call.config.tts.providers.*.apiKey standard SecretRef surface के माध्यम से resolve होते हैं; SecretRef credential surface देखें।प्रदाता exposure और सुरक्षा नोट्स
प्रदाता exposure और सुरक्षा नोट्स
- Twilio, Telnyx, और Plivo सभी को सार्वजनिक रूप से पहुंच योग्य Webhook URL चाहिए।
mockएक local dev provider है (कोई network calls नहीं)।- Telnyx को
telnyx.publicKey(याTELNYX_PUBLIC_KEY) चाहिए, जब तकskipSignatureVerificationtrue न हो। skipSignatureVerificationकेवल local testing के लिए है।- ngrok free tier पर,
publicUrlको exact ngrok URL पर सेट करें; signature verification हमेशा enforce होता है। tunnel.allowNgrokFreeTierLoopbackBypass: trueinvalid signatures वाले Twilio webhooks को केवल तब अनुमति देता है जबtunnel.provider="ngrok"औरserve.bindloopback हो (ngrok local agent)। केवल local dev।- Ngrok free-tier URLs बदल सकते हैं या interstitial behaviour जोड़ सकते हैं; यदि
publicUrldrift होता है, तो Twilio signatures fail हो जाते हैं। Production: stable domain या Tailscale funnel को प्राथमिकता दें।
Streaming connection caps
Streaming connection caps
streaming.preStartTimeoutMsउन sockets को बंद करता है जो कभी validstartframe नहीं भेजते।streaming.maxPendingConnectionsकुल unauthenticated pre-start sockets को cap करता है।streaming.maxPendingConnectionsPerIpप्रति source IP unauthenticated pre-start sockets को cap करता है।streaming.maxConnectionsकुल open media stream sockets (pending + active) को cap करता है।
Legacy config migrations
Legacy config migrations
provider: "log", twilio.from, या legacy
streaming.* OpenAI keys का उपयोग करने वाले पुराने configs को openclaw doctor --fix
द्वारा rewrite किया जाता है। Runtime fallback अभी के लिए पुराने voice-call keys
स्वीकार करता है, लेकिन rewrite path openclaw doctor --fix है और compat shim
अस्थायी है।Auto-migrated streaming keys:streaming.sttProvider→streaming.providerstreaming.openaiApiKey→streaming.providers.openai.apiKeystreaming.sttModel→streaming.providers.openai.modelstreaming.silenceDurationMs→streaming.providers.openai.silenceDurationMsstreaming.vadThreshold→streaming.providers.openai.vadThreshold
Session scope
डिफ़ॉल्ट रूप से, Voice CallsessionScope: "per-phone" का उपयोग करता है ताकि
उसी caller से repeat calls conversation memory बनाए रखें। जब हर carrier call
fresh context से शुरू होनी चाहिए, जैसे reception, booking, IVR, या Google Meet
bridge flows जहां वही phone number अलग meetings का प्रतिनिधित्व कर सकता है,
तब sessionScope: "per-call" सेट करें।
Voice Call generated session keys को configured agent namespace
(agent:<agentId>:voice:*) के अंतर्गत store करता है ताकि restarts के बाद
Gateway session-key canonicalization के बावजूद call memory बनी रहे। Raw explicit
integration keys उसी agent namespace का उपयोग करती हैं। canonical
agent:<configuredAgentId>:* key उस owner को बनाए रखती है, और उसके main aliases
core session.mainKey और global scope का सम्मान करते हैं। Foreign या malformed
agent:* input को configured agent के अंतर्गत opaque key की तरह scoped किया जाता है;
global और unknown global sentinels बने रहते हैं। Gateway startup default या
{agentId}-templated stores में पुराने raw keys को promote करता है जहां path एक
owner साबित करता है। Fixed custom stores में, ambiguous legacy rows untouched
रहते हैं क्योंकि उनमें owner चुनने के लिए पर्याप्त जानकारी नहीं होती; नए calls
canonical agent-scoped history का उपयोग करते हैं।
Realtime voice conversations
realtime live call audio के लिए full-duplex realtime voice provider चुनता है।
यह streaming से अलग है, जो केवल audio को realtime transcription providers को
forward करता है।
मौजूदा runtime व्यवहार:
realtime.enabledTwilio Media Streams के लिए समर्थित है।realtime.providerवैकल्पिक है। यदि unset है, तो Voice Call पहला registered realtime voice provider उपयोग करता है।- Bundled realtime voice providers: Google Gemini Live (
google) और OpenAI (openai), जो उनके provider plugins द्वारा registered हैं। - Provider-owned raw config
realtime.providers.<providerId>के अंतर्गत रहता है। - Voice Call shared
openclaw_agent_consultrealtime tool को डिफ़ॉल्ट रूप से expose करता है। जब caller deeper reasoning, current information, या सामान्य OpenClaw tools मांगता है, तो realtime model इसे call कर सकता है। realtime.consultPolicyवैकल्पिक रूप से guidance जोड़ता है कि realtime model कोopenclaw_agent_consultकब call करना चाहिए।realtime.agentContext.enableddefault-off है। enabled होने पर, Voice Call session setup पर realtime provider instructions में bounded agent identity और selected workspace-file capsule inject करता है।realtime.fastContext.enableddefault-off है। enabled होने पर, Voice Call पहले consult question के लिए indexed memory/session context खोजता है और full consult agent पर fallback करने से पहले उन snippets कोrealtime.fastContext.timeoutMsके भीतर realtime model को लौटाता है, केवल यदिrealtime.fastContext.fallbackToConsulttrue हो।- यदि
realtime.providerunregistered provider की ओर point करता है, या कोई realtime voice provider registered नहीं है, तो Voice Call पूरे Plugin को fail करने के बजाय warning log करता है और realtime media छोड़ देता है। - Consult session keys उपलब्ध होने पर stored call session का reuse करती हैं, फिर configured
sessionScopeपर fallback करती हैं (डिफ़ॉल्ट रूप सेper-phone, या isolated calls के लिएper-call)।
Tool policy
realtime.toolPolicy consult run को control करता है:
| नीति | व्यवहार |
|---|---|
safe-read-only | consult tool expose करें और regular agent को read, web_search, web_fetch, x_search, memory_search, और memory_get तक सीमित करें। |
owner | consult tool expose करें और regular agent को normal agent tool policy उपयोग करने दें। |
none | consult tool expose न करें। Custom realtime.tools अब भी realtime provider तक pass through होते हैं। |
realtime.consultPolicy केवल realtime model instructions को control करता है:
| नीति | Guidance |
|---|---|
auto | default prompt रखें और provider को decide करने दें कि consult tool कब call करना है। |
substantive | simple conversational glue का सीधे answer दें और facts, memory, tools, या context से पहले consult करें। |
always | हर substantive answer से पहले consult करें। |
Agent voice context
सामान्य टर्न पर पूर्ण एजेंट-कंसल्ट राउंड ट्रिप का खर्च किए बिना, जब वॉइस ब्रिज को कॉन्फ़िगर किए गए OpenClaw एजेंट जैसा सुनाई देना चाहिए, तबrealtime.agentContext सक्षम करें। संदर्भ कैप्सूल रीयलटाइम सत्र बनाते समय एक बार जोड़ा जाता है, इसलिए यह प्रति-टर्न विलंबता नहीं जोड़ता। openclaw_agent_consult को की गई कॉल अब भी पूरा OpenClaw एजेंट चलाती हैं और इन्हें टूल कार्य, वर्तमान जानकारी, मेमोरी लुकअप, या workspace स्थिति के लिए उपयोग किया जाना चाहिए।
रीयलटाइम प्रदाता उदाहरण
- Google Gemini Live
- OpenAI
डिफ़ॉल्ट: API कुंजी
realtime.providers.google.apiKey,
GEMINI_API_KEY, या GOOGLE_GENERATIVE_AI_API_KEY से; मॉडल
gemini-2.5-flash-native-audio-preview-12-2025; वॉइस Kore।
लंबी, फिर से कनेक्ट हो सकने वाली कॉल के लिए sessionResumption और
contextWindowCompression डिफ़ॉल्ट रूप से चालू रहते हैं। टेलीफ़ोनी ऑडियो पर
तेज़ टर्न-टेकिंग ट्यून करने के लिए silenceDurationMs, startSensitivity, और
endSensitivity का उपयोग करें।स्ट्रीमिंग ट्रांसक्रिप्शन
streaming लाइव कॉल ऑडियो के लिए एक रीयलटाइम ट्रांसक्रिप्शन प्रदाता चुनता है।
वर्तमान runtime व्यवहार:
streaming.providerवैकल्पिक है। यदि सेट नहीं है, तो वॉइस कॉल पहले पंजीकृत रीयलटाइम ट्रांसक्रिप्शन प्रदाता का उपयोग करता है।- बंडल किए गए रीयलटाइम ट्रांसक्रिप्शन प्रदाता: Deepgram (
deepgram), ElevenLabs (elevenlabs), Mistral (mistral), OpenAI (openai), और xAI (xai), जिन्हें उनके प्रदाता plugins द्वारा पंजीकृत किया जाता है। - प्रदाता-स्वामित्व वाला raw config
streaming.providers.<providerId>के अंतर्गत रहता है। - Twilio द्वारा स्वीकृत stream
startसंदेश भेजने के बाद, वॉइस कॉल stream को तुरंत पंजीकृत करता है, प्रदाता के कनेक्ट होने के दौरान inbound media को ट्रांसक्रिप्शन प्रदाता के माध्यम से queue करता है, और प्रारंभिक greeting केवल रीयलटाइम ट्रांसक्रिप्शन तैयार होने के बाद शुरू करता है। - यदि
streaming.providerकिसी अपंजीकृत प्रदाता की ओर इशारा करता है, या कोई भी पंजीकृत नहीं है, तो वॉइस कॉल चेतावनी log करता है और पूरे plugin को विफल करने के बजाय media streaming छोड़ देता है।
स्ट्रीमिंग प्रदाता उदाहरण
- OpenAI
- xAI
डिफ़ॉल्ट: API कुंजी
streaming.providers.openai.apiKey या
OPENAI_API_KEY; मॉडल gpt-4o-transcribe; silenceDurationMs: 800;
vadThreshold: 0.5।कॉल के लिए TTS
वॉइस कॉल, कॉल पर streaming speech के लिए coremessages.tts कॉन्फ़िगरेशन का उपयोग करता है। आप इसे plugin config के अंतर्गत उसी shape से override कर सकते हैं — यह messages.tts के साथ deep-merge होता है।
- plugin config के अंदर legacy
tts.<provider>कुंजियां (openai,elevenlabs,microsoft,edge)openclaw doctor --fixद्वारा repair की जाती हैं; committed config कोtts.providers.<provider>का उपयोग करना चाहिए। - Twilio media streaming सक्षम होने पर core TTS का उपयोग किया जाता है; अन्यथा calls प्रदाता-native voices पर fallback करती हैं।
- यदि Twilio media stream पहले से सक्रिय है, तो वॉइस कॉल TwiML
<Say>पर fallback नहीं करता। यदि उस स्थिति में telephony TTS उपलब्ध नहीं है, तो playback request दो playback paths मिलाने के बजाय विफल हो जाती है। - जब telephony TTS किसी secondary provider पर fallback करता है, तो वॉइस कॉल debugging के लिए provider chain (
from,to,attempts) के साथ चेतावनी log करता है। - जब Twilio barge-in या stream teardown pending TTS queue को clear करता है, तो queued playback requests, playback completion की प्रतीक्षा कर रहे callers को अटकाने के बजाय settle हो जाती हैं।
TTS उदाहरण
- Core TTS only
- Override to ElevenLabs (calls only)
- OpenAI model override (deep-merge)
Inbound calls
Inbound policy का defaultdisabled है। inbound calls सक्षम करने के लिए, सेट करें:
responseModel,
responseSystemPrompt, और responseTimeoutMs से ट्यून करें।
प्रति-number Routing
जब एक वॉइस कॉल Plugin कई phone numbers के लिए calls प्राप्त करता है और हर number को अलग line की तरह व्यवहार करना चाहिए, तबnumbers का उपयोग करें। उदाहरण के लिए, एक number casual personal assistant का उपयोग कर सकता है, जबकि दूसरा business persona, अलग response agent, और अलग TTS voice का उपयोग करता है।
Routes प्रदाता द्वारा दिए गए dialed To number से चुने जाते हैं। Keys
E.164 numbers होनी चाहिए। जब call आती है, वॉइस कॉल matching route को एक बार resolve करता है,
matched route को call record पर store करता है, और greeting, classic auto-response path, realtime consult path, और TTS
playback के लिए उसी effective config को reuse करता है। यदि कोई route match नहीं करता, तो global वॉइस कॉल config का उपयोग होता है।
Outbound calls numbers का उपयोग नहीं करतीं; call शुरू करते समय outbound target, message, और
session स्पष्ट रूप से pass करें।
Route overrides वर्तमान में support करते हैं:
inboundGreetingttsagentIdresponseModelresponseSystemPromptresponseTimeoutMs
tts route value global वॉइस कॉल tts config के ऊपर deep-merge होती है, इसलिए
आप आमतौर पर केवल provider voice override कर सकते हैं:
बोले गए output contract
Auto-responses के लिए, वॉइस कॉल system prompt में एक strict spoken-output contract जोड़ता है:- reasoning/error content के रूप में चिह्नित payloads को अनदेखा करता है।
- direct JSON, fenced JSON, या inline
"spoken"keys parse करता है। - plain text पर fallback करता है और संभावित planning/meta lead-in paragraphs हटाता है।
Conversation startup behavior
Outboundconversation calls के लिए, first-message handling live
playback state से बंधी है:
- Barge-in queue clear और auto-response केवल तब suppress होते हैं जब initial greeting सक्रिय रूप से बोल रहा हो।
- यदि initial playback विफल हो जाता है, तो call
listeningपर लौट आती है और initial message retry के लिए queued रहता है। - Twilio streaming के लिए initial playback stream connect पर बिना extra delay के शुरू होता है।
- Barge-in active playback को abort करता है और queued-but-not-yet-playing Twilio TTS entries को clear करता है। Cleared entries skipped के रूप में resolve होती हैं, ताकि follow-up response logic कभी न चलने वाले audio की प्रतीक्षा किए बिना जारी रह सके।
- Realtime voice conversations realtime stream के अपने opening turn का उपयोग करती हैं। वॉइस कॉल उस initial message के लिए legacy
<Say>TwiML update post नहीं करता, इसलिए outbound<Connect><Stream>sessions attached रहते हैं।
Twilio stream disconnect grace
जब Twilio मीडिया स्ट्रीम डिस्कनेक्ट होती है, Voice Call कॉल को अपने-आप समाप्त करने से पहले 2000 ms प्रतीक्षा करता है:- अगर उस अवधि में स्ट्रीम फिर से कनेक्ट हो जाती है, तो auto-end रद्द कर दिया जाता है।
- अगर grace period के बाद कोई स्ट्रीम फिर से register नहीं होती, तो अटकी हुई सक्रिय कॉलों को रोकने के लिए कॉल समाप्त कर दी जाती है।
पुरानी कॉल reaper
उन कॉलों को समाप्त करने के लिएstaleCallReaperSeconds का उपयोग करें जिन्हें कभी terminal
webhook नहीं मिलता (उदाहरण के लिए, notify-mode कॉल जो कभी पूरी नहीं होतीं)। डिफ़ॉल्ट
0 है (disabled)।
अनुशंसित रेंज:
- Production: notify-style flows के लिए
120–300सेकंड। - इस मान को
maxDurationSecondsसे अधिक रखें ताकि सामान्य कॉल पूरी हो सकें। एक अच्छा शुरुआती मानmaxDurationSeconds + 30–60सेकंड है।
Webhook सुरक्षा
जब Gateway के सामने कोई proxy या tunnel होता है, तो Plugin signature verification के लिए public URL को फिर से बनाता है। ये विकल्प नियंत्रित करते हैं कि कौन-से forwarded headers trusted हैं:forwarding headers से hosts को allowlist करें।
allowlist के बिना forwarded headers पर trust करें।
forwarded headers पर केवल तब trust करें जब request remote IP सूची से match करे।
- Twilio और Plivo के लिए Webhook replay protection enabled है। replay की गई valid webhook requests को acknowledge किया जाता है, लेकिन side effects के लिए skip किया जाता है।
- Twilio conversation turns में
<Gather>callbacks में प्रति-turn token शामिल होता है, इसलिए stale/replayed speech callbacks किसी नए pending transcript turn को satisfy नहीं कर सकते। - जब provider के required signature headers missing होते हैं, तो unauthenticated webhook requests को body reads से पहले reject कर दिया जाता है।
- voice-call webhook shared pre-auth body profile (64 KB / 5 सेकंड) और signature verification से पहले per-IP in-flight cap का उपयोग करता है।
CLI
voicecall commands Gateway-owned
voice-call runtime को delegate करते हैं ताकि CLI दूसरा webhook server bind न करे।
अगर कोई Gateway reachable नहीं है, तो commands standalone CLI runtime पर fall back करती हैं।
latency default voice-call storage path से calls.jsonl पढ़ता है।
किसी अलग log की ओर point करने के लिए --file <path> और analysis को अंतिम N records
तक सीमित करने के लिए --last <n> का उपयोग करें (default 200)। Output में turn latency
और listen-wait times के लिए p50/p90/p99 शामिल होते हैं।
Agent tool
Tool नाम:voice_call.
| Action | Args |
|---|---|
initiate_call | message, to?, mode?, dtmfSequence? |
continue_call | callId, message |
speak_to_user | callId, message |
send_dtmf | callId, digits |
end_call | callId |
get_status | callId |
Gateway RPC
| Method | Args |
|---|---|
voicecall.initiate | to?, message, mode?, dtmfSequence? |
voicecall.continue | callId, message |
voicecall.speak | callId, message |
voicecall.dtmf | callId, digits |
voicecall.end | callId |
voicecall.status | callId |
dtmfSequence केवल mode: "conversation" के साथ valid है। Notify-mode calls को
post-connect digits की आवश्यकता होने पर call मौजूद होने के बाद voicecall.dtmf का
उपयोग करना चाहिए।
समस्या निवारण
Setup webhook exposure में fail होता है
उसी environment से setup चलाएं जो Gateway चलाता है:twilio, telnyx, और plivo के लिए, webhook-exposure green होना चाहिए। configured
publicUrl तब भी fail होता है जब वह local या private network space की ओर point करता है,
क्योंकि carrier उन addresses में callback नहीं कर सकता। publicUrl के रूप में
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 का उपयोग न करें।
Twilio notify-mode outbound calls अपना initial <Say> TwiML सीधे create-call request में
भेजती हैं, इसलिए पहला spoken message Twilio के webhook TwiML fetch करने पर depend नहीं करता।
status callbacks, conversation calls, pre-connect DTMF, realtime streams, और post-connect call
control के लिए public webhook फिर भी required है।
एक public exposure path का उपयोग करें:
voicecall smoke dry run है, जब तक आप --yes pass नहीं करते।
Provider credentials fail होते हैं
selected provider और required credential fields जांचें:- Twilio:
twilio.accountSid,twilio.authToken, औरfromNumber, याTWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN, औरTWILIO_FROM_NUMBER. - Telnyx:
telnyx.apiKey,telnyx.connectionId,telnyx.publicKey, औरfromNumber. - Plivo:
plivo.authId,plivo.authToken, औरfromNumber.
Calls start होती हैं लेकिन provider webhooks नहीं आते
Confirm करें कि provider console exact public webhook URL की ओर point करता है:publicUrl,serve.pathसे अलग path की ओर point करता है।- Gateway start होने के बाद tunnel URL बदल गया।
- कोई proxy request forward करता है लेकिन host/proto headers strip या rewrite कर देता है।
- Firewall या DNS public hostname को Gateway के अलावा कहीं और route करता है।
- Gateway को Voice Call Plugin enabled किए बिना restart किया गया था।
webhookSecurity.allowedHosts को
public hostname पर set करें, या known proxy address के लिए webhookSecurity.trustedProxyIPs
का उपयोग करें। webhookSecurity.trustForwardingHeaders का उपयोग केवल तब करें जब proxy boundary
आपके control में हो।
Signature verification fail होता है
Provider signatures उस public URL के against check किए जाते हैं जिसे OpenClaw incoming request से reconstruct करता है। अगर signatures fail हों:- Confirm करें कि provider webhook URL scheme, host, और path सहित
publicUrlसे exactly match करता है। - ngrok free-tier URLs के लिए, tunnel hostname बदलने पर
publicUrlupdate करें। - Ensure करें कि proxy original host और proto headers preserve करता है, या
webhookSecurity.allowedHostsconfigure करें। - local testing के बाहर
skipSignatureVerificationenable न करें।
Google Meet Twilio joins fail होते हैं
Google Meet, Twilio dial-in joins के लिए इस Plugin का उपयोग करता है। पहले Voice Call verify करें:--dtmf-sequence जांचें। phone call healthy हो सकती है जबकि
meeting incorrect DTMF sequence को reject या ignore करे।
Google Meet, voicecall.start के माध्यम से pre-connect DTMF sequence के साथ Twilio phone leg
start करता है। PIN-derived sequences में leading Twilio wait digits के रूप में Google Meet Plugin का
voiceCall.dtmfDelayMs शामिल होता है। default 12 सेकंड है क्योंकि Meet dial-in prompts देर से आ सकते हैं।
Voice Call फिर intro greeting requested होने से पहले realtime handling पर वापस redirect करता है।
live phase trace के लिए openclaw logs --follow का उपयोग करें। healthy Twilio Meet
join इस order को log करता है:
- Google Meet Twilio join को Voice Call को delegate करता है।
- Voice Call pre-connect DTMF TwiML store करता है।
- Twilio initial TwiML consume और serve होता है, realtime handling से पहले।
- Voice Call Twilio call के लिए realtime TwiML serve करता है।
- Google Meet post-DTMF delay के बाद
voicecall.speakके साथ intro speech request करता है।
openclaw voicecall tail अभी भी persisted call records दिखाता है; यह
call state और transcripts के लिए उपयोगी है, लेकिन हर webhook/realtime transition
वहां दिखाई नहीं देता।
Realtime call में speech नहीं है
Confirm करें कि केवल एक audio mode enabled है।realtime.enabled और
streaming.enabled दोनों true नहीं हो सकते।
realtime Twilio calls के लिए, यह भी verify करें:
- एक realtime provider Plugin loaded और registered है।
realtime.providerunset है या किसी registered provider को नाम देता है।- provider API key Gateway process के लिए available है।
openclaw logs --followदिखाता है कि realtime TwiML served है, realtime bridge started है, और initial greeting queued है।