ஒவ்வொரு அழைப்புக்கும் டைனமிக் உள்ளமைவு

இயல்பாக, ஒவ்வொரு தொலைபேசி எண்ணுக்கும் வெளியிடக்கூடிய விசைக்கும் ஒரு நிலையான ஏஜென்ட் ஒதுக்கப்பட்டிருக்கும். ஒவ்வொரு அழைப்பாளருக்கும் அல்லது ஒவ்வொரு பார்வையாளருக்கும் தனிப்பயனாக்கம் தேவைப்படும்போது — VIP வழிமாற்றம், உள்நுழைந்த பயனர் சூழல், A/B prompt சோதனைகள் — வெப்ஹுக் பயன்முறைக்கு மாறி, உங்கள் சர்வரை முடிவெடுக்க விடுங்கள்.

இது எப்படி செயல்படுகிறது

  1. நீங்கள் telephony.incoming (தொலைபேசி) அல்லது web.incoming (விட்ஜெட்) நிகழ்வுக்கு சந்தா செய்கிறீர்கள். இரண்டும் தடுக்கும் வெப்ஹுக்குகள்: அழைப்பைத் தொடர்வதற்கு முன் ThunderPhone உங்கள் பதிலுக்காக அதிகபட்சம் 10 வினாடிகள் காத்திருக்கும்.
  2. ThunderPhone உங்களுக்கு {call_id, from_number, to_number} அனுப்பும் (விட்ஜெட் அமர்வுகள் எண்களுக்குப் பதிலாக விட்ஜெட்டுக்கான புலங்களைக் கொண்டிருக்கும் — கோரிக்கை வடிவமைப்பைப் பார்க்கவும்).
  3. உங்கள் சர்வர் ஒரு ஏஜென்ட் உள்ளமைவுடன் (prompt, குரல், தயாரிப்பு, கருவிகள்) பதிலளிக்கும். ThunderPhone அந்த உள்ளமைவை அழைப்பிற்குப் பயன்படுத்தும்.
  4. நீங்கள் {}-ஐத் திருப்பியனுப்பினால், நேரம் முடிந்தால் அல்லது பிழை ஏற்பட்டால், நிலையாக ஒதுக்கப்பட்ட ஏஜென்ட் மாற்று வழியாகப் பயன்படுத்தப்படும். பாதுகாப்பான இயல்புநிலை.

1. வெப்ஹுக் இலக்கை உள்ளமைக்கவும்

தொலைபேசி அழைப்புகள்

தொலைபேசி எண்களுக்காக, உங்கள் எண்ட்பாயிண்ட்டை 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"]
  }'

பதில் ஒருமுறை மட்டுமே பயன்படும் secret-ஐக் கொண்டிருக்கும் — அதைச் சேமியுங்கள்; கையொப்பச் சரிபார்ப்புக்கு அதைப் பயன்படுத்துவீர்கள்.

வலை விட்ஜெட்

விட்ஜெட் அமர்வுகளுக்காக, உங்கள் எண்ட்பாயிண்ட் URL உட்பொதிக்கப்பட்ட mode="webhook"-இல் ஒரு வெளியிடக்கூடிய விசையை உருவாக்குங்கள்:

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"]
  }'

ஒவ்வொரு அமர்வு தொடக்கத்திலும் விட்ஜெட் இந்த URL-க்கு POST செய்யும்.

2. ஹேண்ட்லரை செயல்படுத்துங்கள்

மூன்று நடைமுறை விதிகள்:

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
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. பதில் ஸ்கீமா

பதில் உடல் வரும் அழைப்பு பதில் ஸ்கீமா-வுடன் துல்லியமாகப் பொருந்தும். பொதுவாகப் பயன்படுத்தப்படும் புலங்கள்:

புலம்வகைவிளக்கம்
promptstring (தேவை)ஏஜென்ட்டிற்கான சிஸ்டம் prompt
voicestring (தேவை)GET /v1/voices-இலிருந்து குரல் id
productstringஇயல்புநிலை spark
background_trackstring | nullசூழல் ஆடியோ id
acknowledgement_prompt_modestringauto அல்லது manual (ack-உடன் Storm மட்டும்)
acknowledgement_promptstringபயன்முறை manual ஆக இருக்கும்போது தேவை
toolsarrayஇன்லைன் செயல்பாட்டு-கருவி ஸ்கீமாக்கள் — செயல்பாட்டு கருவிகள் என்பதைப் பார்க்கவும்

வடிவங்கள்

உள்நுழைந்த பயனர் சூழல்

Webhook பயன்முறை விட்ஜெட்களில், வருகையாளரின் பக்கத்திற்கே அவர்கள் யார் என்பது ஏற்கனவே தெரியும். விட்ஜெட் SDK முன்னனுப்பும் query string அளவுருவுடன் (?customer_id=123) உங்கள் webhook-ஐ அழைத்து, சர்வர் பக்கத்தில் வாடிக்கையாளரைத் தேடுங்கள்.

A/B prompt வெளியீடு

இதை நீங்களே உருவாக்குவதற்கு முன், ThunderPhone-இல் வகைகளை வரையறுத்து, டிராஃபிக்கைப் பிரித்து, ஒவ்வொரு வகைக்குமான விளைவுகளை ஒப்பிடும் சொந்த சோதனைகள் அம்சம் (/dashboard/experiments மற்றும் ஏஜென்ட் பில்டரின் A/B தாவல்) உள்ளது என்பதை நினைவில் கொள்ளுங்கள் — webhook தேவையில்லை.

எப்படியும் webhook-பக்கக் கட்டுப்பாடு தேவைப்பட்டால்: call_id-ஐ hash செய்து → bucket-ஆகப் பிரியுங்கள்; 0..49 க்கு prompt A-ஐயும் 50..99 க்கு prompt B-ஐயும் வழங்குங்கள். நீங்கள் தேர்ந்தெடுத்த bucket-ஐ உங்கள் சொந்த DB-யில் பதிவு செய்து, பின்னர் முடிக்கப்பட்ட அழைப்பின் தரத்துடன் தொடர்புபடுத்துங்கள்.

நேர அடிப்படையிலான வழிமாற்றம்

வணிக நேரம் → "நேரடி ஆதரவு" ஏஜென்ட்; வணிக நேரத்திற்குப் பிறகு → "செய்தியைப் பெறும்" ஏஜென்ட். உங்கள் handler-இல் new Date().getUTCHours() அடிப்படையில் எளிய switch பயன்படுத்துங்கள்.


அடுத்த படிகள்