ThunderPhone 2.0 è arrivato.Attivazione self-service, da 2¢/min.Leggi l’annuncio

Developer cookbook

Crea un

Consenti al tuo agente di chiamare le tue API durante una conversazione: cerca in un database, crea un ticket, consulta un ordine.

Un'integrazione di strumenti è un endpoint HTTP riutilizzabile che un agente può richiamare durante una chiamata. Fornisci a ThunderPhone una descrizione JSON-schema dello strumento insieme a un URL dell'endpoint; l'agente decide quando chiamarlo in base alla conversazione e ThunderPhone invia la richiesta HTTP in uscita dai propri server e restituisce la risposta all'agente.

Questa guida illustra come creare uno strumento di ricerca meteo dall'inizio alla fine.

Anatomia di uno strumento

Due elementi:

  1. Lo schema — una definizione di funzione in stile OpenAI ({type: "function", function: {name, description, parameters}}) che indica al LLM cosa fa lo strumento e quali argomenti accetta.
  2. L'endpoint — l'URL chiamato dai server ThunderPhone quando il LLM decide di usare lo strumento. La richiesta è un POST JSON con gli argomenti scelti dal LLM nel corpo.

1. Scegli un editor

Dashboard

Apri Connessioni → API, crea o modifica la connessione API, imposta l'editor dei parametri su JSON e aggiungi il formato lì.

API delle integrazioni

Crea la specifica con POST /v1/integrations, oppure aggiornala con PATCH /v1/integrations/{id}.

Entrambi i percorsi creano un'integrazione salvata. Associa quell'integrazione all'agente dopo averla salvata. L'API Agents non dispone di un campo inline tools modificabile. Questa guida usa il percorso dell'API delle integrazioni.

2. Crea l'integrazione

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 l'id restituito (un UUID). I valori delle intestazioni sono di sola scrittura: le risposte elencano solo i nomi delle intestazioni e un successivo PATCH può inviare un'intestazione senza value per mantenere quello memorizzato.

Dichiara format: "email" sui parametri dell'indirizzo email

Un parametro che riceve un indirizzo email deve indicarlo nel proprio schema:

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

format è più di un suggerimento. Per uno schema email risolto, prima che venga chiamato il tuo endpoint ThunderPhone rimuove gli spazi iniziali e finali dal valore, converte il dominio in minuscolo, trasforma le parole inglesi isolate at, dot, underscore, dash e hyphen nei rispettivi caratteri e rimuove gli spazi direttamente attorno a @, ., _ e -. Le parole hanno lo stesso significato indipendentemente dal fatto che la trascrizione contenga già un carattere letterale @: "john dot smith at gmail dot com" diventa john.smith@gmail.com.

Qualsiasi altro spazio interno viene rifiutato anziché unito in modo silenzioso. Le parole pronunciate per i separatori sono supportate solo in inglese; le forme spaziate non inglesi o non riconosciute vengono rifiutate. Sono accettati domini internazionalizzati validi e parti locali SMTPUTF8. L'input Punycode resta Punycode e l'input con dominio Unicode resta Unicode dopo la normalizzazione del parser, quindi la tua API riceve la rappresentazione convenzionale fornita dal chiamante. Se il valore finale non è valido, lo strumento non viene chiamato. L'agente riceve invalid_email_argument, che gli indica di confermare l'ortografia con il chiamante e inviare nuovamente l'indirizzo letterale.

Un'email opzionale omessa non viene modificata. Anche null, una stringa vuota o una stringa contenente solo spazi non vengono modificati quando la proprietà è opzionale o nullable; gli stessi valori vengono rifiutati per un'email obbligatoria non nullable.

I riferimenti locali dello schema come #/$defs/email e #/definitions/email, nonché anyOf, oneOf e allOf, vengono esaminati con limiti di cicli e profondità. Un $ref non locale o non risolvibile è un limite noto di applicazione delle regole e viene passato invariato, così come una chiamata il cui snapshot dello strumento non ha uno schema utilizzabile. Mantieni locali gli schemi email quando devi applicare il controllo.

I parametri senza un formato email applicato vengono passati esattamente come prodotti dal modello.

I formati supportati sono date-time, time, date, duration, email, hostname, ipv4, ipv6 e uuid; oggi solo email viene normalizzato e applicato.

3. Testa l'endpoint nella sandbox

Prima di collegare l'integrazione a un agente, invia una richiesta firmata dai server di ThunderPhone per confermare la connettività:

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

Questo test rafforza anche le protezioni SSRF di ThunderPhone: le richieste a localhost o a intervalli IP privati restituiscono 400 code=url_not_allowed.

4. Collega l'integrazione a un agente

Collega tramite integration_ids quando crei o aggiorni un agente:

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

Puoi collegare molte integrazioni a un agente. Il prompt dell'agente può farvi riferimento per nome — "usa get_weather quando il chiamante chiede delle condizioni" — oppure può individuarle implicitamente dalle descrizioni dello schema.

5. Implementa l'endpoint

Quando l'agente invoca lo strumento, ThunderPhone invia una richiesta POST firmata al tuo 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"}

Il tuo server risponde con JSON che viene restituito all'LLM:

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

L'LLM acquisisce quella risposta e comunica un riepilogo comprensibile al chiamante.

6. Testa il ciclo

Avvia una sessione microfono con l'agente e fai la domanda gestita dal tuo strumento ("Che tempo fa a 94110?"). La trascrizione della chiamata mostra il ciclo completo:

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

Puoi recuperarla tramite GET /v1/calls/{call_id}/transcript; il flusso di eventi non elaborato, con tempistiche e offset audio per voce, è disponibile in GET /v1/calls/{call_id}/history.

Nelle sezioni di elenco chiamate e analisi, ThunderPhone ora riporta separatamente le chiamate di test dal traffico reale. I test e le simulazioni di Browser Talk possono riutilizzare un numero di telefono reale e sembrare in entrata, ma non vengono conteggiati nei totali delle chiamate di produzione, nelle valutazioni o nelle metriche dei problemi.

Problemi comuni

L'agente non chiama mai lo strumento

L'LLM decide in base alla descrizione dello strumento. Se la domanda del chiamante non corrisponde alla descrizione, il modello non invocherà lo strumento. Rendi più precisa la descrizione, aggiungendo sinonimi e formulazioni comuni, oppure menzionalo esplicitamente nel prompt dell'agente ("Quando il chiamante chiede del meteo, usa get_weather.").

Lo strumento restituisce troppi dati

Le risposte superiori a 6 kB vengono troncate nell'anteprima della trascrizione. Restituisci solo i campi necessari all'LLM, non l'intera riga.

Timeout

Gli endpoint degli strumenti hanno un timeout predefinito di 10 secondi. Se ti serve più tempo, gestiscilo in modo asincrono: restituisci {"status": "pending", "request_id": "..."} ed esponi il risultato tramite una chiamata a uno strumento separata.

Versionamento

Ogni PATCH dell'integrazione crea una nuova revisione. Controlla GET /v1/integrations/{id}/versions per vedere chi ha modificato cosa. Se modifichi in modo incompatibile lo schema di uno strumento, puoi ripristinarlo manualmente applicando di nuovo con PATCH uno snapshot precedente.


Passaggi successivi