ThunderPhone 2.0 เปิดให้ใช้งานแล้วเริ่มใช้งานได้ด้วยตัวเอง ราคาเริ่มต้น 2 เซนต์ต่อนาที.อ่านประกาศเปิดตัว

Function Tools

เครื่องมือฟังก์ชัน

มอบเครื่องมือฟังก์ชันให้ AI เอเจนต์ของคุณเพื่อเรียกใช้ API ภายนอกระหว่างการสนทนา — ดึงข้อมูลลูกค้า จองนัดหมาย อัปเดตระเบียน — ด้วยพารามิเตอร์ที่กำหนดประเภท

เครื่องมือฟังก์ชันช่วยให้ AI เอเจนต์ของคุณเรียกใช้ API ภายนอกระหว่างการสนทนาทางโทรศัพท์ ใช้เพื่อค้นหาข้อมูลลูกค้า ตรวจสอบเวลาว่าง จองนัดหมาย หรือดำเนินการใดๆ ที่แบ็กเอนด์ของคุณรองรับ

วิธีการทำงาน

  1. กำหนดเครื่องมือด้วยสคีมา (อาร์กิวเมนต์ที่เครื่องมือรับได้)
  2. ระบุการกำหนดค่า endpoint (ตำแหน่งที่ ThunderPhone เรียก API ของคุณ) หรือไม่ระบุก็ได้เพื่อรับการเรียกใช้เครื่องมือผ่านเว็บฮุกขององค์กร
  3. ระหว่างการสนทนา AI จะตัดสินใจว่าเมื่อใดควรใช้เครื่องมือตามบทสนทนา
  4. ThunderPhone เรียก endpoint ของคุณพร้อมอาร์กิวเมนต์ของเครื่องมือ
  5. ระบบส่งการตอบกลับจาก 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
}

การกำหนดค่าเครื่องมือ

ฟิลด์ประเภทจำเป็นคำอธิบาย
timeoutnumberไม่เวลาดำเนินการสูงสุดเป็นวินาที (ค่าเริ่มต้น: 20 สูงสุด: 180)

คำจำกัดความฟังก์ชัน

ฟิลด์ประเภทจำเป็นคำอธิบาย
namestringใช่ตัวระบุเฉพาะสำหรับเครื่องมือ
descriptionstringใช่อธิบายให้ AI ทราบว่าเมื่อใดควรใช้เครื่องมือนี้
parametersobjectใช่JSON Schema สำหรับอาร์กิวเมนต์ของเครื่องมือ

การกำหนดค่า Endpoint

ฟิลด์ประเภทจำเป็นคำอธิบาย
urlstringใช่URL endpoint ของ API คุณ
methodstringไม่เมธอด HTTP (ค่าเริ่มต้น: POST)
headersobjectไม่เฮดเดอร์แบบกำหนดเองที่จะรวมไว้

เส้นทางการเรียกใช้สองแบบ

คำขอที่เซิร์ฟเวอร์ของคุณได้รับขึ้นอยู่กับว่าเครื่องมือมี endpoint หรือไม่:

เครื่องมือที่มี endpointเครื่องมือที่ไม่มี endpoint
ปลายทางของคำขอส่งตรงไปยัง endpoint.urlURL เว็บฮุกแบบเดิม ขององค์กรคุณ
เนื้อหาคำขออาร์กิวเมนต์ของเครื่องมือโดยตรงซองข้อมูล telephony.tool / web.tool
เฮดเดอร์endpoint.headers ของคุณ + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-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 ลงลายเซ็นสตริงไบต์ว่าง
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 });
});

สูตรการใช้งานฉบับสมบูรณ์ — รวมถึงกรณีเนื้อหาว่างและข้อควรระวังเมื่อไม่มีข้อมูลลับ — อยู่ในตรวจสอบลายเซ็นเว็บฮุก


ตัวอย่าง: โฟลว์การจองแบบครบถ้วน

นี่คือชุดเครื่องมือสำหรับระบบจองนัดหมายแบบครบถ้วน:

{
  "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 จะขอข้อมูลที่จำเป็นจากผู้ใช้ก่อนเรียกใช้เครื่องมือ


ที่เกี่ยวข้อง