ಪ್ರತಿ ಕರೆಯ ಡೈನಾಮಿಕ್ ಕಾನ್ಫಿಗರೇಶನ್

ಪೂರ್ವನಿಯೋಜಿತವಾಗಿ ಪ್ರತಿಯೊಂದು ಫೋನ್ ಸಂಖ್ಯೆ ಮತ್ತು ಪ್ರಕಟಿಸಬಹುದಾದ ಕೀಗೆ ಸ್ಥಿರ ಏಜೆಂಟ್ ಅನ್ನು ನಿಯೋಜಿಸಲಾಗಿರುತ್ತದೆ. ನಿಮಗೆ ಪ್ರತಿ-ಕರೆಮಾಡುವವರ ಅಥವಾ ಪ್ರತಿ-ಭೇಟಿದಾರರ ಗ್ರಾಹಕೀಕರಣ ಬೇಕಾದಾಗ — VIP ಮಾರ್ಗನಿರ್ದೇಶನ, ಲಾಗಿನ್ ಆಗಿರುವ ಬಳಕೆದಾರರ ಸಂದರ್ಭ, A/B prompt ಪರೀಕ್ಷೆಗಳು — ವೆಬ್‌ಹುಕ್ ಮೋಡ್‌ಗೆ ಬದಲಿಸಿ ಮತ್ತು ನಿಮ್ಮ ಸರ್ವರ್‌ಗೆ ನಿರ್ಧರಿಸಲು ಬಿಡಿ.

ಇದು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ

  1. ನೀವು telephony.incoming (ಫೋನ್) ಅಥವಾ web.incoming (ವಿಜೆಟ್) ಈವೆಂಟ್‌ಗೆ ಚಂದಾದಾರರಾಗುತ್ತೀರಿ. ಎರಡೂ ತಡೆಯುವ ವೆಬ್‌ಹುಕ್‌ಗಳಾಗಿವೆ: ಕರೆ ಮುಂದುವರಿಸುವ ಮೊದಲು ThunderPhone ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಗಾಗಿ 10 ಸೆಕೆಂಡುಗಳವರೆಗೆ ಕಾಯುತ್ತದೆ.
  2. ThunderPhone ನಿಮಗೆ {call_id, from_number, to_number} ಕಳುಹಿಸುತ್ತದೆ (ವಿಜೆಟ್ ಸೆಷನ್‌ಗಳು ಸಂಖ್ಯೆಗಳ ಬದಲಿಗೆ ವಿಜೆಟ್-ನಿರ್ದಿಷ್ಟ ಫೀಲ್ಡ್‌ಗಳನ್ನು ಹೊಂದಿರುತ್ತವೆ — ವಿನಂತಿ ಸ್ಕೀಮಾ ನೋಡಿ).
  3. ನಿಮ್ಮ ಸರ್ವರ್ ಏಜೆಂಟ್ ಕಾನ್ಫಿಗರೇಶನ್‌ನೊಂದಿಗೆ ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತದೆ (prompt, ಧ್ವನಿ, ಉತ್ಪನ್ನ, ಪರಿಕರಗಳು). ThunderPhone ಆ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಕರೆಗಾಗಿ ಬಳಸುತ್ತದೆ.
  4. ನೀವು {} ಹಿಂತಿರುಗಿಸಿದರೆ, ಸಮಯ ಮೀರಿದರೆ, ಅಥವಾ ದೋಷ ಉಂಟಾದರೆ, ಸ್ಥಿರವಾಗಿ ನಿಯೋಜಿಸಲಾದ ಏಜೆಂಟ್ ಅನ್ನು ಪರ್ಯಾಯವಾಗಿ ಬಳಸಲಾಗುತ್ತದೆ. ಸುರಕ್ಷಿತ ಡೀಫಾಲ್ಟ್.

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. ಹ್ಯಾಂಡ್ಲರ್ ಅನ್ನು ಅನುಷ್ಠಾನಗೊಳಿಸಿ

ಮೂರು ಸಾಮಾನ್ಯ ನಿಯಮಗಳು:

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
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
  },
);

3. ಪ್ರತಿಕ್ರಿಯೆ ಸ್ಕೀಮಾ

ಪ್ರತಿಕ್ರಿಯೆಯ ದೇಹವು ಒಳಬರುವ-ಕರೆ ಪ್ರತಿಕ್ರಿಯೆ ಸ್ಕೀಮಾ ದೊಂದಿಗೆ ನಿಖರವಾಗಿ ಹೊಂದಿಕೆಯಾಗುತ್ತದೆ. ಸಾಮಾನ್ಯವಾಗಿ ಬಳಸುವ ಫೀಲ್ಡ್‌ಗಳು:

ಫೀಲ್ಡ್ಪ್ರಕಾರವಿವರಣೆ
promptಸ್ಟ್ರಿಂಗ್ (ಅಗತ್ಯವಿದೆ)ಏಜೆಂಟ್‌ಗಾಗಿ ಸಿಸ್ಟಮ್ prompt
voiceಸ್ಟ್ರಿಂಗ್ (ಅಗತ್ಯವಿದೆ)GET /v1/voices ನಿಂದ ಧ್ವನಿ ID
productಸ್ಟ್ರಿಂಗ್ಡೀಫಾಲ್ಟ್ ಆಗಿ spark
background_trackಸ್ಟ್ರಿಂಗ್ | nullಸುತ್ತಮುತ್ತಲಿನ ಆಡಿಯೊ ID
acknowledgement_prompt_modeಸ್ಟ್ರಿಂಗ್auto ಅಥವಾ manual (ಅಂಗೀಕಾರವಿರುವ Storm ಗೆ ಮಾತ್ರ)
acknowledgement_promptಸ್ಟ್ರಿಂಗ್ಮೋಡ್ manual ಆಗಿರುವಾಗ ಅಗತ್ಯವಿದೆ
toolsಅರೇಇನ್‌ಲೈನ್ ಕಾರ್ಯ-ಉಪಕರಣ ಸ್ಕೀಮಾಗಳು — ನೋಡಿ ಕಾರ್ಯ ಉಪಕರಣಗಳು

ಮಾದರಿಗಳು

ಲಾಗಿನ್ ಆಗಿರುವ ಬಳಕೆದಾರರ ಸಂದರ್ಭ

ವೆಬ್‌ಹುಕ್-ಮೋಡ್ ವಿಜೆಟ್‌ಗಳಲ್ಲಿ, ಸಂದರ್ಶಕರ ಪುಟಕ್ಕೆ ಅವರು ಯಾರೆಂದು ಈಗಾಗಲೇ ತಿಳಿದಿರುತ್ತದೆ. ವಿಜೆಟ್ 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() ಮೇಲೆ ಸರಳ ಸ್ವಿಚ್ ಬಳಸಿ.


ಮುಂದಿನ ಹಂತಗಳು