ThunderPhone 2.0 er lanceret.Selvbetjening fra 2 cent pr. minut.Læs mere om lanceringen

Developer cookbook

Byg en værktøjsintegration (API)

Lad din agent kalde dine API

En værktøjsintegration er et genanvendeligt HTTP-endepunkt, som en agent kan kalde under et opkald. Du giver ThunderPhone en JSON-skema-beskrivelse af værktøjet samt en endepunkt-URL; agenten afgør ud fra samtalen, hvornår det skal kaldes, og ThunderPhone foretager den udgående HTTP-anmodning fra sine servere og returnerer svaret til agenten.

Denne vejledning gennemgår opbygningen af et værktøj til vejr-opslag fra start til slut.

Et værktøjs opbygning

To dele:

  1. Skemaet — en funktionsdefinition i OpenAI-stil ({type: "function", function: {name, description, parameters}}) der fortæller LLM'en, hvad værktøjet gør, og hvilke argumenter det tager.
  2. Endepunktet — den URL, ThunderPhones servere kalder, når LLM'en beslutter at bruge værktøjet. Anmodningen er en JSON POST med LLM'ens valgte argumenter som brødtekst.

1. Vælg en editor

Dashboard

Åbn Forbindelser → API'er, opret eller rediger API-forbindelsen, skift parametereditoren til JSON, og tilføj formatet der.

Integrations-API

Opret specifikationen med POST /v1/integrations, eller opdater den med PATCH /v1/integrations/{id}.

Begge veje opretter en gemt integration. Tilknyt integrationen til agenten, når du har gemt den. Agents API'et har intet skrivbart indlejret tools- felt. Denne vejledning bruger integrations-API-ruten.

2. Opret integrationen

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

Gem det returnerede id (en UUID). Headerværdier er kun skrivbare: Svar viser kun headernavne, og en senere PATCH kan sende en header uden en value for at bevare den gemte værdi.

Angiv format: "email" på adresseparametre

En parameter, der modtager en e-mailadresse, skal angive det i sit skema:

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

format er mere end et hint. For et e-mailskema, der kan opløses, trimmer ThunderPhone værdien, skriver domænet med små bogstaver, ændrer de selvstændige engelske ord at, dot, underscore, dash og hyphen til deres tegn og fjerner mellemrum direkte omkring @, ., _ og -, før dit endepunkt kaldes. Ordene har samme betydning, uanset om transskriptionen allerede indeholder et bogstaveligt @: "john dot smith at gmail dot com" bliver til john.smith@gmail.com.

Alle andre interne mellemrum afvises i stedet for at blive sat sammen stiltiende. Talte separatorord er kun engelske; ikke-engelske eller ikke-genkendte former med mellemrum afvises sikkert. Gyldige internationaliserede domæner og SMTPUTF8-lokale dele accepteres. Punycode-input forbliver punycode, og Unicode-domæneinput forbliver Unicode efter parsernormalisering, så dit API modtager den konventionelle repræsentation, som opkalderen angav. Hvis den endelige værdi er ugyldig, bliver værktøjet ikke kaldt. Agenten modtager invalid_email_argument, som fortæller den, at den skal bekræfte stavningen med opkalderen og sende den bogstavelige adresse igen.

En udeladt valgfri e-mail er urørt. null, en tom streng eller en streng, der kun indeholder mellemrum, er også urørt, når egenskaben er valgfri eller kan være null; de samme værdier afvises for en påkrævet e-mail, der ikke kan være null.

Lokale skemareferencer som #/$defs/email og #/definitions/email samt anyOf, oneOf og allOf inspiceres med grænser for cyklusser og dybde. En ikke-lokal eller uopløselig $ref er en kendt begrænsning i håndhævelsen og sendes videre uændret, ligesom et kald, hvis værktøjssnapshot ikke har et brugbart skema. Hold e-mailskemaer lokale, når du har brug for, at kontrollen anvendes.

Parametre uden et håndhævet e-mailformat sendes videre præcis, som modellen producerede dem.

Understøttede formater er date-time, time, date, duration, email, hostname, ipv4, ipv6 og uuid; kun email normaliseres og håndhæves i dag.

3. Test endepunktet i sandbox

Før du knytter integrationen til en agent, skal du sende en signeret anmodning fra ThunderPhones servere for at bekræfte forbindelsen:

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 test styrker også ThunderPhones SSRF-beskyttelse — anmodninger til localhost eller private IP-områder returnerer 400 code=url_not_allowed.

4. Knyt integrationen til en agent

Knyt den via integration_ids, når du opretter eller opdaterer 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 integrationer til én agent. Agentens prompt kan referere til dem ved navn — "brug get_weather, når opkalderen spørger om vejrforhold" — eller den kan finde dem implicit ud fra skemabeskrivelserne.

5. Implementer endpointet

Når agenten kalder værktøjet, sender ThunderPhone en signeret 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"}

Din server svarer med JSON, som sendes tilbage til LLM'en:

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

LLM'en indlæser svaret og giver opkalderen en mundtlig opsummering i almindeligt sprog.

6. Test forløbet

Start en mikrofonsession mod agenten, og stil det spørgsmål, dit værktøj håndterer ("Hvordan er vejret i 94110?"). Opkaldets transskription viser hele processen:

{
  "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å hændelsesstrøm med tidsangivelser og lydforskydninger for hver post findes på GET /v1/calls/{call_id}/history.

I opkaldslister og analysetjenester rapporterer ThunderPhone nu testopkald separat fra reel trafik. Browser Talk-tests og simuleringer kan genbruge et rigtigt telefonnummer og kan ligne indgående opkald, men de tæller ikke med i samlede produktionsopkald, vurderinger eller problemmetriker.

Almindelige faldgruber

Agenten kalder aldrig værktøjet

LLM'en træffer beslutningen ud fra værktøjets beskrivelse. Hvis opkalderens spørgsmål ikke matcher beskrivelsen, kalder modellen ikke værktøjet. Gør beskrivelsen mere præcis ved at tilføje almindelige synonymer og formuleringer, eller nævn det eksplicit i agentens prompt ("Når opkalderen spørger om vejret, skal du bruge get_weather.").

Værktøjet returnerer for mange data

Svar over 6 kB afkortes i transskriptionsforhåndsvisningen. Returner kun de felter, LLM'en har brug for — ikke hele din række.

Tidsudløb

Værktøjsendpoints har en standardtimeout på 10 sekunder. Hvis du har brug for længere tid, skal du håndtere det asynkront: Returner {"status": "pending", "request_id": "..."} og vis resultatet via et separat værktøjskald.

Versionering

Hver PATCH af en integration opretter en ny revision. Undersøg GET /v1/integrations/{id}/versions for at se, hvem der ændrede hvad. Hvis du ødelægger et værktøjs skema, kan du rulle tilbage manuelt ved at PATCH'e et ældre øjebliksbillede ind igen.


Næste trin