OpenClaw音声通話プラグイン導入ガイド:Twilio/Telnyx対応
電話機能をアプリケーションに組み込むのは、いつも骨の折れる作業ですよね。API の複雑な仕様を読み込み、Webhook のセキュリティを確保し、さらには音声の遅延対策まで……。開発者が直面するこうした課題を解決するために、OpenClaw の Voice Call プラグインは設計されました。
このプラグインを使えば、OpenClaw を通じてアウトバウンドの通知や、インバウンドポリシーに基づいたマルチターンの会話を簡単に実現できます。
現在サポートされているプロバイダーは以下の通りです:
twilio(Programmable Voice + Media Streams)telnyx(Call Control v2)plivo(Voice API + XML transfer + GetInput speech)mock(開発用、ネットワーク接続なし)
基本的な流れ:
- プラグインをインストール
- Gateway を再起動
plugins.entries.voice-call.configで設定openclaw voicecall ...コマンドまたはvoice_callツールを使用
実行環境(ローカル vs リモート)
Section titled “実行環境(ローカル vs リモート)”Voice Call プラグインは Gateway プロセス内で動作します。
リモートの Gateway を使用している場合は、Gateway が動作しているマシンにプラグインをインストール・設定し、Gateway を再起動して読み込んでください。
インストール
Section titled “インストール”オプション A: npm からインストール(推奨)
Section titled “オプション A: npm からインストール(推奨)”openclaw plugins install @openclaw/voice-callインストール後、Gateway を再起動してください。
オプション B: ローカルフォルダからインストール(開発用)
Section titled “オプション B: ローカルフォルダからインストール(開発用)”PLUGIN_SRC=./path/to/local/voice-call-pluginopenclaw plugins install "$PLUGIN_SRC"cd "$PLUGIN_SRC" && pnpm installインストール後、Gateway を再起動してください。
plugins.entries.voice-call.config の下に設定を記述します:
{ plugins: { entries: { "voice-call": { enabled: true, config: { provider: "twilio", // or "telnyx" | "plivo" | "mock" fromNumber: "+15550001234", toNumber: "+15550005678",
twilio: { accountSid: "ACxxxxxxxx", authToken: "...", },
telnyx: { apiKey: "...", connectionId: "...", // Telnyx webhook public key from the Telnyx Mission Control Portal // (Base64 string; 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, streamPath: "/voice/stream", preStartTimeoutMs: 5000, maxPendingConnections: 32, maxPendingConnectionsPerIp: 4, maxConnections: 128, }, }, }, }, },}注意点:
- Twilio/Telnyx/Plivo を使用する場合、外部からアクセス可能な Webhook URL が必要です。
mockはローカル開発用のプロバイダーで、ネットワーク通信を行いません。- Telnyx では、
skipSignatureVerificationが true でない限りtelnyx.publicKey(またはTELNYX_PUBLIC_KEY)が必要です。 skipSignatureVerificationはローカルテスト専用の設定です。- ngrok の無料プランを使用する場合は、
publicUrlに正確な ngrok の URL を設定してください。署名検証は常に強制されます。 tunnel.allowNgrokFreeTierLoopbackBypass: trueを設定すると、tunnel.provider="ngrok"かつserve.bindがループバック(ngrok ローカルエージェント)の場合に限り、署名が無効な Twilio Webhook を許可します。これはローカル開発でのみ使用してください。- ngrok の無料プランの URL は変更されたり、途中に確認画面が挟まったりすることがあります。
publicUrlがずれると Twilio の署名検証に失敗するため、本番環境では固定ドメインや Tailscale Funnel の利用をおすすめします。 - ストリーミングのセキュリティ初期設定:
streaming.preStartTimeoutMs: 有効なstartフレームを送信しないソケットを閉じます。streaming.maxPendingConnections: 認証前の保留状態ソケットの総数を制限します。streaming.maxPendingConnectionsPerIp: 送信元 IP ごとの認証前保留ソケット数を制限します。streaming.maxConnections: オープンなメディアストリームソケット(保留中 + アクティブ)の総数を制限します。
停滞したコールの自動終了(Stale call reaper)
Section titled “停滞したコールの自動終了(Stale call reaper)”staleCallReaperSeconds を使用すると、終了の Webhook が届かないコール(例:完了しない通知モードのコールなど)を強制終了できます。デフォルトは 0(無効)です。
推奨される設定値:
- 本番環境: 通知スタイルのフローでは
120〜300秒。 - 通常のコールが完了できるように、
maxDurationSecondsよりも大きな値を設定してください。maxDurationSeconds + 30–60秒程度が目安です。
例:
{ plugins: { entries: { "voice-call": { config: { maxDurationSeconds: 300, staleCallReaperSeconds: 360, }, }, }, },}Webhook のセキュリティ
Section titled “Webhook のセキュリティ”Gateway の前にプロキシやトンネルがある場合、プラグインは署名検証のために公開 URL を再構成します。以下のオプションで、どの転送ヘッダーを信頼するかを制御できます。
webhookSecurity.allowedHosts は、転送ヘッダー内のホストを許可リストで制限します。
webhookSecurity.trustForwardingHeaders は、許可リストなしで転送ヘッダーを信頼します。
webhookSecurity.trustedProxyIPs は、リクエストの送信元 IP がリストに一致する場合のみ転送ヘッダーを信頼します。
Twilio と Plivo では Webhook のリプレイ保護が有効です。リプレイされた有効なリクエストは、受信確認は行われますが、実際の処理はスキップされます。
Twilio の会話ターンでは、<Gather> コールバックにターンごとのトークンが含まれます。これにより、古い、またはリプレイされた音声コールバックが新しいターンの回答として処理されるのを防ぎます。
プロバイダーが必要とする署名ヘッダーがない未認証のリクエストは、ボディを読み込む前に拒否されます。
通話用 TTS
Section titled “通話用 TTS”Voice Call は、通話中のストリーミング音声にコア設定の messages.tts を使用します。プラグイン設定内で同じ形式で記述することで、設定を上書き(ディープマージ)できます。
{ tts: { provider: "elevenlabs", providers: { elevenlabs: { voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, },}注意点:
- プラグイン設定内の古い形式(
tts.openaiなど)は、読み込み時にtts.providers.openaiへ自動移行されます。今後はproviders形式での記述を推奨します。 - Microsoft の音声は Voice Call では無視されます(電話音声には PCM が必要ですが、現在の Microsoft の実装では対応していないためです)。
- Twilio のメディアストリーミングが有効な場合はコア TTS が使用され、そうでない場合はプロバイダー標準の音声にフォールバックします。
- Twilio メディアストリームがアクティブな場合、TwiML の
<Say>へのフォールバックは行われません。TTS が利用できない場合は、再生リクエストが失敗します。 - フォールバックが発生した際は、デバッグ用にプロバイダーの試行チェーンがログに記録されます。
コア TTS をそのまま使用する場合(上書きなし):
{ messages: { tts: { provider: "openai", providers: { openai: { voice: "alloy" }, }, }, },}通話時のみ ElevenLabs を使用する場合:
{ plugins: { entries: { "voice-call": { config: { tts: { provider: "elevenlabs", providers: { elevenlabs: { apiKey: "elevenlabs_key", voiceId: "pMsXgVXv3BLzUgSXRplE", modelId: "eleven_multilingual_v2", }, }, }, }, }, }, },}通話時のみ OpenAI のモデルを変更する場合(ディープマージの例):
{ 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?",}inboundPolicy: "allowlist" は発信者番号(Caller-ID)による簡易的なフィルタリングです。Webhook の検証によってプロバイダーからの正当なリクエストであることは保証されますが、PSTN/VoIP の発信者番号自体の所有権を証明するものではありません。
自動応答は Agent システムを使用します。以下の項目で調整可能です:
responseModelresponseSystemPromptresponseTimeoutMs
音声出力の規約
Section titled “音声出力の規約”自動応答の際、Voice Call はシステムプロンプトに以下の厳格な出力規約を追加します:
{"spoken":"..."}
プラグインは以下の方法で音声を抽出します:
- 思考プロセス(reasoning)やエラー内容は無視します。
- JSON 直接、フェンス付き JSON、またはインラインの
"spoken"キーを解析します。 - プレーンテキストの場合は、計画やメタ的な導入文を除去して抽出します。
これにより、発信者に不要な思考プロセスを聞かせることなく、適切な応答のみを再生します。
会話開始時の挙動
Section titled “会話開始時の挙動”アウトバウンドの conversation コールでは、最初のメッセージ処理は再生状態と連動します:
- 最初の挨拶を再生している間は、割り込み(Barge-in)キューのクリアや自動応答が抑制されます。
- 再生に失敗した場合、コールは
listening状態に戻り、メッセージはリトライのためにキューに残ります。
Twilio ストリーム切断時の猶予
Section titled “Twilio ストリーム切断時の猶予”Twilio のメディアストリームが切断された場合、Voice Call は 2000ms 待機してからコールを終了します:
- 猶予期間内に再接続されれば、終了処理はキャンセルされます。
- 再接続されない場合は、アクティブなコールが残るのを防ぐために終了処理が行われます。
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 end --call-id <id>openclaw voicecall status --call-id <id>openclaw voicecall tailopenclaw voicecall latency # summarize turn latency from logsopenclaw voicecall expose --mode funnellatency コマンドは calls.jsonl から統計を読み取ります。--file でパスを指定したり、--last <n> で直近のレコード数を制限したりできます。p50/p90/p99 のレイテンシを確認するのに便利です。
Agent ツール
Section titled “Agent ツール”ツール名: voice_call
アクション:
initiate_call(message, to?, mode?)continue_call(callId, message)speak_to_user(callId, message)end_call(callId)get_status(callId)
対応するスキル定義は skills/voice-call/SKILL.md にあります。
Gateway RPC
Section titled “Gateway RPC”voicecall.initiate(to?,message,mode?)voicecall.continue(callId,message)voicecall.speak(callId,message)voicecall.end(callId)voicecall.status(callId)
次のステップ
Section titled “次のステップ”- AI Setup Assistant で設定のサポートを受ける
- TTS 設定ガイド を確認する
- Agent スキルの作成 について学ぶ
{ plugins: { entries: { "voice-call": { config: { publicUrl: "https://voice.example.com/voice/webhook", webhookSecurity: { allowedHosts: ["voice.example.com"], }, }, }, }, },}OpenClaw Expert
まだ解決しませんか?
このページで解決しない場合は、OpenClaw Expertに直接質問してください。