---
title: "Bangun integrasi tool (API)"
description: "Biarkan agen Anda memanggil API Anda di tengah percakapan — mencari database, membuat tiket, memeriksa pesanan."
---

Integrasi **tool** adalah endpoint HTTP yang dapat digunakan kembali dan dapat
dipanggil oleh agen selama panggilan. Anda memberikan ThunderPhone deskripsi skema JSON
untuk tool tersebut beserta URL endpoint; agen memutuskan kapan harus memanggilnya
berdasarkan percakapan, dan ThunderPhone membuat permintaan HTTP keluar dari servernya
serta mengembalikan respons kepada agen.

<Note>
  Dasbor mencakup sebagian besar kebutuhan tool tanpa API ini: **Koneksi
  → Aplikasi** menghubungkan Slack, HubSpot, Salesforce, Google Calendar,
  Google Sheets, dan Cal.com dengan beberapa klik OAuth; **Koneksi →
  APIs** mengubah API HTTP apa pun menjadi tindakan agen (tempel perintah cURL
  dan panduan AI menyusun draf tool, dengan Uji Permintaan bawaan); serta
  **Koneksi → MCP** menambahkan server MCP. Lihat
  [Koneksi](/id/guides/concepts). Panduan ini membahas
  API mentah yang mendasari antarmuka APIs.
</Note>

Panduan ini menjelaskan pembuatan tool pencarian cuaca dari awal hingga akhir.

## Struktur sebuah tool

Dua bagian:

1. **Skema** — definisi fungsi bergaya OpenAI
   (`{type: "function", function: {name, description, parameters}}`)
   yang memberi tahu LLM fungsi tool dan argumen yang diterimanya.
2. **Endpoint** — URL yang dipanggil server ThunderPhone saat
   LLM memutuskan untuk menggunakan tool tersebut. Permintaannya berupa JSON POST dengan
   argumen yang dipilih LLM sebagai isi permintaan.

## 1. Pilih editor

<CardGroup cols={2}>
  <Card title="Dasbor" icon="window-maximize">
    Buka **Koneksi → APIs**, buat atau edit koneksi API,
    alihkan editor parameter ke **JSON**, lalu tambahkan formatnya di sana.
  </Card>
  <Card title="API Integrasi" icon="plug">
    Buat spesifikasi dengan `POST /v1/integrations`, atau perbarui dengan
    `PATCH /v1/integrations/{id}`.
  </Card>
</CardGroup>

Kedua jalur membuat integrasi tersimpan. Hubungkan integrasi tersebut ke
agen setelah menyimpannya. API Agen tidak memiliki field `tools`
inline yang dapat ditulis. Panduan ini menggunakan jalur API integrasi.

## 2. Buat integrasi

```bash
curl -X POST https://api.thunderphone.com/v1/integrations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Weather API",
    "spec": {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a zip code.",
        "parameters": {
          "type": "object",
          "properties": {
            "zip": { "type": "string", "description": "5-digit US ZIP code" }
          },
          "required": ["zip"]
        }
      }
    },
    "endpoint_url":    "https://api.example.com/weather",
    "endpoint_method": "GET",
    "headers": [
      { "key": "X-Api-Key", "value": "your-provider-key" }
    ]
  }'
```

Simpan `id` yang dikembalikan (UUID). Nilai header hanya dapat ditulis: respons hanya mencantumkan nama header, dan `PATCH` berikutnya dapat mengirim header tanpa `value` untuk mempertahankan nilai yang tersimpan.

<Tip>
  Berikan perhatian sungguh-sungguh pada `description` alat dan setiap
  parameter. LLM menggunakan string ini saat runtime untuk memutuskan apakah
  dan bagaimana memanggil alat. Deskripsi yang tidak spesifik → pemanggilan alat yang tidak spesifik.
</Tip>

### Deklarasikan `format: "email"` pada parameter alamat

Parameter yang menerima alamat email harus menyatakannya dalam
skemanya:

```json
"email": { "type": "string", "format": "email", "description": "The caller's email address" }
```

`format` lebih dari sekadar petunjuk. Untuk skema email yang telah
diresolusikan, sebelum endpoint Anda dipanggil ThunderPhone memangkas nilainya,
mengubah domain menjadi huruf kecil, mengubah kata bahasa Inggris mandiri
`at`, `dot`, `underscore`, `dash`, dan `hyphen` menjadi karakter terkait, serta
menghapus spasi tepat di sekitar `@`, `.`, `_`, dan `-`. Kata-kata tersebut memiliki arti yang sama,
baik transkrip sudah berisi karakter literal `@` maupun belum:
`"john dot smith at gmail dot com"` menjadi
`john.smith@gmail.com`.

Spasi internal lainnya ditolak, bukan digabungkan secara diam-diam.
Kata pemisah yang diucapkan hanya tersedia dalam bahasa Inggris; bentuk
berjarak non-Inggris atau yang tidak dikenali akan ditolak secara aman. Domain internasionalisasi yang valid dan bagian lokal SMTPUTF8 diterima. Input Punycode tetap berupa Punycode dan input domain Unicode tetap berupa Unicode setelah normalisasi parser, sehingga API Anda menerima representasi konvensional yang diberikan penelepon. Jika nilai akhir tidak valid, alat **tidak dipanggil**. Agen menerima
`invalid_email_argument` yang memintanya
untuk mengonfirmasi ejaan dengan penelepon dan mengirim ulang alamat literal.

Email opsional yang dihilangkan tidak diubah. `null`, string kosong, atau
string yang hanya berisi spasi juga tidak diubah jika properti bersifat opsional
atau nullable; nilai yang sama ditolak untuk email yang wajib dan non-nullable.

Referensi skema lokal seperti `#/$defs/email` dan
`#/definitions/email`, serta `anyOf`, `oneOf`, dan `allOf`, diperiksa
dengan batas siklus dan kedalaman. `$ref` non-lokal atau yang tidak dapat diresolusikan merupakan
batas penegakan yang diketahui dan diteruskan tanpa perubahan, begitu pula panggilan
yang snapshot alatnya tidak memiliki skema yang dapat digunakan. Pertahankan skema email tetap lokal saat
Anda memerlukan penerapan gerbang ini.

Parameter tanpa format email yang diterapkan diteruskan persis
sebagaimana dihasilkan oleh model.

Format yang didukung adalah `date-time`, `time`, `date`, `duration`,
`email`, `hostname`, `ipv4`, `ipv6`, dan `uuid`; hanya `email` yang
dinormalisasi dan diterapkan saat ini.

## 3. Uji endpoint di sandbox

Sebelum menautkan integrasi ke agen, kirim permintaan bertanda tangan
dari server ThunderPhone untuk mengonfirmasi konektivitas:

```bash
curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url":    "https://api.example.com/weather?zip=94110",
    "method": "GET",
    "headers": { "X-Api-Key": "your-provider-key" }
  }'
```

```json Response
{
  "ok": true,
  "status": 200,
  "elapsed_ms": 187,
  "response_headers": { "content-type": "application/json" },
  "response_preview": "{\"temperature_f\": 64, ...}"
}
```

Pengujian ini juga memperkuat perlindungan SSRF ThunderPhone — permintaan ke
localhost atau rentang IP privat mengembalikan `400 code=url_not_allowed`.

## 4. Tautkan integrasi ke agen

Lampirkan melalui `integration_ids` saat Anda membuat atau memperbarui agen:

```bash
curl -X PATCH https://api.thunderphone.com/v1/agents/12 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "integration_ids": ["f9b5a1a4-..."]
  }'
```

Anda dapat menautkan banyak integrasi ke satu agen. Prompt agen dapat
merujuknya berdasarkan nama — "gunakan `get_weather` saat penelepon menanyakan
tentang kondisi cuaca" — atau agen dapat menemukannya secara implisit dari
deskripsi skema.

## 5. Implementasikan endpoint

Saat agen memanggil tool, ThunderPhone mengirim POST bertanda tangan ke
`endpoint_url` Anda:

```
POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<HMAC-SHA256 hex>
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json

{"zip": "94110"}
```

Server Anda merespons dengan JSON yang diteruskan kembali ke LLM:

```json
{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}
```

LLM memproses respons tersebut dan menyampaikan ringkasan yang mudah dipahami
kepada penelepon.

<Warning>
  Tanda tangan dihitung berdasarkan isi permintaan mentah menggunakan
  `secret` yang sama dengan endpoint webhook Anda. **Verifikasi tanda tangan tersebut** — endpoint tool
  dapat diakses dari internet dan menghadapi risiko pemalsuan yang sama seperti
  webhook. Lihat
  [Verifikasi tanda tangan webhook](/id/guides/verify-webhook-signatures).
</Warning>

## 6. Uji alurnya

Jalankan [sesi mikrofon](/api-reference/mic-sessions) terhadap agen
dan ajukan pertanyaan yang ditangani tool Anda ("Bagaimana cuaca di
94110?"). Transkrip panggilan menampilkan perjalanan lengkapnya:

```json
{
  "call_id": 987654321,
  "transcripts": [
    { "role": "user",
      "content": "What's the weather in 94110?" },
    { "role": "tool_call",
      "content": "{\"tool_call\": \"get_weather\", \"arguments\": {\"zip\": \"94110\"}}" },
    { "role": "tool_response",
      "content": "{\"tool_name\": \"get_weather\", \"response\": {\"temperature_f\": 64, \"condition\": \"Partly cloudy\"}}" },
    { "role": "agent",
      "content": "It's 64 degrees and partly cloudy." }
  ]
}
```

Anda dapat mengambilnya melalui
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript);
aliran peristiwa mentah (dengan waktu per entri dan offset audio) tersedia di
[`GET /v1/calls/{call_id}/history`](/api-reference/calls#get-history).

Di tampilan daftar panggilan dan analitik, ThunderPhone kini melaporkan panggilan pengujian secara terpisah dari trafik nyata. Pengujian dan simulasi Browser Talk dapat menggunakan kembali nomor telepon nyata dan mungkin terlihat sebagai panggilan masuk, tetapi tidak dihitung dalam total panggilan produksi, penilaian, atau metrik masalah.

## Kendala umum

<AccordionGroup>
  <Accordion title="Agen tidak pernah memanggil tool">
    LLM memutuskan berdasarkan deskripsi tool. Jika pertanyaan penelepon
    tidak sesuai dengan deskripsi, model tidak akan memanggil
    tool. Perjelas deskripsi (tambahkan sinonim dan frasa umum)
    atau sebutkan secara eksplisit dalam Prompt agen ("Saat
    penelepon menanyakan cuaca, gunakan `get_weather`.").
  </Accordion>

  <Accordion title="Tool mengembalikan terlalu banyak data">
    Respons yang melebihi 6 kB dipotong dalam pratinjau transkrip. Kembalikan
    hanya kolom yang dibutuhkan LLM — bukan seluruh baris Anda.
  </Accordion>

  <Accordion title="Waktu habis">
    Endpoint tool memiliki batas waktu default 10 detik. Jika Anda memerlukan waktu lebih lama,
    tangani secara asinkron: kembalikan `{"status": "pending", "request_id": "..."}`
    dan tampilkan hasilnya melalui panggilan tool terpisah.
  </Accordion>

  <Accordion title="Pembuatan versi">
    Setiap `PATCH` integrasi membuat revisi baru. Periksa
    [`GET /v1/integrations/{id}/versions`](/api-reference/integrations#version-history)
    untuk melihat siapa yang mengubah apa. Jika Anda merusak skema tool,
    Anda dapat melakukan rollback secara manual dengan melakukan PATCH pada snapshot lama.
  </Accordion>
</AccordionGroup>

---

## Langkah selanjutnya

<CardGroup cols={2}>
  <Card title="Referensi integrasi" icon="plug" href="/api-reference/integrations">
    CRUD, transfer, riwayat versi.
  </Card>
  <Card title="Spesifikasi Function Tools" icon="screwdriver-wrench" href="/id/tools/overview">
    Tata bahasa skema JSON lengkap dan kontrak endpoint bertanda tangan.
  </Card>
  <Card title="Verifikasi tanda tangan" icon="shield-check" href="/id/guides/verify-webhook-signatures">
    Terapkan pola tanda tangan webhook pada endpoint alat.
  </Card>
  <Card title="API transkrip + riwayat" icon="phone" href="/api-reference/calls">
    Periksa seluruh alur pulang-pergi panggilan alat.
  </Card>
</CardGroup>
