# Function calling là gì và hoạt động như thế nào?

> Function calling giúp mô hình ngôn ngữ lớn (LLM) kết nối API, thực hiện hành động thực tế và trích xuất tham số JSON chuẩn xác thay vì chỉ sinh văn bản.

Nguồn: https://camnangai.com/ky-thuat/function-calling-la-gi  
Xuất bản: 2026-09-02

**Function calling** là cơ chế kỹ thuật cho phép mô hình ngôn ngữ lớn
  ([LLM](https://camnangai.com/kien-thuc-ai/llm-la-gi)) kết nối trực tiếp với các công cụ, API và hệ thống phần mềm bên
  ngoài thay vì chỉ sinh văn bản đơn thuần.

Về bản chất, LLM không tự chạy code, cũng không tự vào internet; nó chỉ làm "đầu não" nhận diện yêu
cầu, chọn đúng hàm cần dùng và trích xuất tham số dưới dạng JSON.


  Việc thực thi logic thực tế hoàn toàn nằm ở phía ứng dụng (client), giúp đảm bảo an toàn hệ thống
  và tính kiểm soát cho lập trình viên.


![Mô hình ngôn ngữ nằm giữa cuộc hội thoại và các công cụ bên ngoài, phát ra một lệnh gọi hàm có cấu trúc thay vì tự chạy code](https://camnangai.com/articles/function-calling-la-gi/01-infographic-vn.webp)

## Function calling là gì?

**Function calling** là "cầu nối" chuyển ngôn ngữ tự nhiên thành hành động thực thi có cấu trúc.
Thay vì cố trả lời dựa trên kiến thức tĩnh đã cũ, mô hình trả về một cấu trúc JSON chứa tên hàm và
các đối số (arguments) để ứng dụng của bạn xử lý tiếp.

![Ba nhóm công dụng của function calling: thực hiện hành động, bổ sung kiến thức và mở rộng khả năng tính toán](https://camnangai.com/articles/function-calling-la-gi/02-vn.webp)

Cơ chế này phục vụ ba nhóm công dụng rất thực dụng. Nó cho mô hình thực hiện hành động, tức là tương
tác trực tiếp với thế giới thực qua API: đặt lịch họp, gửi mail, hoặc điều khiển thiết bị IoT như bật
đèn và khóa cửa. Nó bổ sung kiến thức mô hình không có sẵn, bằng cách truy vấn dữ liệu từ các
nguồn bên ngoài như SQL database doanh nghiệp hoặc API thời tiết để trả lời các câu hỏi về thông tin
thời gian thực. Và nó mở rộng khả năng của mô hình: vì mô hình ngôn ngữ lớn vốn có giới hạn về toán
học, bạn đẩy phần tính toán sang máy tính hoặc các thư viện vẽ biểu đồ chuyên dụng thay vì bắt nó tự
nhẩm.

Điểm mấu chốt cần nhớ: khi gọi hàm, mô hình không trả lời trực tiếp câu hỏi của người dùng, nó trả về
JSON. Nếu bạn thấy nó trả về văn bản thường trong tình huống lẽ ra phải gọi API, nghĩa là prompt
hoặc schema của bạn đang có vấn đề chứ không phải mô hình dở.

## Vòng lặp function calling hoạt động như thế nào?

Vòng lặp này gồm 4 bước tách biệt rõ rệt. Đừng bao giờ để mô hình nắm quyền thực thi trực tiếp, vì
đó là lỗ hổng bảo mật chết người. Trách nhiệm thực thi luôn nằm ở phía client của bạn:

1. **Định nghĩa:** Bạn khai báo `tool schema` (thường là JSON Schema) mô tả tên hàm và các tham số
   cho mô hình.
2. **Yêu cầu:** Người dùng gửi prompt, ứng dụng gửi kèm schema đến mô hình. Mô hình phân tích và trả
   về một `function_call` gồm tên hàm và các giá trị tham số đã trích xuất.
3. **Thực thi:** Ứng dụng phía client nhận JSON, kiểm tra tính hợp lệ và chạy mã nguồn thực tế (gọi
   API hoặc truy vấn database). Mô hình hoàn toàn đứng ngoài bước này.
4. **Phản hồi:** Bạn gửi kết quả thực thi ngược lại cho mô hình. Lúc này, mô hình mới tổng hợp toàn
   bộ ngữ cảnh để đưa ra câu trả lời cuối cùng cho người dùng bằng ngôn ngữ tự nhiên.

Để ý kỹ, bước 2 và bước 4 là hai lần gọi mô hình khác nhau, và đó là chỗ nhiều người mới bắt đầu hay
hiểu nhầm thành một. Vòng lặp chỉ kết thúc khi mô hình ngừng yêu cầu gọi hàm. Trong thực tế, bạn viết nó dưới dạng một
vòng `while` bám vào tín hiệu dừng: chừng nào phản hồi còn báo cần dùng công cụ, bạn còn thực thi và
gửi kết quả ngược lại; khi tín hiệu đổi sang kết thúc lượt, mô hình đã có câu trả lời cuối cùng.

## Điều gì thực sự xảy ra bên trong mô hình?

Với các mô hình thế hệ mới thuộc dòng Gemini 3, quá trình này không còn là dự đoán token mù quáng. Mô
hình sử dụng một "quy trình tư duy" (thinking process) nội bộ để lý giải schema phức tạp trước khi
xuất dữ liệu, giúp giảm đáng kể lỗi cú pháp.

![Bốn chế độ của tham số tool_choice đặt cạnh nhau: auto, any, none và validated](https://camnangai.com/articles/function-calling-la-gi/03-vn.webp)

Hành vi này được kiểm soát chặt chẽ qua tham số `tool_choice`:

- **`auto`:** Chế độ mặc định, mô hình tự quyết định có cần dùng tool hay không.
- **`any`:** Ép mô hình phải gọi ít nhất một hàm (thường dùng cho các agent chuyên biệt).
- **`none`:** Cấm gọi tool, chỉ sinh văn bản thuần.
- **`validated`:** Mô hình đảm bảo đầu ra phải tuân thủ nghiêm ngặt schema đã định nghĩa.

Khi nhận diện nhu cầu gọi hàm, mô hình dừng sinh văn bản và trả về một tín hiệu dừng riêng cho việc
dùng công cụ. Quy trình "tư duy" nói trên giúp mô hình kiểm tra logic các tham số trước khi "chốt"
JSON, nhờ đó hạn chế được tình trạng ảo giác tham số. Trong bốn giá trị trên, `auto` xử lý gần hết
các tình huống đời thường; tôi chỉ đụng tới `any` khi con agent có đúng một việc phải làm và không
được phép trả lời suông.

## Định nghĩa một function: JSON Schema và phần mô tả

Schema là ngôn ngữ duy nhất mô hình hiểu về công cụ của bạn. Một định nghĩa chuẩn bắt buộc phải có:
`name`, `description`, `parameters` (loại `object`) và mảng `required`. Lưu ý rằng các nhà cung cấp
chỉ hỗ trợ một tập con của chuẩn OpenAPI, nên schema quá lớn hoặc lồng ghép quá sâu có thể bị từ
chối.

Kinh nghiệm xương máu: phần `description` chính là "prompt ẩn". Đừng viết chung chung kiểu "Hàm chỉnh
màu", hãy viết cụ thể để mô hình biết khi nào nên dùng. Trường `enum` cũng cực kỳ quan trọng: nó
khóa tham số vào một tập giá trị hợp lệ và loại bỏ hẳn một nhóm lỗi ảo giác tham số.

**Mẫu JSON Schema chuẩn cho thiết bị thông minh:**

```json
{
  "name": "set_light_values",
  "description": "Điều chỉnh độ sáng và trạng thái màu sắc của đèn thông minh trong phòng.",
  "parameters": {
    "type": "object",
    "properties": {
      "brightness": {
        "type": "integer",
        "description": "Mức độ sáng từ 0 đến 100."
      },
      "color_temp": {
        "type": "string",
        "enum": ["daylight", "cool", "warm"],
        "description": "Nhiệt độ màu của ánh sáng, chỉ chấp nhận các giá trị: daylight, cool, hoặc warm."
      }
    },
    "required": ["brightness", "color_temp"]
  }
}
```

Mảng `required` phải khớp chính xác tên các thuộc tính bạn đã khai báo. Nghe hiển nhiên, nhưng
sai lệch ở đúng chỗ này lại là một trong những nguyên nhân gây lỗi phổ biến nhất khi lên production,
và nó chỉ lộ ra khi mô hình bắt đầu trả về tham số thiếu.

## Gọi nhiều function: song song, tuần tự và đa công cụ

Các hệ thống agentic phức tạp cần gọi được nhiều công cụ trong cùng một lượt, và có ba kiểu gọi khác
nhau nằm sau cái nhu cầu đó.

![Ba kiểu gọi nhiều hàm: song song với hai hàm chạy cùng lúc, tuần tự khi đầu ra hàm này là đầu vào hàm kia, và đa công cụ kết hợp công cụ sẵn có với hàm API riêng](https://camnangai.com/articles/function-calling-la-gi/04-vn.webp)

Parallel function calling là gọi nhiều hàm độc lập cùng lúc. Bạn bảo "Tắt đèn và hạ rèm", mô hình trả
về cả hai lệnh gọi hàm trong một phản hồi (response) duy nhất, cho phép bạn thực thi song song để
giảm độ trễ.

Compositional (Sequential) calling là gọi hàm theo chuỗi, khi đầu ra của hàm này chính là đầu vào của
hàm kia: kết quả của `get_location` được dùng làm đầu vào cho `get_weather`. Mỗi mắt xích ở đây là
một lượt gửi–nhận (round-trip) đầy đủ tới mô hình, nên chuỗi càng dài thì cái giá phải trả về độ trễ
càng đắt.

Multi-tool use là khả năng kết hợp các công cụ "chính chủ" như Google Search với các hàm API riêng
của bạn trong cùng một lượt yêu cầu (request), để giải quyết những tác vụ đa bước mà không công cụ
đơn lẻ nào tự làm nổi.

## Function calling khác structured outputs và JSON mode ra sao?

Rất nhiều người nhầm lẫn chỗ này, và cái giá phải trả là chọn sai hướng triển khai ngay từ đầu.

![Ba mức tăng dần: JSON mode đảm bảo đúng cú pháp, structured outputs đảm bảo đúng schema, còn function calling là một vòng lặp hành động có thực thi bên ngoài](https://camnangai.com/articles/function-calling-la-gi/05-vn.webp)

JSON Mode chỉ đảm bảo đầu ra là JSON hợp lệ về cú pháp, còn mô hình trả về những key gì, bạn vẫn
phải tự đoán. Structured Outputs đi xa hơn một bậc, ép mô hình tuân thủ 100% schema, nên nó cực kỳ
phù hợp để trích xuất dữ liệu. Function calling khác hẳn cả hai: nó là một vòng lặp hành động
(action loop), không dừng ở chuyện định dạng mà gắn liền với logic thực thi của hệ thống bên ngoài,
và nó còn chờ phản hồi từ API để tiếp tục suy luận.

Ba cơ chế này không loại trừ nhau. Bạn hoàn toàn có thể áp ràng buộc kiểu structured outputs lên
chính các tham số của một lệnh gọi hàm, để đảm bảo đối số sinh ra luôn khớp schema trước khi chạm vào
API thật.

## Mô hình gọi function chính xác đến mức nào?

Đừng nghe quảng cáo, hãy nhìn vào con số thực tế từ **Berkeley Function Calling Leaderboard (BFCL)
V4**. Khả năng xử lý các tham số lồng ghép và đa bước là thước đo thực sự:

- **Claude-Opus-4-5-20251101 (FC):** Dẫn đầu bảng với độ chính xác tổng thể **77.47%**.
- **Claude-Sonnet-4-5-20250929 (FC):** Đạt **73.24%**.
- **Gemini-3-Pro-Preview (Prompt):** Đạt **72.51%**, xếp hạng 3.
- **Qwen3-32B (FC):** Đạt **48.71%**, cho thấy khoảng cách còn khá lớn ở nhóm mô hình mở.

Lưu ý quan trọng cho dân triển khai: bản Gemini-3-Pro-Preview chạy theo lối "Prompt" (72.51%) lại
đứng trên chính bản hỗ trợ gốc Native FC của nó (**68.14%**, hạng 7). Điều này cho thấy việc tối ưu
prompt cho tool vẫn quan trọng, chứ không nên chỉ dựa dẫm vào hỗ trợ mặc định của model.

## Function calling hỏng ở đâu khi lên production

Trên máy của bạn mọi thứ chạy ngọt, còn lên production lại là câu chuyện hoàn toàn khác, với 3 lỗi
kinh điển bạn sẽ gặp đi gặp lại:

![Ba lỗi thường gặp khi lên production: JSON hỏng định dạng, quá nhiều tool khiến mô hình chọn sai hàm, và mô tả mơ hồ khiến mô hình điền sai tham số](https://camnangai.com/articles/function-calling-la-gi/06-vn.webp)

1. **Lỗi `Malformed_Function_Call`:** Xảy ra khi bạn bắt mô hình vừa phải suy nghĩ (văn bản thuần)
   vừa phải xuất JSON gọi hàm ngay lập tức, gây nhiễu định dạng.
2. **Schema quá tải:** Cung cấp quá nhiều tool (vượt quá khoảng 20 tool) hoặc schema lồng ghép 4-5
   tầng khiến mô hình bị "ngợp" và chọn sai hàm hoặc trích xuất sai tham số.
3. **Độ nhạy format:** Mô hình gọi sai enum hoặc thiếu tham số bắt buộc nếu phần mô tả không rõ ràng.

**Giải pháp "Double Call":** dùng một hàm `update` để bao bọc các ghi chú tư duy (pre-tool notes). Mô
hình sẽ thực hiện **hai cuộc gọi đồng thời trong cùng một lượt**: một cuộc gọi hàm `update` để lưu
lại kế hoạch tư duy và một cuộc gọi hàm thực thi chính. Cách này giúp tách biệt phần "nghĩ" ra khỏi
phần "làm", nhờ vậy cú pháp JSON luôn sạch. Đây là kiểu giải pháp không đẹp về mặt thiết kế, nhưng
nó chạy được, và trong sản phẩm thật, tôi chọn cái chạy được.

## Khi nào nên dùng function calling và khi nào không

Hãy dùng **function calling** khi bạn cần tính chính xác tuyệt đối và kết nối dữ liệu thời gian thực.
Đây là "xương sống" cho mọi [AI agent](https://camnangai.com/kien-thuc-ai/ai-agent-la-gi) hiện nay.

Tuy nhiên, đừng lạm dụng nó: nếu bạn chỉ cần định dạng đầu ra để hiển thị, hãy dùng Structured
Outputs.
Một lời khuyên thực tế: hãy giới hạn ở mức **10-20 tool tối đa** cho mỗi request. Nếu hệ thống có
hàng trăm API, hãy dùng thêm một bước [RAG](https://camnangai.com/kien-thuc-ai/rag-la-gi) để lọc ra những tool cần thiết
trước khi gửi schema cho mô hình.

## Tài liệu tham khảo

- [Function calling — OpenAI API](https://developers.openai.com/api/docs/guides/function-calling)
- [How tool use works — Claude Platform Docs](https://platform.claude.com/docs/en/agents-and-tools/tool-use/how-tool-use-works)
- [Function calling with the Gemini API — Google AI for Developers](https://ai.google.dev/gemini-api/docs/function-calling)
- [Introducing advanced tool use on the Claude Developer Platform — Anthropic](https://www.anthropic.com/engineering/advanced-tool-use)
- [Tool Calling Best Practices for LLMs — AI/TLDR](https://ai-tldr.dev/learn/llm-apis/function-calling/tool-calling-best-practices/)
- [When should I use function calling, structured outputs or JSON mode? — Vellum](https://www.vellum.ai/blog/when-should-i-use-function-calling-structured-outputs-or-json-mode)
- [Berkeley Function Calling Leaderboard (BFCL) V4 — UC Berkeley](https://gorilla.cs.berkeley.edu/leaderboard.html)
- [How Function Calling Actually Works Under the Hood — Let's Data Science](https://letsdatascience.com/blog/function-calling-tool-use-ai-agents)
