---
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
```

智能體會在 Socket 連接期間啟動。其問候語仍然可用，
但 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())
```

保留你現有的輸入音訊附加、回應音訊增量、中斷、函數呼叫、錯誤及正常關閉 socket 的處理方式。內嵌自訂函數會在你的用戶端執行；請透過 Realtime 協定傳回結果。已儲存智能體的工具會在 ThunderPhone 上執行。

## 工作階段生命週期及故障

每個 WebSocket 代表一通電話。無效的智能體 ID 或遭拒絕的內嵌設定會產生 `error` 事件。在收到 `session.updated` 前，不應將工作階段視為已啟用。請宣告實際的輸入及輸出格式與取樣率：PCM 取樣率不符會令音訊播放過快或過慢，而不會產生驗證錯誤。

工作階段開始後，當你的應用程式完成工作時，請正常關閉 socket。內嵌工作階段可使用由用戶端執行的函數。已儲存智能體工作階段使用相容的 ThunderPhone 執行工具，且不提供轉接或按鍵輸入。

## 測試整合

先使用[最精簡 Python WAV 用戶端](/api-reference/realtime#minimal-python-client)
及符合其已宣告取樣率的單聲道 PCM16 WAV。請確認：

1. 伺服器接受設定並傳送 `session.updated`。
2. 輸入會以預期速度產生逐字稿及回應音訊事件。
3. 中斷及取消回應會停止餘下的輸出音訊。
4. 內嵌函數結果或已儲存智能體工具結果會傳回至模型。
5. 無效輸入會產生由你的用戶端處理的 `error` 事件。
6. 你的用戶端會關閉 socket，且通話會顯示於[通話記錄](/yue/guides/review-calls)。

[Realtime WebSocket 參考文件](/api-reference/realtime)列出可接受的
事件、音訊格式、工作階段欄位及完整範例。

## 費用

Realtime 通話採用所選產品的標準每分鐘收費。啟用即時逐字稿增量會為整個工作階段增加每分鐘附加費；有關收費請參閱[即時逐字稿](/api-reference/realtime#live-transcripts)，產品收費請參閱[價格](/yue/guides/pricing)。

`POST /v1/realtime/sessions` 是獨立管理的 LiveKit 路徑。它會建立房間及具範圍限制的參與者權杖；直接 WebSocket 連線不需要使用它。

如需框架整合，請參閱[從 Pipecat 使用 ThunderPhone](/yue/guides/use-with-pipecat)
及[從 LiveKit Agents 使用 ThunderPhone](/yue/guides/use-with-livekit)。
