ہر کال کے لیے متحرک کنفیگریشن
بطور ڈیفالٹ ہر فون نمبر اور قابلِ اشاعت کلید کے لیے ایک مستقل ایجنٹ تفویض ہوتا ہے۔ جب آپ کو ہر کالر کے لیے یا ہر وزیٹر کے لیے تخصیص درکار ہو — VIP روٹنگ، لاگ اِن صارف کا سیاق، A/B prompt ٹیسٹس — تو ویب ہک موڈ پر سوئچ کریں اور اپنے سرور کو فیصلہ کرنے دیں۔
یہ کیسے کام کرتا ہے
- آپ
telephony.incoming(فون) یاweb.incoming(ویجٹ) ایونٹ کو سبسکرائب کرتے ہیں۔ دونوں بلاکنگ ویب ہکس ہیں: ThunderPhone کال جاری رکھنے سے پہلے آپ کے جواب کے لیے 10 سیکنڈ تک انتظار کرتا ہے۔ - ThunderPhone آپ کو
{call_id, from_number, to_number}بھیجتا ہے (ویجٹ سیشنز میں نمبروں کے بجائے ویجٹ کے مخصوص فیلڈز ہوتے ہیں — درخواست اسکیما دیکھیں)۔ - آپ کا سرور ایجنٹ کنفیگریشن (prompt، آواز، پروڈکٹ، ٹولز) کے ساتھ جواب دیتا ہے۔ ThunderPhone کال کے لیے وہ کنفیگریشن استعمال کرتا ہے۔
- اگر آپ
{}واپس کرتے ہیں، وقت ختم ہو جاتا ہے، یا خرابی پیش آتی ہے، تو مستقل طور پر تفویض کردہ ایجنٹ فال بیک کے طور پر استعمال ہوتا ہے۔ محفوظ ڈیفالٹ۔
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 تیار کرنا چاہتے ہیں تو پہلے سے تیار کر کے کیش کریں۔
- بخوبی متبادل طریقہ اختیار کریں۔ کسی بھی غیر متوقع حالت میں
{}واپس کریں تاکہ جامد طور پر مقرر کردہ ایجنٹ کال سنبھالے۔
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. جواب کا اسکیما
جواب کا باڈی آنے والی کال کے جواب کے اسکیما سے بالکل مطابقت رکھتا ہے۔ عام طور پر استعمال ہونے والے فیلڈز:
| فیلڈ | قسم | وضاحت |
|---|---|---|
prompt | string (لازمی) | ایجنٹ کے لیے سسٹم prompt |
voice | string (لازمی) | GET /v1/voices سے آواز کا شناخت کار |
product | string | طے شدہ قدر spark ہے |
background_track | string | null | محیطی آڈیو کا شناخت کار |
acknowledgement_prompt_mode | string | auto یا manual (صرف acknowledgement والے Storm کے لیے) |
acknowledgement_prompt | string | موڈ manual ہونے پر لازمی |
tools | array | ان لائن فنکشن ٹول اسکیماز — فنکشن ٹولز دیکھیں |
پیٹرنز
لاگ اِن صارف کا سیاق
ویب ہُک موڈ ویجٹس میں، وزیٹر کا صفحہ پہلے ہی جانتا ہے کہ وہ کون
ہیں۔ اپنے ویب ہُک کو ایک query string پیرامیٹر کے ساتھ کال کریں جسے ویجٹ SDK
فارورڈ کرتا ہے (?customer_id=123) اور سرور سائیڈ پر کسٹمر کو تلاش کریں۔
A/B prompt رول آؤٹ
اسے خود بنانے سے پہلے، نوٹ کریں کہ ThunderPhone میں ایک مقامی
تجربات فیچر
(/dashboard/experiments اور ایجنٹ بلڈر کا A/B ٹیب) موجود ہے جو
ویریئنٹس متعین کرتا ہے، ٹریفک تقسیم کرتا ہے، اور ہر ویریئنٹ کے نتائج کا موازنہ کرتا ہے —
کسی ویب ہُک کی ضرورت نہیں۔
اگر پھر بھی آپ کو ویب ہُک سائیڈ کنٹرول درکار ہو: call_id کو hash کر کے → bucket میں رکھیں؛
0..49 کے لیے prompt A اور 50..99 کے لیے prompt B فراہم کریں۔ آپ نے کون سا
bucket منتخب کیا، اسے اپنے DB میں ریکارڈ کریں اور بعد میں مکمل شدہ کال کے grade کے ساتھ
مطابقت معلوم کریں۔
وقت پر مبنی روٹنگ
کاروباری اوقات → "لائیو سپورٹ" ایجنٹ؛ اوقات کے بعد → "پیغام لیں"
ایجنٹ۔ اپنے handler میں new Date().getUTCHours() پر خالص switch استعمال کریں۔
اگلے مراحل
ہر configuration key سمیت، درست request اور response schemas۔
HMAC کو ایک بار درست کریں؛ ہر جگہ دوبارہ استعمال کریں۔
متحرک روٹنگ کو ہر ایجنٹ کے ٹولز کے ساتھ یکجا کریں۔
دوبارہ کوششیں، ترتیب، ٹائم آؤٹس۔