mock(開發用,無網路)、plivo(Voice API + XML transfer +
GetInput speech)、telnyx(Call Control v2)、twilio(Programmable Voice +
Media Streams)。
Voice Call 外掛會在 閘道程序內 執行。如果你使用
遠端閘道,請在執行閘道的機器上安裝並設定此外掛,
然後重新啟動閘道以載入它。
快速開始
設定提供者與網路鉤子
在
plugins.entries.voice-call.config 底下設定組態(見下方
設定)。最低需求:provider、提供者
認證、fromNumber,以及可公開連線的網路鉤子 URL。設定
如果enabled: true 但所選提供者缺少認證,閘道
啟動時會記錄一則設定未完成警告,列出缺少的鍵,並略過
啟動執行階段。命令、RPC 呼叫和代理工具在使用時仍會回傳
精確缺少的設定。
Voice-call 認證接受 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 會透過標準 SecretRef 介面解析;請參閱 SecretRef 認證介面。設定參考
上方未顯示的plugins.entries.voice-call.config 頂層鍵:
| 鍵 | 預設值 | 備註 |
|---|---|---|
enabled | false | 總開關。 |
inboundPolicy | "disabled" | disabled | allowlist | pairing | open。請參閱來電。 |
allowFrom | [] | inboundPolicy: "allowlist" 的 E.164 允許清單。 |
maxDurationSeconds | 300 | 每通電話的硬性通話時長上限,無論是否已接聽都會強制執行。 |
staleCallReaperSeconds | 120 | 請參閱過期通話清理器。0 會停用它。 |
silenceTimeoutMs | 800 | 傳統(非即時)流程的語音結束靜音偵測。 |
transcriptTimeoutMs | 180000 | 放棄某一輪之前,等待來電者轉錄文字的最長時間。 |
ringTimeoutMs | 30000 | 撥出電話的響鈴逾時。 |
maxConcurrentCalls | 1 | 超過此限制的撥出電話會被拒絕。 |
outbound.notifyHangupDelaySec | 3 | 通知模式中,TTS 之後自動掛斷前等待的秒數。 |
skipSignatureVerification | false | 僅限本機測試;切勿在正式環境啟用。 |
store | unset | 覆寫預設的 ~/.openclaw/voice-calls 通話記錄路徑。 |
agentId | "main" | 用於回應產生和工作階段儲存的代理。 |
responseModel | unset | 覆寫傳統(非即時)回應的預設模型。 |
responseSystemPrompt | generated | 傳統回應的自訂系統提示。 |
responseTimeoutMs | 30000 | 傳統回應產生的逾時時間(毫秒)。 |
提供者曝光與安全注意事項
提供者曝光與安全注意事項
- Twilio、Telnyx 和 Plivo 都需要 可公開連線 的網路鉤子 URL。
mock是本機開發提供者(不進行網路呼叫)。- Telnyx 需要
telnyx.publicKey(或TELNYX_PUBLIC_KEY),除非skipSignatureVerification為 true。 skipSignatureVerification僅供本機測試使用。- 在 ngrok 免費方案上,請將
publicUrl設為精確的 ngrok URL;簽章驗證一律會強制執行。 tunnel.allowNgrokFreeTierLoopbackBypass: true只有在tunnel.provider="ngrok"且serve.bind為 loopback(ngrok 本機代理程式)時,才允許簽章無效的 Twilio 網路鉤子。本機開發專用。- Ngrok 免費方案 URL 可能會變更或加入插頁行為;如果
publicUrl偏移,Twilio 簽章會失敗。正式環境:建議使用穩定網域或 Tailscale funnel。
串流連線上限
串流連線上限
streaming.preStartTimeoutMs(預設5000)會關閉從未傳送有效startframe 的 socket。streaming.maxPendingConnections(預設32)會限制未驗證的預啟動 socket 總數。streaming.maxPendingConnectionsPerIp(預設4)會限制每個來源 IP 的未驗證預啟動 socket 數量。streaming.maxConnections(預設128)會限制所有開啟的媒體串流 socket(待處理 + 作用中)。
舊版設定遷移
舊版設定遷移
設定剖析會自動正規化這些舊版鍵,並記錄
指出替代路徑的警告;此 shim 會在未來
版本(
2026.6.0)移除,因此請執行 openclaw doctor --fix,將已提交的
設定改寫為標準形狀:provider: "log"→provider: "mock"twilio.from→fromNumberstreaming.sttProvider→streaming.providerstreaming.openaiApiKey→streaming.providers.openai.apiKeystreaming.sttModel→streaming.providers.openai.modelstreaming.silenceDurationMs→streaming.providers.openai.silenceDurationMsstreaming.vadThreshold→streaming.providers.openai.vadThresholdrealtime.agentContext.includeSystemPrompt已移除(即時內容現在使用產生的代理提示)
工作階段範圍
預設情況下,Voice Call 使用sessionScope: "per-phone",因此來自
同一位來電者的重複來電會保留對話記憶。當
每通電信商通話都應以全新內容開始時,請設定 sessionScope: "per-call",
例如接待、訂位、IVR,或 Google Meet 橋接流程,其中相同電話號碼可能
代表不同會議。
Voice Call 會將產生的工作階段鍵儲存在設定的代理命名空間下
(agent:<agentId>:voice:*)。原始明確整合鍵會解析到
相同命名空間:標準的 agent:<configuredAgentId>:* 鍵會保留該
擁有者,並遵循核心 session.mainKey/全域範圍別名;外來或
格式錯誤的 agent:* 輸入會以不透明鍵的形式限定在設定的
代理底下;global 和 unknown 仍為全域哨兵值。
即時語音對話
realtime 會為即時通話音訊選擇全雙工即時語音提供者。
它與 streaming 分開,後者只會將音訊轉送給即時
轉錄提供者。
目前的執行階段行為:
- Twilio 和 Telnyx 支援
realtime.enabled。 realtime.provider是選用設定。若未設定,語音通話會使用第一個已註冊的即時語音提供者。- 內建即時語音提供者:Google Gemini Live (
google) 和 OpenAI (openai),由其提供者外掛註冊。 - 提供者擁有的原始設定位於
realtime.providers.<providerId>下。 - 語音通話預設公開共用的
openclaw_agent_consult即時工具。當來電者要求更深入的推理、即時資訊或一般 OpenClaw 工具時,即時模型可以呼叫它。 realtime.consultPolicy可選擇性加入指引,說明即時模型應在何時呼叫openclaw_agent_consult。realtime.agentContext.enabled預設關閉。啟用後,語音通話會在工作階段設定時,將有界的代理身分和選取的工作區檔案膠囊注入即時提供者指令。realtime.fastContext.enabled預設關閉。啟用後,語音通話會先在已索引的記憶/工作階段內容中搜尋諮詢問題,並在realtime.fastContext.timeoutMs內將這些片段傳回即時模型;只有在realtime.fastContext.fallbackToConsult為 true 時,才會後援到完整諮詢代理。- 如果
realtime.provider指向未註冊的提供者,或完全沒有註冊任何即時語音提供者,語音通話會記錄警告並略過即時媒體,而不是讓整個外掛失敗。 - 當
realtime.enabled為 true 時,inboundPolicy不得為"disabled";validateProviderConfig會拒絕這個組合。 - 諮詢工作階段金鑰會在可用時重用已儲存的通話工作階段,然後後援到已設定的
sessionScope(預設為per-phone,隔離通話則為per-call)。
工具政策
realtime.toolPolicy 控制諮詢執行:
| 政策 | 行為 |
|---|---|
safe-read-only | 公開諮詢工具,並將一般代理限制為 read、web_search、web_fetch、x_search、memory_search 和 memory_get。 |
owner | 公開諮詢工具,並讓一般代理使用一般代理工具政策。 |
none | 不公開諮詢工具。自訂 realtime.tools 仍會傳遞給即時提供者。 |
realtime.consultPolicy 只控制即時模型指令:
| 政策 | 指引 |
|---|---|
auto | 保留預設提示,並讓提供者決定何時呼叫諮詢工具。 |
substantive | 直接回答簡單的對話銜接內容,並在事實、記憶、工具或內容之前先諮詢。 |
always | 在每個實質回答之前先諮詢。 |
代理語音內容
當語音橋接應聽起來像已設定的 OpenClaw 代理,但又不想在一般輪次支付完整代理諮詢往返成本時,請啟用realtime.agentContext。內容膠囊會在建立即時工作階段時加入一次,因此不會增加每輪延遲。對 openclaw_agent_consult 的呼叫仍會執行完整 OpenClaw 代理,並應用於工具工作、即時資訊、記憶查詢或工作區狀態。
即時提供者範例
- Google Gemini Live
- OpenAI
預設值:API 金鑰來自
realtime.providers.google.apiKey、GEMINI_API_KEY 或 GOOGLE_API_KEY;模型 gemini-2.5-flash-native-audio-preview-12-2025;語音 Kore。sessionResumption 和 contextWindowCompression 預設開啟,適合較長且可重新連線的通話。使用 silenceDurationMs、startSensitivity 和 endSensitivity 來調整電話語音中的更快速輪替發話。串流轉錄
streaming 會為即時通話音訊選取即時轉錄提供者。
目前執行階段行為:
streaming.provider是選用設定。若未設定,語音通話會使用第一個已註冊的即時轉錄提供者。- 內建即時轉錄提供者:Deepgram (
deepgram)、ElevenLabs (elevenlabs)、Mistral (mistral)、OpenAI (openai) 和 xAI (xai),由其提供者外掛註冊。 - 提供者擁有的原始設定位於
streaming.providers.<providerId>下。 - Twilio 傳送已接受的串流
start訊息後,語音通話會立即註冊串流,在提供者連線時透過轉錄提供者佇列化傳入媒體,並且只有在即時轉錄就緒後才開始初始問候。 - 如果
streaming.provider指向未註冊的提供者,或沒有註冊任何提供者,語音通話會記錄警告並略過媒體串流,而不是讓整個外掛失敗。
串流提供者範例
- OpenAI
- xAI
預設值:API 金鑰
streaming.providers.openai.apiKey 或 OPENAI_API_KEY;模型 gpt-4o-transcribe;silenceDurationMs: 800;vadThreshold: 0.5。通話的 TTS
語音通話會使用核心messages.tts 設定來串流通話語音。你可以在外掛設定下以相同形狀覆寫它,它會與 messages.tts 深度合併。
- 外掛設定中的舊版
tts.<provider>金鑰(openai、elevenlabs、microsoft、edge)會由openclaw doctor --fix修復;已提交的設定應使用tts.providers.<provider>。 - 啟用 Twilio 媒體串流時會使用核心 TTS;否則通話會後援到提供者原生語音。
- 如果 Twilio 媒體串流已啟用,語音通話不會後援到 TwiML
<Say>。如果在該狀態下無法使用電話 TTS,播放請求會失敗,而不是混用兩條播放路徑。 - 當電話 TTS 後援到次要提供者時,語音通話會記錄包含提供者鏈(
from、to、attempts)的警告,以便偵錯。 - 當 Twilio 插話或串流拆除清除待處理 TTS 佇列時,已佇列的播放請求會完成結算,而不是讓等待播放完成的來電者卡住。
TTS 範例
- Core TTS only
- Override to ElevenLabs (calls only)
- OpenAI model override (deep-merge)
傳入通話
傳入政策預設為disabled。若要啟用傳入通話,請設定:
responseModel、responseSystemPrompt 和 responseTimeoutMs 調整。
依號碼路由
當一個 Voice Call 外掛接收多個電話號碼的來電,且每個號碼都應像不同線路一樣運作時,請使用numbers。例如,一個號碼可以使用輕鬆的個人助理,而另一個號碼使用商務 persona、不同的回應代理,以及不同的 TTS 語音。
路由會根據提供者提供的已撥 To 號碼選取。鍵必須是 E.164 號碼。來電抵達時,Voice Call 會解析一次相符路由,將相符路由儲存在通話記錄上,並重複使用該有效設定於問候語、傳統自動回應路徑、即時諮詢路徑與 TTS 播放。如果沒有相符路由,則使用全域 Voice Call 設定。撥出通話不使用 numbers;起始通話時請明確傳入撥出目標、訊息和工作階段。
路由覆寫目前支援:
inboundGreetingttsagentIdresponseModelresponseSystemPromptresponseTimeoutMs
tts 路由值會深度合併到全域 Voice Call tts 設定上,因此你通常只需要覆寫提供者語音:
語音輸出合約
針對自動回應,Voice Call 會在系統提示後附加嚴格的語音輸出合約,要求回覆{"spoken":"..."} JSON。Voice Call 會防禦性地擷取語音文字:
- 忽略標記為推理/錯誤內容的酬載。
- 解析直接 JSON、圍欄 JSON,或行內
"spoken"鍵。 - 回退為純文字,並移除疑似規劃/中繼說明的前導段落。
對話啟動行為
對於撥出的conversation 通話,第一則訊息處理會繫結到即時播放狀態:
- 只有在初始問候語正在主動播放時,插話佇列清除與自動回應才會被抑制。
- 如果初始播放失敗,通話會回到
listening,且初始訊息會保持佇列狀態以便重試。 - Twilio 串流的初始播放會在串流連線時開始,不會有額外延遲。
- 插話會中止作用中播放,並清除已排隊但尚未播放的 Twilio TTS 項目。被清除的項目會解析為已略過,因此後續回應邏輯可以繼續,而不必等待永遠不會播放的音訊。
- 即時語音對話使用即時串流自己的開場回合。Voice Call 不會為該初始訊息張貼舊式
<Say>TwiML 更新,因此撥出的<Connect><Stream>工作階段會保持附加。
Twilio 串流中斷寬限
當 Twilio 媒體串流中斷連線時,Voice Call 會等待 2000 ms 後才自動結束通話:- 如果串流在該時間窗內重新連線,自動結束會被取消。
- 如果寬限期後沒有串流重新註冊,通話會被結束,以防止卡住的作用中通話。
過期通話清理器
使用staleCallReaperSeconds(預設 120)來結束從未接聽且從未到達即時對話狀態的通話,例如提供者從未投遞終止網路鉤子的通知模式通話。設為 0 可停用。
清理器每 30 秒執行一次,且只會結束沒有 answeredAt 時間戳記、且尚未處於終止或即時(speaking/listening)狀態的通話,因此已接聽的對話永遠不會被此計時器清理;maxDurationSeconds(預設 300)是另一個上限,用於結束執行太久的已接聽通話。
對於電信業者可能較慢投遞響鈴/接聽網路鉤子的通知式流程,請將 staleCallReaperSeconds 提高到超過預設值,避免緩慢但正常的通話過早被清理;120-300 秒是合理的正式環境範圍。
網路鉤子安全性
當代理或通道位於閘道前方時,外掛會重建公開 URL 以進行簽章驗證。這些選項控制哪些轉送標頭受信任:來自轉送標頭的主機允許清單。
在沒有允許清單的情況下信任轉送標頭。
只有在請求遠端 IP 符合清單時才信任轉送標頭。
- Twilio、Telnyx 和 Plivo 會啟用網路鉤子重放保護。重放的有效網路鉤子請求會被確認,但會略過副作用。
- Twilio 對話回合會在
<Gather>回呼中包含每回合權杖,因此過期/重放的語音回呼無法滿足較新的待處理逐字稿回合。 - 當缺少提供者必要的簽章標頭時,未驗證的網路鉤子請求會在讀取本文前遭拒。
- voice-call 網路鉤子會使用共享的預驗證本文讀取設定檔(本文最大 64 KB、5 秒讀取逾時),並在簽章驗證前套用每鍵進行中上限(預設每個鍵 8 個並行請求)。
命令列介面
voicecall 命令會委派給閘道擁有的 voice-call 執行階段,因此命令列介面不會綁定第二個網路鉤子伺服器。如果無法連到閘道,命令會回退到獨立命令列介面執行階段。
latency 會從預設 voice-call 儲存路徑讀取 calls.jsonl。使用 --file <path> 指向不同記錄,並使用 --last <n> 將分析限制在最後 N 筆記錄(預設 200)。輸出包含回合延遲與聆聽等待時間的 min/max/avg、p50 和 p95。
代理工具
工具名稱:voice_call。
| 動作 | 引數 |
|---|---|
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 |
閘道 RPC
| 方法 | 引數 | 備註 |
|---|---|---|
voicecall.initiate | to?, message, mode?, sessionKey?, requesterSessionKey? | 當省略 to 時,回退為 toNumber 設定。 |
voicecall.start | to, message?, mode?, dtmfSequence?, sessionKey? | 與 initiate 相同,但也接受連線前 dtmfSequence。 |
voicecall.continue | callId, message | 封鎖直到回合解析;回傳逐字稿。 |
voicecall.continue.start | callId, message | 非同步變體:立即回傳 operationId。 |
voicecall.continue.result | operationId | 輪詢待處理的 voicecall.continue.start 操作以取得結果。 |
voicecall.speak | callId, message | 不等待即發話;當 realtime.enabled 時使用即時橋接。 |
voicecall.dtmf | callId, digits | |
voicecall.end | callId | |
voicecall.status | callId? | 省略 callId 可列出所有作用中通話。 |
dtmfSequence 只在 mode: "conversation" 時有效;通知模式通話若需要連線後數字,應在通話存在後使用 voicecall.dtmf。
疑難排解
設定無法暴露網路鉤子
請從執行閘道的相同環境執行設定:twilio、telnyx 和 plivo,webhook-exposure 必須為綠色。設定的 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 或其他電信業者級 NAT 範圍用作 publicUrl。
Twilio 通知模式撥出通話會在建立通話請求中直接傳送初始 <Say> TwiML,因此第一段語音訊息不依賴 Twilio 擷取網路鉤子 TwiML。狀態回呼、對話通話、連線前 DTMF、即時串流,以及連線後通話控制仍需要公開網路鉤子。
使用一個公開暴露路徑:
--yes,否則 voicecall smoke 是試執行。
提供者憑證失敗
檢查選取的提供者與必要的憑證欄位:- Twilio:
twilio.accountSid、twilio.authToken與fromNumber,或TWILIO_ACCOUNT_SID、TWILIO_AUTH_TOKEN與TWILIO_FROM_NUMBER。 - Telnyx:
telnyx.apiKey、telnyx.connectionId、telnyx.publicKey與fromNumber,或TELNYX_API_KEY、TELNYX_CONNECTION_ID與TELNYX_PUBLIC_KEY。 - Plivo:
plivo.authId、plivo.authToken與fromNumber,或PLIVO_AUTH_ID與PLIVO_AUTH_TOKEN。
通話開始但供應商網路鉤子未送達
確認供應商主控台指向確切的公開網路鉤子 URL:publicUrl指向與serve.path不同的路徑。- 閘道啟動後,通道 URL 已變更。
- 代理轉送了請求,但移除或重寫了 host/proto 標頭。
- 防火牆或 DNS 將公開主機名稱路由到閘道以外的位置。
- 閘道重新啟動時未啟用語音通話外掛。
webhookSecurity.allowedHosts 設為公開主機名稱,或針對已知代理位址使用
webhookSecurity.trustedProxyIPs。只有在代理邊界
受你控制時,才使用 webhookSecurity.trustForwardingHeaders。
簽章驗證失敗
供應商簽章會依據 OpenClaw 從傳入請求重建的公開 URL 進行檢查。 如果簽章失敗:- 確認供應商網路鉤子 URL 與
publicUrl完全相符,包括 scheme、host 與 path。 - 對於 ngrok 免費方案 URL,當通道主機名稱變更時更新
publicUrl。 - 確保代理保留原始 host 與 proto 標頭,或設定
webhookSecurity.allowedHosts。 - 不要在本機測試以外啟用
skipSignatureVerification。
Google Meet Twilio 加入失敗
Google Meet 會使用此外掛進行 Twilio 撥入加入。請先驗證語音 通話:--dtmf-sequence。電話通話可能是正常的,
但會議可能會拒絕或忽略不正確的 DTMF 序列。
Google Meet 會透過 voicecall.start 啟動 Twilio 電話通話端,
並使用預先連線 DTMF 序列。由 PIN 衍生的序列包含 Google Meet
外掛的 voiceCall.dtmfDelayMs(預設 12000 ms)作為前置 Twilio
等待數字,因為 Meet 撥入提示可能會較晚出現。接著語音通話會
在要求開場問候之前重新導向回即時處理。
使用 openclaw logs --follow 查看即時階段追蹤。正常的 Twilio Meet
加入會依此順序記錄:
- Google Meet 將 Twilio 加入委派給語音通話。
- 語音通話儲存預先連線 DTMF TwiML。
- Twilio 初始 TwiML 會在即時處理之前被取用並提供。
- 語音通話為 Twilio 通話提供即時 TwiML。
- Google Meet 在 DTMF 後延遲之後,使用
voicecall.speak要求開場語音。
openclaw voicecall tail 仍會顯示已持久化的通話記錄;這對
通話狀態與逐字稿很有用,但並非每個網路鉤子/即時轉換
都會出現在那裡。
即時通話沒有語音
確認只啟用一種音訊模式:realtime.enabled 與
streaming.enabled 不能同時為 true。
對於即時 Twilio/Telnyx 通話,另請驗證:
- 已載入並註冊即時供應商外掛。
realtime.provider未設定,或命名了一個已註冊的供應商。- 供應商 API 金鑰可供閘道程序使用。
openclaw logs --follow顯示已提供即時 TwiML、即時橋接已啟動,且初始問候已排入佇列。