Plugin guides
Plugin تماس صوتی
تماسهای صوتی برای OpenClaw از طریق یک Plugin: اعلانهای خروجی، مکالمات چندنوبتی، صدای بلادرنگ تمامدوطرفه، رونویسی جریانی و تماسهای ورودی با سیاستهای فهرست مجاز.
ارائهدهندگان: mock (توسعه، بدون شبکه)، plivo (Voice API + انتقال XML +
گفتار GetInput)، telnyx (Call Control v2)، twilio (Programmable Voice +
Media Streams).
شروع سریع
نصب Plugin
از npm
openclaw plugins install @openclaw/voice-callاز یک پوشه محلی (توسعه)
PLUGIN_SRC=./path/to/local/voice-call-pluginopenclaw plugins install "$PLUGIN_SRC"cd "$PLUGIN_SRC" && pnpm installبرای دنبالکردن برچسب انتشار فعلی، از بسته بدون نسخه استفاده کنید. تنها زمانی نسخهای دقیق را ثابت کنید که به نصبی تکرارپذیر نیاز دارید. پس از آن Gateway را مجدداً راهاندازی کنید تا Plugin بارگذاری شود.
پیکربندی ارائهدهنده و Webhook
پیکربندی را در plugins.entries.voice-call.config تنظیم کنید (بخش
پیکربندی را در ادامه ببینید). حداقل موارد لازم:
provider، اطلاعات احراز هویت ارائهدهنده، fromNumber و یک نشانی
Webhook قابلدسترسی عمومی.
تأیید راهاندازی
openclaw voicecall setupopenclaw voicecall setup --jsonفعالبودن Plugin، اطلاعات احراز هویت ارائهدهنده، دسترسی عمومی Webhook
و فعالبودن تنها یک حالت صوتی (streaming یا realtime) را بررسی میکند.
آزمایش اولیه
openclaw voicecall smokeopenclaw voicecall smoke --to "+15555550123"هر دو بهطور پیشفرض اجرای آزمایشی هستند. برای برقراری یک تماس اعلان
خروجی کوتاه، --yes را اضافه کنید:
openclaw voicecall smoke --to "+15555550123" --yesپیکربندی
اگر enabled: true باشد اما اطلاعات احراز هویت ارائهدهنده انتخابشده موجود
نباشد، هنگام شروع Gateway یک هشدار ناقصبودن راهاندازی همراه با کلیدهای
مفقود ثبت میشود و اجرای زماناجرا آغاز نمیگردد. فرمانها، فراخوانیهای RPC
و ابزارهای عامل هنگام استفاده همچنان پیکربندی دقیق مفقود را برمیگردانند.
{ plugins: { entries: { "voice-call": { enabled: true, config: { provider: "twilio", // or "telnyx" | "plivo" | "mock" fromNumber: "+15550001234", // or TWILIO_FROM_NUMBER for Twilio toNumber: "+15550005678", sessionScope: "per-phone", // per-phone | per-call numbers: { "+15550009999": { inboundGreeting: "Silver Fox Cards, how can I help?", responseSystemPrompt: "You are a concise baseball card specialist.", tts: { providers: { openai: { speakerVoice: "alloy" }, }, }, }, }, twilio: { accountSid: "ACxxxxxxxx", authToken: "...", // region: "ie1", // optional: us1 | ie1 | au1; defaults to us1 }, telnyx: { apiKey: "...", connectionId: "...", // Telnyx webhook public key from the Mission Control Portal // (Base64; 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 /* see Streaming transcription */ }, realtime: { enabled: false /* see Realtime voice conversations */ }, }, }, }, },}مرجع پیکربندی
کلیدهای سطح بالای plugins.entries.voice-call.config که در بالا نشان داده نشدهاند:
| کلید | پیشفرض | توضیحات |
|---|---|---|
enabled |
false |
کلید اصلی روشن/خاموش. |
inboundPolicy |
"disabled" |
disabled | allowlist | pairing | open. بخش تماسهای ورودی را ببینید. |
allowFrom |
[] |
فهرست مجاز E.164 برای inboundPolicy: "allowlist". |
maxDurationSeconds |
300 |
سقف قطعی مدت هر تماس که مستقل از وضعیت پاسخگویی اعمال میشود. |
staleCallReaperSeconds |
120 |
بخش پاکساز تماسهای متروک را ببینید. 0 آن را غیرفعال میکند. |
silenceTimeoutMs |
800 |
تشخیص سکوت پایان گفتار برای جریان کلاسیک (غیربلادرنگ). |
transcriptTimeoutMs |
180000 |
حداکثر زمان انتظار برای رونویسی تماسگیرنده پیش از صرفنظر از یک نوبت. |
ringTimeoutMs |
30000 |
مهلت زنگخوردن تماسهای خروجی. |
maxConcurrentCalls |
1 |
تماسهای خروجی فراتر از این محدودیت رد میشوند. |
outbound.notifyHangupDelaySec |
3 |
مدت انتظار بر حسب ثانیه پس از TTS، پیش از قطع خودکار تماس در حالت اعلان. |
skipSignatureVerification |
false |
فقط برای آزمایش محلی؛ هرگز در محیط عملیاتی فعال نکنید. |
store |
تنظیمنشده | مسیر پیشفرض گزارش تماس ~/.openclaw/voice-calls را بازنویسی میکند. |
agentId |
"main" |
عاملی که برای تولید پاسخ و ذخیرهسازی نشست استفاده میشود. |
responseModel |
تنظیمنشده | مدل پیشفرض پاسخهای کلاسیک (غیربلادرنگ) را بازنویسی میکند. |
responseSystemPrompt |
تولیدشده | اعلان سیستمی سفارشی برای پاسخهای کلاسیک. |
responseTimeoutMs |
30000 |
مهلت تولید پاسخ کلاسیک (میلیثانیه). |
Twilio بهطور پیشفرض از نقطه پایانی REST منطقه US1 خود استفاده میکند. برای
پردازش تماسها در یک منطقه پشتیبانیشده خارج از ایالات متحده، twilio.region
را روی ie1 یا au1 تنظیم کنید و از اطلاعات احراز هویت همان منطقه استفاده
کنید. راهنمای REST API خارج از ایالات متحده Twilio
را ببینید.
نکات دسترسی عمومی و امنیت ارائهدهنده
- Twilio، Telnyx و Plivo همگی به یک نشانی Webhook قابلدسترسی عمومی نیاز دارند.
mockیک ارائهدهنده توسعه محلی است (بدون فراخوانی شبکه).- Telnyx به
telnyx.publicKey(یاTELNYX_PUBLIC_KEY) نیاز دارد، مگر اینکهskipSignatureVerificationبرابر با true باشد. skipSignatureVerificationفقط برای آزمایش محلی است.- در سطح رایگان ngrok،
publicUrlرا روی نشانی دقیق ngrok تنظیم کنید؛ تأیید امضا همیشه اعمال میشود. tunnel.allowNgrokFreeTierLoopbackBypass: trueWebhookهای Twilio با امضای نامعتبر را تنها زمانی مجاز میکند کهtunnel.provider="ngrok"وserve.bindبرابر با local loopback باشد (عامل محلی ngrok). فقط برای توسعه محلی.- نشانیهای سطح رایگان Ngrok ممکن است تغییر کنند یا رفتار میانصفحهای اضافه کنند؛ اگر
publicUrlتغییر کند، امضاهای Twilio نامعتبر میشوند. برای محیط عملیاتی، یک دامنه پایدار یا یک تونل Tailscale را ترجیح دهید.
سقف اتصالهای جریانی
streaming.preStartTimeoutMs(پیشفرض5000) سوکتهایی را میبندد که هرگز یک فریم معتبرstartارسال نمیکنند.streaming.maxPendingConnections(پیشفرض32) تعداد کل سوکتهای احراز هویتنشده پیش از شروع را محدود میکند.streaming.maxPendingConnectionsPerIp(پیشفرض4) تعداد سوکتهای احراز هویتنشده پیش از شروع را برای هر نشانی IP مبدأ محدود میکند.streaming.maxConnections(پیشفرض128) تعداد تمام سوکتهای باز جریان رسانهای را محدود میکند (در انتظار + فعال).
مهاجرت پیکربندی قدیمی
تجزیه پیکربندی این کلیدهای قدیمی را بهطور خودکار عادیسازی میکند و
هشداری شامل مسیر جایگزین ثبت میکند؛ این لایه سازگاری در انتشار آینده
(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حذف شده است (زمینه بلادرنگ اکنون از اعلان تولیدشده عامل استفاده میکند)
دامنه نشست
بهطور پیشفرض، تماس صوتی از sessionScope: "per-phone" استفاده میکند تا
تماسهای تکراری از یک تماسگیرنده، حافظه مکالمه را حفظ کنند. زمانی که هر تماس
اپراتور باید با زمینهای تازه آغاز شود، sessionScope: "per-call" را تنظیم
کنید؛ برای نمونه در جریانهای پذیرش، رزرو، IVR یا پل Google Meet که ممکن است
یک شماره تلفن نماینده جلسههای متفاوت باشد.
تماس صوتی کلیدهای نشست تولیدشده را در فضای نام عامل پیکربندیشده
(agent:<agentId>:voice:*) ذخیره میکند. کلیدهای صریح و خام یکپارچهسازی نیز
در همان فضای نام تفکیک میشوند: یک کلید معیار agent:<configuredAgentId>:*
مالک خود را حفظ میکند و از نام مستعار session.mainKey/دامنه سراسری هسته
پیروی میکند؛ ورودی خارجی یا بدشکل agent:* بهعنوان کلیدی مبهم در محدوده
عامل پیکربندیشده قرار میگیرد؛ global و unknown همچنان نشانگرهای سراسری
باقی میمانند.
مکالمات صوتی بلادرنگ
realtime یک ارائهدهنده صدای بلادرنگ تمامدوطرفه را برای صدای زنده تماس
انتخاب میکند. این قابلیت از streaming جدا است؛ streaming فقط صدا را به
ارائهدهندگان رونویسی بلادرنگ ارسال میکند.
رفتار فعلی زماناجرا:
realtime.enabledبرای Twilio و Telnyx پشتیبانی میشود.realtime.providerاختیاری است. اگر تنظیم نشده باشد، تماس صوتی از نخستین ارائهدهندهٔ ثبتشدهٔ صدای بلادرنگ استفاده میکند.- ارائهدهندگان همراهِ صدای بلادرنگ: Google Gemini Live (
google) و OpenAI (openai) که توسط Pluginهای ارائهدهندهٔ خود ثبت میشوند. - پیکربندی خامِ متعلق به ارائهدهنده در
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به ارائهدهندهای ثبتنشده اشاره کند، یا هیچ ارائهدهندهٔ صدای بلادرنگی ثبت نشده باشد، تماس صوتی بهجای از کار انداختن کل Plugin، هشداری ثبت میکند و از رسانهٔ بلادرنگ صرفنظر میکند. - وقتی
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 را اجرا
میکنند و باید برای کار با ابزارها، اطلاعات جاری، جستوجوی حافظه یا وضعیت
فضای کاری استفاده شوند.
{ 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"], }, }, }, }, }, },}نمونههای ارائهدهندهٔ بلادرنگ
Google Gemini Live
پیشفرضها: کلید API از realtime.providers.google.apiKey، GEMINI_API_KEY
یا GOOGLE_API_KEY؛ مدل gemini-3.1-flash-live-preview؛
صدا Kore. گزینههای sessionResumption و contextWindowCompression
برای تماسهای طولانیتر و قابل اتصال مجدد، بهطور پیشفرض فعال هستند.
برای تنظیم نوبتگیری سریعتر روی صدای تلفنی، از silenceDurationMs،
startSensitivity و endSensitivity استفاده کنید.
{ plugins: { entries: { "voice-call": { config: { provider: "twilio", inboundPolicy: "allowlist", allowFrom: ["+15550005678"], realtime: { enabled: true, provider: "google", instructions: "Speak briefly. Call openclaw_agent_consult before using deeper tools.", 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}" }, }, }, }, }, }, },}برای گزینههای صدای بلادرنگِ مختص هر ارائهدهنده، به ارائهدهندهٔ Google و ارائهدهندهٔ OpenAI مراجعه کنید.
رونویسی جریانی
streaming یک ارائهدهندهٔ رونویسی بلادرنگ را برای صدای زندهٔ تماس انتخاب میکند.
رفتار فعلی زمان اجرا:
streaming.providerاختیاری است. اگر تنظیم نشده باشد، تماس صوتی از نخستین ارائهدهندهٔ ثبتشدهٔ رونویسی بلادرنگ استفاده میکند.- ارائهدهندگان همراهِ رونویسی بلادرنگ: Deepgram (
deepgram)، ElevenLabs (elevenlabs)، Mistral (mistral)، OpenAI (openai) و xAI (xai) که توسط Pluginهای ارائهدهندهٔ خود ثبت میشوند. - پیکربندی خامِ متعلق به ارائهدهنده در
streaming.providers.<providerId>قرار میگیرد. - پس از اینکه Twilio پیام پذیرفتهشدهٔ
startمربوط به جریان را ارسال میکند، تماس صوتی بلافاصله جریان را ثبت میکند، هنگام اتصال ارائهدهنده رسانهٔ ورودی را برای پردازش توسط ارائهدهندهٔ رونویسی در صف قرار میدهد و پیام خوشامدگویی اولیه را تنها پس از آمادهشدن رونویسی بلادرنگ آغاز میکند. - اگر
streaming.providerبه ارائهدهندهای ثبتنشده اشاره کند، یا هیچ ارائهدهندهای ثبت نشده باشد، تماس صوتی بهجای از کار انداختن کل Plugin، هشداری ثبت میکند و از پخش جریانی رسانه صرفنظر میکند.
نمونههای ارائهدهندهٔ جریانی
OpenAI
پیشفرضها: کلید API از streaming.providers.openai.apiKey یا
OPENAI_API_KEY؛ مدل 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-...", // optional if OPENAI_API_KEY is set model: "gpt-4o-transcribe", silenceDurationMs: 800, vadThreshold: 0.5, }, }, }, }, }, }, },}xAI
پیشفرضها: کلید API از streaming.providers.xai.apiKey یا XAI_API_KEY
(اگر هیچکدام تنظیم نشده باشند، به نمایهٔ احراز هویت OAuth متعلق به xAI
بازمیگردد)؛ نقطهٔ پایانی wss://api.x.ai/v1/stt؛ کدگذاری mulaw؛
نرخ نمونهبرداری 8000؛ endpointingMs: 800؛ interimResults: true.
{ plugins: { entries: { "voice-call": { config: { streaming: { enabled: true, provider: "xai", streamPath: "/voice/stream", providers: { xai: { apiKey: "${XAI_API_KEY}", // optional if XAI_API_KEY is set endpointingMs: 800, language: "en", }, }, }, }, }, }, },}TTS برای تماسها
تماس صوتی برای گفتار جریانی در تماسها از پیکربندی اصلی messages.tts
استفاده میکند. میتوانید آن را در پیکربندی Plugin با همان ساختار
بازنویسی کنید؛ این پیکربندی بهصورت عمیق با messages.tts ادغام میشود.
{ tts: { provider: "elevenlabs", providers: { elevenlabs: { speakerVoiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, },}نکات رفتاری:
- کلیدهای قدیمی
tts.<provider>در پیکربندی Plugin (openai،elevenlabs،microsoft،edge) توسطopenclaw doctor --fixاصلاح میشوند؛ پیکربندی ثبتشده باید ازtts.providers.<provider>استفاده کند. - وقتی پخش جریانی رسانهٔ Twilio فعال باشد، از TTS اصلی استفاده میشود؛ در غیر این صورت تماسها به صداهای بومی ارائهدهنده بازمیگردند.
- اگر جریان رسانهٔ Twilio از قبل فعال باشد، تماس صوتی به TwiML
OPENCLAW_DOCS_MARKER:calloutOpen:U2F5بازنمیگردد. اگر TTS تلفنی در آن وضعیت در دسترس نباشد، درخواست پخش بهجای ترکیب دو مسیر پخش، ناموفق میشود. - وقتی TTS تلفنی به ارائهدهندهٔ ثانویه بازمیگردد، تماس صوتی برای اشکالزدایی هشداری حاوی زنجیرهٔ ارائهدهندگان (
from،to،attempts) ثبت میکند. - وقتی ورود همزمان گفتار در Twilio یا برچیدن جریان، صف در انتظار TTS را پاک میکند، درخواستهای پخش صفشده تعیینتکلیف میشوند و تماسگیرندگانی که منتظر تکمیل پخش هستند معطل نمیمانند.
نمونههای TTS
Core TTS only
{messages: {tts: {provider: "openai",providers: { openai: { speakerVoice: "alloy" },},},},}Override to ElevenLabs (calls only)
{plugins: {entries: {"voice-call": { config: { tts: { provider: "elevenlabs", providers: { elevenlabs: { apiKey: "elevenlabs_key", speakerVoiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }, },},},},}OpenAI model override (deep-merge)
{plugins: {entries: {"voice-call": { config: { tts: { providers: { openai: { model: "gpt-4o-mini-tts", speakerVoice: "marin", }, }, }, },},},},}تماسهای ورودی
خطمشی تماس ورودی بهطور پیشفرض disabled است. برای فعالکردن تماسهای ورودی، تنظیم کنید:
{inboundPolicy: "allowlist",allowFrom: ["+15550001234"],inboundGreeting: "Hello! How can I help?",}پاسخهای خودکار از سامانه عامل استفاده میکنند. آنها را با responseModel،
responseSystemPrompt و responseTimeoutMs تنظیم کنید.
مسیریابی بر اساس شماره
وقتی یک Plugin تماس صوتی برای چند شماره تلفن تماس دریافت میکند و هر شماره باید
مانند یک خط متفاوت رفتار کند، از numbers استفاده کنید. برای مثال، یک شماره
میتواند از یک دستیار شخصی با لحن غیررسمی استفاده کند، درحالیکه شمارهای دیگر
از یک شخصیت تجاری، عامل پاسخگوی متفاوت و صدای TTS متفاوت استفاده میکند.
مسیرها بر اساس شماره مقصد To که ارائهدهنده اعلام میکند انتخاب میشوند. کلیدها
باید شمارههای E.164 باشند. هنگام ورود تماس، تماس صوتی مسیر منطبق را یکبار
تشخیص میدهد، مسیر منطبق را در رکورد تماس ذخیره میکند و همان پیکربندی مؤثر را
برای پیام خوشامدگویی، مسیر کلاسیک پاسخ خودکار، مسیر مشاوره بلادرنگ و پخش TTS
دوباره به کار میبرد. اگر هیچ مسیری منطبق نباشد، پیکربندی سراسری تماس صوتی استفاده
میشود. تماسهای خروجی از numbers استفاده نمیکنند؛ هنگام آغاز تماس، مقصد خروجی،
پیام و نشست را بهطور صریح ارسال کنید.
در حال حاضر، بازنویسیهای مسیر از موارد زیر پشتیبانی میکنند:
inboundGreetingttsagentIdresponseModelresponseSystemPromptresponseTimeoutMs
مقدار tts مسیر بهصورت ادغام عمیق روی پیکربندی سراسری tts تماس صوتی اعمال
میشود؛ بنابراین معمولاً میتوانید فقط صدای ارائهدهنده را بازنویسی کنید:
{inboundGreeting: "Hello from the main line.",responseSystemPrompt: "You are the default voice assistant.",tts: { provider: "openai", providers: { openai: { speakerVoice: "coral" }, },},numbers: { "+15550001111": { inboundGreeting: "Silver Fox Cards, how can I help?", responseSystemPrompt: "You are a concise baseball card specialist.", tts: { providers: { openai: { speakerVoice: "alloy" }, }, }, },},}قرارداد خروجی گفتاری
برای پاسخهای خودکار، تماس صوتی یک قرارداد سختگیرانه خروجی گفتاری را به اعلان
سیستم میافزاید که پاسخ JSON بهشکل {"spoken":"..."} را الزامی میکند. تماس صوتی
متن گفتار را بهشکل تدافعی استخراج میکند:
- بارهای دادهای را که بهعنوان محتوای استدلال یا خطا علامتگذاری شدهاند نادیده میگیرد.
- JSON مستقیم، JSON حصارشده یا کلیدهای درونخطی
"spoken"را تجزیه میکند. - در صورت نیاز به متن ساده بازمیگردد و بندهای آغازین احتمالی مربوط به برنامهریزی یا فراداده را حذف میکند.
این کار پخش گفتاری را بر متن خطاب به تماسگیرنده متمرکز نگه میدارد و از افشای متن برنامهریزی در صدا جلوگیری میکند.
رفتار آغاز مکالمه
برای تماسهای خروجی conversation، رسیدگی به پیام نخست به وضعیت پخش زنده وابسته است:
- پاکسازی صف هنگام قطع میانگفتار و پاسخ خودکار فقط تا زمانی متوقف میشوند که پیام خوشامدگویی اولیه فعالانه در حال پخش باشد.
- اگر پخش اولیه شکست بخورد، تماس به حالت
listeningبازمیگردد و پیام اولیه برای تلاش مجدد در صف باقی میماند. - پخش اولیه برای جریان Twilio هنگام اتصال جریان و بدون تأخیر اضافی آغاز میشود.
- قطع میانگفتار، پخش فعال را متوقف میکند و ورودیهای TTS مربوط به Twilio را که در صف هستند اما هنوز پخش نشدهاند پاک میکند. ورودیهای پاکشده با وضعیت ردشده خاتمه مییابند تا منطق پاسخ بعدی بدون انتظار برای صدایی که هرگز پخش نخواهد شد ادامه یابد.
- مکالمات صوتی بلادرنگ از نوبت آغازین خود جریان بلادرنگ استفاده میکنند. تماس صوتی برای آن پیام اولیه، بهروزرسانی قدیمی TwiML از نوع
OPENCLAW_DOCS_MARKER:calloutOpen:U2F5ارسال نمیکند؛ بنابراین نشستهای خروجی<Connect><Stream>متصل باقی میمانند.
مهلت قطع اتصال جریان Twilio
هنگامی که جریان رسانهای Twilio قطع میشود، تماس صوتی پیش از پایان خودکار تماس ۲۰۰۰ میلیثانیه صبر میکند:
- اگر جریان در این بازه دوباره متصل شود، پایان خودکار لغو میشود.
- اگر پس از دوره مهلت هیچ جریانی دوباره ثبت نشود، تماس پایان مییابد تا تماسهای فعال گیرکرده ایجاد نشوند.
جمعآوریکننده تماسهای منقضی
از staleCallReaperSeconds با مقدار پیشفرض ۱۲۰ برای پایاندادن به تماسهایی
استفاده کنید که هرگز پاسخ داده نمیشوند و هرگز به وضعیت مکالمه زنده نمیرسند؛
برای نمونه تماسهای حالت اعلان که ارائهدهنده هرگز Webhook پایانی آنها را تحویل
نمیدهد. برای غیرفعالسازی، مقدار آن را روی 0 تنظیم کنید.
جمعآوریکننده هر ۳۰ ثانیه اجرا میشود و فقط تماسهایی را پایان میدهد که مهر زمانی
answeredAt ندارند و از قبل در وضعیت پایانی یا زنده (speaking/listening) نیستند؛
بنابراین مکالمات پاسخدادهشده هرگز توسط این زمانسنج جمعآوری نمیشوند.
maxDurationSeconds با مقدار پیشفرض ۳۰۰، سقف جداگانهای است که تماسهای
پاسخدادهشده و بیشازحد طولانی را پایان میدهد.
برای جریانهای اعلانمحور که اپراتورها ممکن است Webhookهای زنگخوردن یا پاسخ را
با تأخیر تحویل دهند، staleCallReaperSeconds را بیشتر از مقدار پیشفرض تنظیم کنید
تا تماسهای کند اما عادی زودهنگام جمعآوری نشوند؛ بازه ۱۲۰ تا ۳۰۰ ثانیه برای محیط
عملیاتی مناسب است.
{plugins: {entries: { "voice-call": { config: { maxDurationSeconds: 300, staleCallReaperSeconds: 120, }, },},},}امنیت Webhook
وقتی یک پراکسی یا تونل جلوی Gateway قرار دارد، Plugin برای تأیید امضا، نشانی عمومی را بازسازی میکند. گزینههای زیر تعیین میکنند کدام سرآیندهای فورواردشده مورد اعتماد باشند:
webhookSecurity.allowedHostsstring[]میزبانهای مجاز از سرآیندهای فوروارد را مشخص میکند.
webhookSecurity.trustForwardingHeadersbooleanبدون فهرست مجاز به سرآیندهای فورواردشده اعتماد میکند.
webhookSecurity.trustedProxyIPsstring[]فقط زمانی به سرآیندهای فورواردشده اعتماد میکند که نشانی IP راه دور درخواست با فهرست منطبق باشد.
محافظتهای تکمیلی:
- محافظت در برابر بازپخش Webhook برای Twilio، Telnyx و Plivo فعال است. درخواستهای معتبر Webhook که بازپخش شوند تأیید دریافت میشوند، اما اثرات جانبی آنها نادیده گرفته میشود.
- نوبتهای مکالمه Twilio در فراخوانیهای برگشتی
<Gather>یک توکن ویژه هر نوبت دارند؛ بنابراین فراخوانیهای گفتاری قدیمی یا بازپخششده نمیتوانند یک نوبت رونوشت معلق جدیدتر را تکمیل کنند. - وقتی سرآیندهای امضای الزامی ارائهدهنده وجود نداشته باشند، درخواستهای Webhook احرازنشده پیش از خواندن بدنه رد میشوند.
- Webhook تماس صوتی پیش از تأیید امضا از نمایه مشترک خواندن بدنه پیش از احراز هویت، شامل حداکثر بدنه ۶۴ کیلوبایت و مهلت خواندن ۵ ثانیه، بههمراه سقف درخواستهای همزمان درحالاجرا برای هر کلید، با مقدار پیشفرض ۸ درخواست همزمان برای هر کلید، استفاده میکند.
نمونه با میزبان عمومی پایدار:
{plugins: {entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", webhookSecurity: { allowedHosts: ["voice.example.com"], }, }, },},},}CLI
openclaw voicecall call --to "+15555550123" --message "Hello from OpenClaw"openclaw voicecall start --to "+15555550123" # alias for callopenclaw voicecall continue --call-id <id> --message "Any questions?"openclaw voicecall speak --call-id <id> --message "One moment"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 # summarize turn latency from logsopenclaw voicecall expose --mode funnelوقتی Gateway از قبل در حال اجرا است، فرمانهای عملیاتی voicecall به زماناجرای
تماس صوتی تحت مالکیت Gateway واگذار میشوند تا CLI یک سرور Webhook دوم را مقید
نکند. اگر هیچ Gateway در دسترس نباشد، فرمانها به زماناجرای مستقل CLI بازمیگردند.
latency فایل calls.jsonl را از مسیر ذخیرهسازی پیشفرض تماس صوتی میخواند. برای
اشاره به گزارش متفاوت از --file <path> و برای محدودکردن تحلیل به آخرین N رکورد
از --last <n> استفاده کنید؛ مقدار پیشفرض ۲۰۰ است. خروجی شامل کمینه، بیشینه،
میانگین، 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 |
Plugin تماس صوتی همراه با یک Skill عامل منطبق عرضه میشود.
RPC Gateway
| روش | آرگومانها | توضیحات |
|---|---|---|
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 استفاده کنند.
عیبیابی
راهاندازی در ارائه Webhook شکست میخورد
راهاندازی را از همان محیطی اجرا کنید که Gateway در آن اجرا میشود:
openclaw voicecall setupopenclaw voicecall setup --jsonبرای 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، TwiML اولیه OPENCLAW_DOCS_MARKER:calloutOpen:U2F5 خود را مستقیماً در درخواست
ایجاد تماس ارسال میکنند؛ بنابراین نخستین پیام گفتاری به دریافت TwiML از Webhook
توسط Twilio وابسته نیست. همچنان برای فراخوانیهای برگشتی وضعیت، تماسهای مکالمه،
DTMF پیش از اتصال، جریانهای بلادرنگ و کنترل تماس پس از اتصال به Webhook عمومی
نیاز است.
از یکی از مسیرهای ارائه عمومی استفاده کنید:
{plugins: {entries: {"voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", // or tunnel: { provider: "ngrok" }, // or tailscale: { mode: "funnel", path: "/voice/webhook" }, },},},},}پس از تغییر پیکربندی، Gateway را بازراهاندازی یا بازبارگذاری کنید، سپس اجرا کنید:
openclaw voicecall setupopenclaw voicecall smokevoicecall smoke آزمایشی و بدون اجرای واقعی است، مگر اینکه --yes را ارسال کنید.
اعتبارنامههای ارائهدهنده شکست میخورند
ارائهدهنده انتخابشده و فیلدهای الزامی اعتبارنامه را بررسی کنید:
- 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.
اعتبارنامهها باید روی میزبان Gateway موجود باشند. ویرایش پروفایل پوستهٔ محلی تا زمانی که Gateway راهاندازی مجدد نشود یا محیط خود را دوباره بارگذاری نکند، بر Gateway در حال اجرا تأثیری ندارد.
تماسها آغاز میشوند، اما Webhookهای ارائهدهنده دریافت نمیشوند
تأیید کنید که کنسول ارائهدهنده دقیقاً به نشانی عمومی Webhook زیر اشاره میکند:
https://voice.example.com/voice/webhookسپس وضعیت زمان اجرا را بررسی کنید:
openclaw voicecall status --call-id <id>openclaw voicecall tailopenclaw logs --followعلتهای رایج:
publicUrlبه مسیری متفاوت ازserve.pathاشاره میکند.- نشانی تونل پس از شروع Gateway تغییر کرده است.
- یک پراکسی درخواست را هدایت میکند، اما سرآیندهای میزبان یا پروتکل را حذف یا بازنویسی میکند.
- دیوار آتش یا DNS نام میزبان عمومی را به جایی غیر از Gateway هدایت میکند.
- Gateway بدون فعال بودن Plugin تماس صوتی دوباره راهاندازی شده است.
وقتی یک پراکسی معکوس یا تونل در جلوی Gateway قرار دارد،
webhookSecurity.allowedHosts را روی نام میزبان عمومی تنظیم کنید، یا برای
نشانی پراکسی شناختهشده از webhookSecurity.trustedProxyIPs استفاده کنید. از
webhookSecurity.trustForwardingHeaders فقط زمانی استفاده کنید که مرز پراکسی
تحت کنترل شما باشد.
تأیید امضا ناموفق است
امضاهای ارائهدهنده در برابر نشانی عمومیای بررسی میشوند که OpenClaw آن را از درخواست ورودی بازسازی میکند. اگر تأیید امضاها ناموفق است:
- تأیید کنید که نشانی Webhook ارائهدهنده دقیقاً با
publicUrl، شامل طرح، میزبان و مسیر، مطابقت دارد. - برای نشانیهای سطح رایگان ngrok، هنگام تغییر نام میزبان تونل،
publicUrlرا بهروزرسانی کنید. - مطمئن شوید پراکسی سرآیندهای اصلی میزبان و پروتکل را حفظ میکند، یا
webhookSecurity.allowedHostsرا پیکربندی کنید. skipSignatureVerificationرا خارج از آزمایش محلی فعال نکنید.
پیوستن Google Meet از طریق Twilio ناموفق است
Google Meet برای پیوستن از طریق شمارهگیری Twilio از این Plugin استفاده میکند. ابتدا تماس صوتی را تأیید کنید:
openclaw voicecall setupopenclaw voicecall smoke --to "+15555550123"سپس انتقال Google Meet را بهطور صریح تأیید کنید:
openclaw googlemeet setup --transport twilioاگر تماس صوتی سالم است، اما شرکتکننده هرگز به جلسه Meet نمیپیوندد، شمارهٔ
شمارهگیری Meet، پین و --dtmf-sequence را بررسی کنید. تماس تلفنی ممکن است
سالم باشد، در حالی که جلسه یک دنبالهٔ DTMF نادرست را رد یا نادیده میگیرد.
Google Meet بخش تلفنی Twilio را از طریق voicecall.start و با یک دنبالهٔ DTMF
پیش از اتصال آغاز میکند. دنبالههای مشتقشده از پین شامل
voiceCall.dtmfDelayMs متعلق به Plugin Google Meet با مقدار پیشفرض
۱۲۰۰۰ میلیثانیه بهصورت ارقام انتظار ابتدایی Twilio هستند، زیرا اعلانهای
شمارهگیری Meet ممکن است با تأخیر پخش شوند. سپس تماس صوتی، پیش از درخواست
پیام خوشامدگویی آغازین، دوباره به مدیریت بلادرنگ هدایت میشود.
برای مشاهدهٔ ردگیری زندهٔ مراحل از openclaw logs --follow استفاده کنید. در
یک پیوستن سالم به Meet از طریق Twilio، رویدادها با این ترتیب ثبت میشوند:
- Google Meet پیوستن از طریق Twilio را به تماس صوتی واگذار میکند.
- تماس صوتی TwiML مربوط به DTMF پیش از اتصال را ذخیره میکند.
- TwiML اولیهٔ Twilio پیش از مدیریت بلادرنگ مصرف و ارائه میشود.
- تماس صوتی TwiML بلادرنگ را برای تماس Twilio ارائه میکند.
- Google Meet پس از تأخیر بعد از DTMF، گفتار آغازین را با
voicecall.speakدرخواست میکند.
openclaw voicecall tail همچنان رکوردهای ذخیرهشدهٔ تماس را نشان میدهد؛ این
دستور برای وضعیت تماس و رونوشتها مفید است، اما همهٔ انتقالهای Webhook یا
بلادرنگ در آن نمایش داده نمیشوند.
تماس بلادرنگ گفتاری ندارد
تأیید کنید که فقط یک حالت صوتی فعال است: realtime.enabled و
streaming.enabled نمیتوانند هر دو برابر با true باشند.
برای تماسهای بلادرنگ Twilio یا Telnyx، این موارد را نیز تأیید کنید:
- یک Plugin ارائهدهندهٔ بلادرنگ بارگذاری و ثبت شده است.
realtime.providerتنظیم نشده است یا نام یک ارائهدهندهٔ ثبتشده را مشخص میکند.- کلید API ارائهدهنده در دسترس فرایند Gateway است.
openclaw logs --followنشان میدهد که TwiML بلادرنگ ارائه شده، پل بلادرنگ آغاز شده و پیام خوشامدگویی اولیه در صف قرار گرفته است.