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

# Fonksiyon Araçları

> Yapay zeka ajanlarınızın görüşmeler sırasında harici API'leri çağırmasını sağlayın

İşlev araçları, yapay zeka ajanlarınızın telefon görüşmeleri sırasında harici API'leri çağırmasına olanak tanır. Bunları müşteri verilerini sorgulamak, uygunluk durumunu kontrol etmek, randevu oluşturmak veya arka ucunuzun desteklediği herhangi bir işlemi gerçekleştirmek için kullanın.

## Nasıl Çalışır

1. Araçları bir şemayla tanımlarsınız (aracın kabul ettiği argümanlar)
2. Bir `endpoint` yapılandırması sağlarsınız (ThunderPhone'un API'nizi çağırdığı yer) veya araç çağrılarını kuruluşunuzun webhook'unda almak için bunu boş bırakırsınız
3. Görüşme sırasında yapay zeka, konuşmaya göre ne zaman araç kullanacağına karar verir
4. ThunderPhone, araç argümanlarıyla birlikte endpoint'inizi çağırır
5. API yanıtınız, konuşmanın devam etmesi için yapay zekaya geri iletilir

<Note>
  İşlev araçları, kendi API'nizi kullanma seçeneğidir. ThunderPhone ayrıca
  endpoint gerektirmeyen, platform tarafından yönetilen araçlar da sunar:
  [uygulama bağlantıları](/tr/guides/connect-apps) (HubSpot, Salesforce, Slack,
  Google Calendar, Google Sheets, Cal.com),
  [API bağlantıları](/tr/guides/api-connections) ve
  [MCP sunucuları](/tr/guides/mcp-servers).
</Note>

***

## Araç Şeması

Her araç bu yapıyı izler:

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

### İşlev Tanımı

| Alan          | Tür   | Zorunlu | Açıklama                                             |
| ------------- | ----- | ------- | ---------------------------------------------------- |
| `name`        | dize  | Evet    | Araç için benzersiz tanımlayıcı                      |
| `description` | dize  | Evet    | Yapay zekaya bu aracı ne zaman kullanacağını açıklar |
| `parameters`  | nesne | Evet    | Araç argümanları için JSON Şeması                    |

### Endpoint Yapılandırması

| Alan      | Tür   | Zorunlu | Açıklama                          |
| --------- | ----- | ------- | --------------------------------- |
| `url`     | dize  | Evet    | API endpoint URL'niz              |
| `method`  | dize  | Hayır   | HTTP yöntemi (varsayılan: `POST`) |
| `headers` | nesne | Hayır   | Dahil edilecek özel üst bilgiler  |

<Note>
  `endpoint` yapılandırması yapay zeka modeline **gönderilmez**; yalnızca ThunderPhone tarafından araç çağrısını yürütmek için kullanılır.
</Note>

***

## İki çağırma yolu

Sunucunuzun aldığı isteğin türü, aracın bir
`endpoint` değeri olup olmamasına bağlıdır:

|                     | `endpoint` **olan** araç                                                   | `endpoint` **olmayan** araç                                                                 |
| ------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| İsteğin gittiği yer | Doğrudan `endpoint.url`                                                    | Kuruluşunuzun [eski webhook URL'si](/api-reference/organizations#legacy-single-url-webhook) |
| Gövde               | **Yalın araç argümanları**                                                 | `telephony.tool` / `web.tool` zarfı                                                         |
| Üst bilgiler        | `endpoint.headers` + `X-ThunderPhone-Call-ID` + `X-ThunderPhone-Signature` | `Content-Type` + `X-ThunderPhone-Signature`                                                 |
| İmzalama anahtarı   | Kuruluş webhook gizli anahtarı                                             | Kuruluş webhook gizli anahtarı                                                              |

Her iki yol da **bloklayıcıdır** — yapay zeka cümle ortasında sonucu
bekler — ve **20 sn** zaman aşımına sahiptir. İşleyicileri hızlı tutun.
Karma kullanım mümkündür: kuruluşunda webhook URL'si bulunan bir görüşmede,
`endpoint` içeren araçlar doğrudan çağrılır, diğerleri ise webhook'a geri döner.

## Doğrudan endpoint çağrıları

Yapay zeka bir `endpoint` içeren bir aracı çağırdığında ThunderPhone,
URL'nize bir istek gönderir:

### İstek Başlıkları

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

`endpoint.headers` içindeki özel başlıklar her zaman aynen eklenir;
bunlara ek olarak ThunderPhone ad alanına ait iki başlık bulunur:

* `X-ThunderPhone-Signature` — **kuruluş webhook gizli anahtarınızla**
  anahtarlanmış, tam istek gövdesi baytlarının HMAC-SHA256 değeri
* `X-ThunderPhone-Call-ID` — Geçerli çağrı kimliği

`endpoint.headers` ile geçersiz kılınmadığı sürece
`Content-Type: application/json` ayarlanır — özel bir `Content-Type`
önceliklidir.

<Warning>
  İmza, [`GET /v1/webhook`](/api-reference/organizations#legacy-single-url-webhook)
  içindeki kuruluş düzeyindeki webhook gizli anahtarıyla anahtarlanır.
  Kuruluşunuz eski webhook'u hiç yapılandırmadıysa gizli anahtar yoktur
  ve araç çağrıları **yalnızca** `X-ThunderPhone-Call-ID` içerir —
  eksik bir imzada kesin olarak başarısız olan bir işleyici bu çağrıları
  reddeder.
  Gizli anahtar edinmek için eski webhook'u yapılandırın veya kendi
  paylaşılan gizli anahtarınızı `endpoint.headers` içine ekleyin.
</Warning>

### İstek Gövdesi

`POST` / `PUT` / `PATCH` için gövde, kanonik olarak serileştirilmiş
(sıralanmış anahtarlar, sıkıştırılmış ayırıcılar) **yalnızca** araç
bağımsız değişkenlerini içerir (sarmalayıcı yoktur):

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

`GET` / `DELETE` için bağımsız değişkenler **sorgu parametreleri**
olarak gönderilir ve gövde boştur — imza bu durumda boş bayt dizisi
üzerinden hesaplanır. Bkz.
[Webhook imzalarını doğrulama](/tr/guides/verify-webhook-signatures).

### Yanıt

Araç sonucunu içeren bir JSON yanıtı döndürün:

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

Yanıt biçimlendirilir ve konuşmaya devam etmesi için yapay zekaya
sağlanır. JSON olmayan yanıtlar `{"data": "<text>"}` olarak
sarmalanır; zaman aşımları ve bağlantı hataları yapay zekaya hata
olarak bildirilir; böylece ajan duraklamak yerine özür dileyip devam
edebilir.

## Webhook modu dağıtımı

`endpoint` içermeyen araçlar, kuruluşunuzun eski webhook URL'sine
imzalı bir `telephony.tool` (telefon çağrıları) veya `web.tool`
(web çağrıları) isteği olarak gönderilir. Yürütmeden sonra webhook
endpoint'lerine teslim edilen [denetim bildirimlerinden](/tr/webhooks/events)
farklı olarak, bu istek **yürütmenin kendisidir** — HTTP yanıtınız araç
sonucudur.

```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`, `from_number` / `to_number` yerine `origin_domain` taşır.
Araç sonucuyla JSON olarak yanıt verin — doğrudan endpoint çağrılarıyla
aynı yanıt sözleşmesi geçerlidir. İstek, diğer tüm webhook'lar gibi,
ham gövde üzerinden kuruluş webhook gizli anahtarıyla imzalanır.

<Note>
  Abone olunan [webhook endpoint'leri](/tr/webhooks/endpoints), her araç
  yürütmesinden sonra (hangi yol yürüttüyse yürütülsün) aracın yanıtını
  da içeren, engellemeyen bir `telephony.tool` / `web.tool` **bildirimi
  ek olarak alır** — denetim izleri için kullanışlıdır. Bkz.
  [olay kataloğu](/tr/webhooks/events).
</Note>

***

## İmza Doğrulama

Doğrudan araç çağrıları, webhook'larla aynı şekilde imzalanır:

* Tam istek gövdesi baytları üzerinden HMAC-SHA256 (kanonik JSON — sıralanmış anahtarlar, ek boşluk olmadan)
* Kuruluşunuzun webhook gizli anahtarıyla anahtarlanır
* `GET` / `DELETE` araçları boş bayt dizisini imzalar

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

Boş gövde durumu ve gizli anahtar olmamasıyla ilgili uyarı da dahil olmak üzere tüm örnekler [Webhook imzalarını doğrulama](/tr/guides/verify-webhook-signatures) bölümünde yer alır.

***

## Örnek: Eksiksiz Randevu Akışı

Eksiksiz bir randevu rezervasyon sistemi için araç seti aşağıdadır:

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

***

## En İyi Uygulamalar

<AccordionGroup>
  <Accordion title="Açık açıklamalar yazın">
    `description` alanı, yapay zekanın aracı **ne zaman** kullanacağını anlamasına yardımcı olur. Aracın ne yaptığını ve ne zaman uygun olduğunu açıkça belirtin.
  </Accordion>

  <Accordion title="Hataları zarif bir şekilde ele alın">
    Genel 500 hataları yerine yapay zekanın anlayabileceği hata mesajları döndürün: `{"error": "No slots available for that date"}`
  </Accordion>

  <Accordion title="Yanıtları kısa tutun">
    Yalnızca yapay zekanın konuşmaya devam etmek için ihtiyaç duyduğu bilgileri döndürün. Büyük yükler yanıt sürelerini yavaşlatır.
  </Accordion>

  <Accordion title="Zorunlu alanları dikkatli kullanın">
    Alanları yalnızca gerçekten gerekli olduğunda `required` olarak işaretleyin. Yapay zeka, aracı çağırmadan önce kullanıcıdan gerekli bilgileri isteyecektir.
  </Accordion>
</AccordionGroup>

***

## İlgili

<CardGroup cols={2}>
  <Card title="Uygulama bağlantıları" icon="plug" href="/tr/guides/connect-apps">
    HubSpot, Salesforce, Slack, Google
    Calendar, Google Sheets ve Cal.com için platform tarafından yönetilen araçlar — uç nokta gerekmez.
  </Card>

  <Card title="MCP sunucuları" icon="server" href="/tr/guides/mcp-servers">
    Bir MCP sunucusu bağlayın ve ajanın araçlarını çağırmasına izin verin.
  </Card>

  <Card title="API bağlantıları" icon="code" href="/tr/guides/api-connections">
    Ajanlara bağlayabileceğiniz yeniden kullanılabilir REST entegrasyonları.
  </Card>

  <Card title="Webhook imzalarını doğrulayın" icon="shield-check" href="/tr/guides/verify-webhook-signatures">
    Webhook'lar ve araç çağrıları için tek bir doğrulama yardımcısı.
  </Card>
</CardGroup>
