---
title: "Създайте интеграция с инструмент (API)"
description: "Позволете на агента си да извиква вашите API по време на разговор — да търси в база данни, да създава тикет, да проверява поръчка."
---

Интеграцията на **инструмент** е крайна HTTP точка за многократна употреба, която агентът може да
извиква по време на разговор. Предоставяте на ThunderPhone JSON Schema описание
на инструмента плюс URL на крайна точка; агентът решава кога да го извика
въз основа на разговора, а ThunderPhone изпраща изходящата HTTP
заявка от своите сървъри и връща отговора на агента.

<Note>
  Таблото покрива повечето нужди от инструменти без този API: **Връзки
  → Приложения** свързва Slack, HubSpot, Salesforce, Google Calendar,
  Google Sheets и Cal.com с няколко OAuth клика; **Връзки →
  API** превръща всеки HTTP API в действие за агент (поставете cURL команда
  и AI съветник създава чернова на инструмента с вградено „Тестова заявка“); а
  **Връзки → MCP** добавя MCP сървъри. Вижте
  [Връзки](/bg/guides/concepts). Това ръководство разглежда директния
  API, който стои зад интерфейса на API.
</Note>

Това ръководство показва изграждането на инструмент за проверка на времето от край до край.

## Анатомия на инструмент

Две части:

1. **Схемата** — дефиниция на функция в стил OpenAI
   (`{type: "function", function: {name, description, parameters}}`),
   която указва на LLM какво прави инструментът и какви аргументи приема.
2. **Крайната точка** — URL адресът, който сървърите на ThunderPhone извикват, когато
   LLM реши да използва инструмента. Заявката е JSON POST със
   избраните от LLM аргументи в тялото.

## 1. Изберете редактор

<CardGroup cols={2}>
  <Card title="Табло" icon="window-maximize">
    Отворете **Връзки → API**, създайте или редактирайте API връзката,
    превключете редактора на параметри на **JSON** и добавете формата там.
  </Card>
  <Card title="API за интеграции" icon="plug">
    Създайте спецификацията с `POST /v1/integrations` или я актуализирайте с
    `PATCH /v1/integrations/{id}`.
  </Card>
</CardGroup>

И двата подхода създават запазена интеграция. Прикачете тази интеграция към
агента, след като я запазите. API за агенти няма поле `tools` за записване
директно в него. Това ръководство използва подхода чрез API за интеграции.

## 2. Създайте интеграцията

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

Запазете върнатото `id` (UUID).

<Tip>
  Отделете реално внимание на `description` на инструмента и на всеки
  параметър. LLM използва тези низове при изпълнение, за да реши дали
  и как да извика инструмента. Неясни описания → неясни извиквания на инструменти.
</Tip>

### Декларирайте `format: "email"` за параметрите за адреси

Параметър, който получава имейл адрес, трябва да го указва в своята
схема:

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

`format` е повече от подсказка. При разпозната схема за имейл, преди
да бъде извикана вашата крайна точка, ThunderPhone премахва водещите и
завършващите интервали от стойността, преобразува домейна в малки букви,
превръща самостоятелните английски думи `at`, `dot`, `underscore`,
`dash` и `hyphen` в съответните им символи и премахва интервалите
непосредствено около `@`, `.`, `_` и `-`. Думите имат същото значение,
независимо дали транскрипцията вече съдържа буквален `@`:
`"john dot smith at gmail dot com"` става
`john.smith@gmail.com`.

Всеки друг вътрешен интервал се отхвърля, вместо безшумно да бъде
слят. Изговорените думи за разделители са само на английски; неанглийски
или неразпознати форми с интервали се отхвърлят безопасно. Валидни
интернационализирани домейни и локални части по SMTPUTF8 се приемат.
Входът в Punycode остава в Punycode, а входът с Unicode домейн остава в
Unicode след нормализиране от анализатора, така че вашият API получава
конвенционалното представяне, предоставено от обаждащия се. Ако крайната
стойност е невалидна, инструментът **не се извиква**. Агентът получава
`invalid_email_argument`, което му указва
да потвърди изписването с обаждащия се и да изпрати отново буквалния адрес.

Пропуснат незадължителен имейл остава непроменен. `null`, празен низ или
низ само с интервали също остават непроменени, когато свойството е
незадължително или допуска null; същите стойности се отхвърлят за
задължителен имейл, който не допуска null.

Локални референции към схеми, като `#/$defs/email` и
`#/definitions/email`, както и `anyOf`, `oneOf` и `allOf`, се проверяват
с ограничения за цикли и дълбочина. Нелокален или неразрешим `$ref` е
известно ограничение на проверката и се предава без промяна, както и
извикване, чиято моментна снимка на инструмента няма използваема схема.
Поддържайте схемите за имейл локални, когато е необходимо проверката да се прилага.

Параметрите без наложен формат за имейл се предават точно както моделът
ги е създал.

Поддържаните формати са `date-time`, `time`, `date`, `duration`,
`email`, `hostname`, `ipv4`, `ipv6` и `uuid`; днес само `email` се
нормализира и проверява.

## 3. Тествайте крайната точка в пясъчна среда

Преди да свържете интеграцията с агент, изпратете подписана заявка
от сървърите на ThunderPhone, за да потвърдите свързаността:

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

Този тест също подсилва SSRF защитите на ThunderPhone — заявките към
localhost или частни IP диапазони връщат `400 code=url_not_allowed`.

## 4. Свържете интеграцията с агент

Прикачете я чрез `integration_ids`, когато създавате или актуализирате агент:

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

Можете да свържете много интеграции с един агент. Подканата на агента може
да се позовава на тях по име — „използвай `get_weather`, когато обаждащият се попита
за метеорологичните условия“ — или агентът може да ги открие неявно от
описанията на схемата.

## 5. Имплементирайте крайната точка

Когато агентът извика инструмента, ThunderPhone изпраща подписана POST заявка към
вашия `endpoint_url`:

```
POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json

{"zip": "94110"}
```

Вашият сървър отговаря с JSON, който се предава обратно на LLM:

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

LLM обработва този отговор и съобщава на обаждащия се обобщение на естествен език.

<Warning>
  Подписът се изчислява върху необработеното тяло на заявката, като се използва същият
  `secret` като за вашата webhook крайна точка. **Проверете го** — крайните точки на
  инструментите са достъпни от интернет и са изложени на същите рискове от фалшифициране като
  webhook-ите. Вижте
  [Проверка на webhook подписи](/bg/guides/verify-webhook-signatures).
</Warning>

## 6. Тествайте цикъла

Изпълнете [mic сесия](/api-reference/mic-sessions) срещу агента
и задайте въпроса, който вашият инструмент обработва („Какво е времето в
94110?“). Транскриптът на разговора показва пълния цикъл:

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

Можете да извлечете това чрез
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript);
потокът от необработени събития (с времето за всеки запис и отместванията в аудиото) е на
[`GET /v1/calls/{call_id}/history`](/api-reference/calls#get-history).

## Често срещани проблеми

<AccordionGroup>
  <Accordion title="Агентът никога не извиква инструмента">
    LLM взема решение въз основа на описанието на инструмента. Ако въпросът на обаждащия се
    не съответства на описанието, моделът няма да извика
    инструмента. Прецизирайте описанието (добавете често срещани синоними и
    формулировки) или го споменете изрично в подканата на агента („Когато
    обаждащият се пита за времето, използвай `get_weather`.“).
  </Accordion>

  <Accordion title="Инструментът връща твърде много данни">
    Отговорите над 6 kB се съкращават в предварителния преглед на транскрипта. Връщайте
    само полетата, от които LLM се нуждае — не целия ви запис.
  </Accordion>

  <Accordion title="Изчаквания">
    Крайните точки на инструментите имат стандартно изчакване от 10 секунди. Ако ви трябва повече време,
    обработете заявката асинхронно: върнете `{"status": "pending", "request_id": "..."}`
    и предоставете резултата чрез отделно извикване на инструмент.
  </Accordion>

  <Accordion title="Версиониране">
    Всеки `PATCH` на интеграция създава нова редакция. Проверете
    [`GET /v1/integrations/{id}/versions`](/api-reference/integrations#version-history),
    за да видите кой какво е променил. Ако нарушите схемата на инструмент, можете
    ръчно да върнете предишна версия, като приложите чрез PATCH по-старо моментно състояние.
  </Accordion>
</AccordionGroup>

---

## Следващи стъпки

<CardGroup cols={2}>
  <Card title="Справка за интеграции" icon="plug" href="/api-reference/integrations">
    CRUD, прехвърляне, история на версиите.
  </Card>
  <Card title="Спецификация за Function Tools" icon="screwdriver-wrench" href="/bg/tools/overview">
    Пълна граматика на JSON схемата и договорът за подписани крайни точки.
  </Card>
  <Card title="Проверка на подписи" icon="shield-check" href="/bg/guides/verify-webhook-signatures">
    Приложете модела за webhook подписи към крайните точки на инструментите.
  </Card>
  <Card title="API за транскрипции + история" icon="phone" href="/api-reference/calls">
    Прегледайте пълния цикъл на извикване на инструмент.
  </Card>
</CardGroup>
