GPT-Live 接入概览

GPT-Live 通过 SIP 中继连接呼入和呼出电话。服务提供商负责与 OpenAI 交换通话音频,开发者后端则处理会话配置、通话控制及业务逻辑。SIP 信令采用 TLS 协议,通话音频必须使用 SRTP 加密。

  • 处理呼入:接收 incoming-call webhook,随后决定接受或拒绝呼叫。
  • 发起呼出:创建会话并通过提供商拨打号码,无需 webhook 或接受请求。

后端通过侧边通道(sideband)连接接收会话事件或发送命令。该连接附加于现有对话之上,SIP 仅负责承载音频。为防止因重复 webhook 投递或多连接观察导致工具双重执行,需为每个操作分配唯一处理器。

呼入电话处理流程

将来自 SIP 提供商的呼入电话路由至 OpenAI 项目。后端接收 webhook 后,根据业务规则决定是否接受呼叫。

配置电话号码和中继

使用 Twilio 等 SIP 中继提供商连接电话号码至 GPT-Live。购买号码后执行以下步骤:

  1. 在 OpenAI 项目设置的 Webhooks 下,创建订阅了 live.transport.incoming 的 webhook 端点。
  2. 在 General(常规)中获取以 proj_ 开头的项目 ID,确保其与 webhook 所属项目一致。
  3. 将提供商的 SIP 中继指向 sip:$PROJECT_ID@sip.api.openai.com;transport=tls。若需欧洲数据驻留,使用 sip:$PROJECT_ID@sip-eu.api.openai.com;transport=tls。

注意:使用前需确认项目已启用 GPT-Live SIP 支持,且提供商中继已正确路由。

接收与验证呼叫

当 OpenAI 收到针对项目的呼叫时,会向 webhook 端点发送 live.transport.incoming 事件。后端需验证签名并去重,随后决定接受或拒绝。

Webhook 通过 data.type: "sip" 标识 SIP 呼叫,并提供 data.session_id。在所有 Live 呼叫操作中需保持不变地使用该会话 ID。data.sip_headers 应视为不可信的来电元数据,而非授权凭据。

Webhook 主体示例:

{
  "object": "event",
  "id": "evt_abc123",
  "type": "live.transport.incoming",
  "created_at": 1750287018,
  "data": {
    "type": "sip",
    "session_id": "live_123",
    "sip_headers": [
      { "name": "From", "value": "sip:+14155550123@sip.example.com" },
      { "name": "To", "value": "sip:+18005550100@sip.example.com" },
      { "name": "Call-ID", "value": "call-123@example.com" }
    ]
  }
}

created_at 为秒级 Unix 时间戳。投递标头包含用于去重的 webhook-id、时间戳 webhook-timestamp 及签名 webhook-signature。

迁移期间,现有集成可能仍收到已弃用的 live.call.incoming 事件(无 data.type)。建议同时处理两种名称,并在旧版订阅耗尽前保留兼容逻辑。同一待处理呼叫可能触发 Realtime webhook,需确保接受/拒绝决策仅由一个处理器执行。

接受或拒绝呼叫

应用授权和路由规则后,发送经过身份验证的请求以接受或拒绝呼叫。

接受呼叫:发送 POST /v1/live/sessions/{session_id}/accept,附带顶层 session 对象。使用受信任后端的 Authorization: Bearer $OPENAI_API_KEY。由于 SIP 协商音频格式,需省略 audio.format。

{
  "session": {
    "type": "live",
    "model": "gpt-live-1",
    "instructions": "You are answering an inbound support call.",
    "audio": { "output": { "voice": "marin" } },
    "delegation": { "type": "client" }
  }
}

成功接受后返回 200 OK 且空主体。仅在收到 HTTP 成功响应后视为呼叫已接受。

拒绝呼叫:发送 POST /v1/live/sessions/{session_id}/reject,附带 SIP 状态码(如 { "status_code": 486 })。状态码须为 300 至 699 之间的整数。首个决策生效,后续竞争性决策将返回 decision_already_made。

附加后端连接

接受呼叫后,通过 wss://api.openai.com/v1/live/sessions/{session_id}/attach 建立侧边通道 WebSocket 连接。使用相同的会话 ID、项目身份验证和连接标头,切勿再次发送 session.start。

SIP 承载音频,侧边通道传输转录文本、委托、工具、命令及回声音频。即使多连接观察到事件,也需为每个副作用指定单一所有者。连接成功后即可使用通话控制功能(如发送按键音、转移或挂断)。

呼出电话处理流程

通过 Create session API 经由 SIP 提供商拨打号码。提供商负责电话网络连接,GPT-Live 承载对话。呼出 SIP 呼叫通过 Live API 提供,而非 Realtime API。

配置中继

使用支持 TLS 信令和 SDES-SRTP 媒体的中继,并在提供商设置中启用 SRTP。请求中需提供以下中继配置:

字段 值
transport.destination E.164 格式电话号码(如 +14155550123),不支持 SIP URI。
transport.trunk.provider_url 提供商端点(如 sips:sip.example.com:5061)。默认端口 5061,;transport=tcp 可选。
transport.trunk.auth.type SIP Digest 认证使用 digest。
transport.trunk.auth.username 提供商 SIP 用户名。
transport.trunk.auth.password 提供商 SIP 密码。
transport.trunk.caller_number E.164 格式的主叫号码。

提供商端点必须使用 sips: 进行 TLS 信令。URL 中不得包含凭据、路径或额外参数。本地主机名及私有 IP 地址将被拒绝。OpenAI API 密钥和 SIP 凭据应保留在服务器端。

创建会话

发送 POST /v1/live/sessions 请求,包含会话配置及 transport.type: "sip"。同样需省略 audio.format。

cURL 示例:

jq -n \
  --arg username "$SIP_USERNAME" \
  --arg password "$SIP_PASSWORD" \
  '{
    "session": {
      "model": "gpt-live-1",
      "instructions": "Help the user schedule an appointment.",
      "audio": { "output": { "voice": "marin" } },
      "delegation": { "type": "client" }
    },
    "transport": {
      "type": "sip",
      "destination": "+14155550123",
      "trunk": {
        "provider_url": "sips:sip.example.com:5061",
        "auth": {
          "type": "digest",
          "username": $username,
          "password": $password
        },
        "caller_number": "+14155550100"
      }
    }
  }' | curl https://api.openai.com/v1/live/sessions \
    -H "Authorization: Bearer $OPENAI_API_KEY" \
    -H "Content-Type: application/json" \
    --data-binary @-

会话初始化后返回 200 OK,包含 session.id。此响应不代表呼叫已被接听,也不含 SDP 或中继凭据。呼出呼叫无需 webhook 或接受请求。

监控与结束呼叫

使用 API 密钥将后端附加至侧边通道 WebSocket。侧边通道承载对话事件和通话进度,SIP 承载音频。

事件 含义
transport.ringing 提供商报告振铃或早期媒体。
transport.answered 呼叫已接听且媒体已建立。
transport.failed 会话初始化后呼叫设置失败。检查 error.code 和 error.message。

每个事件包含 event_id 和 session_id。建议在创建后立即附加连接,因侧边通道仅重播前 3 秒事件。需按 event_id 对事件去重。保持连接直至收到 session.closed。

限制与错误处理

振铃限制为 3 分钟,已连接呼叫限制为 2 小时,均不可配置。无效配置将在创建请求中返回错误。传输设置失败可能返回 502,超时返回 504。创建成功后需监控 transport.failed 以检测异步失败。

活动呼叫管理

以下控制功能适用于呼入和呼出 SIP 呼叫。

DTMF 按键事件

接收来电者按键时,侧边通道接收 transport.dtmf.received。发送 DTMF 音调时,在 WebSocket 上发送 transport.dtmf.send。成功发送后接收 transport.dtmf.sent。若提供 event_id,通知中将包含 client_event_id;失败时返回带 error.client_event_id 的错误事件。

转移或挂断

转移:发送 POST /v1/live/sessions/{session_id}/refer,附带 { "target_uri": "sip:agent@example.com" }。目标可以是电话 URI 或 SIP URI。提供商负责后续流程。

挂断:发送 POST /v1/live/sessions/{session_id}/hangup,无请求主体。两者成功时均返回 200 OK 且空主体。

在收到 session.closed 前保持侧边通道打开,以获取最终使用情况报告。

SIP 网络要求

GPT-Live SIP 呼叫的信令和媒体使用独立网络路径,需分别配置:

  • SIP 信令:允许向 sip.api.openai.com 和 sip-eu.api.openai.com(基于 GeoIP 路由)的出站 TCP/TLS 流量,端口 5061。
  • SRTP 媒体:允许与以下 CIDR 之间双向的 UDP SRTP 流量:
    • 13.79.45.80/28
    • 23.98.140.64/28
    • 40.67.149.176/28
    • 40.83.204.240/28

后续步骤

  • 提示指南:编写语音代理指令。
  • Webhooks 和服务端控制:从后端管理会话。
  • 委托和工具:连接推理和工具后端。
  • 管理会话:处理转录、状态和关闭。
  • 延迟和成本:了解性能指标。
  • 合作伙伴集成:查找特定提供商指南。