Open in
Xây dựng tích hợp công cụ (API)
Cho phép tác nhân AI của bạn gọi API trong khi trò chuyện — tìm kiếm cơ sở dữ liệu, tạo phiếu yêu cầu, tra cứu đơn hàng.
Một tích hợp công cụ là điểm cuối HTTP có thể tái sử dụng mà tác nhân AI có thể gọi trong cuộc gọi. Bạn cung cấp cho ThunderPhone mô tả lược đồ JSON của công cụ cùng URL điểm cuối; tác nhân AI quyết định khi nào gọi công cụ dựa trên cuộc trò chuyện, và ThunderPhone thực hiện yêu cầu HTTP đi từ máy chủ của mình rồi trả phản hồi về cho tác nhân AI.
Hướng dẫn này trình bày toàn bộ quy trình xây dựng công cụ tra cứu thời tiết.
Cấu trúc của một công cụ
Gồm hai phần:
- Lược đồ — định nghĩa hàm theo kiểu OpenAI
(
{type: "function", function: {name, description, parameters}}) cho LLM biết công cụ làm gì và nhận những đối số nào. - Điểm cuối — URL mà máy chủ ThunderPhone gọi khi LLM quyết định sử dụng công cụ. Yêu cầu là JSON POST với các đối số do LLM chọn làm phần thân.
1. Chọn trình chỉnh sửa
Mở Kết nối → API, tạo hoặc chỉnh sửa kết nối API, chuyển trình chỉnh sửa tham số sang JSON, rồi thêm định dạng tại đó.
Tạo đặc tả bằng POST /v1/integrations, hoặc cập nhật bằng
PATCH /v1/integrations/{id}.
Cả hai cách đều tạo một tích hợp đã lưu. Gắn tích hợp đó vào
tác nhân AI sau khi lưu. Agents API không có trường tools nội tuyến có thể ghi.
Hướng dẫn này sử dụng cách thức API tích hợp.
2. Tạo integration
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" }
]
}'Lưu id được trả về (một UUID). Giá trị header chỉ ghi: phản hồi chỉ liệt kê tên header, và một PATCH sau đó có thể gửi header không có value để giữ lại giá trị đã lưu.
Khai báo format: "email" trên tham số địa chỉ email
Một tham số nhận địa chỉ email cần nêu rõ điều đó trong lược đồ của nó:
"email": { "type": "string", "format": "email", "description": "The caller's email address" }format không chỉ là một gợi ý. Với một lược đồ email đã được phân giải, trước khi
endpoint của bạn được gọi, ThunderPhone sẽ cắt khoảng trắng ở đầu cuối giá trị, chuyển
tên miền thành chữ thường, chuyển các từ tiếng Anh đứng riêng lẻ at, dot, underscore,
dash và hyphen thành ký tự tương ứng, đồng thời xóa khoảng trắng
ngay sát @, ., _ và -. Các từ này có cùng ý nghĩa
dù bản ghi lời thoại đã chứa ký tự @ theo nghĩa đen hay chưa:
"john dot smith at gmail dot com" trở thành
john.smith@gmail.com.
Mọi khoảng trắng nội bộ khác sẽ bị từ chối thay vì được tự động nối lại.
Các từ phân cách được nói chỉ hỗ trợ tiếng Anh; các dạng có khoảng trắng không phải tiếng Anh hoặc không được nhận diện
sẽ bị từ chối. Tên miền quốc tế hóa hợp lệ và phần cục bộ SMTPUTF8 được chấp nhận. Dữ liệu đầu vào Punycode vẫn là Punycode và dữ liệu đầu vào tên miền Unicode vẫn là Unicode sau khi trình phân tích chuẩn hóa, vì vậy API của bạn nhận được biểu diễn thông dụng do người gọi cung cấp. Nếu giá trị cuối cùng không hợp lệ, công cụ sẽ không được gọi. Tác nhân AI nhận
invalid_email_argument, yêu cầu tác nhân AI
xác nhận cách viết với người gọi và gửi lại địa chỉ theo nghĩa đen.
Email tùy chọn bị bỏ qua sẽ không thay đổi. null, chuỗi rỗng hoặc
chuỗi chỉ có khoảng trắng cũng không thay đổi khi thuộc tính là tùy chọn
hoặc cho phép giá trị rỗng; các giá trị tương tự sẽ bị từ chối đối với email bắt buộc, không cho phép giá trị rỗng.
Các tham chiếu lược đồ cục bộ như #/$defs/email và
#/definitions/email, cùng với anyOf, oneOf và allOf, được kiểm tra
với giới hạn chu trình và độ sâu. $ref không cục bộ hoặc không thể phân giải là
một giới hạn thực thi đã biết và được chuyển tiếp không thay đổi, tương tự một lệnh gọi
có ảnh chụp công cụ không có lược đồ có thể sử dụng. Giữ lược đồ email ở dạng cục bộ khi
bạn cần áp dụng lớp kiểm tra này.
Các tham số không có định dạng email được thực thi sẽ được chuyển tiếp chính xác như cách mô hình tạo ra.
Các định dạng được hỗ trợ là date-time, time, date, duration,
email, hostname, ipv4, ipv6 và uuid; hiện tại chỉ email được
chuẩn hóa và thực thi.
3. Kiểm thử endpoint trong sandbox
Trước khi liên kết integration với một tác nhân AI, hãy gửi một yêu cầu đã ký từ máy chủ của ThunderPhone để xác nhận kết nối:
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" }
}'{
"ok": true,
"status": 200,
"elapsed_ms": 187,
"response_headers": { "content-type": "application/json" },
"response_preview": "{\"temperature_f\": 64, ...}"
}Kiểm thử này cũng tăng cường các biện pháp bảo vệ SSRF của ThunderPhone — các yêu cầu đến
localhost hoặc dải IP riêng tư sẽ trả về 400 code=url_not_allowed.
4. Liên kết integration với tác nhân AI
Đính kèm qua integration_ids khi bạn tạo hoặc cập nhật tác nhân AI:
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-..."]
}'Bạn có thể liên kết nhiều integration với một tác nhân AI. Prompt của tác nhân AI có thể
tham chiếu chúng theo tên — "dùng get_weather khi người gọi hỏi
về điều kiện thời tiết" — hoặc có thể ngầm nhận diện chúng từ phần mô tả
schema.
5. Triển khai endpoint
Khi tác nhân AI gọi công cụ, ThunderPhone gửi một POST đã ký đến
endpoint_url của bạn:
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"}
Máy chủ của bạn phản hồi bằng JSON, dữ liệu này được chuyển lại cho LLM:
{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}LLM tiếp nhận phản hồi đó và nói bản tóm tắt tự nhiên cho người gọi.
6. Kiểm thử vòng lặp
Chạy một mic session với tác nhân AI và đặt câu hỏi mà công cụ của bạn xử lý ("Thời tiết ở 94110 thế nào?"). Bản chép lời của cuộc gọi hiển thị toàn bộ quy trình:
{
"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." }
]
}Bạn có thể lấy dữ liệu này qua
GET /v1/calls/{call_id}/transcript;
luồng sự kiện thô (có thời gian cho từng mục và độ lệch âm thanh) nằm tại
GET /v1/calls/{call_id}/history.
Trong các giao diện danh sách cuộc gọi và phân tích, ThunderPhone hiện báo cáo riêng cuộc gọi thử nghiệm với lưu lượng thực tế. Kiểm thử Browser Talk và mô phỏng có thể dùng lại số điện thoại thật và có thể trông như cuộc gọi đến, nhưng không được tính vào tổng số cuộc gọi production, điểm đánh giá hoặc chỉ số sự cố.
Các lỗi thường gặp
Tác nhân AI không bao giờ gọi công cụ
LLM quyết định dựa trên mô tả của công cụ. Nếu câu hỏi của người gọi
không khớp với mô tả, mô hình sẽ không gọi
công cụ. Hãy làm rõ mô tả hơn (thêm các từ đồng nghĩa và
cách diễn đạt phổ biến) hoặc đề cập rõ trong prompt của tác nhân AI ("Khi
người gọi hỏi về thời tiết, hãy dùng get_weather.").
Công cụ trả về quá nhiều dữ liệu
Phản hồi lớn hơn 6 kB sẽ bị cắt ngắn trong phần xem trước bản chép lời. Chỉ trả về các trường mà LLM cần — không phải toàn bộ hàng dữ liệu của bạn.
Hết thời gian chờ
Endpoint công cụ có thời gian chờ mặc định là 10 giây. Nếu bạn cần lâu hơn,
hãy xử lý bất đồng bộ: trả về {"status": "pending", "request_id": "..."}
và hiển thị kết quả thông qua một lệnh gọi công cụ riêng.
Quản lý phiên bản
Mỗi lần PATCH integration sẽ tạo một bản sửa đổi mới. Kiểm tra
GET /v1/integrations/{id}/versions
để xem ai đã thay đổi nội dung nào. Nếu bạn làm hỏng schema của một công cụ, bạn có thể
khôi phục thủ công bằng cách PATCH lại một ảnh chụp cũ.