Open in
డైనమిక్ ప్రతి-కాల్ కాన్ఫిగరేషన్
మీరు నియంత్రించే webhookలోని అనుకూల లాజిక్ ఆధారంగా, ప్రతి ఇన్కమింగ్ కాల్కు విడిగా సమాధానం ఇచ్చే ఏజెంట్ను ఎంచుకోండి — లేదా దాని prompt మరియు సెట్టింగ్లను తిరిగి రాయండి.
డిఫాల్ట్గా ప్రతి ఫోన్ నంబర్ మరియు ప్రచురించదగిన కీకి ఒక స్థిర ఏజెంట్ కేటాయించబడుతుంది. మీకు ప్రతి కాలర్కు లేదా ప్రతి సందర్శకుడికి అనుకూలీకరణ అవసరమైనప్పుడు — VIP రూటింగ్, లాగిన్ అయిన వినియోగదారు సందర్భం, A/B prompt పరీక్షలు — వెబ్హుక్ మోడ్కు మారి, మీ సర్వర్ నిర్ణయించనివ్వండి.
ఇది ఎలా పనిచేస్తుంది
- మీరు
telephony.incoming(ఫోన్) లేదాweb.incoming(విడ్జెట్) ఈవెంట్కు సబ్స్క్రైబ్ అవుతారు. రెండూ బ్లాకింగ్ వెబ్హుక్లు: కాల్ను కొనసాగించే ముందు ThunderPhone మీ ప్రతిస్పందన కోసం వేచి ఉంటుంది; ఫోన్ కాల్కు గరిష్ఠంగా 13 సెకన్లు (ఒక రీట్రైతో సహా), విడ్జెట్ సెషన్కు 10 సెకన్లు. - ThunderPhone మీకు
{call_id, from_number, to_number}పంపుతుంది (విడ్జెట్ సెషన్లు నంబర్ల బదులు విడ్జెట్కు ప్రత్యేకమైన ఫీల్డ్లను కలిగి ఉంటాయి — రిక్వెస్ట్ స్కీమా చూడండి). - మీ సర్వర్ ఏజెంట్ కాన్ఫిగరేషన్తో (prompt, వాయిస్, ప్రొడక్ట్, టూల్స్) ప్రతిస్పందిస్తుంది. ThunderPhone ఆ కాన్ఫిగరేషన్ను కాల్కు ఉపయోగిస్తుంది.
- ఫాల్బ్యాక్ ఏజెంట్ ఉండదు. మీరు
{}లేదా చెల్లని కాన్ఫిగరేషన్ను తిరిగి పంపితే, లేదా దాని రీట్రై తర్వాత కూడా రిక్వెస్ట్ విఫలమైతే, ఫోన్ కాల్ వెంటనే ముగించబడుతుంది మరియుend_reasoninbound_config_webhook_failedతో రికార్డ్ చేయబడుతుంది; విడ్జెట్ సెషన్ రిక్వెస్ట్ విఫలమవుతుంది.
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. హ్యాండ్లర్ను అమలు చేయండి
మూడు ప్రాథమిక నియమాలు:
- ప్రతి అభ్యర్థనలో సంతకాన్ని ధృవీకరించండి (వెబ్హుక్ సంతకాలను ధృవీకరించండి చూడండి). డెవలప్మెంట్లో దీన్ని దాటవేయవద్దు — ఒకసారి సరిగ్గా చేసి, మళ్లీ ఉపయోగించండి.
- త్వరగా ప్రతిస్పందించండి. ఫోన్ కాల్లో మొదటి ప్రయత్నం 10 సెకన్లకు నిలిపివేయబడుతుంది, మొత్తం సంభాషణ 13 సెకన్లకు ముగుస్తుంది; ప్రతి సెకను కాలర్కు నిశ్శబ్దంగానే ఉంటుంది. అవసరమైతే డేటాబేస్ లుక్అప్లు చేయండి, కానీ తదుపరి LLMలను సమకాలికంగా కాల్ చేయవద్దు — మీకు డైనమిక్ prompt జనరేషన్ కావాలంటే, ముందుగానే లెక్కించి క్యాష్ చేయండి.
- సక్రమంగా ఫాల్బ్యాక్ చేయండి. ఊహించని ఏ స్థితికైనా, డిఫాల్ట్
promptమరియుvoiceతో (లేదా సేవ్ చేసినagent_idతో) ప్రతిస్పందించండి.{}లేదా ఎర్రర్ స్థితిని తిరిగి ఇవ్వడం కాల్ను ముగిస్తుంది.
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 నుండి వాయిస్ id |
product | స్ట్రింగ్ | డిఫాల్ట్గా spark ఉంటుంది. ప్రయోగాత్మక ఉత్పత్తులు అనుమతిజాబితాలో ఉన్న సంస్థలకు మాత్రమే అందుబాటులో ఉంటాయి. |
background_track | స్ట్రింగ్ | null | పరిసర ఆడియో id |
acknowledgement_prompt_mode | స్ట్రింగ్ | auto లేదా manual (ackతో ఉన్న Stormకు మాత్రమే) |
acknowledgement_prompt | స్ట్రింగ్ | మోడ్ manual అయినప్పుడు తప్పనిసరి |
tools | అరే | ఇన్లైన్ ఫంక్షన్-టూల్ స్కీమాలు — ఫంక్షన్ టూల్స్ చూడండి |
సేవ్ చేసిన ఏజెంట్ను ఉంచి వేరియబుల్లను అందించండి
ఆ సంస్థ యొక్క సేవ్ చేసిన ఏజెంట్ను ప్రతి-కాల్ డేటాతో ఉపయోగించడానికి {"agent_id": 12, "variables": {"name": "Ada"}}ను తిరిగి ఇవ్వండి. దాని promptలో {{name}} లేదా
{{name|Friend}} ఉండవచ్చు. Webhook వేరియబుల్స్ రిక్వెస్ట్-స్థాయి వేరియబుల్స్పై విలీనం అవుతాయి; null ప్లేస్హోల్డర్ డిఫాల్ట్ను లేదా ఏదీ అందించకపోతే ఖాళీ టెక్స్ట్ను ఉపయోగిస్తుంది. తుది
విలువలు మరియు పరిష్కరించని పేర్లు కాల్ వివరాలు మరియు పూర్తీకరణ webhooksలో కనిపిస్తాయి.
సేవ్ చేసిన ఏజెంట్ ప్రతిస్పందనలు agent_id, variables, మరియు timezoneను మాత్రమే అంగీకరిస్తాయి. prompt ఉన్నట్లయితే,
ప్రతిస్పందన ఇన్లైన్ కాన్ఫిగరేషన్ను ఉపయోగించి agent_idను విస్మరిస్తుంది (null లేదా పూర్ణాంకం కాని మెటాడేటాతో సహా);
ఇన్లైన్ prompt ఇప్పటికీ చెల్లుబాటు కావాలి. ఇన్లైన్ కాన్ఫిగరేషన్ ప్రతిస్పందనల్లో variables కూడా ఉండవచ్చు. సేవ్ చేసిన ఏజెంట్ ప్రతిస్పందనలు
ఫోన్ మరియు విడ్జెట్ కాల్లు రెండింటిలోనూ ఏజెంట్ డిప్లాయ్ చేసిన A/B విభజనను ఉపయోగించి, ఆపై వేరియబుల్స్ను రెండర్ చేస్తాయి. పరిమితులు మరియు సెషన్ API మద్దతు కోసం కాల్ వేరియబుల్స్ చూడండి.
బ్లాకింగ్ కాన్ఫిగరేషన్ లెగసీ ఫోన్-నంబర్/సంస్థ URL లేదా webhook-మోడ్ విడ్జెట్ కీ నుండి వస్తుంది; ఎండ్పాయింట్-సిస్టమ్
ఇన్కమింగ్ ఈవెంట్లు నోటిఫికేషన్లు మాత్రమే.
ప్రతి కాల్కు సమయ మండలిని సెట్ చేయండి
ఒక ఏజెంట్ వేర్వేరు సమయ మండలాల్లోని కాంటాక్ట్లకు సమాధానం ఇవ్వగలదు. సేవ్ చేసిన ఏజెంట్ లేదా ఇన్లైన్ ప్రతిస్పందనకు IANA పేరు అయిన timezoneను జోడించండి. అప్పుడు ఈ కాల్ కోసం ఏజెంట్ తేదీ, సమయాన్ని తెలియజేసి, ఏజెంట్ స్వంత సమయ మండలికి ముందుగా ఆ మండలిలోని సమయాలను అందిస్తుంది:
{"agent_id": 12, "timezone": "America/Chicago", "variables": {"name": "Ada"}}variablesలో టైమ్స్టాంప్కు బదులుగా మండలిని పంపండి: కాల్ జరుగుతున్నంతసేపు ఏజెంట్ గడియారం కొనసాగుతుంది, మీరు పంపిన సమయం పాతబడిపోతుంది. IANA మండలి కాని విలువను విస్మరిస్తారు మరియు కాల్ ఏజెంట్ మండలిలో కనెక్ట్ అవుతుంది.
నమూనాలు
లాగిన్ అయిన వినియోగదారు సందర్భం
వెబ్హుక్-మోడ్ విడ్జెట్లలో, సందర్శకుడి పేజీకి వారు ఎవరో ఇప్పటికే
తెలిసి ఉంటుంది. విడ్జెట్ 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()పై స్వచ్ఛమైన స్విచ్.
తదుపరి దశలు
ప్రతి కాన్ఫిగరేషన్ కీతో సహా ఖచ్చితమైన రిక్వెస్ట్ + ప్రతిస్పందన స్కీమాలు.
HMACను ఒకసారి సరిగ్గా చేయండి; ప్రతిచోటా మళ్లీ ఉపయోగించండి.
డైనమిక్ రూటింగ్ను ప్రతి-ఏజెంట్ టూల్స్తో కలపండి.
మళ్లీ ప్రయత్నాలు, క్రమం, టైమ్అవుట్లు.