---
title: "Алатке функција"
description: "Омогућите својим AI агентима алатке функција које позивају спољне API-је усред разговора — преузимају податке о клијентима, заказују термине, ажурирају евиденцију — са типизираним параметрима."
---

Алатке функција омогућавају Вашим AI агентима да позивају спољне API-је током телефонских позива. Користите их за проналажење података о клијентима, проверу доступности, заказивање термина или извршавање било које радње коју подржава Ваш позадински систем.

## Како функционише

1. Дефинишете алатке помоћу шеме (које аргументе алатка прихвата)
2. Наводите конфигурацију `endpoint` (где ThunderPhone позива Ваш API) — или је изостављате да бисте примали позиве алатки на webhook-у Ваше организације
3. Током позива, AI одлучује када да користи алатку на основу разговора
4. ThunderPhone позива Ваш endpoint са аргументима алатке
5. Одговор Вашег API-ја се враћа AI-ју ради наставка разговора

| Могућност | Где се извршава | Подешавање |
| --- | --- | --- |
| [Уграђене алатке](/sr/guides/built-in-tools) | ThunderPhone | Упутства у prompt-у; неке алатке захтевају и подешавање агента |
| [Повезивања са апликацијама](/sr/guides/connect-apps) | ThunderPhone и повезани добављач | Повежите налог и приложите одобрене радње |
| [API повезивања](/sr/guides/api-connections) и алатке функција | Ваш HTTP API | Дефинишите endpoint и шему или примајте позиве функција преко webhook-а |
| [MCP сервери](/sr/guides/mcp-servers) | Удаљени MCP сервер | Додајте сервер, откријте његове алатке и приложите га агенту |

---

## Шема алатке

Свака алатка прати ову структуру:

```json
{
  "type": "function",
  "function": {
    "name": "search_appointments",
    "description": "Find available appointment slots for a given date",
    "parameters": {
      "type": "object",
      "properties": {
        "date": {
          "type": "string",
          "description": "Date in YYYY-MM-DD format"
        },
        "service": {
          "type": "string",
          "description": "Type of service (e.g., 'consultation', 'follow-up')"
        }
      },
      "required": ["date"]
    }
  },
  "endpoint": {
    "url": "https://api.example.com/appointments/search",
    "method": "POST",
    "headers": {
      "X-Api-Key": "your-api-key"
    }
  },
  "timeout": 120
}
```

### Конфигурација алатке

| Поље | Тип | Обавезно | Опис |
|-------|------|----------|-------------|
| `timeout` | број | Не | Максимално време извршавања у секундама (подразумевано: `20`, максимално: `180`) |

### Дефиниција функције

| Поље | Тип | Обавезно | Опис |
|-------|------|----------|-------------|
| `name` | ниска | Да | Јединствени идентификатор алатке |
| `description` | ниска | Да | Објашњава AI-ју када да користи ову алатку |
| `parameters` | објекат | Да | JSON шема за аргументе алатке |

### Конфигурација endpoint-а

| Поље | Тип | Обавезно | Опис |
|-------|------|----------|-------------|
| `url` | ниска | Да | URL endpoint-а Вашег API-ја |
| `method` | ниска | Не | HTTP метода (подразумевано: `POST`) |
| `headers` | објекат | Не | Прилагођена заглавља која треба укључити |

<Note>
  Конфигурација `endpoint` се **не** шаље AI моделу — ThunderPhone је користи само за извршавање позива алатке.
</Note>

---

## Два пута позивања

Који захтев ће Ваш сервер примити зависи од тога да ли алатка има
`endpoint`:

| | Алатка **са** `endpoint` | Алатка **без** `endpoint` |
|---|---|---|
| Куда захтев иде | Директно на `endpoint.url` | На [застарели URL webhook-а](/api-reference/organizations#legacy-single-url-webhook) Ваше организације |
| Тело | **Само аргументи алатке** | Омотач `telephony.tool` / `web.tool` |
| Заглавља | Ваши `endpoint.headers` + `X-ThunderPhone-Call-ID` + `X-ThunderPhone-Signature` | `Content-Type` + `X-ThunderPhone-Signature` |
| Кључ за потписивање | Тајна webhook-а организације | Тајна webhook-а организације |

Оба пута су **блокирајућа** — AI усред реченице чека
резултат. Подразумевано временско ограничење је **20 s**; подесите `timeout`
на највишем нивоу алатке да бисте омогућили дуже извршавање, до максималних
**180 s** које платформа дозвољава. Нека обрађивачи буду брзи. Можете користити комбинацију:
у позиву чија организација има URL webhook-а, алатке са `endpoint`-ом се
позивају директно, а остале се враћају на webhook.

## Директни позиви крајњих тачака

Када AI позове алат који има `endpoint`, ThunderPhone шаље
захтев на Ваш URL:

### Заглавља захтева

```http
POST /appointments/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-ThunderPhone-Signature: abc123...
X-ThunderPhone-Call-ID: 987654321
X-Api-Key: your-api-key
```

Прилагођена заглавља из Вашег `endpoint.headers` увек су укључена
дословно, уз два заглавља у ThunderPhone простору имена:

- `X-ThunderPhone-Signature` — HMAC-SHA256 тачних бајтова тела
  захтева, потписан тајном **вебхук тајном организације**
- `X-ThunderPhone-Call-ID` — ID тренутног позива

`Content-Type: application/json` је постављен осим ако га Ваш
`endpoint.headers` не замени — прилагођени `Content-Type` има предност.

<Warning>
  Потпис је заснован на вебхук тајни на нивоу организације из
  [`GET /v1/webhook`](/api-reference/organizations#legacy-single-url-webhook).
  Ако Ваша организација никада није конфигурисала застарели вебхук, не постоји
  тајна и позиви алата садрже **само** `X-ThunderPhone-Call-ID` — обрађивач
  који при недостајућем потпису одмах пријављује грешку би их одбио.
  Или конфигуришите застарели вебхук да бисте добили тајну, или поставите сопствену
  дељену тајну у `endpoint.headers`.
</Warning>

### Тело захтева

За `POST` / `PUT` / `PATCH`, тело садржи **само** аргументе алата
(без омотача), серијализоване канонски (сортирани кључеви, сажети
раздвајачи):

```json
{"date":"2025-01-02","service":"consultation"}
```

За `GET` / `DELETE`, аргументи се шаљу као **параметри упита**
а тело је празно — потпис се тада израчунава над празним
низом бајтова. Погледајте
[Верификација потписа вебхука](/sr/guides/verify-webhook-signatures).

### Одговор

Вратите JSON одговор са резултатом алата:

```json
{
  "available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
  "timezone": "America/Los_Angeles"
}
```

Одговор се форматира и доставља AI-ју да настави
разговор. Одговори који нису JSON умотавају се као `{"data": "<text>"}`;
истеци времена и грешке везе пријављују се AI-ју као грешке, тако да
агент може да се извини и настави уместо да застане.

## Отпремање у режиму вебхука

Алати **без** `endpoint` шаљу се на застарели URL вебхука Ваше
организације као потписани захтев `telephony.tool` (телефонски позиви) или `web.tool`
(веб позиви). За разлику од [обавештења за ревизију](/sr/webhooks/events)
која се испоручују вебхук крајњим тачкама након извршавања, овај захтев **јесте**
извршавање — Ваш HTTP одговор је резултат алата.

```json
{
  "type": "telephony.tool",
  "data": {
    "call_id": 987654321,
    "tool_name": "search_appointments",
    "arguments": { "date": "2026-04-21" },
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  }
}
```

`web.tool` садржи `origin_domain` уместо `from_number` /
`to_number`. Одговорите резултатом алата као JSON — исти уговор о одговору
као за директне позиве крајњих тачака. Захтев је потписан вебхук тајном
организације над необрађеним телом, као и сваки други вебхук.

<Note>
  Претплаћене [вебхук крајње тачке](/sr/webhooks/endpoints) додатно
  примају неблокирајуће `telephony.tool` / `web.tool` **обавештење
  након** сваког извршавања алата (без обзира на путању којом је покренут),
  укључујући одговор алата — корисно за ревизијске трагове. Погледајте
  [каталог догађаја](/sr/webhooks/events).
</Note>

---

## Верификација потписа

Директни позиви алата потписују се на исти начин као webhook-ови:

- HMAC-SHA256 преко тачних бајтова тела захтева (канонски JSON —
  сортирани кључеви, без додатног размака)
- Са тајним webhook кључем Ваше организације
- Алати `GET` / `DELETE` потписују празан низ бајтова

<CodeGroup>
```python Python
import hmac
import hashlib

def verify_tool_call(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.post("/appointments/search")
async def search_appointments(request: Request):
    body = await request.body()
    signature = request.headers.get("X-ThunderPhone-Signature", "")

    if not verify_tool_call(body, signature, WEBHOOK_SECRET):
        raise HTTPException(status_code=401)

    data = json.loads(body)
    date = data["date"]

    # Look up availability
    slots = await get_available_slots(date)

    return {"available_slots": slots}
```

```javascript Node.js
app.post('/appointments/search', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-thunderphone-signature'] || '';
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');

  if (!signature ||
      signature.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
    return res.status(401).send('Invalid signature');
  }

  const { date, service } = JSON.parse(req.body);

  // Look up availability
  const slots = getAvailableSlots(date, service);

  res.json({ available_slots: slots });
});
```
</CodeGroup>

Потпуна упутства — укључујући случај празног тела и напомену када тајни кључ није подешен —
налазе се у одељку [Верификација webhook потписа](/sr/guides/verify-webhook-signatures).

---

## Пример: Комплетан ток заказивања

Ево скупа алата за комплетан систем заказивања термина:

```json
{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_appointments",
        "description": "Find available appointment slots",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "service": { "type": "string" }
          },
          "required": ["date"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/search",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "book_appointment",
        "description": "Book an appointment at a specific time",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "time": { "type": "string", "description": "HH:MM format" },
            "customer_name": { "type": "string" },
            "customer_phone": { "type": "string" }
          },
          "required": ["date", "time", "customer_name"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/book",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "cancel_appointment",
        "description": "Cancel an existing appointment",
        "parameters": {
          "type": "object",
          "properties": {
            "confirmation_number": { "type": "string" }
          },
          "required": ["confirmation_number"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/cancel",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    }
  ]
}
```

---

## Најбоље праксе

<AccordionGroup>
  <Accordion title="Пишите јасне описе">
    Поље `description` помаже вештачкој интелигенцији да разуме **када** да користи алат. Наведите прецизно шта алат ради и када је прикладно да се користи.
  </Accordion>

  <Accordion title="Елегантно обрађујте грешке">
    Вратите поруке о грешци које вештачка интелигенција може да разуме: `{"error": "No slots available for that date"}` уместо генеричких грешака 500.
  </Accordion>

  <Accordion title="Нека одговори буду сажети">
    Вратите само оно што је вештачкој интелигенцији потребно да настави разговор. Велики терети података успоравају време одзива.
  </Accordion>

  <Accordion title="Промишљено користите обавезна поља">
    Означите поља као `required` само када је то заиста неопходно. Вештачка интелигенција ће тражити од корисника обавезне информације пре позивања алата.
  </Accordion>
</AccordionGroup>

---

## Повезано

<CardGroup cols={2}>
  <Card title="Уграђени алати" icon="wrench" href="/sr/guides/built-in-tools">
    Покрените радње позива којима управља платформа без дефинисања крајње тачке.
  </Card>
  <Card title="Повезивања апликација" icon="plug" href="/sr/guides/connect-apps">
    Алате којима управља платформа за HubSpot, Salesforce, Slack, Google
    Calendar, Google Sheets и Cal.com — није потребна крајња тачка.
  </Card>
  <Card title="MCP сервери" icon="server" href="/sr/guides/mcp-servers">
    Повежите MCP сервер и омогућите агенту да позива његове алате.
  </Card>
  <Card title="API повезивања" icon="code" href="/sr/guides/api-connections">
    Поново употребљиве REST интеграције које можете повезати са агентима.
  </Card>
  <Card title="Верификујте потписе веб-хука" icon="shield-check" href="/sr/guides/verify-webhook-signatures">
    Један помоћник за верификацију веб-хукова и позива алата.
  </Card>
</CardGroup>
