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

# Funkcióeszközök

> Tegye lehetővé, hogy AI-ügynökei külső API-kat hívjanak meg a beszélgetések során

A funkcióeszközök lehetővé teszik, hogy AI-ügynökei telefonhívások közben külső API-kat hívjanak meg. Használja őket ügyféladatok lekérdezésére, elérhetőség ellenőrzésére, időpontfoglalásra vagy bármely, a háttérrendszere által támogatott művelet elvégzésére.

## Működése

1. Sémával definiálja az eszközöket (milyen argumentumokat fogad el az eszköz)
2. Megad egy `endpoint` konfigurációt (ahol a ThunderPhone meghívja az API-ját) — vagy kihagyja, hogy az eszközhívásokat a szervezete webhookján fogadja
3. Hívás közben az AI a beszélgetés alapján dönti el, mikor használjon egy eszközt
4. A ThunderPhone meghívja az endpointját az eszköz argumentumaival
5. Az API válasza visszakerül az AI-hoz, hogy folytathassa a beszélgetést

<Note>
  A funkcióeszközök a saját API használatára szolgáló megoldást jelentik. A ThunderPhone
  olyan, platform által kezelt eszközöket is kínál, amelyekhez nincs szükség endpointra:
  [alkalmazáskapcsolatok](/hu/guides/connect-apps) (HubSpot, Salesforce, Slack,
  Google Calendar, Google Sheets, Cal.com),
  [API-kapcsolatok](/hu/guides/api-connections) és
  [MCP-szerverek](/hu/guides/mcp-servers).
</Note>

***

## Eszközséma

Minden eszköz ezt a struktúrát követi:

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

### Funkciódefiníció

| Mező          | Típus  | Kötelező | Leírás                                                 |
| ------------- | ------ | -------- | ------------------------------------------------------ |
| `name`        | string | Igen     | Az eszköz egyedi azonosítója                           |
| `description` | string | Igen     | Elmagyarázza az AI-nak, mikor használja ezt az eszközt |
| `parameters`  | object | Igen     | JSON-séma az eszköz argumentumaihoz                    |

### Endpoint konfiguráció

| Mező      | Típus  | Kötelező | Leírás                                 |
| --------- | ------ | -------- | -------------------------------------- |
| `url`     | string | Igen     | Az API-endpoint URL-je                 |
| `method`  | string | Nem      | HTTP-metódus (alapértelmezett: `POST`) |
| `headers` | object | Nem      | Felvenni kívánt egyéni fejlécek        |

<Note>
  Az `endpoint` konfiguráció **nem** kerül elküldésre az AI-modellnek — azt csak a ThunderPhone használja az eszközhívás végrehajtására.
</Note>

***

## Két meghívási útvonal

Az, hogy a szervere melyik kérést kapja, attól függ, hogy az eszköz rendelkezik-e
`endpoint` konfigurációval:

|                  | `endpoint` konfigurációval rendelkező eszköz                                              | `endpoint` konfiguráció nélküli eszköz                                                       |
| ---------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| A kérés célhelye | Közvetlenül az `endpoint.url` címre                                                       | A szervezete [régi webhook URL-jére](/api-reference/organizations#legacy-single-url-webhook) |
| Törzs            | **Csak az eszköz argumentumai**                                                           | `telephony.tool` / `web.tool` boríték                                                        |
| Fejlécek         | Az Ön `endpoint.headers` fejlécei + `X-ThunderPhone-Call-ID` + `X-ThunderPhone-Signature` | `Content-Type` + `X-ThunderPhone-Signature`                                                  |
| Aláírókulcs      | A szervezet webhook-titka                                                                 | A szervezet webhook-titka                                                                    |

Mindkét útvonal **blokkoló** — az AI a mondat közepén vár az
eredményre —, és **20 mp** időkorláttal rendelkezik. Tartsa gyorsan a kezelőket. A
vegyes használat is megfelelő: olyan hívás esetén, amelynek szervezete rendelkezik webhook URL-lel, az
`endpoint` konfigurációval rendelkező eszközök közvetlenül hívódnak meg, a többi pedig
a webhookra vált vissza.

## Közvetlen végpont-hívások

Amikor az AI-ügynök meghív egy `endpoint`-tal rendelkező eszközt, a ThunderPhone
kérést küld az Ön URL-jére:

### Kérésfejlécek

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

Az `endpoint.headers` egyéni fejlécei mindig változatlanul szerepelnek,
valamint két ThunderPhone-névterű fejléc:

* `X-ThunderPhone-Signature` — a pontos kéréstörzs bájtjainak HMAC-SHA256 értéke,
  az Ön **szervezeti webhooktitkával** kulcsolva
* `X-ThunderPhone-Call-ID` — Az aktuális hívásazonosító

A `Content-Type: application/json` be van állítva, kivéve, ha az `endpoint.headers`
felülírja — az egyéni `Content-Type` élvez elsőbbséget.

<Warning>
  Az aláírás a szervezetszintű webhooktitokkal van kulcsolva, amely a
  [`GET /v1/webhook`](/api-reference/organizations#legacy-single-url-webhook)
  végpontból származik. Ha az Ön szervezete még soha nem konfigurálta a régi
  webhookot, nincs titok, és az eszközhívások **csak** az
  `X-ThunderPhone-Call-ID` fejlécet tartalmazzák — egy hiányzó aláírás esetén
  hibával leálló kezelő elutasítaná őket.
  Konfigurálja a régi webhookot a titok megszerzéséhez, vagy helyezze el saját
  megosztott titkát az `endpoint.headers` mezőben.
</Warning>

### Kéréstörzs

`POST` / `PUT` / `PATCH` esetén a törzs **csak** az eszköz argumentumait
tartalmazza (burkoló nélkül), kanonikusan szerializálva (rendezett kulcsok,
tömör elválasztók):

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

`GET` / `DELETE` esetén az argumentumok **lekérdezési paraméterekként**
kerülnek elküldésre, a törzs pedig üres — az aláírás ilyenkor az üres
bájtsoron kerül kiszámításra. Lásd:
[Webhook-aláírások ellenőrzése](/hu/guides/verify-webhook-signatures).

### Válasz

Adjon vissza egy JSON-választ az eszköz eredményével:

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

A válasz formázásra kerül, és az AI megkapja a beszélgetés folytatásához.
A nem JSON-válaszok `{"data": "<text>"}` formában vannak becsomagolva;
az időtúllépéseket és a kapcsolati hibákat az AI hibaként kapja meg, így az
ügynök bocsánatot kérhet és továbbléphet, ahelyett hogy megakadna.

## Webhook módú továbbítás

Az `endpoint` nélküli eszközök a szervezete régi webhook-URL-jére kerülnek
továbbításra aláírt `telephony.tool` (telefonhívások) vagy `web.tool`
(webes hívások) kérésként. A végrehajtás után webhook-végpontokra kézbesített
[auditértesítésekkel](/hu/webhooks/events) ellentétben ez a kérés **maga**
a végrehajtás — az Ön HTTP-válasza az eszköz eredménye.

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

A `web.tool` a `from_number` / `to_number` helyett `origin_domain` mezőt
tartalmaz. Az eszköz eredményét JSON-ként adja vissza — ugyanaz a válaszszerződés,
mint a közvetlen végpont-hívásoknál. A kérés a szervezeti webhooktitokkal,
a nyers törzs alapján van aláírva, mint minden más webhook.

<Note>
  A feliratkozott [webhook-végpontok](/hu/webhooks/endpoints) ezen felül nem blokkoló
  `telephony.tool` / `web.tool` **értesítést kapnak minden eszköz végrehajtása
  után** (bármelyik útvonal futtatta is), beleértve az eszköz válaszát is —
  hasznos auditnaplókhoz. Lásd az
  [eseménykatalógust](/hu/webhooks/events).
</Note>

***

## Aláírás-ellenőrzés

A közvetlen eszközhívások aláírása ugyanúgy történik, mint a webhookoké:

* HMAC-SHA256 a kérés törzsének pontos bájtjain (a kanonikus JSON-on — rendezett kulcsokkal, extra szóközök nélkül)
* Az Ön szervezetének webhooktitkával kulcsolva
* A `GET` / `DELETE` eszközök az üres bájtsorozatot írják alá

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

A teljes példák — beleértve az üres törzs esetét és a titok hiányára vonatkozó megjegyzést — a [Webhook-aláírások ellenőrzése](/hu/guides/verify-webhook-signatures) útmutatóban találhatók.

***

## Példa: teljes foglalási folyamat

Íme egy teljes időpontfoglalási rendszerhez tartozó eszközkészlet:

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

***

## Ajánlott eljárások

<AccordionGroup>
  <Accordion title="Írjon egyértelmű leírásokat">
    A `description` mező segít az AI-nak megérteni, **mikor** használja az eszközt. Pontosan írja le, mit végez, és mikor célszerű használni.
  </Accordion>

  <Accordion title="Kezelje elegánsan a hibákat">
    Az AI számára érthető hibaüzeneteket adjon vissza: `{"error": "No slots available for that date"}` általános 500-as hibák helyett.
  </Accordion>

  <Accordion title="Tartsa tömören a válaszokat">
    Csak azt adja vissza, amire az AI-nak szüksége van a beszélgetés folytatásához. A nagy adatcsomagok lassítják a válaszidőt.
  </Accordion>

  <Accordion title="Használja körültekintően a kötelező mezőket">
    Csak akkor jelölje a mezőket `required` értékűként, ha valóban szükséges. Az AI az eszköz meghívása előtt bekéri a felhasználótól a kötelező információkat.
  </Accordion>
</AccordionGroup>

***

## Kapcsolódó témák

<CardGroup cols={2}>
  <Card title="Alkalmazáskapcsolatok" icon="plug" href="/hu/guides/connect-apps">
    A platform által kezelt eszközök a HubSpothoz, a Salesforce-hoz, a Slackhez, a Google
    Calendarhoz, a Google Sheetshöz és a Cal.comhoz — nincs szükség végpontra.
  </Card>

  <Card title="MCP-szerverek" icon="server" href="/hu/guides/mcp-servers">
    Csatlakoztasson MCP-szervert, és engedje, hogy az ügynök meghívja annak eszközeit.
  </Card>

  <Card title="API-kapcsolatok" icon="code" href="/hu/guides/api-connections">
    Újrahasználható REST-integrációk, amelyeket ügynökökhöz csatolhat.
  </Card>

  <Card title="Webhook-aláírások ellenőrzése" icon="shield-check" href="/hu/guides/verify-webhook-signatures">
    Egy ellenőrzési segédfüggvény webhookokhoz és eszközhívásokhoz.
  </Card>
</CardGroup>
