---
title: "建立工具整合（API）"
description: "讓你的智慧體在對話中呼叫你的 API——搜尋資料庫、建立工單、查詢訂單。"
---

**工具整合**是可重複使用的 HTTP 端點，智慧體可在通話期間
呼叫它。你需向 ThunderPhone 提供工具的 JSON Schema 描述
以及端點 URL；智慧體會根據對話決定何時呼叫工具，而 ThunderPhone
會從其伺服器發出對外 HTTP 請求，並將回應傳回給智慧體。

<Note>
  不使用此 API 的情況下，控制台已涵蓋大多數工具需求：**連線
  → 應用程式**可透過幾次 OAuth 點擊連接 Slack、HubSpot、Salesforce、
  Google Calendar、Google Sheets 與 Cal.com；**連線 →
  API** 可將任何 HTTP API 轉為智慧體動作（貼上 cURL 指令後，
  AI 精靈會草擬工具，並提供內建的「測試請求」）；**連線 → MCP**
  可新增 MCP 伺服器。請參閱
  [連線](/zh-Hant/guides/concepts)。本指南說明 API 介面底層的
  原始 API。
</Note>

本指南會帶你從頭到尾建立天氣查詢工具。

## 工具的結構

包含兩個部分：

1. **Schema**——OpenAI 風格的函式定義
   （`{type: "function", function: {name, description, parameters}}`），
   用於告知 LLM 工具的功能及其接受的引數。
2. **端點**——當 LLM 決定使用工具時，ThunderPhone 伺服器會呼叫的
   URL。請求會以 JSON POST 形式傳送，並將 LLM 選定的引數作為
   主體。

## 1. 選擇編輯器

<CardGroup cols={2}>
  <Card title="控制台" icon="window-maximize">
    開啟 **連線 → API**，建立或編輯 API 連線，
    將參數編輯器切換為 **JSON**，然後在其中新增格式。
  </Card>
  <Card title="Integrations API" icon="plug">
    使用 `POST /v1/integrations` 建立規格，或使用
    `PATCH /v1/integrations/{id}` 更新規格。
  </Card>
</CardGroup>

兩種方式都會建立已儲存的整合。儲存後，將該整合附加至
智慧體。Agents API 沒有可寫入的內嵌 `tools`
欄位。本指南使用 Integrations API 的方式。

## 2. 建立整合

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

儲存傳回的 `id`（UUID）。標頭值僅可寫入：回應只會列出標頭名稱，之後的 `PATCH` 可傳送不含 `value` 的標頭，以保留已儲存的值。

<Tip>
  請認真撰寫工具及各參數的 `description`。LLM 會在執行期間使用這些字串來判斷是否要呼叫工具，以及如何呼叫。描述模糊 → 工具呼叫也會模糊。
</Tip>

### 在地址參數上宣告 `format: "email"`

接收電子郵件地址的參數，應在其 schema 中明確指出：

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

`format` 不只是提示。對於已解析的電子郵件 schema，ThunderPhone 在呼叫你的端點前，會修剪值兩端空白、將網域轉為小寫、把獨立出現的英文單字 `at`、`dot`、`underscore`、`dash` 與 `hyphen` 轉成對應字元，並移除 `@`、`.`、`_` 與 `-` 周圍緊鄰的空白。無論逐字稿是否已包含字面上的 `@`，這些單字的含義都相同：`"john dot smith at gmail dot com"` 會變成 `john.smith@gmail.com`。

任何其他內部空白都會遭拒絕，不會被悄悄串接。口述分隔字僅支援英文；非英文或無法辨識的含空白格式會採取封閉式失敗處理。接受有效的國際化網域與 SMTPUTF8 本機部分。Punycode 輸入在剖析器正規化後仍會保持 Punycode，Unicode 網域輸入也會保持 Unicode，因此你的 API 會收到來電者提供的慣用表示法。若最終值無效，工具**不會被呼叫**。智慧體會收到 `invalid_email_argument`，指示其與來電者確認拼寫，並重新傳送字面上的地址。

省略的選填電子郵件不會被變更。當屬性為選填或可為 null 時，`null`、空字串或僅含空白的字串也不會被變更；但對於必填且不可為 null 的電子郵件，這些值會遭拒絕。

系統會檢查本機 schema 參照，例如 `#/$defs/email` 與 `#/definitions/email`，以及 `anyOf`、`oneOf` 和 `allOf`，並設有循環與深度限制。非本機或無法解析的 `$ref` 屬於已知的強制驗證限制，會原樣傳遞；工具快照沒有可用 schema 的呼叫也是如此。需要套用此閘門時，請將電子郵件 schema 保持為本機參照。

未強制使用電子郵件格式的參數，會完全依照模型產生的內容原樣傳遞。

支援的格式為 `date-time`、`time`、`date`、`duration`、`email`、`hostname`、`ipv4`、`ipv6` 與 `uuid`；目前只有 `email` 會被正規化並強制驗證。

## 3. 在沙箱中測試端點

將整合連結至智慧體前，先從 ThunderPhone 的伺服器發送已簽署的請求，以確認連線能力：

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

此測試也會強化 ThunderPhone 的 SSRF 防護——對 localhost 或私有 IP 範圍的請求會傳回 `400 code=url_not_allowed`。

## 4. 將整合連結至智慧體

建立或更新智慧體時，透過 `integration_ids` 附加整合：

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

你可以將多個整合連結至同一個智慧體。智慧體的提示詞可以依名稱
參照它們——「當來電者詢問天氣狀況時，使用 `get_weather`」——或根據
架構描述隱含地探索它們。

## 5. 實作端點

當智慧體呼叫工具時，ThunderPhone 會向你的 `endpoint_url` 傳送已簽署的 POST 請求：

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

你的伺服器會回傳 JSON，並交回給 LLM：

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

LLM 會處理該回應，並向來電者口述自然的摘要。

<Warning>
  簽章會使用與 webhook 端點相同的 `secret`，根據原始請求本文計算。
  **請驗證簽章**——工具端點面向網際網路，與 webhook 面臨相同的偽造風險。請參閱
  [驗證 webhook 簽章](/zh-Hant/guides/verify-webhook-signatures)。
</Warning>

## 6. 測試流程

針對智慧體執行 [麥克風工作階段](/api-reference/mic-sessions)，
並提出你的工具可處理的問題（「94110 的天氣如何？」）。通話的逐字稿會顯示完整的往返流程：

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

你可以透過
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript)
取得此資訊；原始事件串流（包含每個項目的時間資訊與音訊偏移量）位於
[`GET /v1/calls/{call_id}/history`](/api-reference/calls#get-history)。

在通話清單和分析介面中，ThunderPhone 現在會將測試通話與實際流量分開報告。瀏覽器 Talk 測試和模擬可重複使用真實電話號碼，且可能顯示為撥入通話，但不會計入正式環境的通話總數、評分或問題指標。

## 常見問題

<AccordionGroup>
  <Accordion title="智慧體從未呼叫工具">
    LLM 會根據工具的描述做出決定。若來電者的問題與描述不符，模型就不會呼叫
    工具。請調整描述（加入常見同義詞與措辭），或在智慧體提示詞中明確提及它
    （「當來電者詢問天氣時，使用 `get_weather`。」）。
  </Accordion>

  <Accordion title="工具回傳過多資料">
    超過 6 kB 的回應會在逐字稿預覽中遭到截斷。只回傳 LLM 所需的欄位——不要回傳整列資料。
  </Accordion>

  <Accordion title="逾時">
    工具端點的預設逾時時間為 10 秒。若你需要更長時間，請以非同步方式處理：回傳 `{"status": "pending", "request_id": "..."}`
    並透過另一個工具呼叫提供結果。
  </Accordion>

  <Accordion title="版本管理">
    每次整合 `PATCH` 都會建立新的修訂版本。查看
    [`GET /v1/integrations/{id}/versions`](/api-reference/integrations#version-history)
    以瞭解誰變更了哪些內容。若你破壞了工具的架構，可以手動將較舊的快照 PATCH 回去以復原。
  </Accordion>
</AccordionGroup>

---

## 後續步驟

<CardGroup cols={2}>
  <Card title="整合參考資料" icon="plug" href="/api-reference/integrations">
    CRUD、轉移、版本歷程。
  </Card>
  <Card title="函式工具規格" icon="screwdriver-wrench" href="/zh-Hant/tools/overview">
    完整 JSON schema 語法與已簽署端點契約。
  </Card>
  <Card title="驗證簽章" icon="shield-check" href="/zh-Hant/guides/verify-webhook-signatures">
    將 Webhook 簽章模式套用至工具端點。
  </Card>
  <Card title="逐字稿與通話紀錄 API" icon="phone" href="/api-reference/calls">
    檢視工具呼叫的完整往返流程。
  </Card>
</CardGroup>
