ThunderPhone 2.0 jest już dostępny.Uruchom samodzielnie, od 2¢/min.Przeczytaj komunikat

Developer cookbook

Zbuduj integrację narzędzia (API)

Pozwól swojemu agentowi wywoływać interfejsy API w trakcie rozmowy — przeszukiwać bazę danych, tworzyć zgłoszenia, sprawdzać zamówienia.

integracja narzędzia to wielokrotnego użytku punkt końcowy HTTP, który agent może wywołać podczas rozmowy. Przekazujesz ThunderPhone opis narzędzia w schemacie JSON oraz adres URL punktu końcowego; agent decyduje, kiedy je wywołać, na podstawie rozmowy, a ThunderPhone wysyła wychodzące żądanie HTTP ze swoich serwerów i zwraca odpowiedź agentowi.

Ten przewodnik przedstawia kompleksowe tworzenie narzędzia do sprawdzania pogody.

Elementy narzędzia

Dwa elementy:

  1. Schemat — definicja funkcji w stylu OpenAI ({type: "function", function: {name, description, parameters}}), która informuje LLM, co robi narzędzie i jakie argumenty przyjmuje.
  2. Punkt końcowy — adres URL, który serwery ThunderPhone wywołują, gdy LLM zdecyduje się użyć narzędzia. Żądanie jest żądaniem JSON POST z argumentami wybranymi przez LLM w treści.

1. Wybierz edytor

Panel

Otwórz Połączenia → API, utwórz lub edytuj połączenie API, przełącz edytor parametrów na JSON i dodaj tam format.

API integracji

Utwórz specyfikację za pomocą POST /v1/integrations lub zaktualizuj ją za pomocą PATCH /v1/integrations/{id}.

Obie ścieżki tworzą zapisaną integrację. Po zapisaniu przypisz tę integrację do agenta. API agentów nie ma zapisywalnego wbudowanego pola tools. Ten przewodnik korzysta ze ścieżki API integracji.

2. Utwórz integrację

curl -X POST https://api.thunderphone.com/v1/integrations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Weather API",
    "spec": {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a zip code.",
        "parameters": {
          "type": "object",
          "properties": {
            "zip": { "type": "string", "description": "5-digit US ZIP code" }
          },
          "required": ["zip"]
        }
      }
    },
    "endpoint_url":    "https://api.example.com/weather",
    "endpoint_method": "GET",
    "headers": [
      { "key": "X-Api-Key", "value": "your-provider-key" }
    ]
  }'

Zapisz zwrócone id (UUID). Wartości nagłówków są tylko do zapisu: odpowiedzi zawierają wyłącznie nazwy nagłówków, a późniejszy PATCH może wysłać nagłówek bez value, aby zachować zapisaną wartość.

Zadeklaruj format: "email" dla parametrów adresu e-mail

Parametr, który otrzymuje adres e-mail, powinien to określać w swoim schemacie:

"email": { "type": "string", "format": "email", "description": "The caller's email address" }

format to więcej niż wskazówka. W przypadku rozpoznanego schematu e-mail, zanim zostanie wywołany punkt końcowy, ThunderPhone usuwa spacje z początku i końca wartości, zamienia domenę na małe litery, przekształca samodzielne angielskie słowa at, dot, underscore, dash i hyphen w odpowiadające im znaki oraz usuwa białe znaki bezpośrednio wokół @, ., _ i -. Słowa mają to samo znaczenie, niezależnie od tego, czy transkrypcja zawiera już dosłowny znak @: "john dot smith at gmail dot com" staje się john.smith@gmail.com.

Wszelkie inne wewnętrzne białe znaki są odrzucane, zamiast być po cichu łączone. Wypowiadane słowa separatorów są obsługiwane wyłącznie w języku angielskim; nieangielskie lub nierozpoznane formy ze spacjami są bezpiecznie odrzucane. Prawidłowe umiędzynarodowione domeny i części lokalne SMTPUTF8 są akceptowane. Dane wejściowe Punycode pozostają Punycode, a dane wejściowe domen Unicode pozostają Unicode po normalizacji parsera, więc API otrzymuje konwencjonalną reprezentację podaną przez rozmówcę. Jeśli końcowa wartość jest nieprawidłowa, narzędzie nie jest wywoływane. Agent otrzymuje invalid_email_argument, informujące go, aby potwierdził pisownię z rozmówcą i ponownie wysłał dosłowny adres.

Pominięty opcjonalny adres e-mail pozostaje bez zmian. null, pusty ciąg lub ciąg zawierający wyłącznie białe znaki również pozostają bez zmian, gdy właściwość jest opcjonalna lub dopuszcza wartość null; te same wartości są odrzucane w przypadku wymaganego adresu e-mail niedopuszczającego wartości null.

Lokalne odwołania do schematu, takie jak #/$defs/email i #/definitions/email, a także anyOf, oneOf i allOf, są sprawdzane z limitami cykli i głębokości. Nielokalne lub nierozwiązywalne $ref stanowi znane ograniczenie egzekwowania i jest przekazywane bez zmian, podobnie jak wywołanie, którego migawka narzędzia nie zawiera użytecznego schematu. Zachowaj lokalność schematów e-mail, gdy potrzebujesz zastosowania tej kontroli.

Parametry bez egzekwowanego formatu e-mail są przekazywane dokładnie w postaci wygenerowanej przez model.

Obsługiwane formaty to date-time, time, date, duration, email, hostname, ipv4, ipv6 i uuid; obecnie tylko email jest normalizowany i egzekwowany.

3. Przetestuj punkt końcowy w piaskownicy

Zanim połączysz integrację z agentem, wyślij podpisane żądanie z serwerów ThunderPhone, aby potwierdzić łączność:

curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url":    "https://api.example.com/weather?zip=94110",
    "method": "GET",
    "headers": { "X-Api-Key": "your-provider-key" }
  }'
Response
{
  "ok": true,
  "status": 200,
  "elapsed_ms": 187,
  "response_headers": { "content-type": "application/json" },
  "response_preview": "{\"temperature_f\": 64, ...}"
}

Ten test wzmacnia również zabezpieczenia ThunderPhone przed SSRF — żądania do localhost lub prywatnych zakresów IP zwracają 400 code=url_not_allowed.

4. Połącz integrację z agentem

Dołącz za pomocą integration_ids podczas tworzenia lub aktualizowania agenta:

curl -X PATCH https://api.thunderphone.com/v1/agents/12 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "integration_ids": ["f9b5a1a4-..."]
  }'

Z jednym agentem możesz połączyć wiele integracji. Prompt agenta może odwoływać się do nich po nazwie — „użyj get_weather, gdy rozmówca pyta o warunki pogodowe” — albo może wykrywać je niejawnie na podstawie opisów schematu.

5. Zaimplementuj punkt końcowy

Gdy agent wywołuje narzędzie, ThunderPhone wysyła podpisane żądanie POST do Twojego endpoint_url:

POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<HMAC-SHA256 hex>
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json

{"zip": "94110"}

Twój serwer odpowiada JSON-em, który jest przekazywany z powrotem do LLM:

{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}

LLM przetwarza tę odpowiedź i przekazuje rozmówcy podsumowanie w naturalnym języku.

6. Przetestuj cały przepływ

Uruchom sesję mikrofonową z agentem i zadaj pytanie obsługiwane przez Twoje narzędzie („Jaka jest pogoda w 94110?”). Transkrypcja połączenia pokazuje pełny cykl:

{
  "call_id": 987654321,
  "transcripts": [
    { "role": "user",
      "content": "What's the weather in 94110?" },
    { "role": "tool_call",
      "content": "{\"tool_call\": \"get_weather\", \"arguments\": {\"zip\": \"94110\"}}" },
    { "role": "tool_response",
      "content": "{\"tool_name\": \"get_weather\", \"response\": {\"temperature_f\": 64, \"condition\": \"Partly cloudy\"}}" },
    { "role": "agent",
      "content": "It's 64 degrees and partly cloudy." }
  ]
}

Możesz pobrać ją za pomocą GET /v1/calls/{call_id}/transcript; surowy strumień zdarzeń (z czasem dla każdego wpisu i przesunięciami audio) znajduje się pod GET /v1/calls/{call_id}/history.

W widokach list połączeń i analiz ThunderPhone raportuje teraz połączenia testowe oddzielnie od rzeczywistego ruchu. Testy i symulacje Browser Talk mogą ponownie używać prawdziwego numeru telefonu i mogą wyglądać jak połączenia przychodzące, ale nie są uwzględniane w łącznej liczbie połączeń produkcyjnych, ocenach ani wskaźnikach problemów.

Typowe pułapki

Agent nigdy nie wywołuje narzędzia

LLM podejmuje decyzję na podstawie opisu narzędzia. Jeśli pytanie rozmówcy nie odpowiada opisowi, model nie wywoła narzędzia. Doprecyzuj opis (dodaj popularne synonimy i sformułowania) albo wspomnij o nim wyraźnie w prompcie agenta („Gdy rozmówca pyta o pogodę, użyj get_weather.”).

Narzędzie zwraca zbyt dużo danych

Odpowiedzi większe niż 6 kB są obcinane w podglądzie transkrypcji. Zwracaj tylko pola potrzebne LLM — nie cały rekord.

Limity czasu

Punkty końcowe narzędzi mają domyślny limit czasu 10 sekund. Jeśli potrzebujesz więcej czasu, obsłuż to asynchronicznie: zwróć {"status": "pending", "request_id": "..."} i udostępnij wynik przez osobne wywołanie narzędzia.

Wersjonowanie

Każde żądanie PATCH integracji tworzy nową rewizję. Sprawdź GET /v1/integrations/{id}/versions, aby zobaczyć, kto co zmienił. Jeśli uszkodzisz schemat narzędzia, możesz ręcznie przywrócić wcześniejszą wersję, wykonując PATCH ze starszym zrzutem.


Kolejne kroki