ThunderPhone 2.0 ir klāt.Sāciet uzreiz — no 2 centiem minūtē.Lasīt paziņojumu

Developer cookbook

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

  1. Abonējiet notikumu telephony.incoming (tālrunim) vai web.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.
  2. 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).
  3. Jūsu serveris atbild ar aģenta konfigurāciju (uzvedne, balss, produkts, rīki). ThunderPhone izmanto šo konfigurāciju zvanam.
  4. 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.
FastAPI
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 ...
    pass
Express
import 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:

LauksTipsApraksts
promptvirkne (obligāts)Aģenta sistēmas uzvedne
voicevirkne (obligāts)Balss ID no GET /v1/voices
productvirkneNoklusējuma vērtība ir spark
background_trackvirkne | nullFona audio ID
acknowledgement_prompt_modevirkneauto vai manual (tikai Storm ar apstiprinājumu)
acknowledgement_promptvirkneNepieciešams, ja režīms ir manual
toolsmasīvsIekļ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