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

# Funkční nástroje

> Umožněte svým AI agentům volat externí API během konverzací

Funkční nástroje umožňují vašim AI hlasovým agentům během telefonních hovorů volat externí rozhraní API. Použijte je k vyhledávání údajů o zákaznících, kontrole dostupnosti, rezervaci schůzek nebo provedení libovolné akce, kterou váš backend podporuje.

## Jak to funguje

1. Definujete nástroje pomocí schématu (jaké argumenty nástroj přijímá)
2. Poskytnete konfiguraci `endpoint` (kam ThunderPhone volá vaše API) — nebo ji vynecháte, aby se volání nástrojů přijímala na webhooku vaší organizace
3. Během hovoru AI podle konverzace rozhodne, kdy nástroj použít
4. ThunderPhone zavolá váš endpoint s argumenty nástroje
5. Odpověď vašeho API se předá zpět AI, aby mohla pokračovat v konverzaci

<Note>
  Funkční nástroje představují cestu, při které používáte vlastní API. ThunderPhone také
  nabízí nástroje spravované platformou, které endpoint nepotřebují:
  [připojení aplikací](/cs/guides/connect-apps) (HubSpot, Salesforce, Slack,
  Google Calendar, Google Sheets, Cal.com),
  [připojení API](/cs/guides/api-connections) a
  [servery MCP](/cs/guides/mcp-servers).
</Note>

***

## Schéma nástroje

Každý nástroj má tuto strukturu:

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

### Definice funkce

| Pole          | Typ     | Povinné | Popis                                   |
| ------------- | ------- | ------- | --------------------------------------- |
| `name`        | řetězec | Ano     | Jedinečný identifikátor nástroje        |
| `description` | řetězec | Ano     | Vysvětluje AI, kdy tento nástroj použít |
| `parameters`  | objekt  | Ano     | Schéma JSON pro argumenty nástroje      |

### Konfigurace endpointu

| Pole      | Typ     | Povinné | Popis                                    |
| --------- | ------- | ------- | ---------------------------------------- |
| `url`     | řetězec | Ano     | Adresa URL endpointu vašeho API          |
| `method`  | řetězec | Ne      | Metoda HTTP (výchozí: `POST`)            |
| `headers` | objekt  | Ne      | Vlastní hlavičky, které se mají zahrnout |

<Note>
  Konfigurace `endpoint` se modelu AI **neodesílá** — ThunderPhone ji používá pouze k provedení volání nástroje.
</Note>

***

## Dvě cesty vyvolání

To, jaký požadavek váš server obdrží, závisí na tom, zda nástroj má
`endpoint`:

|                       | Nástroj **s** `endpoint`                                                        | Nástroj **bez** `endpoint`                                                                              |
| --------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Kam požadavek směřuje | Přímo na `endpoint.url`                                                         | Na [starší adresu URL webhooku](/api-reference/organizations#legacy-single-url-webhook) vaší organizace |
| Tělo                  | **Pouhé argumenty nástroje**                                                    | Obálka `telephony.tool` / `web.tool`                                                                    |
| Hlavičky              | Vaše `endpoint.headers` + `X-ThunderPhone-Call-ID` + `X-ThunderPhone-Signature` | `Content-Type` + `X-ThunderPhone-Signature`                                                             |
| Podepisovací klíč     | Tajný klíč webhooku organizace                                                  | Tajný klíč webhooku organizace                                                                          |

Obě cesty jsou **blokující** — AI uprostřed věty čeká na
výsledek — s časovým limitem **20 s**. Udržujte obslužné rutiny rychlé. Kombinace je v pořádku:
při hovoru, jehož organizace má adresu URL webhooku, jsou nástroje s `endpoint`
volány přímo a ostatní se vracejí k webhooku.

## Přímá volání endpointu

Když AI vyvolá nástroj, který má `endpoint`, ThunderPhone odešle
požadavek na vaši adresu URL:

### Hlavičky požadavku

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

Vlastní hlavičky z vašeho `endpoint.headers` jsou vždy zahrnuty
beze změny spolu se dvěma hlavičkami v prostoru názvů ThunderPhone:

* `X-ThunderPhone-Signature` — HMAC-SHA256 přes přesné bajty těla
  požadavku s klíčem ve vašem **tajemství webhooku organizace**
* `X-ThunderPhone-Call-ID` — ID aktuálního hovoru

`Content-Type: application/json` je nastaveno, pokud jej vaše `endpoint.headers`
nepřepíší — vlastní `Content-Type` má přednost.

<Warning>
  Podpis používá jako klíč tajemství webhooku na úrovni organizace z
  [`GET /v1/webhook`](/api-reference/organizations#legacy-single-url-webhook).
  Pokud vaše organizace nikdy nenakonfigurovala starší webhook, žádné
  tajemství neexistuje a volání nástrojů obsahují **pouze**
  `X-ThunderPhone-Call-ID` — obslužná funkce, která selže při chybějícím
  podpisu, by je odmítla.
  Buď nakonfigurujte starší webhook, abyste získali tajemství, nebo do
  `endpoint.headers` vložte vlastní sdílené tajemství.
</Warning>

### Tělo požadavku

Pro `POST` / `PUT` / `PATCH` obsahuje tělo **pouze** argumenty nástroje
(bez obálky), serializované kanonicky (seřazené klíče, kompaktní
oddělovače):

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

Pro `GET` / `DELETE` jsou argumenty odeslány jako **parametry dotazu**
a tělo je prázdné — podpis se pak vypočítá přes prázdný bajtový
řetězec. Viz
[Ověření podpisů webhooků](/cs/guides/verify-webhook-signatures).

### Odpověď

Vraťte odpověď JSON s výsledkem nástroje:

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

Odpověď se naformátuje a poskytne AI, aby mohla pokračovat v
konverzaci. Odpovědi jiné než JSON jsou zabaleny jako `{"data": "<text>"}`;
časové limity a selhání připojení jsou AI nahlášeny jako chyby, takže
se agent může omluvit a pokračovat, místo aby se zasekl.

## Odesílání v režimu webhooku

Nástroje **bez** `endpoint` jsou odesílány na starší adresu URL
webhooku vaší organizace jako podepsaný požadavek `telephony.tool`
(telefonní hovory) nebo `web.tool` (webová volání). Na rozdíl od
[notifikací auditu](/cs/webhooks/events) doručovaných na endpointy webhooků
po provedení je tento požadavek **samotným** provedením — vaše odpověď
HTTP je výsledkem nástroje.

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

`web.tool` obsahuje `origin_domain` místo `from_number` /
`to_number`. Odpovězte výsledkem nástroje ve formátu JSON — se stejným
kontraktem odpovědi jako u přímých volání endpointu. Požadavek je
podepsán tajemstvím webhooku organizace přes nezpracované tělo, stejně
jako každý jiný webhook.

<Note>
  Odebírané [endpointy webhooků](/cs/webhooks/endpoints) navíc obdrží
  neblokující **notifikaci** `telephony.tool` / `web.tool` **po**
  provedení každého nástroje (bez ohledu na použitou cestu), včetně
  odpovědi nástroje — což je užitečné pro auditní záznamy. Viz
  [katalog událostí](/cs/webhooks/events).
</Note>

***

## Ověření podpisu

Přímá volání nástrojů se podepisují stejným způsobem jako webhooky:

* HMAC-SHA256 přes přesné bajty těla požadavku (kanonický JSON —
  seřazené klíče, bez nadbytečných mezer)
* S vaším tajným klíčem webhooku organizace
* Nástroje `GET` / `DELETE` podepisují prázdný bajtový řetězec

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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>

Úplné postupy — včetně případu s prázdným tělem a upozornění na chybějící tajný klíč —
najdete v části [Ověření podpisů webhooků](/cs/guides/verify-webhook-signatures).

***

## Příklad: Kompletní proces rezervace

Zde je sada nástrojů pro kompletní systém rezervace termínů:

```json theme={null}
{
  "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" }
      }
    }
  ]
}
```

***

## Osvědčené postupy

<AccordionGroup>
  <Accordion title="Pište jasné popisy">
    Pole `description` pomáhá AI pochopit, **kdy** nástroj použít. Konkrétně popište, co nástroj dělá a kdy je vhodné ho použít.
  </Accordion>

  <Accordion title="Zpracovávejte chyby vhodně">
    Vracejte chybové zprávy, kterým AI rozumí: `{"error": "No slots available for that date"}` namísto obecných chyb 500.
  </Accordion>

  <Accordion title="Udržujte odpovědi stručné">
    Vracejte pouze to, co AI potřebuje k pokračování v konverzaci. Velké datové objemy zpomalují dobu odezvy.
  </Accordion>

  <Accordion title="Pole povinná k vyplnění používejte uvážlivě">
    Označujte pole jako `required` pouze tehdy, když je to skutečně nutné. AI před voláním nástroje požádá uživatele o požadované informace.
  </Accordion>
</AccordionGroup>

***

## Související

<CardGroup cols={2}>
  <Card title="Připojení aplikací" icon="plug" href="/cs/guides/connect-apps">
    Nástroje spravované platformou pro HubSpot, Salesforce, Slack, Kalendář Google, Tabulky Google a Cal.com — není vyžadován žádný endpoint.
  </Card>

  <Card title="Servery MCP" icon="server" href="/cs/guides/mcp-servers">
    Připojte server MCP a umožněte agentovi volat jeho nástroje.
  </Card>

  <Card title="Připojení API" icon="code" href="/cs/guides/api-connections">
    Znovupoužitelné integrace REST, které můžete připojit k agentům.
  </Card>

  <Card title="Ověřování podpisů webhooků" icon="shield-check" href="/cs/guides/verify-webhook-signatures">
    Jeden pomocný nástroj pro ověřování webhooků a volání nástrojů.
  </Card>
</CardGroup>
