ThunderPhone 2.0 este acum disponibil.Self-service, de la 2 ¢/min.Citiți anunțul

Developer cookbook

Creați o integrare de instrumente (API)

Permiteți agentului dumneavoastră să apeleze API-urile în timpul conversației — să caute într-o bază de date, să creeze un tichet, să verifice o comandă.

O integrare de instrumente este un endpoint HTTP reutilizabil pe care un agent îl poate invoca în timpul unui apel. Oferiți ThunderPhone o descriere JSON Schema a instrumentului, împreună cu un URL de endpoint; agentul decide când să îl apeleze pe baza conversației, iar ThunderPhone efectuează cererea HTTP de ieșire de pe serverele sale și returnează răspunsul agentului.

Acest ghid vă prezintă crearea completă a unui instrument pentru consultarea vremii.

Anatomia unui instrument

Două componente:

  1. Schema — o definiție de funcție în stil OpenAI ({type: "function", function: {name, description, parameters}}) care îi indică LLM-ului ce face instrumentul și ce argumente acceptă.
  2. Endpointul — URL-ul pe care serverele ThunderPhone îl apelează atunci când LLM-ul decide să utilizeze instrumentul. Cererea este un POST JSON, cu argumentele alese de LLM în corpul cererii.

1. Alegeți un editor

Panou de control

Deschideți Conexiuni → API-uri, creați sau editați conexiunea API, comutați editorul de parametri la JSON și adăugați formatul acolo.

API de integrări

Creați specificația cu POST /v1/integrations sau actualizați-o cu PATCH /v1/integrations/{id}.

Ambele căi creează o integrare salvată. Atașați integrarea respectivă la agent după salvare. API-ul Agenți nu are un câmp inline tools care poate fi modificat. Acest ghid utilizează calea API-ului de integrări.

2. Creați integrarea

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

Salvați id-ul returnat (un UUID). Valorile anteturilor pot fi doar scrise: răspunsurile afișează numai numele anteturilor, iar un PATCH ulterior poate trimite un antet fără o value pentru a o păstra pe cea stocată.

Declarați format: "email" pentru parametrii de adresă

Un parametru care primește o adresă de e-mail trebuie să indice acest lucru în schema sa:

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

format este mai mult decât un indiciu. Pentru o schemă de e-mail rezolvată, înainte ca endpointul dumneavoastră să fie apelat, ThunderPhone elimină spațiile de la început și sfârșit din valoare, convertește domeniul în litere mici, transformă cuvintele englezești independente at, dot, underscore, dash și hyphen în caracterele corespunzătoare și elimină spațiile alăturate direct lui @, ., _ și -. Cuvintele au același sens indiferent dacă transcrierea conține deja un @ literal: "john dot smith at gmail dot com" devine john.smith@gmail.com.

Orice alt spațiu intern este respins în loc să fie unit în mod silențios. Cuvintele rostite pentru separatori sunt disponibile numai în engleză; formele cu spații în alte limbi sau nerecunoscute eșuează în mod sigur. Sunt acceptate domenii internaționalizate valide și părți locale SMTPUTF8. Intrarea Punycode rămâne Punycode, iar intrarea cu domeniu Unicode rămâne Unicode după normalizarea analizorului, astfel încât API-ul dumneavoastră primește reprezentarea convențională furnizată de apelant. Dacă valoarea finală este nevalidă, instrumentul nu este apelat. Agentul primește invalid_email_argument, care îi indică să confirme ortografia cu apelantul și să retrimită adresa literală.

Un e-mail opțional omis rămâne nemodificat. null, un șir gol sau un șir alcătuit numai din spații rămân, de asemenea, nemodificate când proprietatea este opțională sau acceptă valori nule; aceleași valori sunt respinse pentru un e-mail obligatoriu, care nu acceptă valori nule.

Referințele locale la scheme, precum #/$defs/email și #/definitions/email, precum și anyOf, oneOf și allOf, sunt inspectate cu limite pentru cicluri și adâncime. Un $ref nelocal sau imposibil de rezolvat reprezintă o limită de aplicare cunoscută și este transmis nemodificat, la fel ca un apel al cărui instantaneu al instrumentului nu are o schemă utilizabilă. Păstrați schemele de e-mail locale când aveți nevoie ca filtrul să se aplice.

Parametrii fără un format de e-mail aplicat sunt transmiși exact așa cum i-a produs modelul.

Formatele acceptate sunt date-time, time, date, duration, email, hostname, ipv4, ipv6 și uuid; numai email este normalizat și aplicat în prezent.

3. Testați endpointul în sandbox

Înainte de a lega integrarea de un agent, trimiteți o cerere semnată de pe serverele ThunderPhone pentru a confirma conectivitatea:

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

Acest test consolidează, de asemenea, protecțiile SSRF ale ThunderPhone — cererile către localhost sau intervale IP private returnează 400 code=url_not_allowed.

4. Conectați integrarea la un agent

Atașați prin integration_ids când creați sau actualizați un 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-..."]
  }'

Puteți conecta multe integrări la un singur agent. Promptul agentului le poate referenția după nume — „folosiți get_weather când apelantul întreabă despre condiții” — sau le poate descoperi implicit din descrierile schemelor.

5. Implementați endpointul

Când agentul invocă instrumentul, ThunderPhone trimite un POST semnat la 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"}

Serverul dumneavoastră răspunde cu JSON, care este transmis înapoi către LLM:

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

LLM-ul procesează acel răspuns și îi comunică apelantului un rezumat natural.

6. Testați fluxul

Porniți o sesiune de microfon cu agentul și adresați întrebarea gestionată de instrumentul dumneavoastră („Cum este vremea în 94110?”). Transcrierea apelului arată întregul circuit:

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

Puteți prelua aceasta prin GET /v1/calls/{call_id}/transcript; fluxul brut de evenimente (cu temporizarea fiecărei intrări și decalajele audio) se află la GET /v1/calls/{call_id}/history.

În interfețele de listare a apelurilor și analiză, ThunderPhone raportează acum apelurile de test separat de traficul real. Testele și simulările Browser Talk pot reutiliza un număr de telefon real și pot părea apeluri primite, dar nu sunt incluse în totalurile apelurilor de producție, evaluări sau metricile privind problemele.

Probleme frecvente

Agentul nu apelează niciodată instrumentul

LLM-ul decide pe baza descrierii instrumentului. Dacă întrebarea apelantului nu corespunde descrierii, modelul nu va invoca instrumentul. Precizați descrierea (adăugați sinonime și formulări frecvente) sau menționați-l explicit în promptul agentului („Când apelantul întreabă despre vreme, utilizați get_weather.”).

Instrumentul returnează prea multe date

Răspunsurile mai mari de 6 kB sunt trunchiate în previzualizarea transcrierii. Returnați doar câmpurile de care LLM-ul are nevoie — nu întregul rând.

Expirări

Endpointurile de instrumente au un timeout implicit de 10 secunde. Dacă aveți nevoie de mai mult timp, gestionați operația asincron: returnați {"status": "pending", "request_id": "..."} și expuneți rezultatul printr-un apel separat al instrumentului.

Versionare

Fiecare PATCH al unei integrări creează o revizie nouă. Consultați GET /v1/integrations/{id}/versions pentru a vedea cine a modificat ce. Dacă deteriorați schema unui instrument, puteți reveni manual aplicând prin PATCH un instantaneu mai vechi.


Pașii următori