---
title: "Crea un'integrazione di strumenti (API)"
description: "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.

<Note>
  La dashboard copre la maggior parte delle esigenze relative agli strumenti senza questa API: **Connessioni
  → App** collega Slack, HubSpot, Salesforce, Google Calendar,
  Google Sheets e Cal.com con pochi clic OAuth; **Connessioni →
  API** trasforma qualsiasi API HTTP in un'azione dell'agente (incolla un comando cURL
  e una procedura guidata AI crea una bozza dello strumento, con un Test Request
  integrato); **Connessioni → MCP** aggiunge server MCP. Consulta
  [Connessioni](/it/guides/concepts). Questa guida descrive l'API
  sottostante all'interfaccia API.
</Note>

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

<CardGroup cols={2}>
  <Card title="Dashboard" icon="window-maximize">
    Apri **Connessioni → API**, crea o modifica la connessione API,
    imposta l'editor dei parametri su **JSON** e aggiungi il formato lì.
  </Card>
  <Card title="API delle integrazioni" icon="plug">
    Crea la specifica con `POST /v1/integrations`, oppure aggiornala con
    `PATCH /v1/integrations/{id}`.
  </Card>
</CardGroup>

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

```bash
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.

<Tip>
  Cura attentamente la `description` dello strumento e di ogni
  parametro. L'LLM usa queste stringhe in fase di esecuzione per decidere se
  e come chiamare lo strumento. Descrizioni vaghe → chiamate allo strumento vaghe.
</Tip>

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

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

```json
"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à:

```bash
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" }
  }'
```

```json 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:

```bash
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:

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

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

<Warning>
  La firma viene calcolata sul corpo della richiesta non elaborato usando lo stesso
  `secret` del tuo endpoint webhook. **Verificala** — gli endpoint degli strumenti
  sono esposti a internet e soggetti agli stessi rischi di spoofing dei
  webhook. Consulta
  [Verifica le firme dei webhook](/it/guides/verify-webhook-signatures).
</Warning>

## 6. Testa il ciclo

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

```json
{
  "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`](/api-reference/calls#get-transcript);
il flusso di eventi non elaborato, con tempistiche e offset audio per voce, è disponibile in
[`GET /v1/calls/{call_id}/history`](/api-reference/calls#get-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

<AccordionGroup>
  <Accordion title="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`.").
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="Versionamento">
    Ogni `PATCH` dell'integrazione crea una nuova revisione. Controlla
    [`GET /v1/integrations/{id}/versions`](/api-reference/integrations#version-history)
    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.
  </Accordion>
</AccordionGroup>

---

## Passaggi successivi

<CardGroup cols={2}>
  <Card title="Riferimento integrazioni" icon="plug" href="/api-reference/integrations">
    CRUD, trasferimento, cronologia delle versioni.
  </Card>
  <Card title="Specifica Function Tools" icon="screwdriver-wrench" href="/it/tools/overview">
    Grammatica completa dello schema JSON e contratto dell'endpoint firmato.
  </Card>
  <Card title="Verifica le firme" icon="shield-check" href="/it/guides/verify-webhook-signatures">
    Applica il modello di firma webhook agli endpoint degli strumenti.
  </Card>
  <Card title="API trascrizione + cronologia" icon="phone" href="/api-reference/calls">
    Ispeziona il ciclo completo di una chiamata a uno strumento.
  </Card>
</CardGroup>
