Nástroje funkcií

Funkčné nástroje umožňujú vašim agentom AI počas telefonátov vyvolávať externé API. Použite ich na vyhľadávanie údajov o zákazníkoch, kontrolu dostupnosti, rezerváciu termínov alebo vykonanie ľubovoľnej akcie, ktorú váš backend podporuje.

Ako to funguje

  1. Definujete nástroje so schémou (aké argumenty nástroj prijíma)
  2. Poskytnete konfiguráciu endpoint (kam ThunderPhone volá vaše API) — alebo ju vynecháte, aby ste volania nástrojov prijímali na webhooku svojej organizácie
  3. Počas hovoru sa AI podľa konverzácie rozhodne, kedy použiť nástroj
  4. ThunderPhone zavolá váš endpoint s argumentmi nástroja
  5. Odpoveď vášho API sa odošle späť AI, aby mohla pokračovať v konverzácii

Schéma nástroja

Každý nástroj má túto štruktúru:

{
  "type": "function",
  "function": {
    "name": "search_appointments",
    "description": "Find available appointment slots for a given date",
    "parameters": {
      "type": "object",
      "properties": {
        "date": {
          "type": "string",
          "description": "Date in YYYY-MM-DD format"
        },
        "service": {
          "type": "string",
          "description": "Type of service (e.g., 'consultation', 'follow-up')"
        }
      },
      "required": ["date"]
    }
  },
  "endpoint": {
    "url": "https://api.example.com/appointments/search",
    "method": "POST",
    "headers": {
      "X-Api-Key": "your-api-key"
    }
  }
}

Definícia funkcie

PoleTypPovinnéPopis
namereťazecÁnoJedinečný identifikátor nástroja
descriptionreťazecÁnoVysvetľuje AI, kedy má tento nástroj použiť
parametersobjektÁnoSchéma JSON pre argumenty nástroja

Konfigurácia endpointu

PoleTypPovinnéPopis
urlreťazecÁnoURL endpointu vášho API
methodreťazecNieMetóda HTTP (predvolené: POST)
headersobjektNieVlastné hlavičky, ktoré sa majú zahrnúť

Dve cesty vyvolania

To, akú požiadavku váš server prijme, závisí od toho, či má nástroj endpoint:

Nástroj s endpointNástroj bez endpoint
Kam požiadavka smerujePriamo na endpoint.urlNa staršiu URL webhooku vašej organizácie
TeloSamotné argumenty nástrojaObálka telephony.tool / web.tool
HlavičkyVaše endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature
Podpisovací kľúčTajný kľúč webhooku organizácieTajný kľúč webhooku organizácie

Obe cesty sú blokujúce — AI uprostred vety čaká na výsledok — s časovým limitom 20 s. Obslužné rutiny udržiavajte rýchle. Kombinovanie je v poriadku: pri hovore, ktorého organizácia má URL webhooku, sa nástroje s endpoint volajú priamo a ostatné sa vrátia k webhooku.

Priame volania endpointov

Keď AI vyvolá nástroj, ktorý má endpoint, ThunderPhone odošle požiadavku na vašu URL:

Hlavičky požiadavky

POST /appointments/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-ThunderPhone-Signature: abc123...
X-ThunderPhone-Call-ID: 987654321
X-Api-Key: your-api-key

Vlastné hlavičky z vášho endpoint.headers sú vždy zahrnuté doslovne spolu s dvoma hlavičkami v mennom priestore ThunderPhone:

Content-Type: application/json sa nastaví, pokiaľ ho váš endpoint.headers neprepíše — vlastný Content-Type má prednosť.

Telo požiadavky

Pre POST / PUT / PATCH telo obsahuje iba argumenty nástroja (bez obalu), serializované kanonicky (zoradené kľúče, kompaktné oddeľovače):

{"date":"2025-01-02","service":"consultation"}

Pre GET / DELETE sa argumenty odosielajú ako parametre dotazu a telo je prázdne — podpis sa potom vypočíta nad prázdnym bajtovým reťazcom. Pozrite si Overenie podpisov webhookov.

Odpoveď

Vráťte odpoveď JSON s výsledkom nástroja:

{
  "available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
  "timezone": "America/Los_Angeles"
}

Odpoveď sa naformátuje a poskytne AI na pokračovanie konverzácie. Odpovede, ktoré nie sú vo formáte JSON, sa zabalia ako {"data": "<text>"}; časové limity a zlyhania pripojenia sa AI hlásia ako chyby, takže sa agent môže ospravedlniť a pokračovať namiesto zaseknutia.

Odosielanie v režime webhooku

Nástroje bez endpoint sa odosielajú na staršiu URL webhooku vašej organizácie ako podpísaná požiadavka telephony.tool (telefonické hovory) alebo web.tool (webové hovory). Na rozdiel od notifikácií auditu, ktoré sa doručujú na endpointy webhookov po vykonaní, táto požiadavka je vykonaním — vaša odpoveď HTTP je výsledkom nástroja.

{
  "type": "telephony.tool",
  "data": {
    "call_id": 987654321,
    "tool_name": "search_appointments",
    "arguments": { "date": "2026-04-21" },
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  }
}

web.tool obsahuje origin_domain namiesto from_number / to_number. Odpovedzte výsledkom nástroja vo formáte JSON — platí rovnaký kontrakt odpovede ako pri priamych volaniach endpointov. Požiadavka je podpísaná tajným kľúčom webhooku organizácie nad nespracovaným telom, rovnako ako každý iný webhook.


Overovanie podpisu

Priame volania nástrojov sa podpisujú rovnako ako webhooky:

import hmac
import hashlib

def verify_tool_call(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.post("/appointments/search")
async def search_appointments(request: Request):
    body = await request.body()
    signature = request.headers.get("X-ThunderPhone-Signature", "")

    if not verify_tool_call(body, signature, WEBHOOK_SECRET):
        raise HTTPException(status_code=401)

    data = json.loads(body)
    date = data["date"]

    # Look up availability
    slots = await get_available_slots(date)

    return {"available_slots": slots}
app.post('/appointments/search', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-thunderphone-signature'] || '';
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');

  if (!signature ||
      signature.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
    return res.status(401).send('Invalid signature');
  }

  const { date, service } = JSON.parse(req.body);

  // Look up availability
  const slots = getAvailableSlots(date, service);

  res.json({ available_slots: slots });
});

Úplné postupy — vrátane prípadu s prázdnym telom a upozornenia pri chýbajúcom tajnom kľúči — nájdete v časti Overenie podpisov webhookov.


Príklad: Kompletný proces rezervácie

Tu je súprava nástrojov pre kompletný systém rezervácie termínov:

{
  "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": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "book_appointment",
        "description": "Book an appointment at a specific time",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "time": { "type": "string", "description": "HH:MM format" },
            "customer_name": { "type": "string" },
            "customer_phone": { "type": "string" }
          },
          "required": ["date", "time", "customer_name"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/book",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "cancel_appointment",
        "description": "Cancel an existing appointment",
        "parameters": {
          "type": "object",
          "properties": {
            "confirmation_number": { "type": "string" }
          },
          "required": ["confirmation_number"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/cancel",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    }
  ]
}

Odporúčané postupy

Píšte jasné popisy

Pole description pomáha AI pochopiť, kedy má nástroj použiť. Jasne uveďte, čo nástroj robí a kedy je vhodné ho použiť.

Správne spracúvajte chyby

Vrátťe chybové hlásenia, ktorým AI rozumie: {"error": "No slots available for that date"} namiesto všeobecných chýb 500.

Odpovede udržiavajte stručné

Vrátťe len to, čo AI potrebuje na pokračovanie v konverzácii. Veľké dátové objemy spomaľujú čas odozvy.

Povinné polia používajte uvážlivo

Polia označte ako required len vtedy, keď je to skutočne nevyhnutné. AI pred volaním nástroja požiada používateľa o povinné informácie.


Súvisiace