Bundled plugin guides
Plugin المكالمات الصوتية
مكالمات صوتية لـ OpenClaw عبر Plugin. يدعم الإشعارات الصادرة، والمحادثات متعددة الأدوار، والصوت الفوري ثنائي الاتجاه الكامل، والتفريغ النصي المتدفق، والمكالمات الواردة مع سياسات قائمة السماح.
المزوّدون الحاليون: twilio (Programmable Voice + Media Streams)،
telnyx (Call Control v2)، plivo (Voice API + XML transfer + GetInput
speech)، mock (تطوير/بلا شبكة).
البدء السريع
ثبّت 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، وعنوان URL لـ Webhook
يمكن الوصول إليه علناً.
تحقق من الإعداد
openclaw voicecall setupيكون الخرج الافتراضي قابلاً للقراءة في سجلات الدردشة والطرفيات. يتحقق من
تفعيل Plugin، وبيانات اعتماد المزوّد، وإتاحة Webhook، وأن وضعاً صوتياً
واحداً فقط (streaming أو realtime) نشط. استخدم
--json للسكربتات.
اختبار سريع
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: { voice: "alloy" }, }, }, }, }, twilio: { accountSid: "ACxxxxxxxx", authToken: "...", }, 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 */ }, }, }, }, },}ملاحظات إتاحة المزوّد والأمان
- تتطلب Twilio وTelnyx وPlivo جميعها عنوان URL لـ Webhook يمكن الوصول إليه علناً.
mockهو مزوّد تطوير محلي (بلا استدعاءات شبكة).- يتطلب Telnyx وجود
telnyx.publicKey(أوTELNYX_PUBLIC_KEY) ما لم تكنskipSignatureVerificationتساوي true. skipSignatureVerificationللاختبار المحلي فقط.- في الطبقة المجانية من ngrok، اضبط
publicUrlعلى عنوان URL الدقيق لـ ngrok؛ يتم فرض التحقق من التوقيع دائماً. - يسمح
tunnel.allowNgrokFreeTierLoopbackBypass: trueبـ Webhook من Twilio ذات التواقيع غير الصالحة فقط عندما يكونtunnel.provider="ngrok"وserve.bindهو loopback (وكيل ngrok المحلي). للتطوير المحلي فقط. - يمكن أن تتغير عناوين URL للطبقة المجانية من Ngrok أو تضيف سلوك صفحات بينية؛ إذا انحرف
publicUrl، تفشل تواقيع Twilio. في الإنتاج: فضّل نطاقاً ثابتاً أو Tailscale funnel.
حدود اتصالات البث
- يغلق
streaming.preStartTimeoutMsالمقابس التي لا ترسل أبداً إطارstartصالحاً. - يحد
streaming.maxPendingConnectionsالعدد الإجمالي لمقابس ما قبل البدء غير المصادقة. - يحد
streaming.maxPendingConnectionsPerIpمقابس ما قبل البدء غير المصادقة لكل عنوان IP مصدر. - يحد
streaming.maxConnectionsالعدد الإجمالي لمقابس بث الوسائط المفتوحة (المعلقة + النشطة).
ترحيلات الإعدادات القديمة
يعيد openclaw doctor --fix كتابة الإعدادات الأقدم التي تستخدم provider: "log"، أو twilio.from، أو مفاتيح OpenAI القديمة
ضمن streaming.*. لا يزال احتياطي وقت التشغيل يقبل مفاتيح voice-call القديمة حالياً، لكن
مسار إعادة الكتابة هو openclaw doctor --fix وطبقة التوافق
مؤقتة.
مفاتيح البث التي يتم ترحيلها تلقائياً:
streaming.sttProvider→streaming.providerstreaming.openaiApiKey→streaming.providers.openai.apiKeystreaming.sttModel→streaming.providers.openai.modelstreaming.silenceDurationMs→streaming.providers.openai.silenceDurationMsstreaming.vadThreshold→streaming.providers.openai.vadThreshold
نطاق الجلسة
افتراضياً، يستخدم Voice Call sessionScope: "per-phone" بحيث تحتفظ المكالمات المتكررة من
المتصل نفسه بذاكرة المحادثة. اضبط sessionScope: "per-call" عندما
ينبغي أن تبدأ كل مكالمة من شركة الاتصالات بسياق جديد، مثل تدفقات الاستقبال،
أو الحجز، أو IVR، أو جسر Google Meet حيث قد يمثل رقم الهاتف نفسه
اجتماعات مختلفة.
محادثات الصوت الفوري
يحدد realtime مزوّد صوت فوري ثنائي الاتجاه الكامل لصوت المكالمة الحي.
وهو منفصل عن streaming، الذي يرسل الصوت فقط إلى
مزوّدي التفريغ النصي الفوري.
سلوك وقت التشغيل الحالي:
realtime.enabledمدعوم لـ Twilio Media Streams.realtime.providerاختياري. إذا لم يُضبط، يستخدم Voice Call أول مزوّد صوت فوري مسجل.- مزوّدو الصوت الفوري المضمنون: Google Gemini Live (
google) وOpenAI (openai)، ويتم تسجيلهم بواسطة Plugins المزوّد الخاصة بهم. - توجد إعدادات المزوّد الخام المملوكة للمزوّد ضمن
realtime.providers.<providerId>. - يكشف Voice Call أداة
openclaw_agent_consultالفورية المشتركة افتراضياً. يمكن للنموذج الفوري استدعاؤها عندما يطلب المتصل استدلالاً أعمق، أو معلومات حالية، أو أدوات OpenClaw العادية. - يضيف
realtime.consultPolicyاختيارياً إرشادات حول متى يجب أن يستدعي النموذج الفوريopenclaw_agent_consult. - يكون
realtime.agentContext.enabledمعطلاً افتراضياً. عند تفعيله، يحقن Voice Call هوية وكيل محدودة، وتجاوز موجه النظام، وكبسولة محددة لملف مساحة العمل في تعليمات المزوّد الفوري عند إعداد الجلسة. - يكون
realtime.fastContext.enabledمعطلاً افتراضياً. عند تفعيله، يبحث Voice Call أولاً في الذاكرة/سياق الجلسة المفهرس عن سؤال الاستشارة ويعيد تلك المقاطع إلى النموذج الفوري ضمنrealtime.fastContext.timeoutMsقبل الرجوع إلى وكيل الاستشارة الكامل فقط إذا كانتrealtime.fastContext.fallbackToConsultتساوي true. - إذا كان
realtime.providerيشير إلى مزوّد غير مسجل، أو لم يكن أي مزوّد صوت فوري مسجلاً إطلاقاً، يسجل Voice Call تحذيراً ويتخطى وسائط الوقت الفوري بدلاً من إفشال Plugin بالكامل. - تعيد مفاتيح جلسة الاستشارة استخدام جلسة المكالمة المخزنة عندما تكون متاحة، ثم تعود إلى
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 |
استشر قبل كل إجابة ذات مضمون. |
سياق صوت الوكيل
فعّل realtime.agentContext عندما ينبغي لجسر الصوت أن يبدو مثل وكيل
OpenClaw المهيأ دون دفع تكلفة ذهاب وإياب لاستشارة الوكيل الكاملة في
الأدوار العادية. تُضاف كبسولة السياق مرة واحدة عند إنشاء الجلسة الفورية،
لذا فهي لا تضيف زمناً لكل دور. لا تزال استدعاءات
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, includeSystemPrompt: true, includeWorkspaceFiles: true, files: ["SOUL.md", "IDENTITY.md", "USER.md"], }, }, }, }, }, },}أمثلة مزوّد الوقت الحقيقي
Google Gemini Live
القيم الافتراضية: مفتاح 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 لضبط تبادل الأدوار بسرعة أكبر على صوت الاتصالات الهاتفية.
{ 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-2.5-flash-native-audio-preview-12-2025", voice: "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)، وتُسجَّل بواسطة Plugins المزوّدين الخاصة بها. - يوجد الإعداد الخام المملوك للمزوّد ضمن
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؛
نقطة النهاية 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: { voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, },}ملاحظات السلوك:
- تُصلَح مفاتيح
tts.<provider>القديمة داخل إعدادات Plugin (openai،elevenlabs،microsoft،edge) بواسطةopenclaw doctor --fix؛ وينبغي أن يستخدم الإعداد الملتزمtts.providers.<provider>. - يُستخدم TTS الأساسي عند تفعيل بث وسائط Twilio؛ وإلا تعود المكالمات إلى أصوات المزوّد الأصلية.
- إذا كان بث وسائط Twilio نشطًا بالفعل، فلا تعود المكالمة الصوتية إلى TwiML
OPENCLAW_DOCS_MARKER:calloutOpen:U2F5. إذا لم يكن TTS الهاتفي متاحًا في تلك الحالة، يفشل طلب التشغيل بدلًا من مزج مساري تشغيل. - عندما يعود TTS الهاتفي إلى مزوّد ثانوي، تسجّل المكالمة الصوتية تحذيرًا مع سلسلة المزوّدين (
from،to،attempts) لأغراض التصحيح. - عندما يؤدي مقاطعة الكلام من Twilio أو تفكيك البث إلى مسح صف TTS المعلّق، تُسوّى طلبات التشغيل الموضوعة في الصف بدلًا من ترك المتصلين معلّقين بانتظار اكتمال التشغيل.
أمثلة TTS
Core TTS only
{messages: {tts: {provider: "openai",providers: { openai: { voice: "alloy" },},},},}Override to ElevenLabs (calls only)
{plugins: {entries: {"voice-call": { config: { tts: { provider: "elevenlabs", providers: { elevenlabs: { apiKey: "elevenlabs_key", voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }, },},},},}OpenAI model override (deep-merge)
{plugins: {entries: {"voice-call": { config: { tts: { providers: { openai: { model: "gpt-4o-mini-tts", voice: "marin", }, }, }, },},},},}المكالمات الواردة
تكون سياسة الوارد افتراضيًا disabled. لتفعيل المكالمات الواردة، اضبط:
{inboundPolicy: "allowlist",allowFrom: ["+15550001234"],inboundGreeting: "Hello! How can I help?",}تستخدم الردود التلقائية نظام الوكيل. اضبطها باستخدام responseModel،
responseSystemPrompt، وresponseTimeoutMs.
التوجيه لكل رقم
استخدم numbers عندما يتلقى Plugin مكالمة صوتية واحد مكالمات لعدة أرقام هاتف
وينبغي أن يتصرف كل رقم كخط مختلف. على سبيل المثال، يمكن أن يستخدم أحد
الأرقام مساعدًا شخصيًا غير رسمي بينما يستخدم آخر شخصية أعمال،
ووكيل استجابة مختلفًا، وصوت 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: { voice: "coral" }, },},numbers: { "+15550001111": { inboundGreeting: "Silver Fox Cards, how can I help?", responseSystemPrompt: "You are a concise baseball card specialist.", tts: { providers: { openai: { voice: "alloy" }, }, }, },},}عقد المخرجات المنطوقة
بالنسبة إلى الردود التلقائية، تضيف المكالمة الصوتية عقد مخرجات منطوقة صارمًا إلى موجّه النظام:
{"spoken":"..."}تستخرج المكالمة الصوتية نص الكلام بأسلوب دفاعي:
- تتجاهل الحمولات الموسومة كمحتوى تفكير/خطأ.
- تحلل JSON المباشر، أو JSON داخل سياج، أو مفاتيح
"spoken"المضمنة. - تعود إلى النص العادي وتزيل فقرات الاستهلال التي تبدو تخطيطية/وصفية.
يحافظ ذلك على تركيز التشغيل المنطوق على النص الموجّه للمتصل، ويتجنب تسريب نص التخطيط إلى الصوت.
سلوك بدء المحادثة
بالنسبة إلى مكالمات conversation الصادرة، ترتبط معالجة الرسالة الأولى بحالة
التشغيل الحية:
- لا يتم إخماد مسح صف مقاطعة الكلام والرد التلقائي إلا أثناء نطق التحية الأولية بنشاط.
- إذا فشل التشغيل الأولي، تعود المكالمة إلى
listeningوتبقى الرسالة الأولية في الصف لإعادة المحاولة. - يبدأ التشغيل الأولي لبث Twilio عند اتصال البث دون تأخير إضافي.
- تقاطع مقاطعة الكلام التشغيل النشط وتمسح إدخالات TTS الخاصة بـ Twilio الموضوعة في الصف والتي لم تبدأ التشغيل بعد. تُحل الإدخالات الممسوحة كمتخطاة، بحيث يمكن لمنطق الاستجابة اللاحقة المتابعة دون انتظار صوت لن يُشغّل أبدًا.
- تستخدم محادثات الصوت في الوقت الحقيقي دور الافتتاح الخاص ببث الوقت الحقيقي نفسه. لا تنشر المكالمة الصوتية تحديث TwiML قديمًا عبر
OPENCLAW_DOCS_MARKER:calloutOpen:U2F5لتلك الرسالة الأولية، لذلك تبقى جلسات<Connect><Stream>الصادرة متصلة.
فترة السماح لانقطاع بث Twilio
عند انقطاع بث وسائط Twilio، تنتظر المكالمة الصوتية 2000 ms قبل إنهاء المكالمة تلقائيًا:
- إذا أعاد البث الاتصال خلال تلك النافذة، يُلغى الإنهاء التلقائي.
- إذا لم يُسجَّل أي بث مجددًا بعد فترة السماح، تُنهى المكالمة لمنع بقاء مكالمات نشطة عالقة.
منظف المكالمات القديمة
استخدم staleCallReaperSeconds لإنهاء المكالمات التي لا تتلقى أبدًا
Webhook نهائيًا (على سبيل المثال، مكالمات وضع الإشعار التي لا تكتمل أبدًا). القيمة الافتراضية
هي 0 (معطّل).
النطاقات الموصى بها:
- الإنتاج: من
120إلى300ثانية لتدفقات نمط الإشعار. - أبقِ هذه القيمة أعلى من
maxDurationSecondsحتى تتمكن الاستدعاءات العادية من الاكتمال. نقطة بدء جيدة هيmaxDurationSeconds + 30–60ثانية.
{plugins: {entries: { "voice-call": { config: { maxDurationSeconds: 300, staleCallReaperSeconds: 360, }, },},},}أمان Webhook
عندما يوجد وكيل أو نفق أمام Gateway، يعيد Plugin بناء عنوان URL العام للتحقق من التوقيع. تتحكم هذه الخيارات في ترويسات التوجيه التي يتم الوثوق بها:
webhookSecurity.allowedHostsstring[]قائمة سماح بالمضيفين من ترويسات التوجيه.
webhookSecurity.trustForwardingHeadersbooleanالوثوق بترويسات التوجيه دون قائمة سماح.
webhookSecurity.trustedProxyIPsstring[]لا تثق بترويسات التوجيه إلا عندما يطابق عنوان IP البعيد للطلب القائمة.
حمايات إضافية:
- يتم تمكين الحماية من إعادة تشغيل Webhook لـ Twilio وPlivo. يتم الإقرار بطلبات Webhook الصالحة المعاد تشغيلها، لكن يتم تخطي آثارها الجانبية.
- تتضمن أدوار محادثة Twilio رمزا مميزا لكل دور في استدعاءات
<Gather>، لذلك لا يمكن لاستدعاءات الكلام القديمة أو المعاد تشغيلها أن تفي بدور نسخة نصية معلقة أحدث. - يتم رفض طلبات Webhook غير المصادق عليها قبل قراءة النص عندما تكون ترويسات التوقيع المطلوبة من المزوّد مفقودة.
- يستخدم Webhook الخاص بالمكالمات الصوتية ملف تعريف النص المشترك قبل المصادقة (64 كيلوبايت / 5 ثوان) إضافة إلى حد أقصى للطلبات الجارية لكل عنوان IP قبل التحقق من التوقيع.
مثال باستخدام مضيف عام ثابت:
{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> للإشارة إلى سجل مختلف و--last <n> لتقييد
التحليل بآخر N سجلات (الافتراضي 200). يتضمن الإخراج p50/p90/p99
لزمن انتقال الدور وأوقات انتظار الاستماع.
أداة الوكيل
اسم الأداة: 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 |
يشحن هذا المستودع مستند مهارة مطابقا في skills/voice-call/SKILL.md.
Gateway RPC
| الطريقة | الوسيطات |
|---|---|
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". يجب على مكالمات
وضع الإشعار استخدام 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 كـ publicUrl.
ترسل مكالمات Twilio الصادرة في وضع الإشعار TwiML الأولي لـ OPENCLAW_DOCS_MARKER:calloutOpen:U2F5 مباشرة في
طلب إنشاء المكالمة، لذلك لا تعتمد الرسالة المنطوقة الأولى على جلب Twilio
لـ TwiML الخاص بـ Webhook. يظل Webhook العام مطلوبا لاستدعاءات الحالة،
ومكالمات المحادثة، وDTMF قبل الاتصال، والتدفقات الفورية، والتحكم بالمكالمة
بعد الاتصال.
استخدم مسار كشف عام واحدا:
{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 smokeيكون voicecall 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. - Plivo:
plivo.authIdوplivo.authTokenوfromNumber.
يجب أن توجد بيانات الاعتماد على مضيف Gateway. لا يؤثر تعديل ملف تعريف shell محلي في Gateway قيد التشغيل بالفعل حتى يعيد التشغيل أو يعيد تحميل بيئته.
تبدأ المكالمات لكن Webhooks الخاصة بالمزوّد لا تصل
تأكد من أن وحدة تحكم المزوّد تشير إلى عنوان URL العام الدقيق لـ Webhook:
https://voice.example.com/voice/webhookثم افحص حالة بيئة التشغيل:
openclaw voicecall status --call-id <id>openclaw voicecall tailopenclaw logs --followالأسباب الشائعة:
- يشير
publicUrlإلى مسار مختلف عنserve.path. - تغيّر عنوان URL الخاص بالنفق بعد بدء Gateway.
- يمرر الوكيل الطلب لكنه يزيل ترويسات المضيف/البروتوكول أو يعيد كتابتها.
- يوجه جدار الحماية أو DNS اسم المضيف العام إلى مكان آخر غير Gateway.
- تمت إعادة تشغيل Gateway دون تمكين Plugin المكالمات الصوتية.
عندما يوجد وكيل عكسي أو نفق أمام Gateway، عيّن
webhookSecurity.allowedHosts إلى اسم المضيف العام، أو استخدم
webhookSecurity.trustedProxyIPs لعنوان وكيل معروف. استخدم
webhookSecurity.trustForwardingHeaders فقط عندما تكون حدود الوكيل تحت
سيطرتك.
فشل التحقق من التوقيع
يتم فحص توقيعات المزوّد مقابل عنوان URL العام الذي يعيد OpenClaw بناءه من الطلب الوارد. إذا فشلت التوقيعات:
- تأكد من أن عنوان URL الخاص بـ Webhook لدى المزوّد يطابق
publicUrlتماما، بما في ذلك المخطط والمضيف والمسار. - بالنسبة إلى عناوين URL في الطبقة المجانية من ngrok، حدّث
publicUrlعندما يتغير اسم مضيف النفق. - تأكد من أن الوكيل يحافظ على ترويسات المضيف والبروتوكول الأصلية، أو كوّن
webhookSecurity.allowedHosts. - لا تمكّن
skipSignatureVerificationخارج الاختبار المحلي.
فشل انضمام Google Meet عبر Twilio
يستخدم Google Meet هذا Plugin للانضمام عبر اتصال Twilio الهاتفي. تحقق أولا من Voice Call:
openclaw voicecall setupopenclaw voicecall smoke --to "+15555550123"ثم تحقق صراحة من نقل Google Meet:
openclaw googlemeet setup --transport twilioإذا كان Voice Call أخضر لكن مشارك Meet لا ينضم أبدا، فتحقق من رقم الاتصال الهاتفي لـ Meet ورقم PIN و--dtmf-sequence. يمكن أن تكون المكالمة الهاتفية سليمة بينما يرفض الاجتماع تسلسل DTMF غير الصحيح أو يتجاهله.
يبدأ Google Meet طرف مكالمة Twilio الهاتفية عبر voicecall.start مع تسلسل
DTMF قبل الاتصال. تتضمن التسلسلات المشتقة من PIN قيمة
voiceCall.dtmfDelayMs الخاصة بـ Plugin Google Meet كأرقام انتظار Twilio بادئة. القيمة الافتراضية هي 12 ثانية
لأن مطالبات الاتصال الهاتفي في Meet قد تصل متأخرة. ثم يعيد Voice Call التوجيه إلى
المعالجة الفورية قبل طلب تحية المقدمة.
استخدم openclaw logs --follow لتتبع المرحلة الحية. يسجل انضمام Twilio Meet
السليم هذا الترتيب:
- يفوض Google Meet انضمام Twilio إلى Voice Call.
- يخزن Voice Call ملف TwiML الخاص بـ DTMF قبل الاتصال.
- يتم استهلاك TwiML الأولي من Twilio وتقديمه قبل المعالجة الفورية.
- يقدم Voice Call ملف TwiML الفوري لمكالمة Twilio.
- يطلب Google Meet كلام المقدمة باستخدام
voicecall.speakبعد تأخير ما بعد DTMF.
ما زال openclaw voicecall tail يعرض سجلات المكالمات المستمرة؛ وهو مفيد
لحالة المكالمة والنسخ النصية، لكن لا يظهر كل انتقال Webhook/فوري
هناك.
المكالمة الفورية بلا كلام
تأكد من تمكين وضع صوت واحد فقط. لا يمكن أن يكون realtime.enabled و
streaming.enabled كلاهما true.
بالنسبة إلى مكالمات Twilio الفورية، تحقق أيضا مما يلي:
- تم تحميل Plugin مزوّد فوري وتسجيله.
realtime.providerغير معيّن أو يسمي مزوّدا مسجلا.- مفتاح API الخاص بالمزوّد متاح لعملية Gateway.
- يعرض
openclaw logs --followتقديم TwiML الفوري، وبدء الجسر الفوري، وإدراج التحية الأولية في قائمة الانتظار.