---
title: "દરેક કૉલ માટે ગતિશીલ કૉન્ફિગરેશન"
description: "તમે નિયંત્રિત કરતા webhookમાં કસ્ટમ લોજિકના આધારે, દરેક આવનારા કૉલ માટે અલગથી જવાબ આપતો એજન્ટ પસંદ કરો — અથવા તેનો prompt અને સેટિંગ્સ ફરીથી લખો."
---

ડિફૉલ્ટ રીતે દરેક ફોન નંબર અને publishable key માટે એક સ્થિર એજન્ટ સોંપાયેલ હોય છે. જ્યારે તમને **દરેક કૉલર માટે** અથવા **દરેક વિઝિટર માટે** કસ્ટમાઇઝેશનની જરૂર હોય
— VIP રાઉટિંગ, લૉગ-ઇન થયેલા વપરાશકર્તાનો સંદર્ભ, A/B prompt પરીક્ષણો — ત્યારે
webhook-mode પર સ્વિચ કરો અને તમારા સર્વરને નિર્ણય લેવા દો.

## તે કેવી રીતે કાર્ય કરે છે

1. તમે [`telephony.incoming`](/gu/webhooks/events)
   (ફોન) અથવા [`web.incoming`](/gu/webhooks/events) (widget)
   ઇવેન્ટને સબ્સ્ક્રાઇબ કરો છો. બંને **બ્લૉકિંગ** webhooks છે: ThunderPhone કૉલ ચાલુ રાખતા પહેલાં
   તમારા પ્રતિસાદ માટે 10 સેકન્ડ સુધી રાહ જુએ છે.
2. ThunderPhone તમને `{call_id, from_number, to_number}` મોકલે છે (widget
   સત્રોમાં નંબરોને બદલે widget-વિશિષ્ટ ફીલ્ડ હોય છે — [request schema](/gu/webhooks/call-incoming)
   જુઓ).
3. તમારો સર્વર એજન્ટ કૉન્ફિગરેશન (prompt, voice,
   product, tools) સાથે પ્રતિસાદ આપે છે. ThunderPhone કૉલ માટે તે કૉન્ફિગરેશનનો ઉપયોગ કરે છે.
4. જો તમે `{}` પરત કરો, સમય સમાપ્ત થાય, અથવા ભૂલ આવે, તો સ્થિર રીતે સોંપાયેલ
   એજન્ટ fallback તરીકે વપરાય છે. સુરક્ષિત ડિફૉલ્ટ.

<Note>
  webhook endpoint પર અથવા legacy single-URL webhook પર ડિલિવર કરવામાં આવે ત્યારે પણ,
  ફોન કૉલ્સ (`telephony.incoming`) અને widget સત્રો (`web.incoming`) માટે
  એકસરખી રીતે કાર્ય કરે છે.
</Note>

<Warning>
  **inline webhook-કૉન્ફિગર કરેલા કૉલ્સ પર ThunderPhoneની સંમતિ જાહેરાત ચલાવવામાં આવતી નથી.**
  આ પાથ એજન્ટ-સ્તરની કૉલ-શરૂઆત જાહેરાતને બાયપાસ કરે છે
  અને ThunderPhoneના સંમતિ-જાહેરાત ફ્રેમવર્કમાંથી (સેવાની શરતો, "રેકોર્ડિંગ અને સંમતિ"
  વિભાગ) સ્પષ્ટપણે બાકાત છે. આ કૉલ્સ પરના તમામ રેકોર્ડિંગ, મોનિટરિંગ,
  AI-ભાગીદારી અને કૉલર-ઓળખ સૂચનાઓ તથા સંમતિઓની જવાબદારી તમારી સંસ્થાની છે.
  inline webhook mode સક્રિય કરતાં પહેલાં, તેને તમારા પોતાના ફ્લોમાં — ઉદાહરણ તરીકે
  promptની શરૂઆતની સ્ક્રિપ્ટમાં — પ્રદાન કરો. સાચવેલા `agent_id`નો ઉલ્લેખ કરતો webhook પ્રતિસાદ
  તે એજન્ટની સામાન્ય રેકોર્ડિંગ અને ખુલાસા નીતિનો ઉપયોગ કરે છે.
</Warning>

## 1. webhook ગંતવ્ય કૉન્ફિગર કરો

<Tabs>
<Tab title="ફોન કૉલ્સ">
ફોન નંબરો માટે, તમારા endpointને `telephony.incoming` માટે સબ્સ્ક્રાઇબ કરો:

```bash
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` શામેલ હોય છે — તેને સાચવો; તમે તેનો ઉપયોગ
signature verification માટે કરશો.
</Tab>
<Tab title="વેબ widget">
widget સત્રો માટે, તમારા endpoint URL સાથે સમાવિષ્ટ `mode="webhook"`માં
publishable key બનાવો:

```bash
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"]
  }'
```

દરેક સત્ર શરૂ થાય ત્યારે widget આ URL પર POST કરશે.
</Tab>
</Tabs>

## 2. હેન્ડલર અમલમાં મૂકો

ત્રણ સામાન્ય નિયમો:

- દરેક વિનંતી પર **સહી ચકાસો** (જુઓ
  [webhook સહી ચકાસો](/gu/guides/verify-webhook-signatures)).
  ડેવલપમેન્ટમાં આ છોડશો નહીં — એકવાર યોગ્ય રીતે કરો અને ફરીથી ઉપયોગ કરો.
- **ઝડપથી પ્રતિસાદ આપો**. દસ સેકન્ડની કડક મર્યાદા છે, અને દરેક સેકન્ડ
  કૉલર માટે મૌન સમય છે. જરૂર હોય તો ડેટાબેઝ લુકઅપ કરો, પરંતુ
  ડાઉનસ્ટ્રીમ LLM ને સિંક્રોનસ રીતે કૉલ કરશો નહીં — ડાયનેમિક
  prompt જનરેશન જોઈએ તો, પૂર્વ-ગણતરી કરીને કૅશ કરો.
- **સ્વચ્છ રીતે ફૉલબૅક કરો**. કોઈપણ અનપેક્ષિત સ્થિતિએ `{}` પરત કરવું જોઈએ જેથી
  સ્થિર રીતે અસાઇન કરેલ એજન્ટ કૉલ સંભાળે.

<CodeGroup>
```python 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
```

```javascript 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
  },
);
```
</CodeGroup>

## 3. પ્રતિસાદ સ્કીમા

પ્રતિસાદ બોડી
[ઇનકમિંગ-કૉલ પ્રતિસાદ સ્કીમા](/gu/webhooks/call-incoming)
સાથે બરાબર મેળ ખાય છે. સામાન્ય રીતે ઉપયોગમાં લેવાતા ફીલ્ડ્સ:

| ફીલ્ડ | પ્રકાર | વર્ણન |
|-------|------|-------------|
| `prompt` | સ્ટ્રિંગ (આવશ્યક) | એજન્ટ માટે સિસ્ટમ પ્રોમ્પ્ટ |
| `voice` | સ્ટ્રિંગ (આવશ્યક) | [`GET /v1/voices`](/api-reference/agents#voices) માંથી વૉઇસ id |
| `product` | સ્ટ્રિંગ | ડિફૉલ્ટ `spark` છે |
| `background_track` | સ્ટ્રિંગ \| નલ | એમ્બિયન્ટ ઑડિયો id |
| `acknowledgement_prompt_mode` | સ્ટ્રિંગ | `auto` અથવા `manual` (ફક્ત ack સાથેના Storm માટે) |
| `acknowledgement_prompt` | સ્ટ્રિંગ | મોડ `manual` હોય ત્યારે આવશ્યક |
| `tools` | એરે | ઇનલાઇન ફંક્શન-ટૂલ સ્કીમાઓ — [ફંક્શન ટૂલ્સ](/gu/tools/overview) જુઓ |

<Note>
  પ્રતિ-કૉલ સ્પીક-ઓર્ડર અને `max_hold_seconds` વેબહૂક
  પ્રતિસાદમાં ઉપલબ્ધ નથી. તમે જે
  [એજન્ટ](/api-reference/agents)નો સંદર્ભ આપો છો તેમાં તેમને સેટ કરો.
</Note>

### સાચવેલ એજન્ટ રાખો અને વેરિએબલ્સ આપો

પ્રતિ-કૉલ ડેટા સાથે તે સંસ્થાના સાચવેલા એજન્ટનો ઉપયોગ કરવા માટે `{"agent_id": 12, "variables": {"name": "Ada"}}` પરત કરો.
તેના પ્રોમ્પ્ટમાં `{{name}}` અથવા
`{{name|Friend}}` હોઈ શકે છે. વેબહૂક વેરિએબલ્સ રિક્વેસ્ટ-સ્તરના વેરિએબલ્સ પર મર્જ થાય છે; નલ હોય ત્યારે પ્લેસહોલ્ડર ડિફૉલ્ટનો ઉપયોગ થાય છે, અથવા કંઈ આપવામાં ન હોય તો ખાલી ટેક્સ્ટનો ઉપયોગ થાય છે. અંતિમ
મૂલ્યો અને ઉકેલાયા ન હોય તેવા નામો કૉલ વિગતો અને કમ્પ્લીશન વેબહૂક્સમાં દેખાય છે.
સાચવેલા-એજન્ટના પ્રતિસાદો ફક્ત `agent_id` અને `variables` સ્વીકારે છે. જો `prompt`
હાજર હોય, તો પ્રતિસાદ ઇનલાઇન કૉન્ફિગરેશનનો ઉપયોગ કરે છે અને `agent_id`ને અવગણે છે (નલ અથવા બિન-પૂર્ણાંક મેટાડેટા સહિત);
ઇનલાઇન પ્રોમ્પ્ટ હજુ પણ માન્ય હોવો જરૂરી છે. ઇનલાઇન
કૉન્ફિગરેશન પ્રતિસાદોમાં `variables` પણ સામેલ હોઈ શકે છે. સાચવેલા-એજન્ટના પ્રતિસાદો
ફોન અને વિજેટ બંને કૉલ્સ પર એજન્ટનો ડિપ્લોય કરેલ A/B સ્પ્લિટ ઉપયોગ કરે છે, પછી વેરિએબલ્સ રેન્ડર કરે છે. [કૉલ વેરિએબલ્સ](/gu/guides/call-variables)
મર્યાદાઓ અને સેશન API સપોર્ટ માટે જુઓ. બ્લોકિંગ કૉન્ફિગરેશન લેગસી
ફોન-નંબર/સંસ્થા URL અથવા વેબહૂક-મોડ વિજેટ કીમાંથી આવે છે; એન્ડપૉઇન્ટ-સિસ્ટમ ઇનકમિંગ ઇવેન્ટ્સ માત્ર સૂચનાઓ છે.

## પેટર્ન્સ

### લૉગ-ઇન થયેલા વપરાશકર્તાનો સંદર્ભ

વેબહૂક-મોડ વિજેટ્સમાં, વિઝિટરનું પેજ પહેલેથી જ જાણે છે કે તેઓ
કોણ છે. તમારા વેબહૂકને વિજેટ SDK ફૉર્વર્ડ કરે તેવા ક્વેરી સ્ટ્રિંગ પેરામીટર
સાથે કૉલ કરો (`?customer_id=123`) અને સર્વર-સાઇડ ગ્રાહક શોધો.

### A/B પ્રોમ્પ્ટ રોલઆઉટ

તમે આ જાતે બનાવો તે પહેલાં, નોંધો કે ThunderPhone પાસે મૂળભૂત
[પ્રયોગો](/gu/guides/concepts) સુવિધા છે
(`/dashboard/experiments` અને એજન્ટ બિલ્ડરના **A/B** ટૅબમાં), જે
વેરિઅન્ટ્સ વ્યાખ્યાયિત કરે છે, ટ્રાફિક વહેંચે છે અને દરેક વેરિઅન્ટના પરિણામોની તુલના કરે છે —
વેબહૂકની જરૂર નથી.

જો તમને તેમ છતાં વેબહૂક-બાજુનું નિયંત્રણ જોઈએ: `call_id` હૅશ કરો → બકેટ;
`0..49` માટે પ્રોમ્પ્ટ A અને `50..99` માટે પ્રોમ્પ્ટ B આપો. તમે પસંદ કરેલો
બકેટ તમારા પોતાના DBમાં રેકોર્ડ કરો અને પછી પૂર્ણ થયેલા કૉલના ગ્રેડ સાથે તેનો
સંબંધ સ્થાપિત કરો.

### સમય-આધારિત રૂટિંગ

વ્યવસાયિક સમય → "લાઇવ સપોર્ટ" એજન્ટ; કામકાજ પછીનો સમય → "સંદેશ લો"
એજન્ટ. તમારા હેન્ડલરમાં `new Date().getUTCHours()` પર સીધું સ્વિચ કરો.

---

## આગળનાં પગલાં

<CardGroup cols={2}>
  <Card title="ઇનકમિંગ-કૉલ વેબહૂક સંદર્ભ" icon="phone" href="/gu/webhooks/call-incoming">
    દરેક કૉન્ફિગરેશન કી સહિત ચોક્કસ રિક્વેસ્ટ + પ્રતિસાદ સ્કીમાઓ.
  </Card>
  <Card title="વેબહૂક સિગ્નેચર્સ ચકાસો" icon="shield-check" href="/gu/guides/verify-webhook-signatures">
    HMAC એક વાર બરાબર કરો; દરેક જગ્યાએ ફરી ઉપયોગ કરો.
  </Card>
  <Card title="ટૂલ ઇન્ટિગ્રેશન બનાવો" icon="screwdriver-wrench" href="/gu/guides/build-tool-integration">
    ડાયનેમિક રૂટિંગને પ્રતિ-એજન્ટ ટૂલ્સ સાથે જોડો.
  </Card>
  <Card title="ડિલિવરી સીમેન્ટિક્સ" icon="bolt" href="/gu/webhooks/overview">
    પુનઃપ્રયાસો, ક્રમ, સમયસમાપ્તિઓ.
  </Card>
</CardGroup>
