扩展

语音通话插件

OpenClaw 的语音通话通过插件提供。支持出站通知、多轮对话、全双工实时语音、流式转录,以及带有允许列表策略的入站通话。

当前提供商: twilio(Programmable Voice + Media Streams)、telnyx(Call Control v2)、plivo(Voice API + XML transfer + GetInput speech)、mock(开发/无网络)。

快速开始

  • 安装插件

    从 npm 安装

    openclaw plugins install @openclaw/voice-call
    

    从本地文件夹安装(开发)

    PLUGIN_SRC=./path/to/local/voice-call-plugin
    openclaw plugins install "$PLUGIN_SRC"
    cd "$PLUGIN_SRC" && pnpm install
    

    使用裸包以跟随当前官方发布标签。仅在需要可复现安装时固定精确版本。

    随后重启 Gateway 网关,以便插件加载。

  • 配置提供商和 webhook

    plugins.entries.voice-call.config 下设置配置(完整结构见下方的配置)。至少需要: provider、提供商凭证、fromNumber,以及一个可公开访问的 webhook URL。

  • 验证设置

    openclaw voicecall setup
    

    默认输出在聊天日志和终端中都易于阅读。它会检查插件是否启用、提供商凭证、webhook 暴露情况,以及是否只有一种音频模式(streamingrealtime)处于启用状态。脚本可使用 --json

  • 冒烟测试

    openclaw voicecall smoke
    openclaw 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 都需要一个可公开访问的 webhook URL。
    • mock 是本地开发提供商(不会发起网络调用)。
    • 除非 skipSignatureVerification 为 true,否则 Telnyx 需要 telnyx.publicKey(或 TELNYX_PUBLIC_KEY)。
    • skipSignatureVerification 仅用于本地测试。
    • 在 ngrok 免费层上,将 publicUrl 设置为确切的 ngrok URL;签名验证始终强制执行。
    • tunnel.allowNgrokFreeTierLoopbackBypass: true 仅在 tunnel.provider="ngrok"serve.bind 为 loopback(ngrok 本地代理)时,允许带有无效签名的 Twilio webhook。仅限本地开发。
    • Ngrok 免费层 URL 可能会变化或增加插页行为;如果 publicUrl 漂移,Twilio 签名会失败。生产环境:优先使用稳定域名或 Tailscale funnel。
    流式连接上限
    • streaming.preStartTimeoutMs 会关闭从未发送有效 start 帧的 socket。
    • streaming.maxPendingConnections 限制未认证的预启动 socket 总数。
    • streaming.maxPendingConnectionsPerIp 限制每个源 IP 的未认证预启动 socket 数量。
    • streaming.maxConnections 限制打开的媒体流 socket 总数(待处理 + 活跃)。
    旧版配置迁移

    使用 provider: "log"twilio.from 或旧版 streaming.* OpenAI 键的旧配置会由 openclaw doctor --fix 重写。运行时回退目前仍接受旧的语音通话键,但重写路径是 openclaw doctor --fix,兼容 shim 是临时的。

    自动迁移的流式传输键:

    • streaming.sttProviderstreaming.provider
    • streaming.openaiApiKeystreaming.providers.openai.apiKey
    • streaming.sttModelstreaming.providers.openai.model
    • streaming.silenceDurationMsstreaming.providers.openai.silenceDurationMs
    • streaming.vadThresholdstreaming.providers.openai.vadThreshold

    会话范围

    默认情况下,Voice Call 使用 sessionScope: "per-phone",因此同一来电者重复来电会保留对话记忆。当每次运营商通话都应以全新上下文开始时,请设置 sessionScope: "per-call",例如前台接待、预订、IVR,或 Google Meet 桥接流程,其中同一个电话号码可能代表不同会议。

    实时语音对话

    realtime 会为实时通话音频选择一个全双工实时语音提供商。它与 streaming 分开,后者只会将音频转发给实时转录提供商。

    当前运行时行为:

    • Twilio Media Streams 支持 realtime.enabled
    • realtime.provider 是可选的。如果未设置,Voice Call 会使用第一个注册的实时语音提供商。
    • 内置实时语音提供商:Google Gemini Live(google)和 OpenAI(openai),由各自的提供商插件注册。
    • 提供商拥有的原始配置位于 realtime.providers.<providerId> 下。
    • Voice Call 默认暴露共享的 openclaw_agent_consult 实时工具。当来电者请求更深入的推理、当前信息或常规 OpenClaw 工具时,实时模型可以调用它。
    • realtime.consultPolicy 可选地添加指导,说明实时模型何时应调用 openclaw_agent_consult
    • realtime.agentContext.enabled 默认关闭。启用后,Voice Call 会在会话设置时向实时提供商指令中注入有边界的智能体身份、系统提示覆盖,以及选定的工作区文件胶囊。
    • realtime.fastContext.enabled 默认关闭。启用后,Voice Call 会先搜索已索引的记忆/会话上下文来回答 consult 问题,并在 realtime.fastContext.timeoutMs 内将这些片段返回给实时模型;仅当 realtime.fastContext.fallbackToConsult 为 true 时,才回退到完整的 consult 智能体。
    • 如果 realtime.provider 指向未注册的提供商,或者根本没有注册任何实时语音提供商,Voice Call 会记录警告并跳过实时媒体,而不是让整个插件失败。
    • Consult 会话键会在可用时复用已存储的通话会话,然后回退到配置的 sessionScope(默认 per-phone,隔离通话为 per-call)。

    工具策略

    realtime.toolPolicy 控制 consult 运行:

    策略 行为
    safe-read-only 暴露 consult 工具,并将常规智能体限制为 readweb_searchweb_fetchx_searchmemory_searchmemory_get
    owner 暴露 consult 工具,并允许常规智能体使用正常的智能体工具策略。
    none 不暴露 consult 工具。自定义 realtime.tools 仍会透传给实时提供商。

    realtime.consultPolicy 仅控制实时模型指令:

    策略 指导
    auto 保留默认提示,并让提供商决定何时调用 consult 工具。
    substantive 直接回答简单的对话衔接内容,并在涉及事实、记忆、工具或上下文前进行 consult。
    always 在每个实质性回答前进行 consult。

    智能体语音上下文

    当语音桥接应听起来像已配置的 OpenClaw 智能体,而普通轮次又不想支付完整智能体 consult 往返成本时,请启用 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,
                  includeSystemPrompt: true,
                  includeWorkspaceFiles: true,
                  files: ["SOUL.md", "IDENTITY.md", "USER.md"],
                },
              },
            },
          },
        },
      },
    }
    

    实时提供商示例

    Google Gemini Live

    默认值:API key 来自 realtime.providers.google.apiKeyGEMINI_API_KEYGOOGLE_GENERATIVE_AI_API_KEY;模型 gemini-2.5-flash-native-audio-preview-12-2025;语音 Kore。 对于更长、可重连的通话,sessionResumptioncontextWindowCompression 默认开启。使用 silenceDurationMsstartSensitivityendSensitivity 来针对电话音频调优更快的轮次切换。

    {
      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",
                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 provider,了解特定提供商的实时语音 选项。

    流式转录

    streaming 为实时通话音频选择实时转录提供商。

    当前运行时行为:

    • streaming.provider 是可选的。如果未设置,Voice Call 会使用第一个已注册的实时转录提供商。
    • 内置实时转录提供商:Deepgram(deepgram)、ElevenLabs(elevenlabs)、Mistral(mistral)、OpenAI(openai)和 xAI(xai),由各自的提供商插件注册。
    • 提供商拥有的原始配置位于 streaming.providers.<providerId> 下。
    • Twilio 发送已接受的流 start 消息后,Voice Call 会立即注册该流,在提供商连接期间通过转录提供商排队入站媒体,并且只会在实时转录就绪后才开始初始问候。
    • 如果 streaming.provider 指向未注册的提供商,或者没有任何提供商已注册,Voice Call 会记录警告并跳过媒体流式传输,而不是让整个插件失败。

    流式提供商示例

    OpenAI

    默认值:API key streaming.providers.openai.apiKeyOPENAI_API_KEY;模型 gpt-4o-transcribesilenceDurationMs: 800vadThreshold: 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 key streaming.providers.xai.apiKeyXAI_API_KEY; 端点 wss://api.x.ai/v1/stt;编码 mulaw;采样率 8000endpointingMs: 800interimResults: 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

    Voice Call 使用核心 messages.tts 配置进行通话上的流式 语音。你可以在插件配置下用相同结构覆盖它——它会与 messages.tts 深度合并。

    {
      tts: {
        provider: "elevenlabs",
        providers: {
          elevenlabs: {
            voiceId: "pMsXgVXv3BLzUgSXRplE",
            modelId: "eleven_multilingual_v2",
          },
        },
      },
    }
    

    行为说明:

    • 插件配置中的旧版 tts.<provider> 键(openaielevenlabsmicrosoftedge)会由 openclaw doctor --fix 修复;提交的配置应使用 tts.providers.<provider>
    • 启用 Twilio 媒体流式传输时会使用核心 TTS;否则通话会回退到提供商原生语音。
    • 如果 Twilio 媒体流已经处于活动状态,Voice Call 不会回退到 TwiML OPENCLAW_DOCS_MARKER:calloutOpen:U2F5。如果在该状态下电话 TTS 不可用,播放请求会失败,而不是混用两条播放路径。
    • 当电话 TTS 回退到辅助提供商时,Voice Call 会记录一条警告,其中包含提供商链(fromtoattempts),用于调试。
    • 当 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?",
    }
    

    自动响应使用智能体系统。可通过 responseModelresponseSystemPromptresponseTimeoutMs 调整。

    按号码路由

    当一个 Voice Call 插件接收多个电话号码的呼叫,并且每个号码都应像不同线路一样工作时,请使用 numbers。例如,一个 号码可以使用休闲的个人助理,而另一个号码可以使用商务 人设、不同的响应智能体和不同的 TTS 语音。

    路由根据提供商提供的被拨 To 号码选择。键必须是 E.164 号码。呼叫到达时,Voice Call 会解析一次匹配的路由, 将匹配的路由存储到通话记录上,并将该有效配置复用于 问候语、经典自动响应路径、实时咨询路径和 TTS 播放。如果没有路由匹配,则使用全局 Voice Call 配置。 出站呼叫不使用 numbers;发起呼叫时请显式传入出站目标、消息和 会话。

    路由覆盖目前支持:

    • inboundGreeting
    • tts
    • agentId
    • responseModel
    • responseSystemPrompt
    • responseTimeoutMs

    tts 路由值会深度合并到全局 Voice Call 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" },
          },
        },
      },
    },
    }
    

    口语输出契约

    对于自动响应,Voice Call 会向系统提示追加严格的口语输出契约:

    {"spoken":"..."}
    

    Voice Call 会防御性地提取语音文本:

    • 忽略标记为推理/错误内容的载荷。
    • 解析直接 JSON、围栏 JSON 或内联 "spoken" 键。
    • 回退到纯文本,并移除看起来像规划/元信息开头的段落。

    这会让语音播放聚焦于面向来电者的文本,并避免 将规划文本泄漏到音频中。

    对话启动行为

    对于出站 conversation 呼叫,首条消息处理会绑定到实时 播放状态:

    • 仅当初始问候语正在主动朗读时,才会抑制插话队列清空和自动响应。
    • 如果初始播放失败,通话会返回 listening,并且初始消息会保持排队以供重试。
    • Twilio 流式传输的初始播放会在流连接时开始,不会额外延迟。
    • 插话会中止正在进行的播放,并清除已排队但尚未播放的 Twilio TTS 条目。被清除的条目会解析为已跳过,因此后续响应逻辑可以继续,而无需等待永远不会播放的音频。
    • 实时语音对话使用实时流自己的开场轮次。Voice Call 不会为该初始消息发布旧版 OPENCLAW_DOCS_MARKER:calloutOpen:U2F5 TwiML 更新,因此出站 &lt;Connect&gt;&lt;Stream&gt; 会话会保持附加状态。

    Twilio 流断开宽限期

    当 Twilio 媒体流断开时,Voice Call 会等待 2000 ms,然后 自动结束通话:

    • 如果流在该窗口期内重新连接,则取消自动结束。
    • 如果宽限期后没有流重新注册,则结束通话以防止活动通话卡住。

    过期通话清理器

    使用 staleCallReaperSeconds 结束从未收到终止 webhook 的通话(例如,永不完成的通知模式通话)。默认值 为 0(禁用)。

    建议范围:

    • 生产环境: 通知类流程使用 120300 秒。
    • 保持此值高于 maxDurationSeconds,这样正常调用才能完成。一个好的起点是 maxDurationSeconds + 30–60 秒。
    {
    plugins: {
    entries: {
      "voice-call": {
        config: {
          maxDurationSeconds: 300,
          staleCallReaperSeconds: 360,
        },
      },
    },
    },
    }
    

    网络钩子安全性

    当代理或隧道位于 Gateway 网关前面时,插件会重建用于签名验证的公开 URL。这些选项控制信任哪些转发头:

    webhookSecurity.allowedHostsstring[]

    允许来自转发头的主机列表。

    webhookSecurity.trustForwardingHeadersboolean

    在没有允许列表的情况下信任转发头。

    webhookSecurity.trustedProxyIPsstring[]

    仅当请求远程 IP 与列表匹配时才信任转发头。

    其他保护措施:

    • Twilio 和 Plivo 已启用网络钩子重放保护。重放的有效网络钩子请求会被确认,但会跳过副作用。
    • Twilio 对话轮次在 &lt;Gather&gt; 回调中包含每轮令牌,因此过期或重放的语音回调无法满足较新的待处理转录轮次。
    • 当缺少提供商要求的签名头时,未认证的网络钩子请求会在读取正文之前被拒绝。
    • voice-call 网络钩子使用共享的预认证正文配置(64 KB / 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 call
    openclaw 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 tail
    openclaw voicecall latency                      # summarize turn latency from logs
    openclaw voicecall expose --mode funnel
    

    当 Gateway 网关已在运行时,操作性 voicecall 命令会委托给 Gateway 网关拥有的 voice-call 运行时,因此 CLI 不会绑定第二个网络钩子服务器。如果无法访问 Gateway 网关,这些命令会回退到独立的 CLI 运行时。

    latency 会从默认 voice-call 存储路径读取 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

    故障排除

    设置无法完成网络钩子暴露

    从运行 Gateway 网关的同一环境运行设置:

    openclaw voicecall setup
    openclaw voicecall setup --json
    

    对于 twiliotelnyxplivowebhook-exposure 必须为绿色。当已配置的 publicUrl 指向本地或专用网络空间时仍会失败,因为运营商无法回拨这些地址。不要将 localhost127.0.0.10.0.0.010.x172.16.x-172.31.x192.168.x169.254.xfc00::/7fd00::/8 用作 publicUrl

    Twilio 通知模式出站调用会在创建调用请求中直接发送初始 OPENCLAW_DOCS_MARKER:calloutOpen:U2F5 TwiML,因此第一条语音消息不依赖 Twilio 获取网络钩子 TwiML。状态回调、对话调用、连接前 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 setup
    openclaw voicecall smoke
    

    除非你传入 --yes,否则 voicecall smoke 是一次空运行。

    提供商凭证失败

    检查所选提供商和必需的凭证字段:

    • Twilio:twilio.accountSidtwilio.authTokenfromNumber,或 TWILIO_ACCOUNT_SIDTWILIO_AUTH_TOKENTWILIO_FROM_NUMBER
    • Telnyx:telnyx.apiKeytelnyx.connectionIdtelnyx.publicKeyfromNumber
    • Plivo:plivo.authIdplivo.authTokenfromNumber

    凭证必须存在于 Gateway 网关主机上。编辑本地 shell 配置文件不会影响已运行的 Gateway 网关,直到它重启或重新加载其环境。

    调用已启动,但提供商网络钩子未到达

    确认提供商控制台指向确切的公开网络钩子 URL:

    https://voice.example.com/voice/webhook
    

    然后检查运行时状态:

    openclaw voicecall status --call-id <id>
    openclaw voicecall tail
    openclaw logs --follow
    

    常见原因:

    • publicUrl 指向的路径与 serve.path 不同。
    • 隧道 URL 在 Gateway 网关启动后发生了变化。
    • 代理转发了请求,但剥离或重写了主机/协议头。
    • 防火墙或 DNS 将公开主机名路由到了 Gateway 网关以外的位置。
    • Gateway 网关重启时未启用 Voice Call 插件。

    当反向代理或隧道位于 Gateway 网关前面时,将 webhookSecurity.allowedHosts 设置为公开主机名,或对已知代理地址使用 webhookSecurity.trustedProxyIPs。仅当代理边界由你控制时才使用 webhookSecurity.trustForwardingHeaders

    签名验证失败

    提供商签名会根据 OpenClaw 从传入请求重建的公开 URL 进行检查。如果签名失败:

    • 确认提供商网络钩子 URL 与 publicUrl 完全匹配,包括协议、主机和路径。
    • 对于 ngrok 免费层 URL,当隧道主机名变化时更新 publicUrl
    • 确保代理保留原始主机和协议头,或配置 webhookSecurity.allowedHosts
    • 不要在本地测试以外启用 skipSignatureVerification

    Google Meet Twilio 加入失败

    Google Meet 使用此插件进行 Twilio 拨入加入。先验证 Voice Call:

    openclaw voicecall setup
    openclaw voicecall smoke --to "+15555550123"
    

    然后显式验证 Google Meet 传输:

    openclaw googlemeet setup --transport twilio
    

    如果 Voice Call 正常但 Meet 参会者从未加入,请检查 Meet 拨入号码、PIN 和 --dtmf-sequence。电话调用可能是健康的,而会议会拒绝或忽略不正确的 DTMF 序列。

    Google Meet 通过 voicecall.start 和连接前 DTMF 序列启动 Twilio 电话线路。由 PIN 派生的序列会将 Google Meet 插件的 voiceCall.dtmfDelayMs 作为前导 Twilio 等待数字包含进去。默认值为 12 秒,因为 Meet 拨入提示可能较晚到达。然后 Voice Call 会在请求介绍问候语之前重定向回实时处理。

    使用 openclaw logs --follow 查看实时阶段跟踪。健康的 Twilio Meet 加入会按以下顺序记录日志:

    • Google Meet 将 Twilio 加入委托给 Voice Call。
    • Voice Call 存储连接前 DTMF TwiML。
    • Twilio 初始 TwiML 在实时处理之前被消费并提供。
    • Voice Call 为 Twilio 调用提供实时 TwiML。
    • Google Meet 在 DTMF 后延迟之后通过 voicecall.speak 请求介绍语音。

    openclaw voicecall tail 仍会显示已持久化的调用记录;它对调用状态和转录很有用,但并非每个网络钩子/实时转换都会出现在那里。

    实时调用没有语音

    确认只启用一种音频模式。realtime.enabledstreaming.enabled 不能同时为 true。

    对于实时 Twilio 调用,还要验证:

    • 已加载并注册实时提供商插件。
    • realtime.provider 未设置,或命名了一个已注册的提供商。
    • 提供商 API key 可供 Gateway 网关进程使用。
    • openclaw logs --follow 显示已提供实时 TwiML、实时桥接已启动,并且初始问候语已排队。

    相关内容