ThunderPhone 2.0 yayında.Hemen kendiniz kullanmaya başlayın; dakikası 2 sentten başlayan fiyatlarla.Duyuruyu okuyun

Function Tools

Fonksiyon Araçları

Yapay zeka ajanlarınıza, konuşma sırasında harici API

Fonksiyon araçları, yapay zeka ajanlarınızın telefon görüşmeleri sırasında harici API'leri çağırmasına olanak tanır. Bunları müşteri verilerini sorgulamak, uygunluk durumunu kontrol etmek, randevu oluşturmak veya arka ucunuzun desteklediği herhangi bir işlemi gerçekleştirmek için kullanın.

Nasıl Çalışır

  1. Araçları bir şemayla tanımlarsınız (aracın kabul ettiği bağımsız değişkenler)
  2. Bir endpoint yapılandırması sağlarsınız (ThunderPhone'un API'nizi çağırdığı yer) veya araç çağrılarını kuruluş webhook'unuzda almak için bunu boş bırakırsınız
  3. Görüşme sırasında yapay zeka, konuşmaya göre bir aracı ne zaman kullanacağına karar verir
  4. ThunderPhone, araç bağımsız değişkenleriyle endpoint'inizi çağırır
  5. API yanıtınız, konuşmayı sürdürmesi için yapay zekaya geri iletilir
ÖzellikÇalıştığı yerKurulum
Yerleşik araçlarThunderPhoneİstem talimatları; bazı araçlar ayrıca bir ajan ayarı gerektirir
Uygulama bağlantılarıThunderPhone ve bağlı sağlayıcıHesabı bağlayın ve onaylanmış eylemleri ekleyin
API bağlantıları ve fonksiyon araçlarıHTTP API'nizEndpoint'i ve şemayı tanımlayın veya fonksiyon çağrılarını webhook üzerinden alın
MCP sunucularıUzak bir MCP sunucusuSunucuyu ekleyin, araçlarını keşfedin ve ajana ekleyin

Araç Şeması

Her araç şu yapıyı izler:

{
  "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"
    }
  },
  "timeout": 120
}

Araç Yapılandırması

AlanTürZorunluAçıklama
timeoutsayıHayırSaniye cinsinden maksimum yürütme süresi (varsayılan: 20, maksimum: 180)

Fonksiyon Tanımı

AlanTürZorunluAçıklama
namedizeEvetAraç için benzersiz tanımlayıcı
descriptiondizeEvetYapay zekaya bu aracı ne zaman kullanacağını açıklar
parametersnesneEvetAraç bağımsız değişkenleri için JSON Şeması

Endpoint Yapılandırması

AlanTürZorunluAçıklama
urldizeEvetAPI endpoint URL'niz
methoddizeHayırHTTP yöntemi (varsayılan: POST)
headersnesneHayırEklenecek özel üst bilgiler

İki çağırma yolu

Sunucunuzun aldığı istek, aracın bir endpoint değerine sahip olup olmamasına bağlıdır:

endpoint olan araçendpoint olmayan araç
İsteğin gönderildiği yerDoğrudan endpoint.urlKuruluşunuzun eski webhook URL'si
GövdeSeçilen istek biçimi (varsayılan olarak yalın bağımsız değişkenler)telephony.tool / web.tool zarfı
Başlıklarendpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature-V2 + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature-V2 + X-ThunderPhone-Signature
İmzalama anahtarıKuruluş webhook gizli anahtarıKuruluş webhook gizli anahtarı

Her iki yol da bloklayıcıdır — yapay zeka, cümlenin ortasında sonucu bekler. Varsayılan zaman aşımı 20 s değeridir; daha uzun bir yürütmeye izin vermek için aracın üst düzey timeout değerini platformun 180 s olan maksimumuna kadar ayarlayın. İşleyicileri hızlı tutun. Karma kullanım uygundur: kuruluşunda webhook URL'si bulunan bir görüşmede, endpoint içeren araçlar doğrudan çağrılır ve diğerleri webhook'a geri döner.

Doğrudan uç nokta çağrıları

Yapay zeka bir endpoint içeren aracı çağırdığında ThunderPhone, URL'nize bir istek gönderir:

İstek Başlıkları

POST /appointments/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-ThunderPhone-Signature-V2: t=1767225600,v1=5f2c...
X-ThunderPhone-Signature: abc123...
X-ThunderPhone-Call-ID: 987654321
X-Api-Key: your-api-key

endpoint.headers içindeki özel üstbilgiler her zaman olduğu gibi aynen eklenir. Buna ek olarak şu ThunderPhone ad alanındaki üstbilgiler de eklenir:

  • X-ThunderPhone-Signature-V2 — yöntemi, yolu, sorguyu ve gövdeyi kapsayan, organizasyon webhook gizli anahtarınızla anahtarlanmış zaman damgalı HMAC-SHA256. Bunu doğrulayın ve 5 dakikadan eski istekleri reddedin; bkz. Webhook imzalarını doğrulama
  • X-ThunderPhone-Signature — tam istek gövdesi baytlarının eski HMAC-SHA256 değeri; aynı anahtarı kullanır ve mevcut doğrulayıcılar için gönderilmeye devam eder
  • X-ThunderPhone-Call-ID — Geçerli arama kimliği

endpoint.headers bunu geçersiz kılmadığı sürece Content-Type: application/json ayarlanır — özel bir Content-Type önceliklidir.

İstek biçimi

Her API bağlantısının bir request_format ayarı vardır. İçe aktarılan bir aracın o platform için oluşturulmuş bir uç noktayı çağırmayı sürdürmesi gerektiğinde vapi veya retell seçin. Yeni ve mevcut bağlantılar varsayılan olarak standard kullanır.

POST / PUT / PATCH için ThunderPhone, seçilen zarfı standart biçimde serileştirir (anahtarlar sıralanır, ayırıcılar sıkıştırılır). Her iki imza da tam olarak bu baytları kapsar.

Standard

standard, sarmalayıcı olmadan yalnızca araç bağımsız değişkenlerini gönderir. Bu varsayılandır ve ThunderPhone'un orijinal istek gövdesini bayt bayt korur:

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

Vapi

vapi, Vapi'nin özel araçlar için belgelediği biçimde Vapi'nin tool-calls sunucu mesajını gönderir. call.id, ThunderPhone arama kimliğidir. Araç çağrısı id değeri çağrıya özeldir ve uç noktanın sonucuyla eşleştirmek için yeniden kullanılır. Arama, function.arguments bir JSON nesnesi olacak şekilde hem toolCallList hem de toolWithToolCallList içinde görünür:

{
  "message": {
    "type": "tool-calls",
    "timestamp": 1725000000123,
    "call": { "id": "987654321" },
    "toolCallList": [
      {
        "id": "call_00112233445566778899aabbccddeeff",
        "type": "function",
        "function": {
          "name": "search_appointments",
          "arguments": { "date": "2025-01-02", "service": "consultation" }
        }
      }
    ],
    "toolWithToolCallList": [
      {
        "type": "function",
        "function": { "name": "search_appointments" },
        "toolCall": {
          "id": "call_00112233445566778899aabbccddeeff",
          "type": "function",
          "function": {
            "name": "search_appointments",
            "arguments": { "date": "2025-01-02", "service": "consultation" }
          }
        }
      }
    ]
  }
}

assistant, artifact ve tam call nesnesi gibi yalnızca Vapi'ye özgü alanlar gönderilmez.

Eşleşen araç çağrısı kimliğiyle Vapi'nin yanıt zarfını döndürün:

{
  "results": [
    {
      "toolCallId": "call_00112233445566778899aabbccddeeff",
      "result": "{\"available_slots\":[\"9:00 AM\",\"2:00 PM\"]}"
    }
  ]
}

ThunderPhone, AI'a sarmalayıcısı kaldırılmış result dizesini verir. Ayrıca, zaten JSON değeri döndüren uç noktalarla uyumluluk için JSON değeri de kabul eder. result yerine bir error değeri, AI'a araç hatası olarak döndürülür. Uç nokta hatalı biçimlendirilmiş veya eşleşmeyen bir Vapi zarfı döndürürse ThunderPhone bir uyarı günlüğe kaydeder ve aramayı başarısız kılmak yerine standart yanıt ayrıştırmasına geri döner.

Retell

retell, bir Retell özel işlevi için belgelenen isteği gönderir:

{
  "name": "search_appointments",
  "call": { "call_id": "987654321" },
  "args": { "date": "2025-01-02", "service": "consultation" }
}

call nesnesi yalnızca call_id içerir. ThunderPhone, gönderim sırasında güvenilir biçimde sağlayamadığı agent_id, transcript, transcript_object, metadata veya dinamik değişkenler gibi Retell'e özgü alanları içermez. Retell herhangi bir yanıt gövdesini kabul eder; ThunderPhone bunu standart yanıt işleme yöntemiyle iletir.

GET / DELETE için bağımsız değişkenler sorgu parametreleri olarak gönderilir ve request_format ne olursa olsun gövde boştur. V2 imzası, gönderildiği şekliyle sorgu dizesini kapsar; eski imza boş bayt dizesi üzerinden hesaplanır. Bkz. Webhook imzalarını doğrulama.

Yanıt

Araç sonucunu içeren bir JSON yanıtı döndürün:

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

Yanıt biçimlendirilir ve görüşmeye devam etmesi için yapay zekaya sağlanır. JSON olmayan yanıtlar {"data": "<text>"} olarak sarmalanır; zaman aşımları ve bağlantı hataları yapay zekaya hata olarak bildirilir, böylece yapay zeka ajanı takılıp kalmak yerine özür dileyip devam edebilir.

Webhook modu yönlendirmesi

endpoint içermeyen araçlar, kuruluşunuzun eski webhook URL'sine imzalı bir telephony.tool (telefon çağrıları) veya web.tool (web çağrıları) isteği olarak yönlendirilir. Yürütmeden sonra webhook uç noktalarına gönderilen denetim bildirimlerinden farklı olarak, bu istek yürütmenin kendisidir — HTTP yanıtınız araç sonucudur.

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

web.tool, from_number / to_number yerine origin_domain içerir. Araç sonucuyla JSON olarak yanıt verin — doğrudan endpoint çağrılarıyla aynı yanıt sözleşmesi geçerlidir. İstek, diğer tüm webhook'lar gibi her iki imza başlığıyla kuruluş webhook gizli anahtarı kullanılarak imzalanır.


İmza Doğrulama

Doğrudan araç çağrıları, kuruluşunuzun webhook gizli anahtarıyla webhooks'larla aynı şekilde imzalanır:

  • X-ThunderPhone-Signature-V2, gönderildiği şekliyle zaman damgasını, yöntemi, yolu ve sorguyu ve gövdenin tam baytlarını imzalar. Zaman damgası saatinizden 5 dakikadan fazla farklı olan istekleri reddedin.
  • X-ThunderPhone-Signature (eski), GET / DELETE için boş bayt dizisi olmak üzere yalnızca gövde baytlarını imzalar. Değiştirilmeden gönderilmeye devam eder.

SDK yardımcıları, 5 dakikalık süre penceresi dahil olmak üzere V2 başlığını kontrol eder:

Python
import json
 
from fastapi import FastAPI, HTTPException, Request
from thunderphone import verify_signature
 
app = FastAPI()
 
@app.post("/appointments/search")
async def search_appointments(request: Request):
    body = await request.body()
    query = request.scope.get("query_string", b"").decode("latin-1")
    path = request.url.path + (f"?{query}" if query else "")
 
    if not verify_signature(
        request.headers.get("X-ThunderPhone-Signature-V2"),
        secret=WEBHOOK_SECRET,
        method=request.method,
        path=path,
        body=body,
    ):
        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}
Node.js
import express from "express";
import { verifySignature } from "@thunderphone/sdk";
 
app.post('/appointments/search', express.raw({type: 'application/json'}), (req, res) => {
  const ok = verifySignature({
    header: req.header('X-ThunderPhone-Signature-V2'),
    secret: WEBHOOK_SECRET,
    method: req.method,
    path: req.originalUrl,
    body: req.body,
  });
  if (!ok) 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 });
});

İmzalı dize, işlenmiş örnek, SDK olmadan kod, GET / DELETE durumu ve gizli anahtar yoksa geçerli olan uyarı dahil tam tarifler Webhook imzalarını doğrulama bölümündedir.


Örnek: Eksiksiz Randevu Akışı

Eksiksiz bir randevu rezervasyon sistemi için araç seti aşağıdadır:

{
  "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" }
      }
    }
  ]
}

En İyi Uygulamalar

Açık açıklamalar yazın

description alanı, yapay zekanın aracı ne zaman kullanacağını anlamasına yardımcı olur. Aracın ne yaptığını ve ne zaman uygun olduğunu açıkça belirtin.

Hataları zarif bir şekilde yönetin

Genel 500 hataları yerine yapay zekanın anlayabileceği hata mesajları döndürün: {"error": "No slots available for that date"}.

Yanıtları kısa tutun

Yalnızca yapay zekanın konuşmayı sürdürmek için ihtiyaç duyduğu bilgileri döndürün. Büyük yükler yanıt sürelerini yavaşlatır.

Zorunlu alanları dikkatli kullanın

Alanları yalnızca gerçekten gerektiğinde required olarak işaretleyin. Yapay zeka, aracı çağırmadan önce kullanıcıdan zorunlu bilgileri ister.


İlgili