1. Tại sao cần hiểu tool-call
Nói đơn giản, một web‑app thông thường vận hành theo sơ đồ “người dùng bấm nút — chúng ta gọi hàm”. Trong thế giới ChatGPT Apps thì khác: người dùng nói gì đó, mô hình suy nghĩ, và nếu thấy cần, nó tạo ra một lệnh gọi công cụ có cấu trúc (tool-call).
Tức là bạn không viết:
onClick={() => callSuggestGiftsApi(formData)}
mà thay vào đó:
- Mô tả công cụ suggest_gifts (tên, mô tả, schema tham số).
- Giải thích cho mô hình trong system-prompt công dụng của công cụ này.
- Trao quyền cho mô hình: nó tự quyết định khi nào và cách gọi công cụ.
Từ đây cần hiểu sớm hai điều:
- GPT không thấy mã backend của bạn. Nó chỉ thấy “phần đầu” của công cụ: tên, mô tả và schema tham số.
- Mức độ “thông minh” khi mô hình sử dụng App của bạn gần như phụ thuộc trực tiếp vào cách bạn viết các mô tả đó. Mô tả tốt chính là “prompt cho công cụ” của bạn.
Bài giảng hôm nay chính là về “bộ não” giữa người dùng và máy chủ của bạn.
2. Mô hình tinh thần tool-call: rốt cuộc chuyện gì diễn ra
Bắt đầu với bức tranh tổng thể. Kịch bản điển hình cho GiftGenius:
- Người dùng: “Hãy chọn quà cho người bạn 30 tuổi, ngân sách 100 đô la, anh ấy thích trò chơi điện tử”.
- GPT đọc thông điệp này và xem có những công cụ nào. Trong App của chúng ta, ví dụ có suggest_gifts.
- GPT quyết định: “Để trả lời tốt, mình cần gọi công cụ này”.
- Thay vì trả lời văn bản thường, nó tạo một cấu trúc: tên công cụ + đối số JSON.
- Client ChatGPT thấy: “À, đây là tool-call”, và gửi nó đến MCP/máy chủ của bạn.
- Máy chủ của bạn thực thi logic nghiệp vụ và trả về kết quả có cấu trúc.
- GPT nhận kết quả, đọc nó, và dựa trên câu trả lời của công cụ để tạo phản hồi dễ hiểu cho người dùng và/hoặc cập nhật widget.
Từ góc nhìn OpenAI API, đây chính là cơ chế LLM-function-calling: trong phản hồi của mô hình, thay cho văn bản thường sẽ xuất hiện một đối tượng với name của công cụ và arguments, còn finish_reason được gắn là tool_calls. Mô hình không tự chạy mã — nó chỉ đề xuất công cụ nào cần gọi, còn việc gọi thực sự do client (ChatGPT/Apps SDK) thực hiện.
Trông điều này như sau (chuỗi rút gọn):
sequenceDiagram
participant U as Người dùng
participant G as GPT (mô hình)
participant C as Client ChatGPT
participant S as MCP/Backend của bạn
U->>G: "Hãy chọn quà cho bạn..."
G->>C: tool-call: { name: "suggest_gifts", args: {...} }
C->>S: HTTP /mcp tools/call (suggest_gifts, args)
S-->>C: Kết quả (JSON với danh sách quà tặng)
C-->>G: kết quả công cụ
G-->>U: Câu trả lời + widget đã cập nhật
Kết luận chính: bạn không viết if (userAskedAboutGifts) callSuggestGifts(). Bạn tạo công cụ và mô tả của nó, còn quyết định là do mô hình đưa ra.
3. Mô hình nhìn thấy gì: System Prompt + danh sách công cụ
Để hiểu cách GPT quyết định làm gì, cần nắm rõ bộ thông tin mà nó có tại thời điểm lựa chọn.
Đơn giản, mô hình thấy:
- system‑prompt của App (chúng ta sẽ phân tích kỹ trong mô-đun 5);
- lịch sử hội thoại: thông điệp người dùng, các câu trả lời trước đó của chính nó, kết quả các lần tool-call trước;
- danh sách công cụ có sẵn (tools) với tên, mô tả và schema tham số;
- các chú giải bổ sung của công cụ (readOnly/destructive, v.v.).
Nó không thấy:
- triển khai các hàm;
- các truy vấn SQL;
- cấu trúc các bảng của bạn;
- nội dung repo riêng tư chứa dịch vụ.
Chúng ta sẽ nói chi tiết về MCP sau. Tạm thời chỉ cần biết rằng ở cấp MCP, công cụ được khai báo dưới dạng descriptor: mỗi công cụ có name, description và inputSchema (JSON Schema). Khi handshake, ChatGPT sẽ yêu cầu MCP‑server cung cấp danh sách công cụ và bắt đầu coi đó là các “hành động” có sẵn.
Ví dụ descriptor cho GiftGenius (JSON rút gọn):
{
"name": "suggest_gifts",
"description": "Gợi ý ý tưởng quà theo độ tuổi, sở thích và ngân sách",
"inputSchema": {
"type": "object",
"properties": {
"age": { "type": "integer" },
"budget": { "type": "number" }
},
"required": ["age", "budget"]
}
}
Mô hình “đọc” ở đây chỉ là văn bản và cấu trúc: age là gì, budget là gì, công cụ làm gì nói chung. Bài giảng tiếp theo sẽ nói về cách mô tả inputSchema cho chuẩn. Còn bây giờ — về việc từ mô tả này sinh ra quyết định “hãy gọi suggest_gifts”.
4. tool-call trông thế nào qua mắt API
ChatGPT gọi các công cụ (tools) của MCP‑server của bạn gần giống cách OpenAI Agent gọi các hàm trên backend của bạn. Trong ChatGPT Apps SDK mọi thứ được bọc nhiều hơn một chút, nhưng cơ chế cơ bản là như nhau.
Hãy hình dung trên backend chúng ta thực hiện một yêu cầu thông thường tới OpenAI API, đồng thời truyền vào công cụ suggest_gifts, mà mô hình có thể gọi trong phản hồi của nó:
const response = await openai.responses.create({
model: 'gpt-5-mini',
messages: [
{
role: 'user',
content: 'Cần quà cho người bạn 30 tuổi, ngân sách 100 đô la'
}
],
tools: [ // ở đây chúng ta truyền danh sách hàm mà LLM có thể "gọi"
{
name: 'suggest_gifts',
description: 'Gợi ý quà theo độ tuổi, ngân sách và sở thích',
parameters: {
type: 'object',
properties: {
age: { type: 'integer' },
budget: { type: 'number' }
},
required: ['age', 'budget']
}
}
]
});
Nếu mô hình quyết định gọi công cụ, bạn sẽ nhận được phản hồi không phải văn bản, mà là thông điệp trợ lý với nội dung kiểu:
{
"role": "assistant",
"tool_calls": [
{
"id": "call_1",
"name": "suggest_gifts",
"arguments": "{\"age\":30,\"budget\":100}"
}
],
"content": []
}
Bằng cách này, LLM nói với backend của bạn rằng nó cần gọi hàm suggest_gifts(30,100).
Ở đây có ba điểm quan trọng:
- Tên công cụ (name) — mô hình thực sự điền vào chuỗi đúng như bạn đã chỉ định trong mô tả tools khi gửi yêu cầu đầu tiên.
- Đối số (arguments) — chuỗi JSON, được lắp ráp dựa trên parameters/inputSchema.
- Không có câu trả lời văn bản thông thường (tạm thời) — thay vào đó bạn nhận được cấu trúc để gọi công cụ.
Khi chạy ChatGPT App cũng tương tự: mô hình trả về “muốn gọi suggest_gifts với các tham số như vậy”, còn client (ChatGPT) sẽ thực hiện HTTP‑request tới MCP/máy chủ của bạn: tools/call với tên công cụ và đối số.
5. Mô hình quyết định như thế nào: tool hay văn bản
Giờ là phần thú vị nhất: khi nào GPT nhớ đến công cụ của bạn?
Cơ chế (đơn giản hóa) như sau:
- Mô hình nhìn thấy thông điệp mới của người dùng và ngữ cảnh hiện tại.
- Bên trong có “lớp” tạo ra thông điệp trợ lý tiếp theo, nhưng thay vì lúc nào cũng xuất văn bản thường, mô hình có thể chọn một trong các cách kết thúc:
- câu trả lời văn bản thường (finish_reason: "stop");
- một hoặc nhiều tool-call (finish_reason: "tool_calls");
- đôi khi là các biến thể khác (ví dụ, “cần thêm thông điệp từ người dùng”).
- Quyết định này chịu ảnh hưởng bởi:
- mức độ giống nhau giữa yêu cầu của người dùng và các tác vụ được mô tả trong công cụ của bạn;
- mức độ rõ ràng của mô tả công cụ khi nói “hãy dùng tôi trong trường hợp này”;
- dữ liệu từ app system prompt, được đặt trong cấu hình Apps SDK.
Nói dễ hiểu, mô hình “ướm thử” công cụ của bạn vào yêu cầu hiện tại. Nếu mô tả là: “Gợi ý quà theo độ tuổi và sở thích”, còn người dùng yêu cầu “phân tích ngân sách nhà nước”, mô hình sẽ không cố gọi công cụ. Nếu mô tả quá mơ hồ — “làm những thứ hay ho” — mô hình không hiểu khi nào nên dùng.
Một điểm thú vị: mô hình không bắt buộc phải gọi công cụ, ngay cả khi bạn đã mô tả nó. GPT có thể quyết: “Trường hợp này đã rõ, mình tự trả lời, không cần tool‑call”. Vì thế về sau trong khóa học, chúng ta sẽ luyện tập viết mô tả công cụ sao cho việc sử dụng công cụ với mô hình là hiển nhiên và có lợi nhất.
6. Tên công cụ: vì sao tool1 là ý tưởng tệ
Tên công cụ thực chất là định danh mà mô hình sẽ dùng trong các lần gọi. Có vẻ như đây là trường kỹ thuật thuần túy, nhưng trên thực tế, tên ảnh hưởng lớn đến hành vi mô hình.
Nếu bạn đặt tên công cụ là tool1, mô hình sẽ không hiểu gì từ đó. Với nó, đó chỉ là một chuỗi ký tự. Nếu bạn đặt là suggest_gifts, search_products hoặc fetch_user_orders, bản thân cái tên đã cho tín hiệu mạnh công cụ này nói về điều gì.
Hãy nghĩ về cách bạn đọc mã lạ. Nhìn thấy hàm calculateCartTotal, bạn phần nào hình dung được kỳ vọng. Mô hình cũng cần một “neo ngữ nghĩa” như vậy.
Với GiftGenius, những tên công cụ hợp lý có thể là:
suggest_gifts
search_products
get_product_details
create_order
Tên tốt khi:
- ngắn gọn nhưng có nội dung;
- đồng nhất về phong cách (snake_case, chữ Latinh, động_từ_danh_từ);
- phản ánh một hành động cụ thể.
Ý tưởng tệ là trộn nhiều hành động khác nhau vào một công cụ, kiểu do_all_gift_stuff. Mô hình khó hiểu khi nào nên dùng, và trong các bài giảng sau ta sẽ thấy cách điều này phá vỡ schema tham số và làm khó việc debug.
7. Mô tả công cụ: prompt dành cho mô hình
Nếu tên là tiêu đề, thì description là tài liệu mini — nhưng không phải cho lập trình viên con người, mà cho GPT. Lập trình viên sẽ đọc mã; mô hình thì không. Nó dựa vào văn bản mô tả để quyết định khi nào gọi công cụ và điền đối số thế nào.
Hãy viết mô tả theo kiểu “hướng dẫn sử dụng”:
- khi nào dùng công cụ;
- các giới hạn là gì;
- những gì không nên làm.
Lấy suggest_gifts làm ví dụ. Dưới đây là ba biến thể mô tả.
Quá rộng:
"Gợi ý quà tặng."
Mô hình sẽ không hiểu về dịp gì, cho ai, với tham số nào. Công cụ này có thể “cạnh tranh” với kiến thức chung về quà trong đầu mô hình, và nó thường sẽ chọn trả lời bằng văn bản.
Quá hẹp:
"Chỉ gợi ý quà cho em trai vào sinh nhật."
Ở đây chúng ta gần như cấm dùng công cụ trong hầu hết tình huống. Các kịch bản khác — mẹ, đồng nghiệp, kỷ niệm — đều “không phù hợp”, và mô hình sẽ tránh gọi.
Tối ưu:
"Hãy dùng công cụ này khi cần chọn quà cho một người theo độ tuổi, loại quan hệ (bạn, đối tác, đồng nghiệp, v.v.), ngân sách và sở thích.
Không gọi nó cho các câu hỏi không liên quan đến quà tặng (ví dụ, chính trị hay thời tiết)."
Ở đây mô tả rõ ràng công cụ làm gì, có những tham số nào và khi nào gọi, đồng thời thêm điều kiện phủ định — các truy vấn nào thì không nên động tới.
Mô hình “thích” những giới hạn rõ ràng như vậy. Càng nêu rõ bạn “gắn” công cụ với những cách diễn đạt (intent) của người dùng nào, hành vi App càng dễ đoán.
Bài tập nhỏ
Ngay bây giờ, bạn có thể lấy App tương lai của mình (không nhất thiết về quà) và nghĩ ra cho một công cụ ba mô tả: rất rộng, rất hẹp và cân bằng. Rồi thử kiểm tra xem GPT cư xử thế nào với các phiên bản khác nhau.
8. Schema tham số: nó giúp quyết định ra sao
Chúng ta sẽ nói chi tiết về JSON Schema trong bài tiếp theo, nhưng để hiểu về các tool-call, cần có cảm nhận ở tầng cao.
Khi mô hình quyết định gọi công cụ, nó cần:
- Hiểu công cụ này kỳ vọng những đối số nào.
- Trích xuất các giá trị đó từ văn bản người dùng (hoặc từ ngữ cảnh).
- Tạo JSON với các đối số này.
Vì vậy mô tả công cụ có schema tham số (inputSchema) nói với mô hình rằng:
- có những trường nào (age, budget, relationship_type, interests, v.v.);
- trường nào là bắt buộc (required);
- các kiểu dữ liệu (integer, number, string, mảng, v.v.);
- đôi khi — các giá trị hợp lệ (enum) và chú giải cho trường (description).
Một interface TypeScript đơn giản cho tham số của suggest_gifts có thể như sau:
interface SuggestGiftsParams {
age: number;
relationship_type: 'friend' | 'partner' | 'colleague';
budget: number;
interests?: string[];
}
Ở mức mô hình, điều này trở thành JSON Schema, và mô hình sẽ dựa theo tên và mô tả của từng trường để suy ra rằng:
- age lấy từ các cụm “30 tuổi”, “cho thiếu niên”, v.v.;
- budget từ “ngân sách 100 đô la”, “tối đa 50 euro”;
- relationship_type từ “bạn”, “đồng nghiệp”;
- interests — từ “thích trò chơi điện tử”.
Nếu bạn đưa ra schema không có mô tả và với tên trường trừu tượng (a, b, c), mô hình sẽ sai nhiều hơn khi điền đối số. Chúng ta sẽ quay lại chủ đề này trong mô-đun về bản địa hóa và gợi ý UX. Ý chính rất đơn giản: schema không chỉ là kiểm tra trên backend, mà trước hết là gợi ý cho mô hình, cái gì đặt vào đâu.
Chúng ta đã nói về cách schema giúp mô hình lắp đúng đối số. Nhưng ngoài “gọi cái gì và gọi thế nào”, còn quan trọng “có thể gọi ngay bây giờ và có an toàn không”. Đây là lúc permissions và meta‑info của công cụ tham gia.
9. Permissions và ngữ cảnh: không phải công cụ nào cũng luôn sẵn sàng
Ngoài tên, mô tả và schema tham số, công cụ còn có một chiều quan trọng khác — bảo mật và truy cập. Công cụ trong App thực tế rất khác nhau về mức “nguy hiểm”. Một chuyện là tìm kiếm quà trong danh mục công khai, chuyện khác là trừ tiền trên thẻ của người dùng.
Apps SDK và MCP cho phép phản ánh điều này trong mô tả công cụ và chú giải — ví dụ, đánh dấu là read-only hoặc destructive.
Ý tưởng là:
- Các công cụ chỉ đọc dữ liệu công khai (search_products, get_weather) có thể gọi mà không cần xác nhận thêm.
- Các công cụ thay đổi dữ liệu (create_order, cancel_order, charge_user) được đánh dấu “mang tính phá hủy”. UI của ChatGPT có thể yêu cầu người dùng xác nhận bổ sung (“Bạn có chắc muốn đặt hàng không?”), và bản thân mô hình cũng sẽ ít đề xuất chúng khi không có yêu cầu rõ ràng.
Trong các mô-đun sau khi cấu hình MCP, bạn sẽ thấy các chú giải (_meta, destructiveHint, readOnlyHint) trông như thế nào trong các JSON‑descriptor thực tế, chúng ảnh hưởng ra sao tới UX và cách ChatGPT tạo các hộp thoại “Are you sure?” trước khi gọi. Hiện giờ chỉ cần hiểu:
- GPT xét đến không chỉ văn bản mô tả mà còn cả meta‑info về an toàn.
- Công cụ yêu cầu xác thực sẽ không được dùng cho đến khi người dùng đăng nhập (hoặc App nhận được token cần thiết).
Đây là một yếu tố nữa ảnh hưởng đến quyết định “gọi tool hay không”: dù về nghĩa là phù hợp, công cụ có thể không sẵn do permissions, và khi đó mô hình sẽ chọn cách khác.
10. Công cụ đến với ChatGPT bằng cách nào
Xét về kiến trúc, công cụ có thể đến với mô hình theo hai con đường chính.
Thứ nhất, từ cấu hình ChatGPT App của bạn. Khi đăng ký App, bạn chỉ định những MCP‑server (và công cụ của chúng) được gắn vào, hoặc những tools tích hợp sẵn trong chính ứng dụng. Khi bắt đầu phiên, ChatGPT nhận cấu hình này và hiểu những công cụ nào sẵn có.
Thứ hai, trực tiếp từ MCP. MCP (Model Context Protocol) xác định cách chuẩn để client (trong trường hợp của chúng ta là ChatGPT/Apps SDK) biết server của bạn làm được gì: nó gọi tools/list, nhận về JSON mô tả công cụ và lưu chúng như capabilities. Cơ chế chi tiết sẽ bàn trong mô-đun riêng về MCP, hiện tại chỉ cần nắm ý chính.
Sơ đồ:
flowchart LR A[Client ChatGPT] -->|handshake| B[MCP Server] B -->|tools/list| A A -->|truyền danh sách| G[GPT Model]
Sau đó danh sách công cụ trở thành một phần ngữ cảnh cho mô hình. Nếu bạn thay đổi schema hoặc mô tả công cụ trên server và khởi động lại App, descriptor mới sẽ được ChatGPT lấy trong lần handshake tiếp theo, và mô hình sẽ bắt đầu đưa ra quyết định gọi theo cách mới.
Và một lưu ý thực tế quan trọng: khi bạn chỉ sửa backend (triển khai công cụ), mô hình không biết điều đó. Nhưng khi bạn đổi name/description/schema, bạn đang thực sự đổi “bộ não” của App. Đôi khi sửa một dòng trong description có ích hơn là viết 200 dòng mã với heuristic.
11. Áp dụng cho GiftGenius: tạo công cụ mà mô hình muốn gọi
Giờ hãy liên kết mọi thứ với ứng dụng học tập GiftGenius. Giả sử ta đã có MCP‑server hoặc lớp backend, nơi đăng ký công cụ. Hãy đăng ký công cụ suggest_gifts bằng server.registerTool(...).
Phác thảo thô bằng TypeScript (chưa có logic thực):
// pseudo-mcp-server/tools/suggestGifts.ts
server.registerTool(
'suggest_gifts', // tên công cụ
{
title: 'Chọn quà tặng',
description:
'Hãy dùng công cụ này để gợi ý ý tưởng quà theo độ tuổi, ' +
'loại quan hệ và ngân sách. Không gọi cho các câu hỏi không liên quan đến quà tặng.',
inputSchema: { // mô tả tham số của công cụ
type: 'object',
properties: {
age: { type: 'integer', description: 'Tuổi của người nhận (tính theo năm)' },
relationship_type: {
type: 'string',
description: 'Loại quan hệ: friend, partner, colleague'
},
budget: {
type: 'number',
description: 'Ngân sách tối đa cho quà, theo đơn vị tiền tệ của người dùng'
}
},
required: ['age', 'budget']
}
},
async ({ age, relationship_type, budget }) => { // mã hàm/công cụ
// Logic thực sẽ có sau
return { suggestions: [] };
}
);
Lưu ý các chi tiết chúng ta đã nghĩ kỹ ngay lúc này, dù logic còn là “stub”:
- Tên: suggest_gifts, không phải tool1.
- Mô tả: giải thích rõ khi nào nên gọi công cụ và khi nào không.
- Mô tả trường: giúp mô hình map chính xác văn bản người dùng sang đối số.
Kết quả là khi người dùng viết “Chọn quà cho đồng nghiệp với 50 đô la”, mô hình sẽ thấy rằng:
- có công cụ tên suggest_gifts với mô tả về chọn quà;
- nó có các trường age, relationship_type, budget;
- budget — “ngân sách tối đa cho quà”, relationship_type — “loại quan hệ: friend, partner, colleague”.
Ngay cả khi người dùng diễn đạt không chuẩn (“tối đa nửa trăm”, “cho bạn cùng dự án”), mô hình vẫn có đủ ngữ cảnh để cố gắng tạo JSON đối số hợp lý.
Khi công cụ hoạt động thực sự (trong mô-đun về backend và MCP), bạn đã rất rành chủ đề: GPT sẽ gọi công cụ một cách dễ dự đoán, đơn giản vì chúng ta đã thiết kế interface và mô tả tốt.
12. Thực hành nhỏ cho bạn
Để chủ đề không chỉ là lý thuyết, tôi khuyên bạn làm một thử nghiệm nhỏ ngay sau bài giảng.
Đầu tiên, lấy một kịch bản trong GiftGenius của bạn hoặc nghĩ một App mới. Ghi ra trên giấy hoặc trong editor một hàm mà bạn muốn cung cấp cho mô hình — kiểu như search_products, find_hotels, calculate_shipping.
Sau đó, nghĩ cho cùng một công cụ ba cặp “tên + mô tả”:
- Tên và mô tả rất trừu tượng.
- Quá cụ thể (gần như special‑case).
- Tên + mô tả cân bằng tốt, nói rõ khi nào gọi công cụ và những gì nó không nên làm.
Tiếp theo — nếu muốn — bạn có thể dùng OpenAI SDK thông thường để tạo một yêu cầu đơn giản với các phiên bản này và xem hành vi mô hình thay đổi ra sao: có gọi công cụ không, nó điền đối số như thế nào. Trong nghiên cứu về chủ đề này cũng có một bài tập kiểu như vậy cho suggest_gifts.
13. Lỗi thường gặp khi thiết kế tool-call và mô tả
Lỗi №1: Đặt tên công cụ tool1, handler, doStuff.
Kiểu đặt tên này hoàn toàn vô ích với mô hình. GPT không đoán “ý định của lập trình viên” qua tên file; nó cần một tên có ý nghĩa ngữ nghĩa. Nếu bạn đưa một bộ tool1, tool2, tool3 không có mô tả, công cụ sẽ hầu như không được gọi: mô hình đơn giản không hiểu từng cái làm gì, và hoặc sẽ bỏ qua, hoặc chọn ngẫu nhiên.
Lỗi №2: Xem description như ghi chú cho con người.
Nhiều người viết mô tả kiểu công thức như “Hàm chọn quà”, cho rằng chi tiết đã có trong mã. Nhưng mô hình không thấy mã, nó chỉ thấy văn bản mô tả và schema tham số. Mô tả không rõ ràng biến thành nguồn gây ảo giác: GPT hoặc sẽ tự trả lời khi lẽ ra cần gọi công cụ, hoặc gọi công cụ trong tình huống kỳ quặc.
Lỗi №3: Viết mô tả quá rộng hoặc quá hẹp.
Nếu bạn viết “Làm những thứ hay ho”, mô hình không hiểu ranh giới áp dụng. Nếu viết “Chỉ chọn quà cho em trai 18 tuổi”, bạn gần như cấm dùng công cụ trong đa số trường hợp. Mô tả tối ưu đặt ra một phạm vi nhiệm vụ rõ ràng (chọn quà theo một số tham số), danh sách tham số chính (tuổi, quan hệ, ngân sách, sở thích) và nêu rõ với những nhóm câu hỏi nào thì không nên dùng công cụ.
Lỗi №4: Bỏ qua schema tham số như một phần của “prompt”.
Một số lập trình viên chỉ xem JSON Schema là cách để validate trên server. Thực tế, mô hình phân tích tên trường, kiểu và mô tả để hiểu cần lấy dữ liệu gì từ văn bản người dùng. Nếu bạn đặt tên trường là x không có mô tả và cho nó là tùy chọn, GPT sẽ điền lung tung hoặc bỏ trống. Schema đúng đắn với tên rõ ràng và mô tả ngắn gọn giúp giảm mạnh số tool-call không hợp lệ.
Lỗi №5: Kỳ vọng mô hình “phải” gọi công cụ.
Đôi khi lập trình viên thắc mắc: “Vì sao GPT không gọi công cụ của tôi, nó vẫn ở đó mà?”. Câu trả lời hầu như luôn là: từ mô tả hoặc system‑prompt không suy ra rằng công cụ cần cho đúng câu hỏi đó, hoặc văn bản truy vấn rơi vào vùng mà mô hình cho rằng dễ trả lời trực tiếp hơn.
Lỗi №6: Trộn nhiều hành động khác loại vào một công cụ.
Thi thoảng ta muốn làm một manage_orders “tất cả trong một”, vừa tìm, vừa tạo, vừa hủy đơn. Với con người còn có thể giải thích, nhưng với mô hình thì thành một công cụ mơ hồ, không có ranh giới rõ. GPT sẽ kém hiểu khi nào nên gọi, và khó điền đối số — vì bên trong có hàng đống trường tùy chọn. Tốt hơn là tách ra thành nhiều công cụ hẹp (get_order, create_order, cancel_order) với mô tả và schema rõ ràng.
Lỗi №7: Không tính đến permissions và an toàn trong thiết kế tool.
Nếu bạn mô tả một công cụ có thể làm hành động phá hủy (trừ tiền, xóa dữ liệu) nhưng không đánh dấu destructive và không giới hạn phạm vi trong mô tả, bạn tạo ra rủi ro. UI ChatGPT sẽ không hỏi xác nhận thêm, và mô hình có thể quyết định gọi công cụ ngay cả trong các tình huống “rìa”. Các chú giải đúng và mô tả cẩn thận (“chỉ dùng sau khi có sự đồng ý rõ ràng của người dùng”) giúp giảm rủi ro ngay ở cấp tool‑call.
GO TO FULL VERSION