Plugin guides
Plugin panggilan suara
Panggilan suara untuk OpenClaw melalui plugin: notifikasi keluar, percakapan multi-giliran, suara waktu nyata dupleks penuh, transkripsi streaming, dan panggilan masuk dengan kebijakan daftar izin.
Penyedia: mock (pengembangan, tanpa jaringan), plivo (API Suara + transfer XML +
ucapan GetInput), telnyx (Call Control v2), twilio (Suara Terprogram +
Media Streams).
Mulai cepat
Instal plugin
Dari npm
openclaw plugins install @openclaw/voice-callDari folder lokal (pengembangan)
PLUGIN_SRC=./path/to/local/voice-call-pluginopenclaw plugins install "$PLUGIN_SRC"cd "$PLUGIN_SRC" && pnpm installGunakan paket tanpa versi untuk mengikuti tag rilis saat ini. Sematkan versi yang tepat hanya saat Anda memerlukan instalasi yang dapat direproduksi. Setelah itu, mulai ulang Gateway agar plugin dimuat.
Konfigurasikan penyedia dan webhook
Atur konfigurasi di bawah plugins.entries.voice-call.config (lihat
Konfigurasi di bawah). Setidaknya: provider, kredensial
penyedia, fromNumber, dan URL webhook yang dapat dijangkau secara publik.
Verifikasi penyiapan
openclaw voicecall setupopenclaw voicecall setup --jsonMemeriksa pengaktifan plugin, kredensial penyedia, eksposur webhook, dan
bahwa hanya satu mode audio (streaming atau realtime) yang aktif.
Uji cepat
openclaw voicecall smokeopenclaw voicecall smoke --to "+15555550123"Keduanya merupakan uji coba tanpa eksekusi secara default. Tambahkan --yes untuk melakukan panggilan
notifikasi keluar singkat:
openclaw voicecall smoke --to "+15555550123" --yesKonfigurasi
Jika enabled: true tetapi penyedia yang dipilih tidak memiliki kredensial, proses awal
Gateway mencatat peringatan penyiapan belum lengkap beserta kunci yang hilang dan melewati
inisialisasi runtime. Perintah, panggilan RPC, dan alat agen tetap mengembalikan
konfigurasi tepat yang hilang saat digunakan.
{ plugins: { entries: { "voice-call": { enabled: true, config: { provider: "twilio", // atau "telnyx" | "plivo" | "mock" fromNumber: "+15550001234", // atau TWILIO_FROM_NUMBER untuk Twilio toNumber: "+15550005678", sessionScope: "per-phone", // per-phone | per-call numbers: { "+15550009999": { inboundGreeting: "Silver Fox Cards, ada yang bisa saya bantu?", responseSystemPrompt: "Anda adalah spesialis kartu bisbol yang ringkas.", tts: { providers: { openai: { speakerVoice: "alloy" }, }, }, }, }, twilio: { accountSid: "ACxxxxxxxx", authToken: "...", // region: "ie1", // opsional: us1 | ie1 | au1; default-nya us1 }, telnyx: { apiKey: "...", connectionId: "...", // Kunci publik webhook Telnyx dari Mission Control Portal // (Base64; juga dapat diatur melalui TELNYX_PUBLIC_KEY). publicKey: "...", }, plivo: { authId: "MAxxxxxxxxxxxxxxxxxxxx", authToken: "...", }, // Server webhook serve: { port: 3334, path: "/voice/webhook", }, // Keamanan webhook (direkomendasikan untuk tunnel/proksi) webhookSecurity: { allowedHosts: ["voice.example.com"], trustedProxyIPs: ["100.64.0.1"], }, // Eksposur publik (pilih satu) // publicUrl: "https://example.ngrok.app/voice/webhook", // tunnel: { provider: "ngrok" }, // tailscale: { mode: "funnel", path: "/voice/webhook" }, outbound: { defaultMode: "notify", // notify | conversation }, streaming: { enabled: true /* khusus Twilio; lihat Transkripsi streaming */ }, realtime: { enabled: false /* lihat Percakapan suara waktu nyata */ }, }, }, }, },}Referensi konfigurasi
Kunci tingkat atas di bawah plugins.entries.voice-call.config yang tidak ditampilkan di atas:
| Kunci | Default | Catatan |
|---|---|---|
enabled |
false |
Sakelar aktif/nonaktif utama. |
inboundPolicy |
"disabled" |
disabled | allowlist | pairing | open. Lihat Panggilan masuk. |
allowFrom |
[] |
Daftar izin E.164 untuk inboundPolicy: "allowlist". |
maxDurationSeconds |
300 |
Batas keras durasi per panggilan, diterapkan terlepas dari status terjawab. |
staleCallReaperSeconds |
120 |
Lihat Pembersih panggilan usang. 0 menonaktifkannya. |
silenceTimeoutMs |
800 |
Deteksi keheningan akhir ucapan untuk alur klasik (non-waktu nyata). |
transcriptTimeoutMs |
180000 |
Waktu tunggu maksimum untuk transkrip penelepon sebelum menyerah pada satu giliran. |
ringTimeoutMs |
30000 |
Batas waktu berdering untuk panggilan keluar. |
maxConcurrentCalls |
1 |
Panggilan keluar yang melampaui batas ini ditolak. |
outbound.notifyHangupDelaySec |
3 |
Detik untuk menunggu setelah TTS sebelum menutup panggilan otomatis dalam mode notifikasi. |
skipSignatureVerification |
false |
Hanya untuk pengujian lokal; jangan pernah aktifkan dalam produksi. |
store |
tidak diatur | Mengganti jalur default $OPENCLAW_STATE_DIR/voice-calls (biasanya ~/.openclaw/voice-calls). |
agentId |
"main" |
Agen yang digunakan untuk pembuatan respons dan penyimpanan sesi. |
responseModel |
tidak diatur | Mengganti model default untuk respons klasik (non-waktu nyata). |
responseSystemPrompt |
dihasilkan | Prompt sistem khusus untuk respons klasik. |
responseTimeoutMs |
30000 |
Batas waktu pembuatan respons klasik (md). |
Twilio secara default menggunakan endpoint REST US1-nya. Untuk memproses panggilan di
Wilayah non-AS yang didukung, atur twilio.region ke ie1 atau au1 dan gunakan kredensial dari
Wilayah tersebut. Lihat
panduan REST API non-AS Twilio.
Catatan eksposur dan keamanan penyedia
- Twilio, Telnyx, dan Plivo semuanya memerlukan URL webhook yang dapat dijangkau secara publik.
mockadalah penyedia pengembangan lokal (tanpa panggilan jaringan).- Telnyx memerlukan
telnyx.publicKey(atauTELNYX_PUBLIC_KEY) kecualiskipSignatureVerificationbernilai true. skipSignatureVerificationhanya untuk pengujian lokal.- Pada tingkat gratis ngrok, atur
publicUrlke URL ngrok yang tepat; verifikasi tanda tangan selalu diterapkan. tunnel.allowNgrokFreeTierLoopbackBypass: truemengizinkan webhook Twilio dengan tanda tangan tidak valid hanya saattunnel.provider="ngrok"danserve.bindmerupakan loopback (agen lokal ngrok). Hanya untuk pengembangan lokal.- URL tingkat gratis ngrok dapat berubah atau menambahkan perilaku interstisial; jika
publicUrlbergeser, tanda tangan Twilio gagal. Produksi: pilih domain stabil atau funnel Tailscale.
Batas koneksi streaming
streaming.preStartTimeoutMs(default5000) menutup soket yang tidak pernah mengirim bingkaistartyang valid.streaming.maxPendingConnections(default32) membatasi total soket pra-mulai yang belum diautentikasi.streaming.maxPendingConnectionsPerIp(default4) membatasi soket pra-mulai yang belum diautentikasi per alamat IP sumber.streaming.maxConnections(default128) membatasi semua soket aliran media yang terbuka (tertunda + aktif).
Migrasi konfigurasi lama
Penguraian konfigurasi menormalkan kunci lama ini secara otomatis dan mencatat
peringatan yang menyebutkan jalur pengganti; shim dihapus dalam rilis mendatang
(2026.6.0), jadi jalankan openclaw doctor --fix untuk menulis ulang konfigurasi
yang telah di-commit ke bentuk kanonis:
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.includeSystemPromptdihapus (konteks waktu nyata sekarang menggunakan prompt agen yang dihasilkan)
Cakupan sesi
Secara default, Panggilan Suara menggunakan sessionScope: "per-phone" sehingga panggilan berulang dari
penelepon yang sama mempertahankan memori percakapan. Atur sessionScope: "per-call" ketika
setiap panggilan operator harus dimulai dengan konteks baru, misalnya alur resepsionis,
pemesanan, IVR, atau jembatan Google Meet, saat nomor telepon yang sama dapat
mewakili rapat yang berbeda.
Panggilan Suara menyimpan kunci sesi yang dihasilkan di bawah namespace agen yang dikonfigurasi
(agent:<agentId>:voice:*). Kunci integrasi eksplisit mentah diselesaikan ke dalam
namespace yang sama: kunci agent:<configuredAgentId>:* kanonis mempertahankan
pemilik tersebut dan mematuhi alias cakupan global/session.mainKey inti; masukan
agent:* asing atau cacat dicakup sebagai kunci opak di bawah agen yang
dikonfigurasi; global dan unknown tetap menjadi sentinel global.
Percakapan suara waktu nyata
realtime memilih penyedia suara waktu nyata dupleks penuh untuk audio panggilan langsung.
Ini terpisah dari streaming, yang hanya meneruskan audio ke penyedia
transkripsi waktu nyata.
Perilaku runtime saat ini:
realtime.enableddidukung untuk Twilio dan Telnyx.realtime.providerbersifat opsional. Jika tidak diatur, Voice Call menggunakan penyedia suara waktu nyata pertama yang terdaftar.- Penyedia suara waktu nyata bawaan: Google Gemini Live (
google) dan OpenAI (openai), yang didaftarkan oleh plugin penyedianya. - Konfigurasi mentah milik penyedia berada di bawah
realtime.providers.<providerId>. - Voice Call menyediakan alat waktu nyata bersama
openclaw_agent_consultsecara default. Model waktu nyata dapat memanggilnya ketika penelepon meminta penalaran yang lebih mendalam, informasi terkini, atau alat OpenClaw biasa. realtime.consultPolicysecara opsional menambahkan panduan mengenai kapan model waktu nyata harus memanggilopenclaw_agent_consult.realtime.agentContext.enableddinonaktifkan secara default. Saat diaktifkan, Voice Call menyisipkan identitas agen yang dibatasi dan kapsul file ruang kerja terpilih ke dalam instruksi penyedia waktu nyata saat penyiapan sesi.realtime.fastContext.enableddinonaktifkan secara default. Saat diaktifkan, Voice Call terlebih dahulu mencari konteks memori/sesi yang telah diindeks untuk pertanyaan konsultasi dan mengembalikan cuplikan tersebut kepada model waktu nyata dalam batasrealtime.fastContext.timeoutMs, sebelum beralih ke agen konsultasi lengkap hanya jikarealtime.fastContext.fallbackToConsultbernilai true.- Jika
realtime.providermengarah ke penyedia yang tidak terdaftar, atau sama sekali tidak ada penyedia suara waktu nyata yang terdaftar, Voice Call mencatat peringatan dan melewati media waktu nyata alih-alih menggagalkan seluruh plugin. inboundPolicytidak boleh berupa"disabled"ketikarealtime.enabledbernilai true;validateProviderConfigmenolak kombinasi tersebut.- Kunci sesi konsultasi menggunakan kembali sesi panggilan tersimpan jika tersedia, lalu beralih ke
sessionScopeyang dikonfigurasi (per-phonesecara default, atauper-calluntuk panggilan terisolasi).
Kebijakan alat
realtime.toolPolicy mengendalikan proses konsultasi:
| Kebijakan | Perilaku |
|---|---|
safe-read-only |
Sediakan alat konsultasi dan batasi agen reguler ke read, web_search, web_fetch, x_search, memory_search, dan memory_get. |
owner |
Sediakan alat konsultasi dan izinkan agen reguler menggunakan kebijakan alat agen normal. |
none |
Jangan sediakan alat konsultasi. realtime.tools khusus tetap diteruskan ke penyedia waktu nyata. |
realtime.consultPolicy hanya mengendalikan instruksi model waktu nyata:
| Kebijakan | Panduan |
|---|---|
auto |
Pertahankan prompt default dan biarkan penyedia menentukan kapan alat konsultasi harus dipanggil. |
substantive |
Jawab penghubung percakapan sederhana secara langsung dan lakukan konsultasi sebelum memberikan fakta, menggunakan memori, alat, atau konteks. |
always |
Lakukan konsultasi sebelum setiap jawaban substantif. |
Konteks suara agen
Aktifkan realtime.agentContext ketika jembatan suara harus terdengar seperti
agen OpenClaw yang dikonfigurasi tanpa menanggung perjalanan bolak-balik konsultasi agen penuh pada
interaksi biasa. Kapsul konteks ditambahkan satu kali saat sesi waktu nyata
dibuat, sehingga tidak menambah latensi per interaksi. Panggilan ke
openclaw_agent_consult tetap menjalankan agen OpenClaw lengkap dan sebaiknya digunakan
untuk pekerjaan alat, informasi terkini, pencarian memori, atau status ruang kerja.
{ plugins: { entries: { "voice-call": { config: { agentId: "main", realtime: { enabled: true, provider: "google", toolPolicy: "safe-read-only", consultPolicy: "substantive", agentContext: { enabled: true, maxChars: 6000, includeIdentity: true, includeWorkspaceFiles: true, files: ["SOUL.md", "IDENTITY.md", "USER.md"], }, }, }, }, }, },}Contoh penyedia waktu nyata
Google Gemini Live
Default: kunci API dari realtime.providers.google.apiKey, GEMINI_API_KEY,
atau GOOGLE_API_KEY; model gemini-3.1-flash-live-preview;
suara Kore. sessionResumption dan contextWindowCompression aktif secara default
untuk panggilan yang lebih panjang dan dapat disambungkan kembali. Gunakan silenceDurationMs,
startSensitivity, dan endSensitivity untuk menyesuaikan pergantian giliran yang lebih cepat pada
audio telepon.
{ plugins: { entries: { "voice-call": { config: { provider: "twilio", inboundPolicy: "allowlist", allowFrom: ["+15550005678"], realtime: { enabled: true, provider: "google", instructions: "Bicaralah dengan singkat. Panggil openclaw_agent_consult sebelum menggunakan alat yang lebih mendalam.", toolPolicy: "safe-read-only", consultPolicy: "substantive", consultThinkingLevel: "low", consultFastMode: true, agentContext: { enabled: true }, providers: { google: { apiKey: "${GEMINI_API_KEY}", model: "gemini-3.1-flash-live-preview", speakerVoice: "Kore", silenceDurationMs: 500, startSensitivity: "high", }, }, }, }, }, }, },}OpenAI
{ plugins: { entries: { "voice-call": { config: { realtime: { enabled: true, provider: "openai", providers: { openai: { apiKey: "${OPENAI_API_KEY}" }, }, }, }, }, }, },}Lihat penyedia Google dan penyedia OpenAI untuk opsi suara waktu nyata khusus penyedia.
Transkripsi streaming
streaming menghubungkan Twilio Media Streams ke penyedia transkripsi waktu nyata.
Jalur streaming klasik memerlukan provider: "twilio"; konfigurasi dengan
Telnyx, Plivo, atau mock ditolak. Audio langsung Telnyx menggunakan jalur
realtime.enabled yang diautentikasi secara terpisah.
Perilaku runtime saat ini:
streaming.providerbersifat opsional. Jika tidak diatur, Voice Call menggunakan penyedia transkripsi waktu nyata pertama yang terdaftar.- Penyedia transkripsi waktu nyata bawaan: Deepgram (
deepgram), ElevenLabs (elevenlabs), Mistral (mistral), OpenAI (openai), dan xAI (xai), yang didaftarkan oleh plugin penyedianya. - Konfigurasi mentah milik penyedia berada di bawah
streaming.providers.<providerId>. - Setelah Twilio mengirim pesan stream
startyang diterima, Voice Call segera mendaftarkan stream tersebut, mengantrekan media masuk melalui penyedia transkripsi selagi penyedia tersambung, dan memulai sapaan awal hanya setelah transkripsi waktu nyata siap. - Jika
streaming.providermengarah ke penyedia yang tidak terdaftar, atau tidak ada penyedia yang terdaftar, Voice Call mencatat peringatan dan melewati streaming media alih-alih menggagalkan seluruh plugin.
Contoh penyedia streaming
OpenAI
Default: kunci API streaming.providers.openai.apiKey atau
OPENAI_API_KEY; model gpt-4o-transcribe; silenceDurationMs: 800;
vadThreshold: 0.5.
{ plugins: { entries: { "voice-call": { config: { streaming: { enabled: true, provider: "openai", streamPath: "/voice/stream", providers: { openai: { apiKey: "sk-...", // opsional jika OPENAI_API_KEY diatur model: "gpt-4o-transcribe", silenceDurationMs: 800, vadThreshold: 0.5, }, }, }, }, }, }, },}xAI
Default: kunci API streaming.providers.xai.apiKey atau XAI_API_KEY (beralih
ke profil autentikasi OAuth xAI jika keduanya tidak diatur); endpoint
wss://api.x.ai/v1/stt; pengodean mulaw; laju sampel 8000;
endpointingMs: 800; interimResults: true.
{ plugins: { entries: { "voice-call": { config: { streaming: { enabled: true, provider: "xai", streamPath: "/voice/stream", providers: { xai: { apiKey: "${XAI_API_KEY}", // opsional jika XAI_API_KEY diatur endpointingMs: 800, language: "en", }, }, }, }, }, }, },}TTS untuk panggilan
Voice Call menggunakan konfigurasi inti messages.tts untuk ucapan streaming pada
panggilan. Anda dapat menggantinya di bawah konfigurasi plugin dengan bentuk yang sama —
konfigurasi tersebut digabungkan secara mendalam dengan messages.tts.
{ tts: { provider: "elevenlabs", providers: { elevenlabs: { speakerVoiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, },}Catatan perilaku:
- Kunci
tts.<provider>lama di dalam konfigurasi plugin (openai,elevenlabs,microsoft,edge) diperbaiki olehopenclaw doctor --fix; konfigurasi yang di-commit harus menggunakantts.providers.<provider>. - TTS inti digunakan ketika streaming media Twilio diaktifkan; jika tidak, panggilan beralih ke suara bawaan penyedia.
- Jika stream media Twilio sudah aktif, Voice Call tidak beralih ke
OPENCLAW_DOCS_MARKER:calloutOpen:U2F5TwiML. Jika TTS telepon tidak tersedia dalam keadaan tersebut, permintaan pemutaran akan gagal alih-alih mencampurkan dua jalur pemutaran. - Ketika TTS telepon beralih ke penyedia sekunder, Voice Call mencatat peringatan beserta rantai penyedia (
from,to,attempts) untuk proses debug. - Ketika interupsi Twilio atau penghentian stream menghapus antrean TTS yang tertunda, permintaan pemutaran dalam antrean diselesaikan alih-alih membuat penelepon yang menunggu penyelesaian pemutaran terus tertahan.
Contoh TTS
Hanya TTS inti
{messages: {tts: {provider: "openai",providers: { openai: { speakerVoice: "alloy" },},},},}Ganti ke ElevenLabs (hanya panggilan)
{plugins: {entries: {"voice-call": { config: { tts: { provider: "elevenlabs", providers: { elevenlabs: { apiKey: "elevenlabs_key", speakerVoiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }, },},},},}Penggantian model OpenAI (deep-merge)
{plugins: {entries: {"voice-call": { config: { tts: { providers: { openai: { model: "gpt-4o-mini-tts", speakerVoice: "marin", }, }, }, },},},},}Panggilan masuk
Kebijakan panggilan masuk secara default adalah disabled. Untuk mengaktifkan panggilan masuk, tetapkan:
{inboundPolicy: "allowlist",allowFrom: ["+15550001234"],inboundGreeting: "Halo! Ada yang bisa saya bantu?",}Respons otomatis menggunakan sistem agen. Sesuaikan dengan responseModel,
responseSystemPrompt, dan responseTimeoutMs.
Perutean per nomor
Gunakan numbers saat satu Plugin Voice Call menerima panggilan untuk beberapa nomor
telepon dan setiap nomor harus berperilaku seperti saluran yang berbeda. Misalnya,
satu nomor dapat menggunakan asisten pribadi yang santai, sementara nomor lain menggunakan persona
bisnis, agen respons yang berbeda, dan suara TTS yang berbeda.
Rute dipilih dari nomor To yang dihubungi dan diberikan oleh penyedia. Kunci harus
berupa nomor E.164. Saat panggilan masuk, Voice Call menentukan rute yang cocok
satu kali, menyimpan rute yang cocok pada catatan panggilan, dan menggunakan kembali
konfigurasi efektif tersebut untuk salam, jalur respons otomatis klasik, jalur
konsultasi realtime, dan pemutaran TTS. Jika tidak ada rute yang cocok, konfigurasi
Voice Call global akan digunakan. Panggilan keluar tidak menggunakan numbers; teruskan target
keluar, pesan, dan sesi secara eksplisit saat memulai panggilan.
Penggantian rute saat ini mendukung:
inboundGreetingttsagentIdresponseModelresponseSystemPromptresponseTimeoutMs
Nilai rute tts di-deep-merge ke atas konfigurasi tts Voice Call global, sehingga
Anda biasanya cukup mengganti suara penyedia:
{inboundGreeting: "Halo dari saluran utama.",responseSystemPrompt: "Anda adalah asisten suara default.",tts: { provider: "openai", providers: { openai: { speakerVoice: "coral" }, },},numbers: { "+15550001111": { inboundGreeting: "Silver Fox Cards, ada yang bisa saya bantu?", responseSystemPrompt: "Anda adalah spesialis kartu bisbol yang ringkas.", tts: { providers: { openai: { speakerVoice: "alloy" }, }, }, },},}Kontrak keluaran lisan
Untuk respons otomatis, Voice Call menambahkan kontrak keluaran lisan yang ketat ke
prompt sistem yang mewajibkan balasan JSON {"spoken":"..."}. Voice Call
mengekstrak teks ucapan secara defensif:
- Mengabaikan muatan yang ditandai sebagai konten penalaran/kesalahan.
- Mengurai JSON langsung, JSON berpagar, atau kunci
"spoken"sebaris. - Menggunakan teks biasa sebagai cadangan dan menghapus paragraf pembuka yang kemungkinan berisi perencanaan/meta.
Hal ini menjaga agar pemutaran lisan tetap berfokus pada teks yang ditujukan kepada penelepon dan mencegah teks perencanaan bocor ke audio.
Perilaku awal percakapan
Untuk panggilan conversation keluar, penanganan pesan pertama terikat pada status
pemutaran langsung:
- Pengosongan antrean saat interupsi dan respons otomatis hanya ditekan selama salam awal sedang aktif diucapkan.
- Jika pemutaran awal gagal, panggilan kembali ke
listeningdan pesan awal tetap dalam antrean untuk dicoba kembali. - Pemutaran awal untuk streaming Twilio dimulai saat stream tersambung tanpa penundaan tambahan.
- Interupsi membatalkan pemutaran aktif dan menghapus entri TTS Twilio yang sudah mengantre tetapi belum diputar. Entri yang dihapus diselesaikan sebagai dilewati, sehingga logika respons lanjutan dapat diteruskan tanpa menunggu audio yang tidak akan pernah diputar.
- Percakapan suara realtime menggunakan giliran pembuka milik stream realtime itu sendiri. Voice Call tidak mengirim pembaruan TwiML
OPENCLAW_DOCS_MARKER:calloutOpen:U2F5lama untuk pesan awal tersebut, sehingga sesi<Connect><Stream>keluar tetap terhubung.
Masa tenggang pemutusan stream Twilio
Saat stream media Twilio terputus, Voice Call menunggu 2000 ms sebelum mengakhiri panggilan secara otomatis:
- Jika stream tersambung kembali selama jangka waktu tersebut, pengakhiran otomatis dibatalkan.
- Jika tidak ada stream yang didaftarkan kembali setelah masa tenggang, panggilan diakhiri untuk mencegah panggilan aktif macet.
Pembersih panggilan kedaluwarsa
Gunakan staleCallReaperSeconds (default 120) untuk mengakhiri panggilan yang tidak pernah
dijawab dan tidak pernah mencapai status percakapan langsung, misalnya panggilan mode notifikasi
ketika penyedia tidak pernah mengirimkan Webhook terminal. Tetapkan ke 0 untuk
menonaktifkannya.
Pembersih berjalan setiap 30 detik dan hanya mengakhiri panggilan yang tidak memiliki
stempel waktu answeredAt serta belum berada dalam status terminal atau langsung
(speaking/listening), sehingga percakapan yang telah dijawab tidak pernah dibersihkan
oleh pewaktu ini; maxDurationSeconds (default 300) adalah batas terpisah yang
mengakhiri panggilan terjawab yang berlangsung terlalu lama.
Untuk alur bergaya notifikasi ketika operator dapat lambat mengirimkan Webhook
dering/jawab, naikkan staleCallReaperSeconds melebihi nilai default agar panggilan yang lambat tetapi normal
tidak dibersihkan terlalu dini; 120-300 detik merupakan rentang produksi yang
wajar.
{plugins: {entries: { "voice-call": { config: { maxDurationSeconds: 300, staleCallReaperSeconds: 120, }, },},},}Keamanan Webhook
Saat proksi atau tunnel berada di depan Gateway, Plugin merekonstruksi URL publik untuk verifikasi tanda tangan. Opsi berikut mengontrol header yang diteruskan dan dipercaya:
webhookSecurity.allowedHostsstring[]Host dalam daftar izin dari header penerusan.
webhookSecurity.trustForwardingHeadersbooleanPercayai header yang diteruskan tanpa daftar izin.
webhookSecurity.trustedProxyIPsstring[]Hanya percayai header yang diteruskan saat IP jarak jauh permintaan cocok dengan daftar.
Perlindungan tambahan:
- Perlindungan pemutaran ulang Webhook diaktifkan untuk Twilio, Telnyx, dan Plivo. Permintaan Webhook valid yang diputar ulang dikonfirmasi tetapi dilewati untuk efek samping.
- Giliran percakapan Twilio menyertakan token per giliran dalam callback
<Gather>, sehingga callback ucapan yang kedaluwarsa/diputar ulang tidak dapat memenuhi giliran transkrip tertunda yang lebih baru. - Permintaan Webhook yang tidak diautentikasi ditolak sebelum isi dibaca saat header tanda tangan yang diwajibkan penyedia tidak ada.
- Webhook voice-call menggunakan profil pembacaan isi pra-autentikasi bersama (ukuran isi maksimum 64 KB, batas waktu baca 5 detik) ditambah batas permintaan berjalan per kunci (8 permintaan bersamaan per kunci secara default) sebelum verifikasi tanda tangan.
Contoh dengan host publik yang stabil:
{plugins: {entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", webhookSecurity: { allowedHosts: ["voice.example.com"], }, }, },},},}CLI
openclaw voicecall call --to "+15555550123" --message "Halo dari OpenClaw"openclaw voicecall start --to "+15555550123" # alias untuk callopenclaw voicecall continue --call-id <id> --message "Ada pertanyaan?"openclaw voicecall speak --call-id <id> --message "Tunggu sebentar"openclaw voicecall dtmf --call-id <id> --digits "ww123456#"openclaw voicecall end --call-id <id>openclaw voicecall status --call-id <id>openclaw voicecall tailopenclaw voicecall latency # meringkas latensi giliran dari logopenclaw voicecall expose --mode funnelSaat Gateway sudah berjalan, perintah operasional voicecall
mendelegasikan ke runtime voice-call milik Gateway agar CLI tidak mengikat
server Webhook kedua. Jika tidak ada Gateway yang dapat dijangkau, perintah akan menggunakan
runtime CLI mandiri sebagai cadangan.
latency membaca calls.jsonl dari jalur penyimpanan voice-call default. Gunakan
--file <path> untuk menunjuk ke log yang berbeda dan --last <n> untuk membatasi
analisis pada N catatan terakhir (default 200). Keluaran mencakup min/maks/rata-rata,
p50, dan p95 untuk latensi giliran dan waktu tunggu mendengarkan.
Alat agen
Nama alat: voice_call.
| Tindakan | Argumen |
|---|---|
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 |
Plugin voice-call menyertakan skill agen yang sesuai.
RPC Gateway
| Metode | Argumen | Catatan |
|---|---|---|
voicecall.initiate |
to?, message, mode?, sessionKey?, requesterSessionKey? |
Menggunakan konfigurasi toNumber sebagai fallback jika to dihilangkan. |
voicecall.start |
to, message?, mode?, dtmfSequence?, sessionKey? |
Sama seperti initiate, tetapi juga menerima dtmfSequence sebelum tersambung. |
voicecall.continue |
callId, message |
Memblokir hingga giliran selesai; mengembalikan transkrip. |
voicecall.continue.start |
callId, message |
Varian asinkron: segera mengembalikan operationId. |
voicecall.continue.result |
operationId |
Melakukan polling pada operasi voicecall.continue.start yang tertunda untuk memperoleh hasilnya. |
voicecall.speak |
callId, message |
Berbicara tanpa menunggu; menggunakan jembatan waktu nyata saat realtime.enabled. |
voicecall.dtmf |
callId, digits |
|
voicecall.end |
callId |
|
voicecall.status |
callId? |
Hilangkan callId untuk mencantumkan semua panggilan aktif. |
dtmfSequence hanya valid dengan mode: "conversation"; panggilan mode notifikasi
harus menggunakan voicecall.dtmf setelah panggilan tersedia jika memerlukan digit
setelah tersambung.
Pemecahan masalah
Penyiapan gagal mengekspos Webhook
Jalankan penyiapan dari lingkungan yang sama dengan tempat Gateway berjalan:
openclaw voicecall setupopenclaw voicecall setup --jsonUntuk twilio, telnyx, dan plivo, webhook-exposure harus berstatus hijau. publicUrl yang
telah dikonfigurasi tetap gagal jika mengarah ke ruang jaringan lokal atau privat,
karena operator tidak dapat melakukan panggilan balik ke alamat tersebut.
Jangan gunakan 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, atau rentang NAT
tingkat operator lainnya sebagai publicUrl.
Panggilan keluar mode notifikasi Twilio mengirim TwiML OPENCLAW_DOCS_MARKER:calloutOpen:U2F5 awalnya secara langsung
dalam permintaan pembuatan panggilan, sehingga pesan lisan pertama tidak bergantung pada
Twilio yang mengambil TwiML Webhook. Webhook publik tetap diperlukan untuk callback
status, panggilan percakapan, DTMF sebelum tersambung, aliran waktu nyata, dan
kontrol panggilan setelah tersambung.
Gunakan satu jalur eksposur publik:
{plugins: {entries: {"voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", // atau tunnel: { provider: "ngrok" }, // atau tailscale: { mode: "funnel", path: "/voice/webhook" }, },},},},}Setelah mengubah konfigurasi, mulai ulang atau muat ulang Gateway, lalu jalankan:
openclaw voicecall setupopenclaw voicecall smokevoicecall smoke adalah uji coba tanpa eksekusi kecuali Anda memberikan --yes.
Kredensial penyedia gagal
Periksa penyedia yang dipilih dan bidang kredensial yang diwajibkan:
- Twilio:
twilio.accountSid,twilio.authToken, danfromNumber, atauTWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN, danTWILIO_FROM_NUMBER. - Telnyx:
telnyx.apiKey,telnyx.connectionId,telnyx.publicKey, danfromNumber, atauTELNYX_API_KEY,TELNYX_CONNECTION_ID, danTELNYX_PUBLIC_KEY. - Plivo:
plivo.authId,plivo.authToken, danfromNumber, atauPLIVO_AUTH_IDdanPLIVO_AUTH_TOKEN.
Kredensial harus tersedia di host Gateway. Mengedit profil shell lokal tidak memengaruhi Gateway yang sudah berjalan hingga Gateway dimulai ulang atau memuat ulang lingkungannya.
Panggilan dimulai, tetapi Webhook penyedia tidak diterima
Pastikan konsol penyedia mengarah ke URL Webhook publik yang tepat:
https://voice.example.com/voice/webhookKemudian periksa status runtime:
openclaw voicecall status --call-id <id>openclaw voicecall tailopenclaw logs --followPenyebab umum:
publicUrlmengarah ke jalur yang berbeda dariserve.path.- URL tunnel berubah setelah Gateway dimulai.
- Proksi meneruskan permintaan, tetapi menghapus atau menulis ulang header host/proto.
- Firewall atau DNS merutekan nama host publik ke lokasi selain Gateway.
- Gateway dimulai ulang tanpa mengaktifkan Plugin Voice Call.
Saat proksi terbalik atau tunnel berada di depan Gateway, atur
webhookSecurity.allowedHosts ke nama host publik, atau gunakan
webhookSecurity.trustedProxyIPs untuk alamat proksi yang dikenal. Gunakan
webhookSecurity.trustForwardingHeaders hanya saat batas proksi
berada di bawah kendali Anda.
Verifikasi tanda tangan gagal
Tanda tangan penyedia diperiksa terhadap URL publik yang direkonstruksi OpenClaw dari permintaan masuk. Jika tanda tangan gagal:
- Pastikan URL Webhook penyedia sama persis dengan
publicUrl, termasuk skema, host, dan jalur. - Untuk URL tingkat gratis ngrok, perbarui
publicUrlsaat nama host tunnel berubah. - Pastikan proksi mempertahankan header host dan proto asli, atau konfigurasikan
webhookSecurity.allowedHosts. - Jangan aktifkan
skipSignatureVerificationdi luar pengujian lokal.
Kegagalan bergabung ke Google Meet melalui Twilio
Google Meet menggunakan Plugin ini untuk bergabung melalui sambungan telepon Twilio. Pertama, verifikasi Voice Call:
openclaw voicecall setupopenclaw voicecall smoke --to "+15555550123"Kemudian verifikasi transport Google Meet secara eksplisit:
openclaw googlemeet setup --transport twilioJika Voice Call berstatus hijau, tetapi peserta Meet tidak pernah bergabung, periksa nomor
sambungan telepon Meet, PIN, dan --dtmf-sequence. Panggilan telepon dapat berfungsi dengan baik
sementara rapat menolak atau mengabaikan urutan DTMF yang salah.
Google Meet memulai bagian panggilan telepon Twilio melalui voicecall.start dengan
urutan DTMF sebelum tersambung. Urutan yang berasal dari PIN menyertakan
voiceCall.dtmfDelayMs milik Plugin Google Meet (default 12000 ms) sebagai digit tunggu
Twilio di awal, karena prompt sambungan telepon Meet dapat terlambat tiba. Voice Call kemudian
mengalihkan kembali ke penanganan waktu nyata sebelum salam pembuka diminta.
Gunakan openclaw logs --follow untuk pelacakan fase langsung. Proses bergabung ke Meet
melalui Twilio yang berfungsi dengan baik mencatat urutan ini:
- Google Meet mendelegasikan proses bergabung melalui Twilio kepada Voice Call.
- Voice Call menyimpan TwiML DTMF sebelum tersambung.
- TwiML awal Twilio digunakan dan disajikan sebelum penanganan waktu nyata.
- Voice Call menyajikan TwiML waktu nyata untuk panggilan Twilio.
- Google Meet meminta ucapan pembuka dengan
voicecall.speaksetelah penundaan pasca-DTMF.
openclaw voicecall tail tetap menampilkan rekaman panggilan yang dipertahankan; berguna untuk
status dan transkrip panggilan, tetapi tidak setiap transisi Webhook/waktu nyata
ditampilkan di sana.
Panggilan waktu nyata tidak mengeluarkan suara
Pastikan hanya satu mode audio yang diaktifkan: realtime.enabled dan
streaming.enabled tidak boleh sama-sama bernilai true.
Untuk panggilan Twilio/Telnyx waktu nyata, verifikasi juga:
- Plugin penyedia waktu nyata dimuat dan didaftarkan.
realtime.providertidak ditetapkan atau menyebutkan penyedia yang terdaftar.- Kunci API penyedia tersedia bagi proses Gateway.
openclaw logs --followmenampilkan TwiML waktu nyata disajikan, jembatan waktu nyata dimulai, dan salam awal dimasukkan ke antrean.