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

# Funkciju rīki

> Ļaujiet saviem balss aģentiem sarunu laikā izsaukt ārējas API

Funkciju rīki ļauj jūsu balss aģentiem tālruņa zvanu laikā izsaukt ārējas API. Izmantojiet tos, lai meklētu klientu datus, pārbaudītu pieejamību, rezervētu tikšanās vai veiktu jebkuru darbību, ko atbalsta jūsu aizmugursistēma.

## Kā tas darbojas

1. Definējiet rīkus ar shēmu (kādus argumentus rīks pieņem)
2. Norādiet `endpoint` konfigurāciju (kur ThunderPhone izsauc jūsu API) — vai neiekļaujiet to, lai rīku izsaukumus saņemtu organizācijas webhook
3. Zvanu laikā AI, pamatojoties uz sarunu, izlemj, kad izmantot rīku
4. ThunderPhone izsauc jūsu galapunktu ar rīka argumentiem
5. Jūsu API atbilde tiek nodota atpakaļ AI, lai turpinātu sarunu

<Note>
  Funkciju rīki ir iespēja izmantot savu API. ThunderPhone piedāvā arī
  platformas pārvaldītus rīkus, kuriem nav nepieciešams galapunkts:
  [lietotņu savienojumi](/lv/guides/connect-apps) (HubSpot, Salesforce, Slack,
  Google Calendar, Google Sheets, Cal.com),
  [API savienojumi](/lv/guides/api-connections) un
  [MCP serveri](/lv/guides/mcp-servers).
</Note>

***

## Rīka shēma

Katrs rīks izmanto šādu struktūru:

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

### Funkcijas definīcija

| Lauks         | Tips   | Obligāts | Apraksts                        |
| ------------- | ------ | -------- | ------------------------------- |
| `name`        | string | Jā       | Unikāls rīka identifikators     |
| `description` | string | Jā       | Norāda AI, kad izmantot šo rīku |
| `parameters`  | object | Jā       | JSON shēma rīka argumentiem     |

### Galapunkta konfigurācija

| Lauks     | Tips   | Obligāts | Apraksts                          |
| --------- | ------ | -------- | --------------------------------- |
| `url`     | string | Jā       | Jūsu API galapunkta URL           |
| `method`  | string | Nē       | HTTP metode (noklusējums: `POST`) |
| `headers` | object | Nē       | Iekļaujamās pielāgotās galvenes   |

<Note>
  `endpoint` konfigurācija AI modelim **netiek** nosūtīta — ThunderPhone to izmanto tikai rīka izsaukuma izpildei.
</Note>

***

## Divi izsaukšanas ceļi

Tas, kuru pieprasījumu saņem jūsu serveris, ir atkarīgs no tā, vai rīkam ir
`endpoint`:

|                                | Rīks **ar** `endpoint`                                                          | Rīks **bez** `endpoint`                                                                          |
| ------------------------------ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Kur tiek nosūtīts pieprasījums | Tieši uz `endpoint.url`                                                         | Jūsu organizācijas [mantotā webhook URL](/api-reference/organizations#legacy-single-url-webhook) |
| Pamatteksts                    | **Tikai rīka argumenti**                                                        | `telephony.tool` / `web.tool` aploksne                                                           |
| Galvenes                       | Jūsu `endpoint.headers` + `X-ThunderPhone-Call-ID` + `X-ThunderPhone-Signature` | `Content-Type` + `X-ThunderPhone-Signature`                                                      |
| Parakstīšanas atslēga          | Organizācijas webhook noslēpums                                                 | Organizācijas webhook noslēpums                                                                  |

Abi ceļi ir **bloķējoši** — AI rezultātu gaida teikuma vidū — un tiem ir
**20 s** noildze. Nodrošiniet ātru apstrādātāju darbību. Var izmantot abus:
zvanā, kura organizācijai ir webhook URL, rīki ar `endpoint` tiek
izsaukti tieši, bet pārējiem tiek izmantots webhook.

## Tiešie galapunktu izsaukumi

Kad AI izsauc rīku, kuram ir `endpoint`, ThunderPhone nosūta
pieprasījumu uz jūsu URL:

### Pieprasījuma galvenes

```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
```

Pielāgotās galvenes no jūsu `endpoint.headers` vienmēr tiek iekļautas
burtiski, kā arī divas ThunderPhone vārdtelpas galvenes:

* `X-ThunderPhone-Signature` — precīzo pieprasījuma pamatteksta
  baitu HMAC-SHA256, izmantojot jūsu **organizācijas tīmekļa aizķeres noslēpumu**
* `X-ThunderPhone-Call-ID` — pašreizējās sarunas ID

`Content-Type: application/json` tiek iestatīts, ja vien jūsu `endpoint.headers`
to nepārraksta — pielāgots `Content-Type` ir noteicošais.

<Warning>
  Parakstam tiek izmantots organizācijas līmeņa tīmekļa aizķeres noslēpums no
  [`GET /v1/webhook`](/api-reference/organizations#legacy-single-url-webhook).
  Ja jūsu organizācija nekad nav konfigurējusi mantoto tīmekļa aizķeri, noslēpuma
  nav, un rīku izsaukumos ir **tikai** `X-ThunderPhone-Call-ID` — apstrādātājs,
  kas pārtrauc darbu, ja paraksta nav, tos noraidīs.
  Vai nu konfigurējiet mantoto tīmekļa aizķeri, lai iegūtu noslēpumu, vai ievietojiet
  savu koplietojamo noslēpumu sadaļā `endpoint.headers`.
</Warning>

### Pieprasījuma pamatteksts

`POST` / `PUT` / `PATCH` pieprasījumiem pamattekstā ir **tikai** rīka
argumenti (bez aplauka), kas serializēti kanoniski (sakārtotas atslēgas,
kompakti atdalītāji):

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

`GET` / `DELETE` pieprasījumiem argumenti tiek nosūtīti kā **vaicājuma parametri**,
un pamatteksts ir tukšs — paraksts tad tiek aprēķināts tukšajai
baitu virknei. Skatiet
[Tīmekļa aizķeres parakstu pārbaude](/lv/guides/verify-webhook-signatures).

### Atbilde

Atgrieziet JSON atbildi ar rīka rezultātu:

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

Atbilde tiek formatēta un nodota AI, lai turpinātu
sarunu. Atbildes, kas nav JSON, tiek ietītas kā `{"data": "<text>"}`;
par noildzēm un savienojuma kļūmēm AI tiek ziņots kā par kļūdām, lai
balss aģents varētu atvainoties un turpināt, nevis apstāties.

## Nosūtīšana tīmekļa aizķeres režīmā

Rīki **bez** `endpoint` tiek nosūtīti uz jūsu organizācijas mantotās
tīmekļa aizķeres URL kā parakstīts `telephony.tool` (tālruņa zvani) vai `web.tool`
(tīmekļa zvani) pieprasījums. Atšķirībā no [audita paziņojumiem](/lv/webhooks/events),
kas pēc izpildes tiek piegādāti tīmekļa aizķeres galapunktiem, šis pieprasījums
**ir** izpilde — jūsu HTTP atbilde ir rīka rezultāts.

```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` satur `origin_domain`, nevis `from_number` /
`to_number`. Atbildiet ar rīka rezultātu JSON formātā — tas ir tas pats
atbildes līgums kā tiešajiem galapunktu izsaukumiem. Pieprasījums tiek parakstīts
ar organizācijas tīmekļa aizķeres noslēpumu, izmantojot neapstrādāto pamattekstu, tāpat kā
katra cita tīmekļa aizķere.

<Note>
  Abonētie [tīmekļa aizķeres galapunkti](/lv/webhooks/endpoints) papildus
  saņem neblokējošu `telephony.tool` / `web.tool` **paziņojumu
  pēc** katra rīka izpildes (neatkarīgi no ceļa, kas to izpildīja), tostarp
  rīka atbildi — noderīgi audita pierakstiem. Skatiet
  [notikumu katalogu](/lv/webhooks/events).
</Note>

***

## Paraksta verificēšana

Tiešie rīku izsaukumi tiek parakstīti tāpat kā tīmekļa aizķeres:

* HMAC-SHA256, izmantojot precīzus pieprasījuma pamatteksta baitus (kanoniskais JSON —
  sakārtotas atslēgas, bez papildu atstarpēm)
* Ar jūsu organizācijas tīmekļa aizķeres noslēpumu
* `GET` / `DELETE` rīki paraksta tukšu baitu virkni

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

Pilnas receptes — tostarp tukša pamatteksta gadījumam un situācijai, kad nav noslēpuma, —
ir pieejamas sadaļā [Tīmekļa aizķeres parakstu verificēšana](/lv/guides/verify-webhook-signatures).

***

## Piemērs: pilnīga rezervēšanas plūsma

Šeit ir rīku kopa pilnīgai pierakstu rezervēšanas sistēmai:

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

***

## Paraugprakse

<AccordionGroup>
  <Accordion title="Rakstiet skaidrus aprakstus">
    Lauks `description` palīdz MI saprast, **kad** izmantot rīku. Konkrēti norādiet, ko tas dara un kad to ir lietderīgi izmantot.
  </Accordion>

  <Accordion title="Kļūdas apstrādājiet korekti">
    Atgrieziet MI saprotamus kļūdu ziņojumus: `{"error": "No slots available for that date"}` vispārīgu 500 kļūdu vietā.
  </Accordion>

  <Accordion title="Saglabājiet atbildes īsas">
    Atgrieziet tikai to, kas MI nepieciešams sarunas turpināšanai. Lielas datu paketes palēnina atbildes laiku.
  </Accordion>

  <Accordion title="Pārdomāti izmantojiet obligātos laukus">
    Atzīmējiet laukus kā `required` tikai tad, ja tas patiešām ir nepieciešams. Pirms rīka izsaukšanas MI lūgs lietotājam norādīt obligāto informāciju.
  </Accordion>
</AccordionGroup>

***

## Saistītā informācija

<CardGroup cols={2}>
  <Card title="Lietotņu savienojumi" icon="plug" href="/lv/guides/connect-apps">
    Platformas pārvaldīti rīki HubSpot, Salesforce, Slack, Google
    Calendar, Google Sheets un Cal.com — galapunkts nav nepieciešams.
  </Card>

  <Card title="MCP serveri" icon="server" href="/lv/guides/mcp-servers">
    Pievienojiet MCP serveri un ļaujiet balss aģentam izsaukt tā rīkus.
  </Card>

  <Card title="API savienojumi" icon="code" href="/lv/guides/api-connections">
    Atkārtoti izmantojamas REST integrācijas, ko varat pievienot balss aģentiem.
  </Card>

  <Card title="Pārbaudiet tīmekļa aizķeres parakstus" icon="shield-check" href="/lv/guides/verify-webhook-signatures">
    Viens pārbaudes palīgrīks tīmekļa aizķerēm un rīku izsaukumiem.
  </Card>
</CardGroup>
