---
title: "ਹਰ ਕਾਲ ਲਈ ਡਾਇਨਾਮਿਕ ਸੰਰਚਨਾ"
description: "ਤੁਹਾਡੇ ਨਿਯੰਤਰਣ ਹੇਠਲੇ webhook ਵਿੱਚ ਕਸਟਮ ਤਰਕ ਦੇ ਆਧਾਰ 'ਤੇ, ਹਰ ਆਉਣ ਵਾਲੀ ਕਾਲ ਲਈ ਜਵਾਬ ਦੇਣ ਵਾਲਾ ਏਜੰਟ ਵੱਖਰੇ ਤੌਰ 'ਤੇ ਚੁਣੋ — ਜਾਂ ਉਸਦਾ prompt ਅਤੇ ਸੈਟਿੰਗਾਂ ਮੁੜ ਲਿਖੋ।"
---

ਮੂਲ ਰੂਪ ਵਿੱਚ ਹਰ ਫ਼ੋਨ ਨੰਬਰ ਅਤੇ ਪ੍ਰਕਾਸ਼ਯੋਗ ਕੀ ਨਾਲ ਇੱਕ ਸਥਿਰ ਏਜੰਟ
ਨਿਰਧਾਰਤ ਹੁੰਦਾ ਹੈ। ਜਦੋਂ ਤੁਹਾਨੂੰ **ਹਰ ਕਾਲਰ ਲਈ** ਜਾਂ **ਹਰ ਵਿਜ਼ਟਰ ਲਈ** ਕਸਟਮਾਈਜ਼ੇਸ਼ਨ
ਚਾਹੀਦੀ ਹੋਵੇ — VIP ਰੂਟਿੰਗ, ਲੌਗ-ਇਨ ਵਰਤੋਂਕਾਰ ਸੰਦਰਭ, A/B prompt ਟੈਸਟ — ਤਾਂ
ਵੈੱਬਹੁੱਕ ਮੋਡ ਵਰਤੋ ਅਤੇ ਆਪਣੇ ਸਰਵਰ ਨੂੰ ਫ਼ੈਸਲਾ ਕਰਨ ਦਿਓ।

## ਇਹ ਕਿਵੇਂ ਕੰਮ ਕਰਦਾ ਹੈ

1. ਤੁਸੀਂ [`telephony.incoming`](/pa/webhooks/events)
   (ਫ਼ੋਨ) ਜਾਂ [`web.incoming`](/pa/webhooks/events) (ਵਿਜੇਟ)
   ਇਵੈਂਟ ਦੀ ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਲੈਂਦੇ ਹੋ। ਦੋਵੇਂ **ਬਲਾਕਿੰਗ** ਵੈੱਬਹੁੱਕ ਹਨ:
   ThunderPhone ਕਾਲ ਜਾਰੀ ਰੱਖਣ ਤੋਂ ਪਹਿਲਾਂ ਤੁਹਾਡੇ ਜਵਾਬ ਲਈ ਵੱਧ ਤੋਂ ਵੱਧ
   10 ਸਕਿੰਟ ਉਡੀਕ ਕਰਦਾ ਹੈ।
2. ThunderPhone ਤੁਹਾਨੂੰ `{call_id, from_number, to_number}` ਭੇਜਦਾ ਹੈ (ਵਿਜੇਟ
   ਸੈਸ਼ਨਾਂ ਵਿੱਚ ਨੰਬਰਾਂ ਦੀ ਥਾਂ ਵਿਜੇਟ-ਵਿਸ਼ੇਸ਼ ਫ਼ੀਲਡ ਹੁੰਦੇ ਹਨ — [ਰਿਕਵੇਸਟ
   ਸਕੀਮਾ](/pa/webhooks/call-incoming) ਦੇਖੋ)।
3. ਤੁਹਾਡਾ ਸਰਵਰ ਏਜੰਟ ਕੌਂਫਿਗਰੇਸ਼ਨ ਨਾਲ ਜਵਾਬ ਦਿੰਦਾ ਹੈ (prompt, ਆਵਾਜ਼,
   ਉਤਪਾਦ, ਟੂਲ)। ThunderPhone ਉਸ ਕਾਲ ਲਈ ਉਹ ਕੌਂਫਿਗਰੇਸ਼ਨ ਵਰਤਦਾ ਹੈ।
4. ਜੇ ਤੁਸੀਂ `{}` ਵਾਪਸ ਕਰਦੇ ਹੋ, ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਜਾਂਦਾ ਹੈ, ਜਾਂ ਗਲਤੀ ਆਉਂਦੀ ਹੈ,
   ਤਾਂ ਸਥਿਰ ਤੌਰ 'ਤੇ ਨਿਰਧਾਰਤ ਏਜੰਟ ਨੂੰ ਫਾਲਬੈਕ ਵਜੋਂ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ। ਸੁਰੱਖਿਅਤ ਮੂਲ ਵਿਕਲਪ।

<Note>
  ਫ਼ੋਨ ਕਾਲਾਂ (`telephony.incoming`) ਅਤੇ ਵਿਜੇਟ ਸੈਸ਼ਨਾਂ (`web.incoming`) ਲਈ
  ਇੱਕੋ ਤਰ੍ਹਾਂ ਕੰਮ ਕਰਦਾ ਹੈ, ਭਾਵੇਂ ਵੈੱਬਹੁੱਕ ਐਂਡਪੁਆਇੰਟ 'ਤੇ ਭੇਜਿਆ ਜਾਵੇ ਜਾਂ
  ਪੁਰਾਣੇ ਸਿੰਗਲ-URL ਵੈੱਬਹੁੱਕ 'ਤੇ।
</Note>

<Warning>
  **ਇਨਲਾਈਨ ਵੈੱਬਹੁੱਕ-ਕੌਂਫਿਗਰ ਕੀਤੀਆਂ ਕਾਲਾਂ 'ਤੇ ThunderPhone ਦੀ ਸਹਿਮਤੀ ਘੋਸ਼ਣਾ ਨਹੀਂ ਚਲਾਈ ਜਾਂਦੀ।**
  ਇਹ ਮਾਰਗ ਏਜੰਟ-ਪੱਧਰੀ ਕਾਲ-ਸ਼ੁਰੂਆਤ ਘੋਸ਼ਣਾ ਨੂੰ ਬਾਈਪਾਸ ਕਰਦਾ ਹੈ
  ਅਤੇ ThunderPhone ਦੇ ਸਹਿਮਤੀ-ਘੋਸ਼ਣਾ ਫਰੇਮਵਰਕ (ਸੇਵਾ ਦੀਆਂ ਸ਼ਰਤਾਂ, "ਰਿਕਾਰਡਿੰਗ ਅਤੇ ਸਹਿਮਤੀ"
  ਭਾਗ) ਤੋਂ ਸਪੱਸ਼ਟ ਤੌਰ 'ਤੇ ਬਾਹਰ ਹੈ। ਤੁਹਾਡੀ ਸੰਸਥਾ ਇਨ੍ਹਾਂ ਕਾਲਾਂ ਵਿੱਚ ਸਾਰੀਆਂ
  ਰਿਕਾਰਡਿੰਗ, ਨਿਗਰਾਨੀ, AI-ਭਾਗੀਦਾਰੀ ਅਤੇ ਕਾਲਰ-ਪਛਾਣ ਸੂਚਨਾਵਾਂ ਅਤੇ ਸਹਿਮਤੀਆਂ ਲਈ
  ਜ਼ਿੰਮੇਵਾਰ ਹੈ। ਇਨਲਾਈਨ ਵੈੱਬਹੁੱਕ ਮੋਡ ਯੋਗ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਉਨ੍ਹਾਂ ਨੂੰ ਆਪਣੇ
  ਫ਼ਲੋ ਵਿੱਚ ਦਿਓ — ਉਦਾਹਰਨ ਲਈ prompt ਦੀ ਸ਼ੁਰੂਆਤੀ ਸਕ੍ਰਿਪਟ ਵਿੱਚ।
  ਇੱਕ ਵੈੱਬਹੁੱਕ ਜਵਾਬ ਜੋ ਸੁਰੱਖਿਅਤ ਕੀਤੇ `agent_id` ਦਾ ਹਵਾਲਾ ਦਿੰਦਾ ਹੈ, ਉਸ ਏਜੰਟ ਦੀ
  ਆਮ ਰਿਕਾਰਡਿੰਗ ਅਤੇ ਖੁਲਾਸਾ ਨੀਤੀ ਵਰਤਦਾ ਹੈ।
</Warning>

## 1. ਵੈੱਬਹੁੱਕ ਟਿਕਾਣਾ ਕੌਂਫਿਗਰ ਕਰੋ

<Tabs>
<Tab title="ਫ਼ੋਨ ਕਾਲਾਂ">
ਫ਼ੋਨ ਨੰਬਰਾਂ ਲਈ, ਆਪਣੇ ਐਂਡਪੁਆਇੰਟ ਨੂੰ `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` ਸ਼ਾਮਲ ਹੁੰਦਾ ਹੈ — ਇਸਨੂੰ ਸੁਰੱਖਿਅਤ ਕਰੋ; ਤੁਸੀਂ ਇਸਨੂੰ
ਦਸਤਖ਼ਤ ਤਸਦੀਕ ਲਈ ਵਰਤੋਗੇ।
</Tab>
<Tab title="ਵੈੱਬ ਵਿਜੇਟ">
ਵਿਜੇਟ ਸੈਸ਼ਨਾਂ ਲਈ, ਆਪਣੇ ਐਂਡਪੁਆਇੰਟ URL ਨੂੰ ਸ਼ਾਮਲ ਕਰਕੇ `mode="webhook"`
ਵਿੱਚ ਇੱਕ ਪ੍ਰਕਾਸ਼ਯੋਗ ਕੀ ਬਣਾਓ:

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

ਹਰ ਸੈਸ਼ਨ ਸ਼ੁਰੂ ਹੋਣ 'ਤੇ ਵਿਜੇਟ ਇਸ URL ਨੂੰ POST ਕਰੇਗਾ।
</Tab>
</Tabs>

## 2. ਹੈਂਡਲਰ ਲਾਗੂ ਕਰੋ

ਤਿੰਨ ਮੁੱਢਲੇ ਨਿਯਮ:

- ਹਰ ਬੇਨਤੀ ਉੱਤੇ **ਦਸਤਖ਼ਤ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ** (ਵੇਖੋ
  [ਵੈੱਬਹੁੱਕ ਦਸਤਖ਼ਤਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ](/pa/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. ਜਵਾਬ ਸਕੀਮਾ

ਜਵਾਬ ਦਾ ਬਾਡੀ
[ਇਨਕਮਿੰਗ-ਕਾਲ ਜਵਾਬ ਸਕੀਮਾ](/pa/webhooks/call-incoming)
ਨਾਲ ਬਿਲਕੁਲ ਮੇਲ ਖਾਂਦਾ ਹੈ। ਆਮ ਤੌਰ 'ਤੇ ਵਰਤੇ ਜਾਣ ਵਾਲੇ ਫੀਲਡ:

| ਫੀਲਡ | ਕਿਸਮ | ਵੇਰਵਾ |
|-------|------|-------------|
| `prompt` | ਸਟ੍ਰਿੰਗ (ਲਾਜ਼ਮੀ) | ਏਜੰਟ ਲਈ ਸਿਸਟਮ prompt |
| `voice` | ਸਟ੍ਰਿੰਗ (ਲਾਜ਼ਮੀ) | [`GET /v1/voices`](/api-reference/agents#voices) ਤੋਂ ਵੌਇਸ id |
| `product` | ਸਟ੍ਰਿੰਗ | ਡਿਫਾਲਟ `spark` ਹੈ |
| `background_track` | ਸਟ੍ਰਿੰਗ \| null | ਐਂਬੀਅੰਟ ਆਡੀਓ id |
| `acknowledgement_prompt_mode` | ਸਟ੍ਰਿੰਗ | `auto` ਜਾਂ `manual` (ਸਿਰਫ਼ ack ਵਾਲੇ Storm ਲਈ) |
| `acknowledgement_prompt` | ਸਟ੍ਰਿੰਗ | ਜਦੋਂ ਮੋਡ `manual` ਹੋਵੇ ਤਾਂ ਲਾਜ਼ਮੀ |
| `tools` | ਐਰੇ | ਇਨਲਾਈਨ ਫੰਕਸ਼ਨ-ਟੂਲ ਸਕੀਮਾ — [Function Tools](/pa/tools/overview) ਵੇਖੋ |

<Note>
  ਪ੍ਰਤੀ-ਕਾਲ ਬੋਲਣ ਦਾ ਕ੍ਰਮ ਅਤੇ `max_hold_seconds` ਵੈੱਬਹੁੱਕ ਜਵਾਬ ਵਿੱਚ
  ਉਪਲਬਧ ਨਹੀਂ ਹਨ। ਉਹਨਾਂ ਨੂੰ ਉਸ
  [ਏਜੰਟ](/api-reference/agents) 'ਤੇ ਸੈੱਟ ਕਰੋ ਜਿਸ ਦਾ ਤੁਸੀਂ ਹਵਾਲਾ ਦਿੰਦੇ ਹੋ।
</Note>

### ਸੇਵ ਕੀਤਾ ਏਜੰਟ ਰੱਖੋ ਅਤੇ ਵੇਰੀਏਬਲ ਦਿਓ

ਉਸ ਸੰਗਠਨ ਦੇ ਸੇਵ ਕੀਤੇ ਏਜੰਟ ਨੂੰ ਪ੍ਰਤੀ-ਕਾਲ ਡਾਟਾ ਨਾਲ ਵਰਤਣ ਲਈ `{"agent_id": 12, "variables": {"name": "Ada"}}` ਵਾਪਸ ਕਰੋ।
ਇਸ ਦੇ prompt ਵਿੱਚ `{{name}}` ਜਾਂ
`{{name|Friend}}` ਹੋ ਸਕਦਾ ਹੈ। ਵੈੱਬਹੁੱਕ ਵੇਰੀਏਬਲ ਬੇਨਤੀ-ਪੱਧਰ ਦੇ ਵੇਰੀਏਬਲਾਂ ਨੂੰ ਮਿਲਾ ਕੇ
ਓਵਰਰਾਈਡ ਕਰਦੇ ਹਨ; null ਪਲੇਸਹੋਲਡਰ ਡਿਫਾਲਟ ਵਰਤਦਾ ਹੈ, ਜਾਂ ਜੇ ਕੋਈ ਨਾ ਦਿੱਤਾ ਹੋਵੇ ਤਾਂ
ਖਾਲੀ ਟੈਕਸਟ ਵਰਤਦਾ ਹੈ। ਅੰਤਿਮ ਮੁੱਲ ਅਤੇ ਅਣਸੁਲਝੇ ਨਾਮ ਕਾਲ ਵੇਰਵਿਆਂ ਅਤੇ ਕੰਪਲੀਸ਼ਨ ਵੈੱਬਹੁੱਕਾਂ ਵਿੱਚ ਦਿਖਾਈ ਦਿੰਦੇ ਹਨ।
ਸੇਵ ਕੀਤੇ ਏਜੰਟ ਦੇ ਜਵਾਬ ਸਿਰਫ਼ `agent_id` ਅਤੇ `variables` ਸਵੀਕਾਰ ਕਰਦੇ ਹਨ। ਜੇ `prompt`
ਮੌਜੂਦ ਹੋਵੇ, ਤਾਂ ਜਵਾਬ ਇਨਲਾਈਨ ਕੌਂਫਿਗਰੇਸ਼ਨ ਵਰਤਦਾ ਹੈ ਅਤੇ `agent_id` ਨੂੰ ਅਣਡਿੱਠਾ ਕਰਦਾ ਹੈ (null ਜਾਂ
ਗੈਰ-ਪੂਰਨ ਅੰਕ ਮੈਟਾਡੇਟਾ ਸਮੇਤ); ਇਨਲਾਈਨ prompt ਫਿਰ ਵੀ ਵੈਧ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ। ਇਨਲਾਈਨ
ਕੌਂਫਿਗਰੇਸ਼ਨ ਜਵਾਬਾਂ ਵਿੱਚ `variables` ਵੀ ਸ਼ਾਮਲ ਹੋ ਸਕਦੇ ਹਨ। ਸੇਵ ਕੀਤੇ ਏਜੰਟ ਦੇ ਜਵਾਬ
ਫੋਨ ਅਤੇ ਵਿਜਿਟ ਦੋਵਾਂ ਕਾਲਾਂ 'ਤੇ ਏਜੰਟ ਦੀ ਡਿਪਲੋਇ ਕੀਤੀ A/B ਵੰਡ ਵਰਤਦੇ ਹਨ, ਫਿਰ ਵੇਰੀਏਬਲ ਰੈਂਡਰ ਕਰਦੇ ਹਨ। ਸੀਮਾਵਾਂ ਅਤੇ ਸੈਸ਼ਨ API ਸਹਾਇਤਾ ਲਈ [ਕਾਲ ਵੇਰੀਏਬਲ](/pa/guides/call-variables)
ਵੇਖੋ। ਬਲਾਕਿੰਗ ਕੌਂਫਿਗਰੇਸ਼ਨ ਪੁਰਾਣੇ
ਫੋਨ-ਨੰਬਰ/ਸੰਗਠਨ URL ਜਾਂ ਵੈੱਬਹੁੱਕ-ਮੋਡ ਵਿਜਿਟ ਕੀ ਤੋਂ ਆਉਂਦੀ ਹੈ; ਐਂਡਪੌਇੰਟ-ਸਿਸਟਮ
ਇਨਕਮਿੰਗ ਇਵੈਂਟ ਸਿਰਫ਼ ਸੂਚਨਾਵਾਂ ਹਨ।

## ਪੈਟਰਨ

### ਲੌਗ-ਇਨ ਯੂਜ਼ਰ ਸੰਦਰਭ

ਵੈੱਬਹੁੱਕ-ਮੋਡ ਵਿਜਿਟਾਂ ਵਿੱਚ, ਵਿਜ਼ਿਟਰ ਦੇ ਪੇਜ ਨੂੰ ਪਹਿਲਾਂ ਹੀ ਪਤਾ ਹੁੰਦਾ ਹੈ ਕਿ ਉਹ
ਕੌਣ ਹਨ। ਆਪਣੇ ਵੈੱਬਹੁੱਕ ਨੂੰ ਉਸ ਕਵੇਰੀ ਸਟ੍ਰਿੰਗ ਪੈਰਾਮੀਟਰ ਨਾਲ ਕਾਲ ਕਰੋ ਜਿਸ ਨੂੰ ਵਿਜਿਟ SDK
ਅੱਗੇ ਭੇਜਦਾ ਹੈ (`?customer_id=123`) ਅਤੇ ਸਰਵਰ-ਸਾਈਡ 'ਤੇ ਗਾਹਕ ਨੂੰ ਲੱਭੋ।

### A/B prompt ਰੋਲਆਉਟ

ਇਸ ਨੂੰ ਖੁਦ ਬਣਾਉਣ ਤੋਂ ਪਹਿਲਾਂ, ਧਿਆਨ ਦਿਓ ਕਿ ThunderPhone ਵਿੱਚ ਇੱਕ ਨੇਟਿਵ
[ਐਕਸਪੇਰੀਮੈਂਟਸ](/pa/guides/concepts) ਫੀਚਰ ਹੈ
(`/dashboard/experiments` ਅਤੇ ਏਜੰਟ ਬਿਲਡਰ ਦੀ **A/B** ਟੈਬ) ਜੋ
ਵੇਰੀਐਂਟ ਪਰਿਭਾਸ਼ਿਤ ਕਰਦਾ ਹੈ, ਟ੍ਰੈਫਿਕ ਵੰਡਦਾ ਹੈ, ਅਤੇ ਹਰ ਵੇਰੀਐਂਟ ਦੇ ਨਤੀਜਿਆਂ ਦੀ ਤੁਲਨਾ ਕਰਦਾ ਹੈ —
ਕਿਸੇ ਵੈੱਬਹੁੱਕ ਦੀ ਲੋੜ ਨਹੀਂ।

ਜੇ ਤੁਹਾਨੂੰ ਫਿਰ ਵੀ ਵੈੱਬਹੁੱਕ-ਸਾਈਡ ਕੰਟਰੋਲ ਚਾਹੀਦਾ ਹੈ: `call_id` ਨੂੰ ਹੈਸ਼ ਕਰਕੇ → ਬਕੇਟ ਬਣਾਓ;
`0..49` ਲਈ prompt A ਅਤੇ `50..99` ਲਈ prompt B ਦਿਓ। ਆਪਣੀ DB ਵਿੱਚ ਤੁਹਾਡੇ ਦੁਆਰਾ ਚੁਣਿਆ
ਬਕੇਟ ਰਿਕਾਰਡ ਕਰੋ ਅਤੇ ਬਾਅਦ ਵਿੱਚ ਇਸ ਨੂੰ ਪੂਰੀ ਹੋਈ ਕਾਲ ਦੇ ਗ੍ਰੇਡ ਨਾਲ ਜੋੜੋ।

### ਸਮੇਂ-ਅਧਾਰਿਤ ਰਾਊਟਿੰਗ

ਕਾਰੋਬਾਰੀ ਸਮਾਂ → "ਲਾਈਵ ਸਹਾਇਤਾ" ਏਜੰਟ; ਕਾਰੋਬਾਰੀ ਸਮੇਂ ਤੋਂ ਬਾਅਦ → "ਸੁਨੇਹਾ ਲਓ"
ਏਜੰਟ। ਆਪਣੇ ਹੈਂਡਲਰ ਵਿੱਚ `new Date().getUTCHours()` 'ਤੇ ਸਿੱਧਾ ਸਵਿਚ ਕਰੋ।

---

## ਅਗਲੇ ਕਦਮ

<CardGroup cols={2}>
  <Card title="ਇਨਕਮਿੰਗ-ਕਾਲ ਵੈੱਬਹੁੱਕ ਹਵਾਲਾ" icon="phone" href="/pa/webhooks/call-incoming">
    ਹਰ ਕੌਂਫਿਗਰੇਸ਼ਨ ਕੀ ਸਮੇਤ ਸਹੀ ਬੇਨਤੀ + ਜਵਾਬ ਸਕੀਮਾ।
  </Card>
  <Card title="ਵੈੱਬਹੁੱਕ ਦਸਤਖਤਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ" icon="shield-check" href="/pa/guides/verify-webhook-signatures">
    HMAC ਨੂੰ ਇੱਕ ਵਾਰ ਸਹੀ ਕਰੋ; ਹਰ ਥਾਂ ਦੁਬਾਰਾ ਵਰਤੋ।
  </Card>
  <Card title="ਟੂਲ ਇੰਟੀਗ੍ਰੇਸ਼ਨ ਬਣਾਓ" icon="screwdriver-wrench" href="/pa/guides/build-tool-integration">
    ਡਾਇਨਾਮਿਕ ਰਾਊਟਿੰਗ ਨੂੰ ਪ੍ਰਤੀ-ਏਜੰਟ ਟੂਲਾਂ ਨਾਲ ਜੋੜੋ।
  </Card>
  <Card title="ਡਿਲਿਵਰੀ ਸੇਮੈਂਟਿਕਸ" icon="bolt" href="/pa/webhooks/overview">
    ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ਾਂ, ਕ੍ਰਮਬੱਧਤਾ, ਟਾਈਮਆਊਟ।
  </Card>
</CardGroup>
