telephony.incoming / web.incoming
కేటాయించిన ఏజెంట్ లేని నంబర్కు ఇన్బౌండ్ ఫోన్ కాల్ వచ్చినప్పుడు లేదా
mode="webhook"లో ఉన్న ప్రచురించదగిన కీపై వెబ్ విడ్జెట్ సెషన్ ప్రారంభమైనప్పుడు,
ThunderPhone మీ లెగసీ వెబ్హుక్ URLకు ఒక నిరోధక
telephony.incoming / web.incoming అభ్యర్థనను పంపి, కాన్ఫిగరేషన్ ప్రతిస్పందన కోసం
గరిష్ఠంగా 10 సెకన్లు వేచి ఉంటుంది. ప్రతి కాల్కు prompt, వాయిస్, టూల్స్ను డైనమిక్గా
ఎంచుకోవడానికి ఈ మార్పిడిని ఉపయోగించండి — పూర్తి విధానం కోసం
డైనమిక్ కాల్ కాన్ఫిగరేషన్ గైడ్ చూడండి.
ఈ నిరోధక మార్పిడికి ఫాల్బ్యాక్ లేదు: మీ హ్యాండ్లర్ 2xx కాని స్టేటస్ను తిరిగి ఇస్తే,
టైమ్ అవుట్ అయితే లేదా ధ్రువీకరణలో విఫలమయ్యే కాన్ఫిగ్ను తిరిగి ఇస్తే, కాల్ తిరస్కరించబడుతుంది
(ఫోన్ కాల్ కనెక్ట్ కాదు; విడ్జెట్ సెషన్ అభ్యర్థన 502/422తో విఫలమవుతుంది). త్వరగా
స్పందించండి — మీరు నిర్ణయిస్తున్నప్పుడు కాలర్ రింగ్బ్యాక్ వింటున్నారు.
అభ్యర్థన పేలోడ్
ఫోన్ కాల్ల కోసం (telephony.incoming):
{
"type": "telephony.incoming",
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}
| ఫీల్డ్ | రకం | వివరణ |
|---|---|---|
call_id | integer | కాల్ ID — ఈ కాల్కు సంబంధించిన అన్ని ఈవెంట్లలో స్థిరంగా ఉంటుంది |
from_number | string | E.164 కాలర్ నంబర్ |
to_number | string | E.164 గమ్యం (మీ ThunderPhone నంబర్లలో ఒకటి) |
వెబ్ విడ్జెట్ సెషన్ల కోసం (web.incoming), data ఫోన్ నంబర్లకు బదులుగా
ఎంబెడ్ చేసిన పేజీని గుర్తిస్తుంది:
{
"type": "web.incoming",
"data": {
"call_id": 987654322,
"origin_domain": "https://example.com",
"publishable_key_prefix": "pk_live_a1b2"
}
}
| ఫీల్డ్ | రకం | వివరణ |
|---|---|---|
call_id | integer | కాల్ ID |
origin_domain | string | విడ్జెట్ను హోస్ట్ చేస్తున్న పేజీ ఆరిజిన్ |
publishable_key_prefix | string | సెషన్ను ప్రారంభించిన ప్రచురించదగిన కీలోని మొదటి అక్షరాలు |
language, primary_language | string | విడ్జెట్ సెషన్ భాష ఓవర్రైడ్ను అభ్యర్థించినప్పుడు అందుబాటులో ఉంటుంది |
voice | string | విడ్జెట్ సెషన్ వాయిస్ ఓవర్రైడ్ను అభ్యర్థించినప్పుడు అందుబాటులో ఉంటుంది |
website_context | string | విడ్జెట్ ప్రతి సెషన్కు పేజీ సందర్భాన్ని పంపినప్పుడు అందుబాటులో ఉంటుంది |
ప్రతిస్పందన స్కీమా
ఈ కాల్కు సంబంధించిన ఏజెంట్ కాన్ఫిగరేషన్ను వివరించే JSON ఆబ్జెక్ట్ను తిరిగి ఇవ్వండి.
prompt మరియు voice తప్పనిసరి; మిగతావన్నీ ఐచ్ఛికం.
{
"prompt": "You are a helpful booking assistant for Acme Restaurant.",
"voice": "john",
"product": "spark",
"background_track": null,
"tools": []
}
| ఫీల్డ్ | రకం | తప్పనిసరి | వివరణ |
|---|---|---|---|
prompt | స్ట్రింగ్ | అవును | ఏజెంట్ను నడిపించే సిస్టమ్ prompt |
voice | స్ట్రింగ్ | అవును | GET /v1/voices నుండి వాయిస్ ID, ఉదాహరణకు john. voice_nameను ప్రత్యామ్నాయ పేరుగా అంగీకరిస్తారు. తెలియని వాయిస్లు ధ్రువీకరణలో విఫలమై కాల్ను తిరస్కరిస్తాయి |
product | స్ట్రింగ్ | కాదు | డిఫాల్ట్గా spark. అనుమతించబడినవి: spark, bolt, storm-base, storm-base-with-ack, storm-extra, storm-extra-with-ack |
thinking_level | స్ట్రింగ్ | కాదు | minimal, base (డిఫాల్ట్), లేదా extra. Storm ఉత్పత్తుల కోసం భర్తీ చేయబడుతుంది: storm-extra* extraను బలవంతం చేస్తుంది, ఇతర storm-* baseను బలవంతం చేస్తాయి |
audio_context_mode | స్ట్రింగ్ | కాదు | full (డిఫాల్ట్) లేదా reduced |
watchdog_enabled | బూలియన్ | కాదు | ఈ కాల్కు పర్యవేక్షణను ప్రారంభించండి. డిఫాల్ట్ false |
storm_feedback_mode | స్ట్రింగ్ | కాదు | none, acknowledgement (డిఫాల్ట్), లేదా tick |
language | స్ట్రింగ్ | కాదు | primary_languageకు సంక్షిప్త రూపం |
primary_language | స్ట్రింగ్ | కాదు | భాషా కోడ్, సాధారణీకరించబడింది (డిఫాల్ట్ en). పరిష్కరించలేని కోడ్లు కాల్ను తిరస్కరిస్తాయి |
has_additional_languages | బూలియన్ | కాదు | డిఫాల్ట్ false |
additional_languages | స్ట్రింగ్ల శ్రేణి | కాదు | ఏజెంట్ మారగల అదనపు భాషలు |
background_track | స్ట్రింగ్ | null | కాదు | పరిసర ఆడియో ID లేదా null |
acknowledgement_prompt_mode | స్ట్రింగ్ | కాదు | auto (డిఫాల్ట్) లేదా manual (Storm-with-ack ఉత్పత్తులు) |
acknowledgement_prompt | స్ట్రింగ్ | కాదు | acknowledgement_prompt_mode="manual" అయినప్పుడు ఉపయోగించబడుతుంది |
silence_interval_seconds | పూర్ణసంఖ్య | null | కాదు | 5–120. తనిఖీకి ముందు కాలర్ నిశ్శబ్దంగా ఉండే సెకన్లు |
silence_max_checkins | పూర్ణసంఖ్య | null | కాదు | 1–10 |
silence_checkins_enabled | బూలియన్ | కాదు | డిఫాల్ట్ true |
connect_tone_enabled | బూలియన్ | కాదు | డిఫాల్ట్ false |
voicemail_action | స్ట్రింగ్ | కాదు | prompt (డిఫాల్ట్), hangup, లేదా message |
voicemail_message | స్ట్రింగ్ | కాదు | voicemail_action="message" అయినప్పుడు ఉపయోగించబడుతుంది |
agent_name | స్ట్రింగ్ | కాదు | డ్యాష్బోర్డులు మరియు విడ్జెట్కు నివేదించబడే ప్రదర్శన పేరు |
org_name | స్ట్రింగ్ | కాదు | ఏజెంట్ వ్యక్తిత్వం కోసం సంస్థ ప్రదర్శన పేరు |
tools | శ్రేణి | కాదు | ఇన్లైన్ ఫంక్షన్-టూల్ స్కీమాలు (ఫంక్షన్ టూల్స్ చూడండి) |
call_id | పూర్ణసంఖ్య | కాదు | అభ్యర్థనలోని కాల్ IDకి ఐచ్ఛిక ప్రతిధ్వని; విస్మరించబడుతుంది |
prompt మరియు voice తప్పనిసరి కాబట్టి, {} లేదా ధ్రువీకరణలో విఫలమయ్యే ఏదైనా
ప్రతిస్పందన కాల్ను 422తో తిరస్కరిస్తుంది — ఈ మార్గంలో స్థిర-ఏజెంట్ ప్రత్యామ్నాయం లేదు
(వెబ్హుక్ మోడ్లోని నంబర్ లేదా కీకి కేటాయించిన ఏజెంట్ ఉండదు).
ప్రతిస్పందన పరిమాణ పరిమితి
ఉదాహరణ హ్యాండ్లర్
import hashlib
import hmac
import json
import os
from fastapi import FastAPI, HTTPException, Request
app = FastAPI()
WEBHOOK_SECRET = os.environ["THUNDERPHONE_WEBHOOK_SECRET"]
def verify(body: bytes, signature: str) -> bool:
expected = hmac.new(WEBHOOK_SECRET.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature or "")
@app.post("/thunderphone-webhook")
async def webhook(request: Request):
body = await request.body()
if not verify(body, request.headers.get("X-ThunderPhone-Signature", "")):
raise HTTPException(status_code=401)
event = json.loads(body)
if event["type"] == "telephony.incoming":
caller = event["data"]["from_number"]
prompt = (
"Greet the caller as a San Francisco local…"
if caller.startswith("+1415")
else "You are a friendly customer support agent…"
)
return {
"prompt": prompt,
"voice": "john",
"product": "spark",
}
if event["type"] == "web.incoming":
return {
"prompt": "You are the website's helpful voice assistant…",
"voice": "john",
"product": "spark",
}
return {}
import crypto from "node:crypto";
import express from "express";
const app = express();
const SECRET = process.env.THUNDERPHONE_WEBHOOK_SECRET;
function verify(body, signature) {
const expected = crypto
.createHmac("sha256", SECRET)
.update(body)
.digest("hex");
return signature &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
app.post(
"/thunderphone-webhook",
express.raw({ type: "application/json" }),
(req, res) => {
if (!verify(req.body, req.header("X-ThunderPhone-Signature"))) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString("utf8"));
if (event.type === "telephony.incoming" || event.type === "web.incoming") {
const caller = event.data.from_number || "web";
const prompt = caller.startsWith("+1415")
? "Greet the caller as a San Francisco local…"
: "You are a friendly customer support agent…";
return res.json({
prompt,
voice: "john",
product: "spark",
});
}
res.json({});
},
);
ఫంక్షన్ టూల్స్తో ప్రతిస్పందన
సంభాషణ మధ్యలో AI మీ APIలను కాల్ చేయడానికి టూల్స్ను జత చేయండి:
{
"prompt": "You are a booking assistant. Use the available tools to help customers schedule appointments.",
"voice": "john",
"product": "spark",
"tools": [
{
"type": "function",
"function": {
"name": "search_appointments",
"description": "Find available appointment slots",
"parameters": {
"type": "object",
"properties": {
"date": { "type": "string", "description": "YYYY-MM-DD" },
"service": { "type": "string" }
},
"required": ["date"]
}
},
"endpoint": {
"url": "https://api.example.com/appointments/search",
"method": "POST",
"headers": {
"X-Api-Key": "your-key"
}
}
}
]
}
ప్రొడక్ట్ టియర్ చీట్ షీట్
| ప్రొడక్ట్ | లేటెన్సీ | రీజనింగ్ | అంగీకార స్పందన |
|---|---|---|---|
spark | అత్యల్పం | ప్రాథమికం | — |
bolt | తక్కువ | మెరుగుపరచబడింది | — |
storm-base | మధ్యస్థం | శక్తివంతమైనది | — |
storm-base-with-ack | మధ్యస్థం | శక్తివంతమైనది | ఆలోచిస్తున్నప్పుడు ఆటో ఫిల్లర్ |
storm-extra | ఎక్కువ | లోతైనది | — |
storm-extra-with-ack | ఎక్కువ | లోతైనది | ఆలోచిస్తున్నప్పుడు ఆటో ఫిల్లర్ |
సంబంధిత
బ్లాక్ చేయని కాల్ ముగింపు ఈవెంట్.
tools[] కోసం పూర్తి JSON స్కీమా మరియు సంతకం చేసిన ఎండ్పాయింట్ కాంట్రాక్ట్.
telephony.incoming / web.incomingకు బహుళ URLలను సబ్స్క్రైబ్ చేయండి.
ప్రతి కాలర్కు సంబంధించిన promptలు, టూల్స్ మరియు A/B పరీక్షల కోసం నమూనాలు.