---
title: "Creați o integrare de instrumente (API)"
description: "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.

<Note>
  Panoul de control acoperă majoritatea nevoilor de instrumente fără acest API: **Conexiuni
  → Aplicații** conectează Slack, HubSpot, Salesforce, Google Calendar,
  Google Sheets și Cal.com în câteva clicuri OAuth; **Conexiuni →
  API-uri** transformă orice API HTTP într-o acțiune a agentului (lipiți o comandă cURL
  și un asistent AI creează schița instrumentului, cu o funcție integrată de Testare cerere); iar
  **Conexiuni → MCP** adaugă servere MCP. Consultați
  [Conexiuni](/ro/guides/concepts). Acest ghid acoperă API-ul de bază
  din spatele interfeței API-uri.
</Note>

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

<CardGroup cols={2}>
  <Card title="Panou de control" icon="window-maximize">
    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.
  </Card>
  <Card title="API de integrări" icon="plug">
    Creați specificația cu `POST /v1/integrations` sau actualizați-o cu
    `PATCH /v1/integrations/{id}`.
  </Card>
</CardGroup>

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

```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ț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ă.

<Tip>
  Acordați atenție reală `description`-ului instrumentului și fiecărui
  parametru. LLM-ul folosește aceste șiruri la rulare pentru a decide dacă
  și cum să apeleze instrumentul. Descrieri vagi → apeluri vagi ale instrumentului.
</Tip>

### 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:

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

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

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:

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

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:

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

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

<Warning>
  Semnătura este calculată peste corpul brut al cererii, folosind același
  `secret` ca endpointul webhook. **Verificați-o** — endpointurile de instrumente
  sunt expuse pe internet și sunt supuse acelorași riscuri de falsificare ca
  webhookurile. Consultați
  [Verificați semnăturile webhook](/ro/guides/verify-webhook-signatures).
</Warning>

## 6. Testați fluxul

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

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

Puteți prelua aceasta prin
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript);
fluxul brut de evenimente (cu temporizarea fiecărei intrări și decalajele audio) se află la
[`GET /v1/calls/{call_id}/history`](/api-reference/calls#get-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

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

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

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

  <Accordion title="Versionare">
    Fiecare `PATCH` al unei integrări creează o revizie nouă. Consultați
    [`GET /v1/integrations/{id}/versions`](/api-reference/integrations#version-history)
    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.
  </Accordion>
</AccordionGroup>

---

## Pașii următori

<CardGroup cols={2}>
  <Card title="Referință pentru integrări" icon="plug" href="/api-reference/integrations">
    CRUD, transfer, istoric al versiunilor.
  </Card>
  <Card title="Specificația Function Tools" icon="screwdriver-wrench" href="/ro/tools/overview">
    Gramatica completă a schemei JSON și contractul endpointului semnat.
  </Card>
  <Card title="Verificați semnăturile" icon="shield-check" href="/ro/guides/verify-webhook-signatures">
    Aplicați modelul de semnătură webhook la endpointurile instrumentelor.
  </Card>
  <Card title="API pentru transcriere și istoric" icon="phone" href="/api-reference/calls">
    Examinați întregul flux dus-întors al unui apel de instrument.
  </Card>
</CardGroup>
