> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thunderphone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Создайте интеграцию инструмента (API)

> Позвольте вашему голосовому агенту вызывать ваши API прямо во время разговора — искать в базе данных, создавать тикеты, находить заказы.

**Интеграция инструмента** — это повторно используемая HTTP-конечная точка, которую агент может
вызывать во время звонка. Вы предоставляете ThunderPhone описание инструмента
в формате JSON-схемы и URL конечной точки; агент решает, когда вызвать его,
на основе разговора, а ThunderPhone выполняет исходящий HTTP-запрос со своих
серверов и возвращает ответ агенту.

<Note>
  Панель управления покрывает большинство задач с инструментами без этого API: **Подключения
  → Приложения** подключает Slack, HubSpot, Salesforce, Google Calendar,
  Google Sheets и Cal.com несколькими OAuth-кликами; **Подключения →
  API** превращает любой HTTP API в действие агента (вставьте команду cURL,
  и мастер на основе ИИ создаст черновик инструмента со встроенной функцией «Тестовый запрос»); а
  **Подключения → MCP** добавляет MCP-серверы. См.
  [Подключения](/ru/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="paperclip">
    Добавьте разовый инструмент в массив `tools` агента. Это просто, но
    не подходит для повторного использования.
  </Card>

  <Card title="Сохранённая интеграция" icon="plug">
    Сохраните инструмент как повторно используемую [интеграцию](/api-reference/integrations)
    и привяжите его к нескольким агентам. Рекомендуется для всего, что используется
    более одного раза.
  </Card>
</CardGroup>

В этом руководстве используется путь с сохранённой интеграцией.

## 2. Создайте интеграцию

```bash theme={null}
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>

## 3. Протестируйте конечную точку в песочнице

Прежде чем привязывать интеграцию к агенту, отправьте подписанный запрос
с серверов ThunderPhone, чтобы подтвердить подключение:

```bash theme={null}
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 theme={null}
{
  "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 theme={null}
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 theme={null}
{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}
```

LLM обрабатывает этот ответ и сообщает звонящему краткую информацию понятным языком.

<Warning>
  Подпись вычисляется по необработанному телу запроса с использованием того же
  `secret`, что и для вашего эндпоинта вебхуков. **Проверяйте её** — эндпоинты
  инструментов доступны из интернета и подвержены тем же рискам подмены, что
  и вебхуки. См.
  [Проверка подписей вебхуков](/ru/guides/verify-webhook-signatures).
</Warning>

## 6. Протестируйте цикл

Запустите [сеанс с микрофоном](/api-reference/mic-sessions) для агента
и задайте вопрос, который обрабатывает ваш инструмент («Какая погода в
94110?»). В расшифровке звонка отображается полный цикл:

```json theme={null}
{
  "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 кБ обрезаются в предпросмотре расшифровки. Возвращайте
    только поля, нужные 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="Спецификация инструментов-функций" icon="screwdriver-wrench" href="/ru/tools/overview">
    Полная грамматика схемы JSON и контракт подписанного эндпоинта.
  </Card>

  <Card title="Проверка подписей" icon="shield-check" href="/ru/guides/verify-webhook-signatures">
    Применяйте шаблон подписи вебхука к эндпоинтам инструментов.
  </Card>

  <Card title="API расшифровки и истории" icon="phone" href="/api-reference/calls">
    Просматривайте полный цикл вызова инструмента.
  </Card>
</CardGroup>
