---
title: "将 ThunderPhone 与 OpenAI Realtime 客户端配合使用"
description: "使用已保存的智能体或内联会话配置，将兼容 OpenAI Realtime 的服务器客户端连接到 ThunderPhone。"
---

ThunderPhone 实现了 OpenAI Realtime 事件模型中经过聚焦的一个子集。
现有服务端客户端可以在使用 ThunderPhone 语音智能体时，保留其 WebSocket、音频、会话和响应事件流。

## 连接前准备

您需要 ThunderPhone 组织密钥 API 密钥，以及能够打开 WebSocket 的服务器运行环境。请勿从浏览器代码连接，也不要将密钥暴露给浏览器。若要使用已保存的智能体，请先部署该智能体并复制其数字智能体 ID。

连接至：

```text
wss://api.thunderphone.com/v1/realtime
```

从您的服务器对 WebSocket 升级进行身份验证：

```http
Authorization: Bearer sk_live_YOUR_API_KEY
```

对于无法设置握手标头的客户端，可以使用查询字符串身份验证，但 URL 更容易泄露到日志中。

## 选择配置由谁负责

| 模式 | 连接方式 | 配置来源 |
| --- | --- | --- |
| 已保存的智能体 | `?agent_id=12` | 已部署的提示词、语音、产品、语言、知识库，以及兼容的服务器端运行工具 |
| 内联 | 无 `agent_id` | 客户端首次被接受的 `session.update` |

### 已保存的智能体

使用已部署的智能体 ID 连接：

```text
wss://api.thunderphone.com/v1/realtime?agent_id=12
```

智能体会在套接字连接时启动。其问候语仍然可用，
但 Realtime 会禁用其语音静默确认，并省略 `transfer_call`
和 `send_keypad_input`。其他兼容工具将在 ThunderPhone 上运行。请勿为此模式发送内联指令或由客户端执行的工具。

在智能体启动前，通过 `input_audio_format`、
`output_audio_format`、`input_rate` 和 `output_rate` 查询参数设置传输音频。连接后，您无法更改已保存的配置或音频格式。

### 内联会话

不使用 `agent_id` 时，请等待 `session.created`，然后发送 `session.update`：

```json
{
  "type": "session.update",
  "session": {
    "type": "realtime",
    "instructions": "Answer questions clearly and keep responses brief.",
    "audio": {
      "input": {
        "format": { "type": "audio/pcm", "rate": 24000 }
      },
      "output": {
        "format": { "type": "audio/pcm", "rate": 24000 },
        "voice": "olivia"
      }
    },
    "config": {
      "product": "bolt"
    }
  }
}
```

首次被接受的更新会创建通话。`session.updated` 表示
会话已激活。此后，指令、语音、产品、工具和音频格式均无法更改。

内联会话没有自动问候语或语音静默确认。若要让智能体先说话，请追加一条系统或用户消息，并发送
`response.create`。完全空闲的会话仍会在平台的静默通话限制时结束，默认限制为 600 秒。

## 使用官方 OpenAI SDK

传入以 `/v1` 结尾的 WebSocket 基础 URL；SDK 会追加 `/realtime`。`model` 值是兼容性名称，不会选择 ThunderPhone 产品。请在会话配置或已保存的智能体中选择产品。

此连接检查会创建一个内联 Bolt 会话，持续打印事件直到第一个 `session.updated`，然后关闭。使用[最简 Python 客户端](/api-reference/realtime#minimal-python-client)流式传输音频。

```python
import asyncio
import os

from openai import AsyncOpenAI


async def main():
    client = AsyncOpenAI(
        api_key=os.environ["THUNDERPHONE_API_KEY"],
        websocket_base_url="wss://api.thunderphone.com/v1",
    )

    async with client.realtime.connect(
        model="thunderphone-realtime"
    ) as connection:
        await connection.session.update(session={
            "type": "realtime",
            "instructions": "Listen to the caller and help them complete the call.",
            "config": {"product": "bolt"},
        })
        async for event in connection:
            print(event.type)
            if event.type == "session.updated":
                break


if __name__ == "__main__":
    asyncio.run(main())
```

保留您现有的输入音频追加、响应音频增量、中断、函数调用、错误处理以及套接字正常关闭逻辑。内联自定义函数在您的客户端中执行；请通过 Realtime 协议返回其结果。已保存智能体的工具在 ThunderPhone 上执行。

## 会话生命周期和失败情况

一个 WebSocket 对应一个通话。无效的智能体 ID 或被拒绝的内联配置会产生 `error` 事件。请在收到 `session.updated` 后再将会话视为已启动。声明实际的输入和输出格式以及采样率：PCM 采样率不匹配会导致音频播放过快或过慢，而不会产生验证错误。

会话启动后，请在您的应用完成时正常关闭套接字。内联会话可以使用由客户端执行的函数。已保存智能体会话使用由 ThunderPhone 运行的兼容工具，且不提供转接或按键输入功能。

## 测试集成

请从[最简 Python WAV 客户端](/api-reference/realtime#minimal-python-client)开始，并使用与其声明采样率相同的单声道 PCM16 WAV。验证：

1. 服务器接受配置并发送 `session.updated`。
2. 输入以预期速度生成转录和响应音频事件。
3. 中断和响应取消会停止剩余的输出音频。
4. 内联函数结果或已保存智能体工具结果会返回给模型。
5. 无效输入会产生由您的客户端处理的 `error` 事件。
6. 您的客户端关闭套接字，且该通话显示在[通话记录](/zh/guides/review-calls)中。

[Realtime WebSocket 参考](/api-reference/realtime)列出了可接受的事件、音频格式、会话字段和完整示例。

## 费用

Realtime 通话采用所选产品的常规每分钟费率。启用实时转录增量会为整个会话增加每分钟附加费用；有关费率，请参阅[实时转录](/api-reference/realtime#live-transcripts)，有关产品费率，请参阅[定价](/zh/guides/pricing)。

`POST /v1/realtime/sessions` 是独立的托管 LiveKit 路径。它会创建房间和作用域参与者令牌；直接 WebSocket 连接不需要它。

如需框架集成，请参阅[从 Pipecat 使用 ThunderPhone](/zh/guides/use-with-pipecat)和[从 LiveKit Agents 使用 ThunderPhone](/zh/guides/use-with-livekit)。
