Skip to content

本页是 OpenClaw Voice Call 插件的完整配置参考。插件支持 Twilio(Programmable Voice)、Telnyx(Call Control v2)、Plivo(Voice API)三个语音平台,以及本地 mock 提供商。覆盖从 npm 安装、配置文件结构、流式转录(OpenAI Realtime STT)、入站呼叫策略、TTS 自定义、Webhook 安全加固,到 CLI 命令和 Agent voice_call 工具的全部内容。想让龙虾打电话,这页文档是必读。

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 工具。

Voice Call 插件运行在 Gateway 进程内部。如果你使用远程 Gateway,在运行 Gateway 的机器上安装和配置插件,然后重启 Gateway。

安装

方式 A:从 npm 安装(推荐)

bash
openclaw plugins install @openclaw/voice-call

安装后重启 Gateway。

方式 B:从本地目录安装(开发用)

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

安装后重启 Gateway。

配置

plugins.entries.voice-call.config 下设置:

json5
{
  plugins: {
    entries: {
      "voice-call": {
        enabled: true,
        config: {
          provider: "twilio", // 或 "telnyx" | "plivo" | "mock"
          fromNumber: "+15550001234",
          toNumber: "+15550005678",

          twilio: {
            accountSid: "ACxxxxxxxx",
            authToken: "...",
          },

          telnyx: {
            apiKey: "...",
            connectionId: "...",
            // Telnyx webhook 公钥(Base64;也可通过 TELNYX_PUBLIC_KEY 设置)
            publicKey: "...",
          },

          plivo: {
            authId: "MAxxxxxxxxxxxxxxxxxxxx",
            authToken: "...",
          },

          // Webhook 服务器
          serve: {
            port: 3334,
            path: "/voice/webhook",
          },

          // Webhook 安全(隧道/代理场景推荐)
          webhookSecurity: {
            allowedHosts: ["voice.example.com"],
            trustedProxyIPs: ["100.64.0.1"],
          },

          // 公网暴露方式(三选一)
          // publicUrl: "https://example.ngrok.app/voice/webhook",
          // tunnel: { provider: "ngrok" },
          // tailscale: { mode: "funnel", path: "/voice/webhook" }

          outbound: {
            defaultMode: "notify", // notify | conversation
          },

          streaming: {
            enabled: true,
            provider: "openai",
            streamPath: "/voice/stream",
            providers: {
              openai: {
                apiKey: "sk-...",
                model: "gpt-4o-transcribe",
                silenceDurationMs: 800,
                vadThreshold: 0.5,
              },
            },
          },
        },
      },
    },
  },
}

注意事项:

  • Twilio/Telnyx/Plivo 均需公网可访问的 Webhook URL
  • mock 是本地开发提供商,不产生实际网络调用
  • 如果旧配置还在用 provider: "log" 或旧版流式配置键,运行 openclaw doctor --fix 自动修复
  • Telnyx 必须提供 telnyx.publicKey(或 TELNYX_PUBLIC_KEY),除非设了 skipSignatureVerification
  • skipSignatureVerification 仅用于本地测试

流式转录

streaming 配置选择用于实时通话音频的转录提供商。

  • streaming.provider 可选;未设置时使用第一个注册的实时转录提供商
  • 当前内置提供商是 OpenAI,由内置 openai 插件注册
  • Provider 特定配置在 streaming.providers.<providerId>

OpenAI 流式转录默认值:

  • API Key:streaming.providers.openai.apiKeyOPENAI_API_KEY
  • 模型:gpt-4o-transcribe
  • silenceDurationMs800
  • vadThreshold0.5

旧版配置键自动迁移(通过 openclaw doctor --fix):

  • streaming.sttProviderstreaming.provider
  • streaming.openaiApiKeystreaming.providers.openai.apiKey
  • streaming.sttModelstreaming.providers.openai.model

通话 TTS 配置

Voice Call 使用核心 messages.tts 配置进行通话中的流式语音合成。你也可以在插件配置中覆盖它(使用相同的结构,与 messages.tts 深度合并):

json5
// 覆盖为 ElevenLabs(仅用于通话)
{
  plugins: {
    entries: {
      "voice-call": {
        config: {
          tts: {
            provider: "elevenlabs",
            providers: {
              elevenlabs: {
                apiKey: "elevenlabs_key",
                voiceId: "pMsXgVXv3BLzUgSXRplE",
                modelId: "eleven_multilingual_v2",
              },
            },
          },
        },
      },
    },
  },
}

注意:Microsoft 语音在通话中被忽略(电话音频需要 PCM;当前 Microsoft 传输不暴露电话 PCM 输出)。

失效通话清理器

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

推荐范围:

  • 生产环境:notify 模式通话用 120300
  • 保持高于 maxDurationSeconds,让正常通话能正常结束
json5
{
  plugins: {
    entries: {
      "voice-call": {
        config: {
          maxDurationSeconds: 300,
          staleCallReaperSeconds: 360,
        },
      },
    },
  },
}

Webhook 安全

当代理或隧道在 Gateway 前面时,插件重建公网 URL 以进行签名验证。

  • webhookSecurity.allowedHosts:从转发头中白名单允许的主机
  • webhookSecurity.trustForwardingHeaders:不使用白名单直接信任转发头
  • webhookSecurity.trustedProxyIPs:仅当请求远程 IP 匹配列表时信任转发头

Twilio 和 Plivo 已启用 Webhook 重放保护,重放的有效请求会被确认但跳过副作用。

呼入通话

呼入策略默认为 disabled。启用呼入:

json5
{
  inboundPolicy: "allowlist",
  allowFrom: ["+15550001234"],
  inboundGreeting: "你好!有什么可以帮您?",
}

inboundPolicy: "allowlist" 是低保证的来电号码过滤,将提供商提供的 From 值规范化后与 allowFrom 比对。Webhook 验证认证提供商交付和载荷完整性,但无法证明 PSTN/VoIP 主叫号码所有权。将 allowFrom 视为来电 ID 过滤,而非强身份认证。

自动回复使用 agent 系统,可调整:

  • responseModel
  • responseSystemPrompt
  • responseTimeoutMs

会话启动行为

对于出站 conversation 通话,首条消息处理与实时播放状态绑定:

  • 只有在初始问候语正在播放时,才会抑制 barge-in 队列清空和自动回复。
  • 如果初始播放失败,通话会返回 listening 状态,初始消息保留在队列中等待重试。
  • Twilio streaming 的初始播放在 stream 连接时立即开始,无需额外等待。

Twilio Stream 断开宽限期

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

  • 若 stream 在此窗口内重连,自动结束会被取消。
  • 若宽限期结束后仍未重新注册 stream,通话将被终止,防止出现卡住的活跃通话。

CLI 命令

bash
openclaw voicecall call --to "+15555550123" --message "你好,来自 OpenClaw"
openclaw voicecall start --to "+15555550123"   # call 的别名
openclaw voicecall continue --call-id <id> --message "还有其他问题吗?"
openclaw voicecall speak --call-id <id> --message "请稍等"
openclaw voicecall end --call-id <id>
openclaw voicecall status --call-id <id>
openclaw voicecall tail
openclaw voicecall latency                     # 从日志汇总通话延迟
openclaw voicecall expose --mode funnel

latency 从默认 voice-call 存储路径读取 calls.jsonl,使用 --file <path> 指定其他日志,--last <n> 限制分析最后 N 条记录(默认 200)。输出包含通话轮次延迟和监听等待时间的 p50/p90/p99。

Agent 工具

工具名:voice_call

可用动作:

  • initiate_call(message, to?, mode?)
  • continue_call(callId, message)
  • speak_to_user(callId, message)
  • end_call(callId)
  • get_status(callId)

Gateway RPC

  • voicecall.initiate(to?, message, mode?)
  • voicecall.continue(callId, message)
  • voicecall.speak(callId, message)
  • voicecall.end(callId)
  • voicecall.status(callId)

常见问题

Q: Twilio 通话总是报签名验证失败,怎么排查?

A: 最常见的原因是 publicUrl 与 Twilio 实际访问的 URL 不一致(尤其是用 ngrok 免费版时 URL 会变化)。确认 publicUrl 配置的 URL 和 Twilio 控制台中配置的 Webhook URL 完全一致,包括路径和协议。如果使用代理,检查 webhookSecurity.allowedHosts 是否包含了代理的主机名。

Q: 通话中 TTS 没声音,但 chat TTS 是正常的,怎么办?

A: Voice Call 使用的是 电话优化 TTStextToSpeechTelephony)。确认 TTS 提供商支持电话模式。Microsoft TTS 当前不支持电话 PCM 输出,如果你配置的是 Microsoft 语音,需要切换到 OpenAI 或 ElevenLabs。另外检查 streaming.enabled 是否为 true,流式模式下 TTS 优先于 TwiML <Say>

Q: 呼入通话配置了 allowFrom 但还是被拒绝,原因是什么?

A: allowFrom 是来电号码白名单,格式需要和提供商传入的 From 格式一致(通常是 E.164 格式,如 +15550001234)。检查格式是否完全一致,包括国家代码。inboundPolicy 必须设为 "allowlist" 而非 "disabled"(默认值)。