ThunderPhone 2.0 正式登場。自助開通,價格低至每分鐘 2¢查看公告

Function Tools

函數工具

為你的 AI 智能體提供函數工具,可在對話期間呼叫外部 API——擷取客戶資料、預約、更新記錄——並支援具類型的參數。

函數工具讓你的 AI 智能體可在通話期間調用外部 API。你可用它們查詢客戶資料、檢查可用時段、預約服務,或執行後端支援的任何操作。

運作方式

  1. 以綱要定義工具(工具可接受哪些參數)
  2. 提供 endpoint 設定(ThunderPhone 在何處調用你的 API)——或不設定,以便透過組織 webhook 接收工具調用
  3. 通話期間,AI 會根據對話決定何時使用工具
  4. ThunderPhone 會連同工具參數調用你的端點
  5. 你的 API 回應會傳回 AI,以繼續對話
功能執行位置設定方式
內建工具ThunderPhone提示指示;部分工具亦需要設定智能體
應用程式連接ThunderPhone 及已連接的服務供應商連接帳戶並附加已核准操作
API 連接及函數工具你的 HTTP API定義端點及綱要,或透過 webhook 接收函數調用
MCP 伺服器遠端 MCP 伺服器新增伺服器、探索其工具,並將其附加至智能體

工具綱要

每個工具均遵循以下結構:

{
  "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"
    }
  },
  "timeout": 120
}

工具設定

欄位類型必填說明
timeout數字最長執行時間,以秒計(預設:20,上限:180

函數定義

欄位類型必填說明
name字串工具的唯一識別碼
description字串向 AI 說明何時使用此工具
parameters物件工具參數的 JSON 綱要

端點設定

欄位類型必填說明
url字串你的 API 端點 URL
method字串HTTP 方法(預設:POST
headers物件要包括的自訂標頭

兩種調用路徑

你的伺服器會收到哪一種請求,取決於工具是否設有 endpoint

設有 endpoint 的工具不設 endpoint 的工具
請求發送位置直接發送至 endpoint.url你的組織舊版 webhook URL
內文純工具參數telephony.tool / web.tool 封裝
標頭你的 endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature
簽署金鑰組織 webhook 密鑰組織 webhook 密鑰

兩種路徑均為阻塞式——AI 會在句子中途等待 結果。預設逾時時間為 20 s;設定工具頂層的 timeout 可允許較長執行時間,最高為平台的 180 s 上限。請保持處理程式快速執行。可混合使用: 在組織設有 webhook URL 的通話中,設有 endpoint 的工具會 直接調用,其餘則回退至 webhook。

直接端點呼叫

當 AI 呼叫具有 endpoint 的工具時,ThunderPhone 會向你的 URL 傳送 請求:

請求標頭

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 中的自訂標頭一律會原樣包含, 另外亦會加入兩個 ThunderPhone 命名空間標頭:

  • X-ThunderPhone-Signature —— 使用你的機構 webhook 密鑰作為金鑰,對完全一致的請求主體 位元組計算的 HMAC-SHA256
  • X-ThunderPhone-Call-ID —— 目前的通話 ID

除非你的 endpoint.headers 覆寫,否則會設定 Content-Type: application/json —— 自訂 Content-Type 會優先採用。

請求主體

對於 POST / PUT / PATCH,主體只包含工具 引數(不含包裝層),並會以標準格式序列化(鍵已排序,分隔符號精簡):

{"date":"2025-01-02","service":"consultation"}

對於 GET / DELETE,引數會以查詢參數傳送, 而主體為空 —— 簽名會根據空位元組字串計算。請參閱 驗證 webhook 簽名

回應

以 JSON 回應工具結果:

{
  "available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
  "timezone": "America/Los_Angeles"
}

回應會經過格式化並提供予 AI,以繼續對話。非 JSON 回應會包裝為 {"data": "<text>"};逾時及連線失敗會以錯誤形式報告予 AI, 讓智能體可以致歉並繼續處理,而不會停滯。

Webhook 模式分派

沒有 endpoint 的工具,會以已簽署的 telephony.tool(電話通話)或 web.tool (網頁通話)請求,分派至你機構的舊版 webhook URL。與工具執行後 傳送至 webhook 端點的稽核通知不同,此請求就是 執行本身 —— 你的 HTTP 回應即為工具結果。

{
  "type": "telephony.tool",
  "data": {
    "call_id": 987654321,
    "tool_name": "search_appointments",
    "arguments": { "date": "2026-04-21" },
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  }
}

web.tool 會帶有 origin_domain,而非 from_number / to_number。以 JSON 回應工具結果 —— 回應協定與直接端點呼叫相同。 與其他所有 webhook 一樣,請求會使用機構 webhook 密鑰對原始主體進行簽署。


簽名驗證

直接工具呼叫的簽名方式與 Webhook 相同:

  • 對完全相同的請求主體位元組計算 HMAC-SHA256(規範 JSON——鍵值已排序,沒有額外空白字元)
  • 使用你的機構 Webhook 密鑰作為金鑰
  • GET / DELETE 工具會對空位元組字串簽名
Python
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}
Node.js
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 });
});

完整範例——包括空主體情況及沒有密鑰時的注意事項——請參閱驗證 Webhook 簽名


範例:完整預約流程

以下是一組適用於完整預約系統的工具:

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

最佳實務

撰寫清晰描述

description 欄位可協助 AI 理解何時使用工具。請具體說明工具的功能及適用時機。

妥善處理錯誤

回傳 AI 能夠理解的錯誤訊息:{"error": "No slots available for that date"},而非一般的 500 錯誤。

保持回應精簡

只回傳 AI 繼續對話所需的資訊。大型負載會拖慢回應時間。

審慎使用必填欄位

只在確實必要時才將欄位標示為 required。AI 會在呼叫工具前向使用者索取必填資料。


相關內容