Open in
เครื่องมือฟังก์ชัน
มอบเครื่องมือฟังก์ชันให้ AI เอเจนต์ของคุณเพื่อเรียกใช้ API ภายนอกระหว่างการสนทนา — ดึงข้อมูลลูกค้า จองนัดหมาย อัปเดตระเบียน — ด้วยพารามิเตอร์ที่กำหนดประเภท
เครื่องมือฟังก์ชันช่วยให้ AI เอเจนต์ของคุณเรียกใช้ API ภายนอกระหว่างการสนทนาทางโทรศัพท์ ใช้เพื่อค้นหาข้อมูลลูกค้า ตรวจสอบเวลาว่าง จองนัดหมาย หรือดำเนินการใดๆ ที่แบ็กเอนด์ของคุณรองรับ
วิธีการทำงาน
- กำหนดเครื่องมือด้วยสคีมา (อาร์กิวเมนต์ที่เครื่องมือรับได้)
- ระบุการกำหนดค่า
endpoint(ตำแหน่งที่ ThunderPhone เรียก API ของคุณ) หรือไม่ระบุก็ได้เพื่อรับการเรียกใช้เครื่องมือผ่านเว็บฮุกขององค์กร - ระหว่างการสนทนา AI จะตัดสินใจว่าเมื่อใดควรใช้เครื่องมือตามบทสนทนา
- ThunderPhone เรียก endpoint ของคุณพร้อมอาร์กิวเมนต์ของเครื่องมือ
- ระบบส่งการตอบกลับจาก API ของคุณกลับไปยัง AI เพื่อดำเนินบทสนทนาต่อ
| ความสามารถ | ตำแหน่งที่ทำงาน | การตั้งค่า |
|---|---|---|
| เครื่องมือในตัว | ThunderPhone | คำสั่งในพรอมป์ต์ เครื่องมือบางรายการต้องมีการตั้งค่าเอเจนต์ด้วย |
| การเชื่อมต่อแอป | ThunderPhone และผู้ให้บริการที่เชื่อมต่อ | เชื่อมต่อบัญชีและแนบการดำเนินการที่อนุมัติแล้ว |
| การเชื่อมต่อ API และเครื่องมือฟังก์ชัน | HTTP API ของคุณ | กำหนด endpoint และสคีมา หรือรับการเรียกใช้ฟังก์ชันผ่านเว็บฮุก |
| เซิร์ฟเวอร์ 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 | number | ไม่ | เวลาดำเนินการสูงสุดเป็นวินาที (ค่าเริ่มต้น: 20 สูงสุด: 180) |
คำจำกัดความฟังก์ชัน
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
name | string | ใช่ | ตัวระบุเฉพาะสำหรับเครื่องมือ |
description | string | ใช่ | อธิบายให้ AI ทราบว่าเมื่อใดควรใช้เครื่องมือนี้ |
parameters | object | ใช่ | JSON Schema สำหรับอาร์กิวเมนต์ของเครื่องมือ |
การกำหนดค่า Endpoint
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
url | string | ใช่ | URL endpoint ของ API คุณ |
method | string | ไม่ | เมธอด HTTP (ค่าเริ่มต้น: POST) |
headers | object | ไม่ | เฮดเดอร์แบบกำหนดเองที่จะรวมไว้ |
เส้นทางการเรียกใช้สองแบบ
คำขอที่เซิร์ฟเวอร์ของคุณได้รับขึ้นอยู่กับว่าเครื่องมือมี
endpoint หรือไม่:
เครื่องมือที่มี endpoint | เครื่องมือที่ไม่มี endpoint | |
|---|---|---|
| ปลายทางของคำขอ | ส่งตรงไปยัง endpoint.url | URL เว็บฮุกแบบเดิม ขององค์กรคุณ |
| เนื้อหาคำขอ | อาร์กิวเมนต์ของเครื่องมือโดยตรง | ซองข้อมูล telephony.tool / web.tool |
| เฮดเดอร์ | endpoint.headers ของคุณ + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature |
| คีย์สำหรับลงนาม | ซีเคร็ตเว็บฮุกขององค์กร | ซีเคร็ตเว็บฮุกขององค์กร |
ทั้งสองเส้นทางเป็นแบบ บล็อกการทำงาน — AI กำลังรอผลลัพธ์อยู่กลางประโยค
ค่าเวลาหมดอายุเริ่มต้นคือ 20 วินาที ตั้งค่า
timeout ระดับบนสุดของเครื่องมือเพื่ออนุญาตให้ดำเนินการนานขึ้นได้ สูงสุดถึง 180 วินาที ซึ่งเป็น
ขีดจำกัดสูงสุดของแพลตฟอร์ม ทำให้ตัวจัดการทำงานรวดเร็ว การผสมการใช้งานทำได้:
ในการสนทนาที่องค์กรมี URL เว็บฮุก เครื่องมือที่มี endpoint จะถูก
เรียกใช้โดยตรง และเครื่องมือที่เหลือจะย้อนกลับไปใช้เว็บฮุก
การเรียกใช้ endpoint โดยตรง
เมื่อ 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 อีก 2 รายการ:
X-ThunderPhone-Signature— HMAC-SHA256 ของไบต์เนื้อหาคำขอ ที่ตรงกันทุกประการ โดยใช้ ความลับ webhook ขององค์กร เป็นคีย์X-ThunderPhone-Call-ID— ID การโทรปัจจุบัน
จะตั้งค่า Content-Type: application/json เว้นแต่ endpoint.headers
ของคุณจะแทนที่ค่า — Content-Type แบบกำหนดเองจะมีผลเหนือกว่า
เนื้อหาคำขอ
สำหรับ POST / PUT / PATCH เนื้อหาจะมี เฉพาะ อาร์กิวเมนต์ของเครื่องมือ
(ไม่มี wrapper) ซึ่งถูกซีเรียลไลซ์ในรูปแบบมาตรฐาน (เรียงลำดับคีย์ ตัวคั่นแบบกระชับ):
{"date":"2025-01-02","service":"consultation"}สำหรับ GET / DELETE อาร์กิวเมนต์จะถูกส่งเป็น พารามิเตอร์ query
และเนื้อหาจะว่างเปล่า — จากนั้นลายเซ็นจะคำนวณจาก
สตริงไบต์ว่าง ดู
ตรวจสอบลายเซ็น webhook
การตอบกลับ
ส่งคืนการตอบกลับ JSON พร้อมผลลัพธ์ของเครื่องมือ:
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}การตอบกลับจะถูกจัดรูปแบบและส่งให้ AI เพื่อสนทนาต่อ
การตอบกลับที่ไม่ใช่ JSON จะถูกห่อเป็น {"data": "<text>"};
การหมดเวลาและการเชื่อมต่อล้มเหลวจะถูกรายงานให้ AI เป็นข้อผิดพลาด เพื่อให้
เอเจนต์สามารถขออภัยและดำเนินการต่อแทนที่จะหยุดชะงัก
การส่งต่อแบบ webhook
เครื่องมือที่ไม่มี endpoint จะถูกส่งต่อไปยัง URL webhook แบบเดิมขององค์กรคุณ
เป็นคำขอ telephony.tool (การโทร) หรือ web.tool
(การโทรผ่านเว็บ) ที่มีลายเซ็น ซึ่งต่างจากการแจ้งเตือนการตรวจสอบ
ที่ส่งไปยัง endpoint ของ 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 — ใช้สัญญาการตอบกลับ
เดียวกับการเรียกใช้ endpoint โดยตรง คำขอมีลายเซ็นโดยใช้ความลับ webhook ขององค์กร
กับเนื้อหาแบบดิบ เช่นเดียวกับ webhook อื่นทั้งหมด
การตรวจสอบลายเซ็น
การเรียกใช้เครื่องมือโดยตรงจะมีการลงลายเซ็นเช่นเดียวกับเว็บฮุก:
- HMAC-SHA256 บนไบต์ของเนื้อหาคำขอแบบตรงตัว (JSON มาตรฐาน — เรียงลำดับคีย์ ไม่มีช่องว่างเพิ่มเติม)
- ใช้ข้อมูลลับเว็บฮุกขององค์กรคุณเป็นคีย์
- เครื่องมือ
GET/DELETEลงลายเซ็นสตริงไบต์ว่าง
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}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 });
});สูตรการใช้งานฉบับสมบูรณ์ — รวมถึงกรณีเนื้อหาว่างและข้อควรระวังเมื่อไม่มีข้อมูลลับ — อยู่ในตรวจสอบลายเซ็นเว็บฮุก
ตัวอย่าง: โฟลว์การจองแบบครบถ้วน
นี่คือชุดเครื่องมือสำหรับระบบจองนัดหมายแบบครบถ้วน:
{
"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 จะขอข้อมูลที่จำเป็นจากผู้ใช้ก่อนเรียกใช้เครื่องมือ
ที่เกี่ยวข้อง
สั่งให้ดำเนินการโทรที่แพลตฟอร์มจัดการโดยไม่ต้องกำหนดเอนด์พอยต์
เครื่องมือที่แพลตฟอร์มจัดการสำหรับ HubSpot, Salesforce, Slack, Google Calendar, Google Sheets และ Cal.com — ไม่ต้องมีเอนด์พอยต์
แนบเซิร์ฟเวอร์ MCP และให้เอเจนต์เรียกใช้เครื่องมือของเซิร์ฟเวอร์
การผสานรวม REST ที่ใช้ซ้ำได้ซึ่งคุณสามารถแนบกับเอเจนต์ได้
ตัวช่วยตรวจสอบเดียวสำหรับ Webhook และการเรียกใช้เครื่องมือ