Dinamiska konfigurācija katram zvanam
Katram ienākošajam zvanam atsevišķi izvēlieties atbildes balss aģentu vai pārrakstiet tā uzvedni un iestatījumus, izmantojot pielāgotu loģiku jūsu pārvaldītā tīmekļa aizķerē.
Pēc noklusējuma katram tālruņa numuram un publicējamajai atslēgai ir piešķirts statisks aģents. Ja nepieciešama pielāgošana katram zvanītājam vai katram apmeklētājam — VIP maršrutēšana, pieteikušos lietotāju konteksts, A/B uzvedņu testi — pārslēdzieties uz tīmekļa aizķeres režīmu un ļaujiet serverim pieņemt lēmumu.
Kā tas darbojas
- Abonējiet notikumu
telephony.incoming(tālrunim) vaiweb.incoming(logrīkam). Abas ir bloķējošas tīmekļa aizķeres: ThunderPhone pirms zvana turpināšanas gaida jūsu atbildi līdz 10 sekundēm. - ThunderPhone nosūta jums
{call_id, from_number, to_number}(logrīka sesijās numuru vietā tiek nosūtīti logrīkam specifiski lauki — skatiet pieprasījuma shēmu). - Jūsu serveris atbild ar aģenta konfigurāciju (uzvedne, balss, produkts, rīki). ThunderPhone izmanto šo konfigurāciju zvanam.
- Ja atgriežat
{}, tiek pārsniegts laiks vai rodas kļūda, kā rezerves variants tiek izmantots statiski piešķirtais aģents. Droša noklusējuma izvēle.
1. Konfigurējiet tīmekļa aizķeres galamērķi
Tālruņa numuriem abonējiet savu galapunktu notikumam telephony.incoming:
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"label": "Prod call-incoming",
"url": "https://example.com/thunderphone/incoming",
"events": ["telephony.incoming"]
}'Atbildē ir vienreizējs secret — saglabājiet to; izmantosiet to
paraksta pārbaudei.
Logrīka sesijām izveidojiet publicējamu atslēgu ar mode="webhook",
kurā ir iekļauts jūsu galapunkta URL:
curl -X POST https://api.thunderphone.com/v1/publishable-key \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Dynamic widget",
"mode": "webhook",
"webhook_url": "https://example.com/thunderphone/widget-incoming",
"allowed_domains": ["example.com"]
}'Logrīks katras sesijas sākumā nosūtīs POST pieprasījumu uz šo URL.
2. Ieviesiet apstrādātāju
Trīs pamatprincipi:
- Pārbaudiet parakstu katram pieprasījumam (skatiet Tīmekļa aizķeres parakstu pārbaude). Neizlaidiet to izstrādes vidē — ieviesiet to pareizi vienreiz un izmantojiet atkārtoti.
- Atbildiet ātri. Desmit sekundes ir stingrais limits, un katra sekunde ir klusums zvanītājam. Vajadzības gadījumā veiciet datubāzes uzmeklēšanu, bet nesauciet pakārtotos LLM sinhroni — ja vēlaties dinamisku uzvednes ģenerēšanu, iepriekš aprēķiniet un saglabājiet kešatmiņā.
- Korekti izmantojiet rezerves variantu. Jebkuram neparedzētam stāvoklim jāatgriež
{}, lai statiski piešķirtais aģents apstrādātu zvanu.
import hashlib
import hmac
import json
import os
from fastapi import FastAPI, HTTPException, Request
app = FastAPI()
SECRET = os.environ["THUNDERPHONE_WEBHOOK_SECRET"]
def verify(body: bytes, sig: str) -> bool:
expected = hmac.new(SECRET.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig or "")
@app.post("/thunderphone/incoming")
async def incoming(request: Request):
body = await request.body()
if not verify(body, request.headers.get("X-ThunderPhone-Signature", "")):
raise HTTPException(401)
event = json.loads(body)
if event["type"] not in ("telephony.incoming", "web.incoming"):
return {} # fall back to default
caller = event["data"]["from_number"]
# Cheap DB lookup: is this a known VIP?
customer = lookup_customer(caller)
if customer and customer.tier == "vip":
return {
"prompt": f"You are a VIP concierge for {customer.name}. Be proactive…",
"voice": "john",
"product": "storm-base",
}
return {} # default agent handles non-VIPs
def lookup_customer(phone: str):
# ... your CRM integration ...
passimport crypto from "node:crypto";
import express from "express";
const app = express();
const SECRET = process.env.THUNDERPHONE_WEBHOOK_SECRET;
function verify(body, sig) {
const expected = crypto.createHmac("sha256", SECRET).update(body).digest("hex");
return sig &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
}
app.post(
"/thunderphone/incoming",
express.raw({ type: "application/json" }),
async (req, res) => {
if (!verify(req.body, req.header("X-ThunderPhone-Signature"))) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString("utf8"));
const IMPORTANT_TYPES = new Set([
"telephony.incoming",
"web.incoming",
]);
if (!IMPORTANT_TYPES.has(event.type)) return res.json({});
const customer = await lookupCustomer(event.data.from_number);
if (customer?.tier === "vip") {
return res.json({
prompt: `You are a VIP concierge for ${customer.name}. Be proactive…`,
voice: "john",
product: "storm-base",
});
}
res.json({}); // fall back to default agent
},
);3. Atbildes shēma
Atbildes pamatteksts precīzi atbilst ienākošā zvana atbildes shēmai. Biežāk izmantotie lauki:
| Lauks | Tips | Apraksts |
|---|---|---|
prompt | virkne (obligāts) | Aģenta sistēmas uzvedne |
voice | virkne (obligāts) | Balss ID no GET /v1/voices |
product | virkne | Noklusējuma vērtība ir spark |
background_track | virkne | null | Fona audio ID |
acknowledgement_prompt_mode | virkne | auto vai manual (tikai Storm ar apstiprinājumu) |
acknowledgement_prompt | virkne | Nepieciešams, ja režīms ir manual |
tools | masīvs | Iekļautās funkciju rīku shēmas — skatiet Funkciju rīki |
Modeļi
Pieteikušā lietotāja konteksts
Tīmekļa aizķeres režīma logrīkos apmeklētāja lapa jau zina, kas viņš
ir. Izsauciet savu tīmekļa aizķeri ar vaicājuma virknes parametru, ko
logrīka SDK pārsūta (?customer_id=123), un servera pusē atrodiet klientu.
A/B uzvedņu ieviešana
Pirms veidojat to manuāli, ņemiet vērā, ka ThunderPhone piedāvā iebūvētu
Eksperimentu funkciju
(/dashboard/experiments un balss aģenta veidotāja cilni A/B), kas
definē variantus, sadala datplūsmu un salīdzina katra varianta rezultātus —
tīmekļa aizķere nav nepieciešama.
Ja jums tomēr nepieciešama vadība tīmekļa aizķeres pusē: jauciet call_id → segments;
rādiet uzvedni A vērtībām 0..49 un uzvedni B vērtībām 50..99. Saglabājiet savā
datubāzē izvēlēto segmentu un vēlāk sasaistiet to ar pabeigtā zvana
novērtējumu.
Maršrutēšana pēc laika
Darba laikā → balss aģents “tiešsaistes atbalsts”; ārpus darba laika → balss aģents “ziņas pieņemšana”.
Apstrādātājā izmantojiet vienkāršu pārslēgšanu pēc new Date().getUTCHours().
Nākamās darbības
Precīzas pieprasījuma un atbildes shēmas, tostarp katra konfigurācijas atslēga.
Pareizi iestatiet HMAC vienreiz; izmantojiet to atkārtoti visur.
Apvienojiet dinamisko maršrutēšanu ar katra balss aģenta rīkiem.
Atkārtoti mēģinājumi, secība, noildzes.