Open in
ہر کال کے لیے متحرک کنفیگریشن
اپنے کنٹرول والے webhook میں کسٹم منطق کی بنیاد پر، ہر آنے والی کال کے لیے جواب دینے والا ایجنٹ منتخب کریں — یا اس کا prompt اور ترتیبات الگ سے تبدیل کریں۔
بطور ڈیفالٹ ہر فون نمبر اور قابل اشاعت کلید کے ساتھ ایک جامد ایجنٹ منسلک ہوتا ہے۔ جب آپ کو ہر کالر کے لیے یا ہر وزیٹر کے لیے تخصیص درکار ہو — 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 ...
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. رسپانس اسکیما
رسپانس باڈی بالکل ان کمنگ کال رسپانس اسکیما سے مطابقت رکھتی ہے۔ عام طور پر استعمال ہونے والی فیلڈز:
| فیلڈ | قسم | وضاحت |
|---|---|---|
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() پر سادہ سوئچ استعمال کریں۔