telephony.incoming / web.incoming
Kai įeinantis telefono skambutis pasiekia numerį be priskirto
agento arba žiniatinklio valdiklio sesija pradedama naudojant viešinį raktą
su mode="webhook", ThunderPhone siunčia blokuojančią
telephony.incoming / web.incoming užklausą į jūsų
senąjį žiniatinklio kablio URL
ir laukia iki 10 sekundžių konfigūracijos atsakymo. Naudokite šį
apsikeitimą, kad kiekvienam skambučiui dinamiškai parinktumėte raginimą, balsą
ir įrankius — visą procesą rasite
dinaminio skambučio konfigūravimo vadove.
Blokuojantis apsikeitimas neturi atsarginio varianto: jei jūsų apdorotojas grąžina
ne 2xx būseną, baigiasi jo laikas arba jis grąžina konfigūraciją, kuri
nepraeina tikrinimo, skambutis atmetamas (telefono skambutis neprisijungia;
valdiklio sesijos užklausa nepavyksta su 502/422). Atsakykite greitai —
kol sprendžiate, skambintojas girdi skambučio signalą.
Užklausos duomenys
Telefono skambučiams (telephony.incoming):
{
"type": "telephony.incoming",
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}
| Laukas | Tipas | Aprašymas |
|---|---|---|
call_id | integer | Skambučio ID — nekinta visuose šio skambučio įvykiuose |
from_number | string | E.164 skambintojo numeris |
to_number | string | E.164 paskirties numeris (vienas iš jūsų ThunderPhone numerių) |
Žiniatinklio valdiklio sesijoms (web.incoming) data identifikuoja
įterpimo puslapį, o ne telefono numerius:
{
"type": "web.incoming",
"data": {
"call_id": 987654322,
"origin_domain": "https://example.com",
"publishable_key_prefix": "pk_live_a1b2"
}
}
| Laukas | Tipas | Aprašymas |
|---|---|---|
call_id | integer | Skambučio ID |
origin_domain | string | Puslapio, kuriame talpinamas valdiklis, kilmė |
publishable_key_prefix | string | Pirmieji viešinio rakto, kuriuo pradėta sesija, simboliai |
language, primary_language | string | Pateikiama, kai valdiklio sesijoje prašoma pakeisti kalbą |
voice | string | Pateikiama, kai valdiklio sesijoje prašoma pakeisti balsą |
website_context | string | Pateikiama, kai valdiklis perduoda kiekvienos sesijos puslapio kontekstą |
Atsako schema
Grąžinkite JSON objektą, aprašantį šio skambučio agento konfigūraciją.
prompt ir voice yra privalomi; visa kita neprivaloma.
{
"prompt": "You are a helpful booking assistant for Acme Restaurant.",
"voice": "john",
"product": "spark",
"background_track": null,
"tools": []
}
| Laukas | Tipas | Privalomas | Aprašymas |
|---|---|---|---|
prompt | string | taip | Sisteminė užklausa, valdanti agentą |
voice | string | taip | Balso ID iš GET /v1/voices, pvz., john. voice_name priimamas kaip sinonimas. Nežinomi balsai neatitinka validavimo ir skambutis atmetamas |
product | string | ne | Numatytoji reikšmė yra spark. Leidžiama: spark, bolt, storm-base, storm-base-with-ack, storm-extra, storm-extra-with-ack |
thinking_level | string | ne | minimal, base (numatytoji reikšmė) arba extra. Storm produktams perrašoma: storm-extra* priverstinai naudoja extra, kiti storm-* priverstinai naudoja base |
audio_context_mode | string | ne | full (numatytoji reikšmė) arba reduced |
watchdog_enabled | boolean | ne | Įjungti šio skambučio priežiūrą. Numatytoji reikšmė false |
storm_feedback_mode | string | ne | none, acknowledgement (numatytoji reikšmė) arba tick |
language | string | ne | Trumpinys, skirtas primary_language |
primary_language | string | ne | Kalbos kodas, normalizuotas (numatytoji reikšmė en). Neišsprendžiami kodai lemia skambučio atmetimą |
has_additional_languages | boolean | ne | Numatytoji reikšmė false |
additional_languages | array of string | ne | Papildomos kalbos, į kurias agentas gali persijungti |
background_track | string | null | ne | Aplinkos garso ID arba null |
acknowledgement_prompt_mode | string | ne | auto (numatytoji reikšmė) arba manual (Storm su patvirtinimu produktams) |
acknowledgement_prompt | string | ne | Naudojama, kai acknowledgement_prompt_mode="manual" |
silence_interval_seconds | integer | null | ne | 5–120. Skambinančiojo tylos sekundės prieš patikrinimą |
silence_max_checkins | integer | null | ne | 1–10 |
silence_checkins_enabled | boolean | ne | Numatytoji reikšmė true |
connect_tone_enabled | boolean | ne | Numatytoji reikšmė false |
voicemail_action | string | ne | prompt (numatytoji reikšmė), hangup arba message |
voicemail_message | string | ne | Naudojama, kai voicemail_action="message" |
agent_name | string | ne | Rodomas pavadinimas, pateikiamas valdymo skydeliuose ir valdiklyje |
org_name | string | ne | Organizacijos rodomas pavadinimas agento personai |
tools | array | ne | Įterptinės funkcijų įrankių schemos (žr. Funkcijų įrankiai) |
call_id | integer | ne | Pasirenkamas užklausos skambučio ID atkartojimas; ignoruojamas |
Kadangi prompt ir voice yra privalomi, grąžinus {} arba bet kokį
validavimo neatitinkantį atsaką, skambutis atmetamas su 422 — šiame
kelyje nėra statinio agento atsarginio varianto (numeriui arba raktui
žiniatinklio kablio režimu nėra priskirtas agentas).
Atsako dydžio riba
Pavyzdinė apdorojimo funkcija
import hashlib
import hmac
import json
import os
from fastapi import FastAPI, HTTPException, Request
app = FastAPI()
WEBHOOK_SECRET = os.environ["THUNDERPHONE_WEBHOOK_SECRET"]
def verify(body: bytes, signature: str) -> bool:
expected = hmac.new(WEBHOOK_SECRET.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature or "")
@app.post("/thunderphone-webhook")
async def webhook(request: Request):
body = await request.body()
if not verify(body, request.headers.get("X-ThunderPhone-Signature", "")):
raise HTTPException(status_code=401)
event = json.loads(body)
if event["type"] == "telephony.incoming":
caller = event["data"]["from_number"]
prompt = (
"Greet the caller as a San Francisco local…"
if caller.startswith("+1415")
else "You are a friendly customer support agent…"
)
return {
"prompt": prompt,
"voice": "john",
"product": "spark",
}
if event["type"] == "web.incoming":
return {
"prompt": "You are the website's helpful voice assistant…",
"voice": "john",
"product": "spark",
}
return {}
import crypto from "node:crypto";
import express from "express";
const app = express();
const SECRET = process.env.THUNDERPHONE_WEBHOOK_SECRET;
function verify(body, signature) {
const expected = crypto
.createHmac("sha256", SECRET)
.update(body)
.digest("hex");
return signature &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
app.post(
"/thunderphone-webhook",
express.raw({ type: "application/json" }),
(req, res) => {
if (!verify(req.body, req.header("X-ThunderPhone-Signature"))) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString("utf8"));
if (event.type === "telephony.incoming" || event.type === "web.incoming") {
const caller = event.data.from_number || "web";
const prompt = caller.startsWith("+1415")
? "Greet the caller as a San Francisco local…"
: "You are a friendly customer support agent…";
return res.json({
prompt,
voice: "john",
product: "spark",
});
}
res.json({});
},
);
Atsakymas su funkcijų įrankiais
Pridėkite įrankius, kad DI galėtų iškviesti jūsų API pokalbio metu:
{
"prompt": "You are a booking assistant. Use the available tools to help customers schedule appointments.",
"voice": "john",
"product": "spark",
"tools": [
{
"type": "function",
"function": {
"name": "search_appointments",
"description": "Find available appointment slots",
"parameters": {
"type": "object",
"properties": {
"date": { "type": "string", "description": "YYYY-MM-DD" },
"service": { "type": "string" }
},
"required": ["date"]
}
},
"endpoint": {
"url": "https://api.example.com/appointments/search",
"method": "POST",
"headers": {
"X-Api-Key": "your-key"
}
}
}
]
}
Produktų lygių atmintinė
| Produktas | Vėlinimas | Samprotavimas | Patvirtinimas |
|---|---|---|---|
spark | Mažiausias | Bazinis | — |
bolt | Mažas | Patobulintas | — |
storm-base | Vidutinis | Stiprus | — |
storm-base-with-ack | Vidutinis | Stiprus | Automatinis užpildymas mąstant |
storm-extra | Didesnis | Gilus | — |
storm-extra-with-ack | Didesnis | Gilus | Automatinis užpildymas mąstant |
Susiję
Neblokuojantis skambučio pabaigos įvykis.
Visa tools[] JSON schema ir pasirašytos galinio taško sutartis.
Užsiprenumeruokite kelių URL adresų telephony.incoming / web.incoming įvykius.
Šablonai, skirti pagal skambinantįjį pritaikomoms užklausoms, įrankiams ir A/B testams.