用 Node.js 與 Wixzel Voice 打造 Twilio AI 接待員
完成後,打到您現有 Twilio 號碼的電話會由您打造的 AI 接待員接聽:它會問候來電者、依照您的提示詞回答問題,並安排預約,您可以透過 API 讀回這些預約。以 Node.js 搭配 TypeScript 與 JavaScript 用的 wixzel-voice SDK 和 Twilio Elastic SIP 中繼,約需 30 分鐘。classic 引擎的引擎時間為每接通一分鐘 $0.0867,三分鐘的通話約 $0.26,從預付餘額按秒計費。Twilio 會直接向您收取中繼分鐘費用,不加價。
作者:Aqeel Shamsudheen · 發布於 · 更新於
- 所需時間
- 約 30 分鐘
- 引擎
- classic
- 引擎時間
- 每接通分鐘 $0.0867
開始之前需要準備什麼?
- 一個開通 Elastic SIP Trunking 的 Twilio 帳號,以及一個 Twilio 電話號碼。
- 一把 Wixzel Voice API 金鑰(
wv_live_…),帳號中要有點數。最低儲值金額為 $5。 - Node.js 20 或更新版本。
如何在 Wixzel Voice 上逐步打造?
01在 Twilio 建立 Elastic SIP 中繼
在 Twilio 主控台開啟「Elastic SIP Trunking」並建立中繼。在「Termination」下選擇一個 Termination SIP URI,例如
your-clinic.pstn.twilio.com。這個主機名稱就是下一步要連接的中繼的host。請保持 Twilio 主控台開啟。等 API 給您要輸入的兩個位址後,您會再回到這裡。
02安裝 SDK 並連接中繼
安裝 SDK,並將 API 金鑰放入環境變數:
shellnpm install wixzel-voice export WIXZEL_API_KEY="wv_live_..."trunk.mjsimport { WixzelVoice } from 'wixzel-voice'; const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); const trunk = await client.sipTrunks.create({ name: 'Twilio', host: 'your-clinic.pstn.twilio.com', // your Termination SIP URI port: 5060, transport: 'udp', }); console.log('TRUNK_ID', trunk.id); console.log('Allowlist at Twilio:', trunk.platform_ip); console.log('Origination URI:', trunk.origination_uri);這裡沒有使用者名稱或密碼,因為 Twilio 以來源 IP 授權,這是下一步的內容。若要改用 Twilio 的 Credential List,請傳入其
username和password。密碼會加密儲存,API 之後絕不會再回傳。03讓 Twilio 指向 Wixzel Voice,雙向都要設定
Twilio 的外撥和來電是分開設定的,少了任何一項都會在沒有任何提示的情況下失敗。
在「Termination」的「Authentication」下,將上面印出的
platform_ip加入 IP Access Control List。少了這項,Twilio 會在約一秒內以掛斷原因 21 拒絕通話。在「Origination」下新增一個 Origination SIP URI,設為上面印出的
origination_uri。少了這項,打到您號碼的電話永遠不會到達代理,兩邊的日誌也都不會有任何紀錄,因為通話從未離開 Twilio。最後,在「Numbers」下將您的 Twilio 號碼掛到這個中繼。
04建立接待員
代理由提示詞、開場白和語音引擎組成。
appointment_booking_enabled讓它能在通話中列出、安排和取消預約;提示詞則告訴它可以提供哪些日子、時段和預約長度。agent.mjsimport { WixzelVoice } from 'wixzel-voice'; const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); const agent = await client.agents.create({ name: 'Reception', system_prompt: [ 'You are the receptionist for Riverside Dental, answering the phone.', 'Keep every reply to one or two short sentences, and never read out lists.', 'You can book, move and cancel check-ups and cleanings.', 'Offer appointments Monday to Friday, 09:00 to 17:00, 30 minutes each.', 'Before booking, ask for the full name of the caller and repeat the day and time back.', 'For a dental emergency, tell the caller to hang up and ring the emergency number.', 'If you cannot help, take a message and promise a callback.', ].join('\n'), opening_message: 'Riverside Dental, this is the automated assistant. How can I help?', appointment_booking_enabled: true, voice: { stt: { model: 'deepgram/nova-3', language: 'en-US' }, llm: { model: 'openrouter/gpt-4o-mini' }, tts: { model: 'elevenlabs/eleven_flash_v2_5' }, }, }); console.log('AGENT_ID', agent.id);這是 classic 引擎:Deepgram Nova-3、GPT-4o-mini 和 ElevenLabs Flash v2.5,是英文最便宜且可靠的組合,每分鐘 $0.0867。在
tts區塊加入voice即可選擇說話者;client.engines.voices('classic')會列出可用的語音。開場白告訴來電者正在與自動語音助理通話。若法律要求告知這一點,或要求告知通話會被錄音,就應放在開場白中。
05將您的號碼導向接待員
在中繼上登記號碼,並指定由該代理接聽:
number.mjsimport { WixzelVoice } from 'wixzel-voice'; const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); const number = await client.phoneNumbers.create({ phone_number: '+14155550100', // your Twilio number, in E.164 sip_trunk_id: process.env.TRUNK_ID, inbound_agent_id: process.env.AGENT_ID, }); console.log('NUMBER_ID', number.id);沒有
inbound_agent_id的號碼會拒絕所有來電。若要讓同一個代理也能撥出電話(例如提醒通話或測試通話),請用client.agents.update(agentId, { outbound_phone_number_id: number.id })將該號碼設為它的來電顯示號碼。06撥打看看,再讀取通話與預約
用手機撥打您的 Twilio 號碼並預約一個時段。掛斷後,通話和預約都會出現在 API 中:
results.mjsimport { WixzelVoice } from 'wixzel-voice'; const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); // Lists are newest first. const calls = await client.calls.list({ direction: 'inbound', limit: 1 }); const latest = calls.data[0]; if (latest) { const call = await client.calls.retrieve(latest.id); console.log(call.status, call.duration_seconds + 's', (call.cost_micros ?? 0) / 1e6, 'USD'); for (const line of call.transcript) console.log(line.role + ': ' + line.content); } const appointments = await client.appointments.list({ limit: 5 }); for (const a of appointments.data) { console.log(a.date_time, a.client_name, a.phone_number, a.status); }date_time一律為 UTC。每筆預約也會觸發appointmentBookedwebhook,您可以藉此即時將預約複製到自己的行事曆。
在 Wixzel Voice 上打造這個要花多少錢?
在 classic 引擎上進行 3 分鐘通話的引擎時間,以每接通分鐘 $0.0867 計算:每通約 $0.26。 電信使用您自己的中繼,按您電信業者的費率計算,不包含在內。
| 每月通話數 | 接通分鐘數 | 每月引擎費用 |
|---|---|---|
| 200 | 600 | $52.02 |
| 1,000 | 3,000 | $260 |
| 3,000 | 9,000 | $780 |
Wixzel Voice 只對引擎時間收費,依通話秒數從預付餘額扣款。Twilio 會依您的 Twilio 費率,將 Elastic SIP Trunking 分鐘費用計入您的 Twilio 帳號;Wixzel Voice 不會經手這筆費用,也不會加價。
預付制,沒有訂閱,也沒有免費方案:從 $5 起儲值點數,使用時從中扣除。估算您自己的使用組合。
這個實作適用哪些 Wixzel Voice 限制?
- 接待員從提示詞得知您的營業時間。v1 API 沒有可用時段端點,因此它看不到您真正的行事曆:已透過 API 預約的時段會被拒絕,但您在其他地方管理的預約它看不到。
- 預約以帳號時區讀取,除非更改過,否則為 UTC,而 v1 API 目前還無法更改時區。請先檢查最初幾筆預約的
date_time再依賴它們;如果您的商家不在 UTC 時區,請寫信至 aqeel@wixzel.com。 - 每個帳號預設最多可同時進行五通通話。超過時,新的通話會被拒絕,直到有通話結束;可申請提高上限。
- 您的號碼仍留在 Twilio。Wixzel Voice 不販售、不攜碼也不持有號碼。
- Wixzel Voice 的行為變更一律透過附日期的
Wixzel-Version標頭推出。
常見問題
可以在 Twilio 上打造 AI 接待員嗎?
inbound_agent_id 登記您的 Twilio 號碼。之後打到該號碼的電話就會由您的代理接聽,Twilio 也會繼續直接向您收取中繼費用。我必須把號碼從 Twilio 移走嗎?
為什麼打到我 Twilio 號碼的電話無法到達代理?
origination_uri 相符,號碼也需要設定 inbound_agent_id。一通 AI 接待員通話要多少錢?
除了 JavaScript,還有其他語言的 SDK 嗎?
wixzel-voice,以及 pub.dev 上適用 Dart 和 Flutter 的 wixzel_voice。其他語言可直接呼叫同一個 HTTP API,其說明見 https://docs.voice.wixzel.com/api-reference 的 OpenAPI 文件。延伸閱讀
關於 Wixzel Voice
Wixzel Voice 是一個語音 AI API,用於打造 AI 代理,透過您自己的 SIP 中繼撥打和接聽真實的電話,或在您的網頁和行動應用程式中與人對話。一把 API 金鑰和一份預付餘額即可使用所有語音引擎,依實際用量按秒計費。
更多指南
Claude 在 Claude Code 或 claude.ai 中透過您的 SIP 中繼撥打真實電話並讀回逐字稿,撥號前一律先徵求確認。
兩個電話代理,一個說印地語、一個說馬拉雅拉姆語,使用 Sarvam 的印度語言模型,透過您的 SIP 中繼接聽或撥出電話。
一個讓使用者透過 WebSocket 與您的語音代理對話的 Flutter 應用程式,API 金鑰保存在您的伺服器上,完全不需要電話號碼。
透過四個 cURL 請求,讓 Gemini Live 代理經由您的 SIP 中繼撥打真實電話,並取得包含逐字稿與費用的通話紀錄。
由您的代理透過您的 SIP 中繼撥打一份潛在客戶名單,依同時通話上限分批進行,並讀回每通電話的狀態和逐字稿。
網站角落有一個會說話的吉祥物,訪客可從瀏覽器撥打給它,僅限您的網域並受每日上限約束,每位來電者都會列出。
一個有代理吉祥物的 Flutter 畫面,吉祥物在即時通話中隨代理的語音動嘴,API 金鑰保存在您的伺服器上。

