ThunderPhone 2.0 اب لائیو ہے۔سیلف سرو، قیمت 2¢ فی منٹ سے شروع۔اعلان پڑھیں

Developer cookbook

ہر کال کے لیے متحرک کنفیگریشن

اپنے کنٹرول والے webhook میں کسٹم منطق کی بنیاد پر، ہر آنے والی کال کے لیے جواب دینے والا ایجنٹ منتخب کریں — یا اس کا prompt اور ترتیبات الگ سے تبدیل کریں۔

بطور ڈیفالٹ ہر فون نمبر اور قابل اشاعت کلید کے ساتھ ایک جامد ایجنٹ منسلک ہوتا ہے۔ جب آپ کو ہر کالر کے لیے یا ہر وزیٹر کے لیے تخصیص درکار ہو — 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. ہینڈلر نافذ کریں

تین بنیادی اصول:

  • ہر درخواست پر دستخط کی توثیق کریں (دیکھیں ویب ہُک دستخط کی توثیق کریں)۔ ڈویلپمنٹ میں بھی اسے نظر انداز نہ کریں — اسے ایک بار درست کریں اور دوبارہ استعمال کریں۔
  • فوراً جواب دیں۔ دس سیکنڈ حتمی حد ہے، اور ہر سیکنڈ کال کرنے والے کے لیے خاموشی ہے۔ ضرورت ہو تو ڈیٹابیس لک اَپس کریں، مگر ڈاؤن اسٹریم LLMs کو ہم وقت انداز میں کال نہ کریں — اگر آپ کو متحرک prompt جنریشن چاہیے تو پہلے سے حساب کر کے کیش کریں۔
  • درست انداز میں فال بیک کریں۔ کسی بھی غیر متوقع حالت میں {} واپس کریں تاکہ مستقل طور پر مقرر کردہ ایجنٹ کال سنبھال لے۔
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. رسپانس اسکیما

رسپانس باڈی بالکل ان کمنگ کال رسپانس اسکیما سے مطابقت رکھتی ہے۔ عام طور پر استعمال ہونے والی فیلڈز:

فیلڈقسموضاحت
promptاسٹرنگ (لازمی)ایجنٹ کے لیے سسٹم prompt
voiceاسٹرنگ (لازمی)GET /v1/voices سے وائس آئی ڈی
productاسٹرنگڈیفالٹ spark ہے
background_trackاسٹرنگ | nullمحیطی آڈیو آئی ڈی
acknowledgement_prompt_modeاسٹرنگauto یا manual (صرف ack کے ساتھ Storm)
acknowledgement_promptاسٹرنگموڈ manual ہونے پر لازمی
toolsارےان لائن فنکشن-ٹول اسکیماز — فنکشن ٹولز دیکھیں

محفوظ شدہ ایجنٹ رکھیں اور ویری ایبلز فراہم کریں

اس تنظیم کے محفوظ شدہ ایجنٹ کو فی کال ڈیٹا کے ساتھ استعمال کرنے کے لیے {"agent_id": 12, "variables": {"name": "Ada"}} واپس کریں۔ اس کے prompt میں {{name}} یا {{name|Friend}} شامل ہو سکتا ہے۔ ویب ہک ویری ایبلز ریکویسٹ-سطح کے ویری ایبلز پر ضم ہو جاتے ہیں؛ null پلیس ہولڈر کا ڈیفالٹ استعمال کرتا ہے، یا اگر کوئی فراہم نہ کیا گیا ہو تو خالی متن استعمال ہوتا ہے۔ حتمی قدریں اور حل نہ ہونے والے نام کال کی تفصیلات اور تکمیلی ویب ہکس میں ظاہر ہوتے ہیں۔ محفوظ شدہ ایجنٹ رسپانس صرف agent_id اور variables قبول کرتے ہیں۔ اگر prompt موجود ہو تو رسپانس ان لائن کنفیگریشن استعمال کرتا ہے اور agent_id کو نظر انداز کر دیتا ہے (بشمول null یا غیر عددی میٹا ڈیٹا)؛ ان لائن prompt پھر بھی درست ہونا ضروری ہے۔ ان لائن کنفیگریشن رسپانس میں variables بھی شامل ہو سکتے ہیں۔ محفوظ شدہ ایجنٹ رسپانس فون اور وجٹ، دونوں کالز پر ایجنٹ کی ڈیپلائے شدہ A/B تقسیم استعمال کرتے ہیں، پھر ویری ایبلز رینڈر کرتے ہیں۔ حدود اور سیشن API سپورٹ کے لیے کال ویری ایبلز دیکھیں۔ بلاکنگ کنفیگریشن پرانے فون نمبر/تنظیم URL یا ویب ہک موڈ وجٹ کی سے آتی ہے؛ اینڈ پوائنٹ-سسٹم ان کمنگ ایونٹس صرف اطلاعات ہیں۔

پیٹرنز

لاگ اِن صارف کا سیاق

ویب ہک موڈ وجٹس میں، وزیٹر کا صفحہ پہلے ہی جانتا ہے کہ وہ کون ہیں۔ اپنے ویب ہک کو ایک کوئری اسٹرنگ پیرامیٹر کے ساتھ کال کریں جسے وجٹ SDK آگے بھیجتا ہے (?customer_id=123) اور صارف کو سرور سائیڈ پر تلاش کریں۔

A/B prompt رول آؤٹ

اسے خود تیار کرنے سے پہلے، نوٹ کریں کہ ThunderPhone میں مقامی ایکسپیریمنٹس فیچر (/dashboard/experiments اور ایجنٹ بلڈر کا A/B ٹیب) موجود ہے جو ویریئنٹس متعین کرتا ہے، ٹریفک تقسیم کرتا ہے، اور ہر ویریئنٹ کے نتائج کا موازنہ کرتا ہے — کسی ویب ہک کی ضرورت نہیں۔

اگر آپ کو پھر بھی ویب ہک سائیڈ کنٹرول درکار ہو: call_id کو ہیش کر کے بکٹ بنائیں؛ 0..49 کے لیے prompt A اور 50..99 کے لیے prompt B فراہم کریں۔ اپنے DB میں منتخب کردہ بکٹ ریکارڈ کریں اور بعد میں اسے مکمل شدہ کال کے گریڈ سے مربوط کریں۔

وقت پر مبنی روٹنگ

کاروباری اوقات → "براہ راست سپورٹ" ایجنٹ؛ کاروباری اوقات کے بعد → "پیغام لیں" ایجنٹ۔ اپنے ہینڈلر میں new Date().getUTCHours() پر سادہ سوئچ استعمال کریں۔


اگلے مراحل