Open in
Bygg en verktygsintegration (API)
Låt din röstagent anropa dina API:er mitt i ett samtal – sök i en databas, skapa ett ärende eller slå upp en beställning.
En verktygsintegration är en återanvändbar HTTP-slutpunkt som en röstagent kan anropa under ett samtal. Du ger ThunderPhone en JSON-schemabeskrivning av verktyget tillsammans med en slutpunkts-URL; röstagenten avgör när den ska anropa det utifrån samtalet, och ThunderPhone skickar den utgående HTTP-begäran från sina servrar och returnerar svaret till röstagenten.
Den här guiden visar hur du bygger ett verktyg för väderuppslagning från början till slut.
Verktygets uppbyggnad
Två delar:
- Schemat — en OpenAI-liknande funktionsdefinition
(
{type: "function", function: {name, description, parameters}}) som talar om för LLM:en vad verktyget gör och vilka argument det tar. - Slutpunkten — URL:en som ThunderPhones servrar anropar när LLM:en beslutar att använda verktyget. Begäran är en JSON-POST med de argument som LLM:en har valt som brödtext.
1. Välj redigeringsmetod
Öppna Anslutningar → API:er, skapa eller redigera API-anslutningen, växla parameterredigeraren till JSON och lägg till formatet där.
Skapa specifikationen med POST /v1/integrations, eller uppdatera den med
PATCH /v1/integrations/{id}.
Båda vägarna skapar en sparad integration. Koppla integrationen till
röstagenten efter att du har sparat den. Agents API har inget skrivbart inbyggt fält för tools.
Den här guiden använder integrations-API-vägen.
2. Skapa 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" }
]
}'Spara det returnerade id-värdet (ett UUID). Headervärden är endast skrivbara: svar listar endast headernamn, och en senare PATCH kan skicka en header utan ett value för att behålla det lagrade värdet.
Ange format: "email" för adressparametrar
En parameter som tar emot en e-postadress bör ange det i sitt schema:
"email": { "type": "string", "format": "email", "description": "The caller's email address" }format är mer än en ledtråd. För ett tolkat e-postschema, innan din
slutpunkt anropas, trimmar ThunderPhone värdet, gör domänen till
gemener, omvandlar de fristående engelska orden at, dot, underscore,
dash och hyphen till sina tecken och tar bort blanksteg direkt runt
@, ., _ och -. Orden har samma betydelse oavsett om transkriptet
redan innehåller ett bokstavligt @:
"john dot smith at gmail dot com" blir
john.smith@gmail.com.
Alla andra interna blanksteg avvisas i stället för att tyst slås ihop.
Talade avgränsarord stöds endast på engelska; andra språk eller okända
former med blanksteg avvisas. Giltiga internationaliserade domäner och
SMTPUTF8-lokala delar godtas. Punycode-indata förblir punycode och
Unicode-domänindata förblir Unicode efter parsernormalisering, så ditt API
tar emot den konventionella representation som uppringaren angav. Om det
slutliga värdet är ogiltigt anropas verktyget inte. Agenten får
invalid_email_argument, som instruerar den att
bekräfta stavningen med uppringaren och skicka om den bokstavliga adressen.
En utelämnad valfri e-postadress lämnas orörd. null, en tom sträng eller
en sträng som endast innehåller blanksteg lämnas också orörd när egenskapen
är valfri eller kan vara null; samma värden avvisas för en obligatorisk
e-postadress som inte kan vara null.
Lokala schemareferenser som #/$defs/email och
#/definitions/email, samt anyOf, oneOf och allOf, granskas
med cykel- och djupgränser. En icke-lokal eller olösbar $ref är en känd
begränsning i valideringen och skickas vidare oförändrad, liksom ett anrop
vars verktygsögonblicksbild saknar ett användbart schema. Håll
e-postscheman lokala när du behöver att spärren tillämpas.
Parametrar utan ett framtvingat e-postformat skickas vidare exakt så som modellen producerade dem.
Format som stöds är date-time, time, date, duration,
email, hostname, ipv4, ipv6 och uuid; endast email
normaliseras och framtvingas i dag.
3. Testa slutpunkten i sandboxmiljön
Innan du kopplar integrationen till en agent skickar du en signerad begäran från ThunderPhones servrar för att bekräfta anslutningen:
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" }
}'{
"ok": true,
"status": 200,
"elapsed_ms": 187,
"response_headers": { "content-type": "application/json" },
"response_preview": "{\"temperature_f\": 64, ...}"
}Det här testet förstärker också ThunderPhones SSRF-skydd — begäranden till
localhost eller privata IP-intervall returnerar 400 code=url_not_allowed.
4. Koppla integrationen till en agent
Koppla via integration_ids när du skapar eller uppdaterar 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 koppla många integrationer till en agent. Agentens instruktion kan
referera till dem med namn — ”använd get_weather när den som ringer frågar
om väderförhållanden” — eller så kan den upptäcka dem implicit utifrån
schemabeskrivningarna.
5. Implementera slutpunkten
När agenten anropar verktyget skickar ThunderPhone en signerad POST-begäran till
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 svarar med JSON som skickas tillbaka till LLM:en:
{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}LLM:en tar emot svaret och säger en sammanfattning på naturligt språk till den som ringer.
6. Testa flödet
Kör en mikrofonsession mot agenten och ställ frågan som verktyget hanterar (”Hur är vädret i 94110?”). Samtalets transkription visar hela tur- och returflödet:
{
"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 hämta detta via
GET /v1/calls/{call_id}/transcript;
den råa händelseströmmen (med tidsangivelser och ljudförskjutningar per post) finns på
GET /v1/calls/{call_id}/history.
I samtalslistor och analysvyer rapporterar ThunderPhone nu testsamtal separat från verklig trafik. Browser Talk-tester och simuleringar kan återanvända ett riktigt telefonnummer och kan se ut som inkommande samtal, men de räknas inte in i produktionssamtalens totaler, betyg eller incidentmått.
Vanliga fallgropar
Agenten anropar aldrig verktyget
LLM:en avgör utifrån verktygets beskrivning. Om den som ringer ställer en
fråga som inte matchar beskrivningen anropar modellen inte
verktyget. Förtydliga beskrivningen (lägg till vanliga synonymer och
formuleringar) eller nämn det uttryckligen i agentens instruktion (”När den
som ringer frågar om vädret, använd get_weather.”).
Verktyget returnerar för mycket data
Svar över 6 kB trunkeras i förhandsvisningen av transkriptionen. Returnera bara de fält som LLM:en behöver — inte hela raden.
Tidsgränser
Verktygsslutpunkter har en standardtidsgräns på 10 sekunder. Om du behöver längre tid
hanterar du det asynkront: returnera {"status": "pending", "request_id": "..."}
och visa resultatet via ett separat verktygsanrop.
Versionshantering
Varje PATCH av en integration skapar en ny revision. Kontrollera
GET /v1/integrations/{id}/versions
för att se vem som ändrade vad. Om du förstör ett verktygs schema kan du
återställa manuellt genom att PATCH:a tillbaka en äldre ögonblicksbild.
Nästa steg
CRUD, överföring, versionshistorik.
Fullständig JSON-schemagrammatik och kontraktet för signerade slutpunkter.
Tillämpa mönstret för webhook-signaturer på verktygsslutpunkter.
Granska hela tur-och-retur-flödet för ett verktygsanrop.