ThunderPhone 2.0 jest już dostępny.Uruchom samodzielnie — od 2 centów/min.Przeczytaj komunikat

Function Tools

Narzędzia funkcji

Wyposaż swoich agentów AI w narzędzia funkcji, które wywołują zewnętrzne interfejsy API w trakcie rozmowy — pobierają dane klientów, umawiają wizyty, aktualizują rekordy — z parametrami typowanymi.

Narzędzia funkcji umożliwiają Twoim agentom AI wywoływanie zewnętrznych interfejsów API podczas rozmów telefonicznych. Używaj ich do wyszukiwania danych klientów, sprawdzania dostępności, umawiania wizyt lub wykonywania dowolnych działań obsługiwanych przez Twój backend.

Jak to działa

  1. Definiujesz narzędzia za pomocą schematu (jakie argumenty narzędzie akceptuje)
  2. Podajesz konfigurację endpoint (gdzie ThunderPhone wywołuje Twoje API) — lub pomijasz ją, aby odbierać wywołania narzędzi na webhooku organizacji
  3. Podczas rozmowy AI decyduje, kiedy użyć narzędzia, na podstawie rozmowy
  4. ThunderPhone wywołuje Twój endpoint z argumentami narzędzia
  5. Odpowiedź Twojego API jest przekazywana z powrotem do AI, aby kontynuować rozmowę

Schemat narzędzia

Każde narzędzie ma następującą strukturę:

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

Konfiguracja narzędzia

PoleTypWymaganeOpis
timeoutliczbaNieMaksymalny czas wykonania w sekundach (domyślnie: 20, maksymalnie: 180)

Definicja funkcji

PoleTypWymaganeOpis
nameciąg znakówTakUnikalny identyfikator narzędzia
descriptionciąg znakówTakWyjaśnia AI, kiedy użyć tego narzędzia
parametersobiektTakSchemat JSON dla argumentów narzędzia

Konfiguracja endpointu

PoleTypWymaganeOpis
urlciąg znakówTakAdres URL endpointu Twojego API
methodciąg znakówNieMetoda HTTP (domyślnie: POST)
headersobiektNieNiestandardowe nagłówki do uwzględnienia

Dwie ścieżki wywołania

To, jakie żądanie otrzyma Twój serwer, zależy od tego, czy narzędzie ma endpoint:

Narzędzie z endpointNarzędzie bez endpoint
Dokąd trafia żądanieBezpośrednio do endpoint.urlNa starszy adres URL webhooka Twojej organizacji
TreśćSame argumenty narzędziaObwiednia telephony.tool / web.tool
NagłówkiTwoje endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature
Klucz podpisuSekret webhooka organizacjiSekret webhooka organizacji

Obie ścieżki są blokujące — AI czeka w środku zdania na wynik. Domyślny limit czasu wynosi 20 s; ustaw timeout na najwyższym poziomie narzędzia, aby zezwolić na dłuższe wykonanie, maksymalnie do limitu platformy wynoszącego 180 s. Zadbaj o szybkie działanie handlerów. Możesz używać obu: w rozmowie, której organizacja ma adres URL webhooka, narzędzia z endpoint są wywoływane bezpośrednio, a pozostałe korzystają z webhooka.

Bezpośrednie wywołania endpointów

Gdy AI wywołuje narzędzie z endpoint, ThunderPhone wysyła żądanie na Twój adres URL:

Nagłówki żądania

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

Niestandardowe nagłówki z endpoint.headers są zawsze dołączane dosłownie, wraz z dwoma nagłówkami z przestrzeni nazw ThunderPhone:

  • X-ThunderPhone-Signature — HMAC-SHA256 dokładnych bajtów treści żądania, z kluczem będącym Twoim sekretem webhooka organizacji
  • X-ThunderPhone-Call-ID — ID bieżącego połączenia

Content-Type: application/json jest ustawiany, chyba że endpoint.headers go zastąpi — niestandardowy Content-Type ma pierwszeństwo.

Treść żądania

Dla POST / PUT / PATCH treść zawiera wyłącznie argumenty narzędzia (bez otoczki), serializowane kanonicznie (posortowane klucze, zwięzłe separatory):

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

Dla GET / DELETE argumenty są wysyłane jako parametry zapytania, a treść jest pusta — podpis jest wtedy obliczany na pustym ciągu bajtów. Zobacz Weryfikowanie podpisów webhooków.

Odpowiedź

Zwróć odpowiedź JSON z wynikiem narzędzia:

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

Odpowiedź jest formatowana i przekazywana AI, aby kontynuować rozmowę. Odpowiedzi inne niż JSON są opakowywane jako {"data": "<text>"}; przekroczenia czasu i błędy połączenia są zgłaszane AI jako błędy, dzięki czemu agent może przeprosić i przejść dalej zamiast się zatrzymać.

Dystrybucja w trybie webhooka

Narzędzia bez endpoint są kierowane na starszy adres URL webhooka Twojej organizacji jako podpisane żądanie telephony.tool (połączenia telefoniczne) lub web.tool (połączenia internetowe). W przeciwieństwie do powiadomień audytowych dostarczanych do endpointów webhooków po wykonaniu, to żądanie jest wykonaniem — Twoja odpowiedź HTTP stanowi wynik narzędzia.

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

web.tool zawiera origin_domain zamiast from_number / to_number. Odpowiedz wynikiem narzędzia jako JSON — obowiązuje ten sam kontrakt odpowiedzi co dla bezpośrednich wywołań endpointów. Żądanie jest podpisywane sekretem webhooka organizacji na podstawie nieprzetworzonej treści, tak jak każdy inny webhook.


Weryfikacja podpisu

Bezpośrednie wywołania narzędzi są podpisywane tak samo jak webhooki:

  • HMAC-SHA256 na dokładnych bajtach treści żądania (kanoniczny JSON — posortowane klucze, bez dodatkowych białych znaków)
  • Z użyciem sekretu webhooka organizacji
  • Narzędzia GET / DELETE podpisują pusty ciąg bajtów
Python
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}
Node.js
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 });
});

Pełne przykłady — w tym przypadek pustej treści oraz zastrzeżenie dotyczące braku sekretu — znajdziesz w sekcji Weryfikowanie podpisów webhooków.


Przykład: kompletny proces rezerwacji

Oto zestaw narzędzi dla kompletnego systemu rezerwacji wizyt:

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

Najlepsze praktyki

Pisz jasne opisy

Pole description pomaga AI zrozumieć, kiedy użyć narzędzia. Precyzyjnie określ, co robi i kiedy należy go użyć.

Odpowiednio obsługuj błędy

Zwracaj komunikaty o błędach, które AI może zrozumieć: {"error": "No slots available for that date"} zamiast ogólnych błędów 500.

Zachowuj zwięzłość odpowiedzi

Zwracaj tylko to, czego AI potrzebuje, aby kontynuować rozmowę. Duże ładunki danych spowalniają czas odpowiedzi.

Rozważnie używaj pól wymaganych

Oznaczaj pola jako required tylko wtedy, gdy jest to naprawdę konieczne. AI poprosi użytkownika o wymagane informacje przed wywołaniem narzędzia.


Powiązane