ThunderPhone 2.0 er lansert.Kom i gang selv – fra 2¢/min.Les mer om lanseringen

Developer cookbook

Bygg en verktøyintegrasjon (API)

La stemmeagenten din kalle API-ene dine midt i en samtale – søk i en database, opprett en sak, slå opp en bestilling.

En verktøyintegrasjon er et gjenbrukbart HTTP-endepunkt som en agent kan kalle under en samtale. Du gir ThunderPhone en JSON-skjemabeskrivelse av verktøyet sammen med en endepunkt-URL; agenten avgjør når den skal kalle det basert på samtalen, og ThunderPhone utfører den utgående HTTP- forespørselen fra sine servere og returnerer svaret til agenten.

Denne veiledningen går gjennom hvordan du bygger et verktøy for værslag opp fra start til slutt.

Oppbygningen av et verktøy

To deler:

  1. Skjemaet — en funksjonsdefinisjon i OpenAI-stil ({type: "function", function: {name, description, parameters}}) som forteller LLM-en hva verktøyet gjør og hvilke argumenter det tar.
  2. Endepunktet — URL-en som ThunderPhone-serverne kaller når LLM-en bestemmer seg for å bruke verktøyet. Forespørselen er en JSON POST med argumentene LLM-en har valgt som forespørselskropp.

1. Velg en redigerer

Dashbord

Åpne Tilkoblinger → API-er, opprett eller rediger API-tilkoblingen, bytt parameterredigereren til JSON, og legg til formatet der.

Integrasjons-API

Opprett spesifikasjonen med POST /v1/integrations, eller oppdater den med PATCH /v1/integrations/{id}.

Begge alternativene oppretter en lagret integrasjon. Knytt integrasjonen til agenten etter at du har lagret den. Agents API har ikke et skrivbart innebygd tools -felt. Denne veiledningen bruker integrasjons-API-veien.

2. Opprett integrasjonen

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

Lagre den returnerte id-en (en UUID). Headerværdier er bare skrivbare: svar viser bare headernavn, og en senere PATCH kan sende en header uten en value for å beholde den lagrede verdien.

Angi format: "email" for adresseparametere

En parameter som mottar en e-postadresse, bør angi dette i skjemaet sitt:

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

format er mer enn et hint. For et løst e-postskjema, før endepunktet ditt kalles, trimmer ThunderPhone verdien, gjør domenet om til små bokstaver, konverterer de frittstående engelske ordene at, dot, underscore, dash og hyphen til tegnene sine, og fjerner mellomrom rett rundt @, ., _ og -. Ordene har samme betydning uansett om transkripsjonen allerede inneholder en bokstavelig @: "john dot smith at gmail dot com" blir til john.smith@gmail.com.

Andre interne mellomrom avvises i stedet for å bli slått sammen i stillhet. Talte skilletegnord er kun på engelsk; ikke-engelske eller ugjenkjente mellomromsdelte former avvises. Gyldige internasjonaliserte domener og SMTPUTF8- lokaldeler godtas. Punycode-inndata forblir punycode, og Unicode-domeneinndata forblir Unicode etter parsernormalisering, slik at API-et ditt mottar den vanlige representasjonen som innringeren oppga. Hvis den endelige verdien er ugyldig, blir verktøyet ikke kalt. Stemmeagenten mottar invalid_email_argument, som ber den bekrefte stavemåten med innringeren og sende den bokstavelige adressen på nytt.

En utelatt valgfri e-postadresse forblir urørt. null, en tom streng eller en streng som bare inneholder mellomrom, forblir også urørt når egenskapen er valgfri eller kan være null; de samme verdiene avvises for en obligatorisk e-postadresse som ikke kan være null.

Lokale skjemareferanser som #/$defs/email og #/definitions/email, samt anyOf, oneOf og allOf, inspiseres med grenser for sykluser og dybde. En ikke-lokal eller uløselig $ref er en kjent begrensning i håndhevingen og sendes videre uendret, det samme gjelder et kall der verktøyets øyeblikksbilde ikke har noe brukbart skjema. Hold e-postskjemaer lokale når du trenger at kontrollen skal gjelde.

Parametere uten et håndhevet e-postformat sendes videre nøyaktig slik modellen produserte dem.

Støttede formater er date-time, time, date, duration, email, hostname, ipv4, ipv6 og uuid; bare email normaliseres og håndheves i dag.

3. Sandbox-test endepunktet

Før du kobler integrasjonen til en stemmeagent, sender du en signert forespørsel fra ThunderPhone-serverne for å bekrefte tilkoblingen:

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, ...}"
}

Denne testen styrker også ThunderPhones SSRF-beskyttelse — forespørsler til localhost eller private IP-områder returnerer 400 code=url_not_allowed.

4. Knytt integrasjonen til en agent

Knytt den til via integration_ids når du oppretter eller oppdaterer en agent:

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-..."]
  }'

Du kan knytte mange integrasjoner til én agent. Agentens prompt kan referere til dem ved navn — «bruk get_weather når innringeren spør om forhold» — eller den kan oppdage dem implisitt fra skjemabeskrivelsene.

5. Implementer endepunktet

Når agenten bruker verktøyet, sender ThunderPhone en signert POST til din 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"}

Serveren din svarer med JSON som sendes tilbake til LLM-en:

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

LLM-en tar inn svaret og gir innringeren en menneskelig oppsummering.

6. Test flyten

Kjør en mikrofonøkt mot agenten og still spørsmålet verktøyet ditt håndterer («Hvordan er været i 94110?»). Samtalens transkripsjon viser hele forespørselsrunden:

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

Du kan hente dette via GET /v1/calls/{call_id}/transcript; den rå hendelsesstrømmen (med tidsangivelse per oppføring og lydforskyvninger) finnes på GET /v1/calls/{call_id}/history.

I samtaleoversikter og analyseflater rapporterer ThunderPhone nå testsamtaler separat fra reell trafikk. Tester og simuleringer i Browser Talk kan gjenbruke et ekte telefonnummer og kan se ut som innkommende samtaler, men de teller ikke med i produksjonens samtaletotaler, vurderinger eller problemstatistikk.

Vanlige fallgruver

Agenten bruker aldri verktøyet

LLM-en avgjør basert på verktøyets beskrivelse. Hvis innringerens spørsmål ikke samsvarer med beskrivelsen, bruker modellen ikke verktøyet. Gjør beskrivelsen mer presis (legg til vanlige synonymer og formuleringer), eller nevn det eksplisitt i agentens prompt («Når innringeren spør om vær, bruk get_weather.»).

Verktøyet returnerer for mye data

Svar over 6 kB blir avkortet i forhåndsvisningen av transkripsjonen. Returner bare feltene LLM-en trenger — ikke hele raden.

Tidsavbrudd

Verktøyendepunkter har en standard tidsavbruddsgrense på 10 sekunder. Hvis du trenger lengre tid, håndter det asynkront: returner {"status": "pending", "request_id": "..."} og vis resultatet via et separat verktøykall.

Versjonering

Hver PATCH av en integrasjon oppretter en ny revisjon. Se på GET /v1/integrations/{id}/versions for å se hvem som endret hva. Hvis du ødelegger et verktøys skjema, kan du rulle tilbake manuelt ved å PATCH-e et eldre øyeblikksbilde tilbake.


Neste trinn