從 Function Calling 到 MAF 中的 tool use

我覺得今年真的是 AI Agent 崛起的一年。
AI 輔助開發在今年幾乎可以說是全面 Agent 化,而一般的消費者應用領域,也開始有許多 AI Agent 出現。最近身邊的幾個專案,都不約而同地從傳統的 Web應用程式升級成採用單一對談式介面為主要入口的 AI Agnet。
上課時,和學員聊到這些改變。
其中有位學員問到,這是因為MCP出現的關係嗎? 我說不是,真要說的話,其實應該從 Function Calling 開始說起。
一切從 Function Calling 開始
還記得 Function Calling 嗎?
最初的 LLM 只能聊天。你問,它答。但它就是個黑箱,不會上網,不能查資料庫,不知道今天幾月幾號,現在是幾點,當然也不可能去執行你的 API。
後來模型的推理能力變強了(約莫是在 gpt 4o 前後的那個階段),OpenAI 才提供了一個新的能力:讓模型可以「要求系統替它做事」。
這因為當時的LLM開始能夠理解、進行結構化輸出、並且能做到多步驟推理的這個基礎上。
那時候你跟模型聊天,模型可以依照你的對話,來判斷是否需要呼叫外部函式(API),如果需要,模型就回你一段結構化的JSON,像是底下這樣(例如你在聊天的過程中提到要進行請假):
"function_call": {
"name": "leave_request",
"arguments": "{ start_date:2026-5-12,end_date:2026-5-13,leave_type:病假,substitute:張大寶 }"
}
這就是 Function Calling。
很多人看到 Function Calling 這個字眼,誤以為「LLM 模型能夠直接呼叫API」?? 不,其實並沒有,也不能。
真正執行 API 的,是你的 Runtime、你的 Framework、或是你的AI Agent程式。
LLM 模型做的只有三件事:
- 依照對談或語意,判斷需不需要呼叫 API
- 以及,呼叫哪個 API (像是上面的 name)
- 還有,組出呼叫API時所需要的參數 (像是上面的 arguments)
然後你的程式(例如網頁、例如 LINE Bot、例如 Teams Bot),就拿著上述 Function Calling 所組出的呼叫參數,來呼叫 API。這才實現了看起來像是 LLM 呼叫 API 的功能。(但其實,是你幫LLM呼叫了那個API)
基於這個基礎,慢慢的,開發框架開始實作出了 AI Agent 所需要的重要能力,就是 Tool Call。
Kernel Function 就是這種能力的實作
很多人第一次碰到 Semantic Kernel 時,最有感的機制其實是 Kernel Function。
以前它也常被叫做 Semantic Function / Native Function,本質上就是:讓 LLM 可以呼叫的外部功能或方法。
你可以把它想成「Tool 的前身」,掛在 Kernel 物件上,給模型在需要時來呼叫,並完成一些事情。
這技術很務實,不管是查天氣、讀資料庫、發 email、請假、刪除檔案…等,其實所有能力都可以包裝成 Kernel Function。
最典型的寫法是底下這樣:
public class WeatherPlugin
{
[KernelFunction]
[Description("查詢指定城市天氣")]
public string GetWeather([Description("城市名稱")] string city)
{
return $"{city} 晴天";
}
}
var builder = Kernel.CreateBuilder();
builder.Plugins.AddFromType<WeatherPlugin>();
var kernel = builder.Build();
上面的程式運行之後,模型在Kernel上註冊了WeatherPlugin,模型(嚴格來說是框架)就能在需要的時候,自動呼叫 GetWeather("Taipei")。
用戶會感覺「哇,AI (LLM) 真的聽我的指令去幫我查天氣了耶」,但真正執行這個查天氣的API的,仍然是你的程式碼(或者嚴格一點說,是你使用的開發框架幫你執行的),不是LLM模型。
而LLM的角色,則是幫你(依照和用戶之間的對談來)判斷是否需要呼叫、以及如何呼叫這個查天氣的API。
Kernel Function 到底怎麼做到?這個流程和 Function Calling 有何關係?
我們可以把它拆成兩個層面來講:
- 概念上怎麼做到:Kernel Function 是掛給 AI 用的「工具」。技術上是我們把這個「工具」的呼叫規格,當作前後文(context)跟LLM說一聲。
- 實作上是不是透過 Function Calling:多數情境下,是。而背後就是靠現代模型的 Function Calling(GPT系列) / Tool Calling(Claude系列) 能力。
簡化後的流程大概長這樣:

所以,(重要的再講一次)不是模型自己去執行程式碼(它做不到)。
模型只是「決定要呼叫哪個 function、以及應該要帶什麼參數」,真正執行該API的,是 Semantic Kernel Runtime 或 你的程式。
因此,我們可以說:
Kernel Function 雖然不直接等於 Function Calling,但 Kernel Function 實踐自動呼叫的內涵,確實是透過 Function Calling 實現的。
所以,從 Function Calling、Kernel Function、一直到今天的 Tool / MCP,核心思路一直沒變:
模型推理 → 依需選用 Tool 並建立參數 → 你的 App / AI Agent 執行
各家模型的差別?名字不同,作法相似
這功能在每一個高階模型中,都有支援。
讓模型判斷何時需要呼叫外部 Function ,並且提供適當的參數,這是 Kernel Function 的基礎。
這機制在 OpenAI 叫 Function Calling,在 Claude 叫 Tool Use,在 Gemini 叫 Function Declaration。
到了 MAF 的時代,這功能依就是 AI Agent 開發的重點。
即便 API 長得不一樣:
最初 Function Calling 給出的是 JSON Schema,後來到了 Kernel Function 我們只需要給 function signature(類別參照)。到了MAF,簡化到只需要跟框架登記一下類別方法即可。
雖然持續換了好幾個不同的稱呼,但核心流程一直都沒變:
模型推理 → 依需選用 Tool 並建立參數 → 你的 App / AI Agent 執行。
看一段 MAF 的程式碼,你就會懂 Tool 的落地方式
在這段 MAF 範例程式碼中,我們把請假類別(LeaveRequestTools)中,相關的方法(GetLeaveRecordAmount, LeaveRequest) 變成 AI 可用的工具(Tool):
public class LeaveRequestTools
{
[Description("取得指定員工已請假的天數")]
public int GetLeaveRecordAmount(
[Description("要查詢請假天數的員工名稱")]
string employeeName)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"\n[action] 查詢 {employeeName} 請假天數。\n");
Console.ResetColor();
//測試用的回傳職(David已請了5天假、Eric8天)
return employeeName.ToLower() switch
{
"david" => 5,
"eric" => 8,
_ => 3
};
}
[Description("建立一筆員工請假申請")]
public bool LeaveRequest(
[Description("請假起始日期")]
DateTime startDate,
[Description("請假天數")]
string days,
[Description("請假事由")]
string reason,
[Description("代理人")]
string substitute,
[Description("請假者姓名")]
string employeeName)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"""
[action] 建立假單:
{employeeName} 請假 {days} 天,
從 {startDate:yyyy-MM-dd} 開始,
事由為 {reason},
代理人 {substitute}
""");
Console.ResetColor();
return true;
}
}
定義好之後,具體用法如下:
AIAgent agent = new OpenAIClient(openAIApiKey)
.GetResponsesClient()
.AsAIAgent(
model: "gpt-4.1",
instructions: "...",
tools:
[
AIFunctionFactory.Create(leaveTools.GetLeaveRecordAmount),
AIFunctionFactory.Create(leaveTools.LeaveRequest),
]);
這裡有趣的不只是那個 AIFunctionFactory 的 Create 方法。
LeaveRequestTools 類別方法上的 Description 修飾字也很重要。
這些描述不是寫給人看的,是寫給模型「推理」用的。
讓模型在和人對談的過程中,如果發現有必要,就去呼叫相對應的(註冊過的)Method。
Tool 是 AI 世界的新 API Layer
過去,我們寫 API,是讓前端畫面來呼叫。
現在,我們開始寫 Tool,讓 AI 來呼叫。
以前系統的使用者是「人」。
接下來,越來越多系統真正的使用者,可能會變成 AI Agent。
這也是最近這一年多來,整個軟體世界正在發生的改變。
AI Agent 並非是新冒出來的新名詞。
你如果回頭去看,就會發現:
從 Function Calling、Kernel Function、Tool、MCP,一直到今天的 Agent Framework。
其實一直都在做同一件事:
讓 AI 從「只會回答用戶問題」,變成「真的能幫用戶做事」。
而我們這些寫程式的人,正在參與的,不只是下一代 Framework 的演進。
而是下一代「軟體操作方式」的誕生。
過去,人類透過 UI 操作系統。
接下來,AI Agent 會開始透過 Tool、MCP、Workflow,在你的授權下,直接操作這個世界。
而 Function Calling,正是這一切的最初起點。
相關課程:
https://www.studyhost.tw/NewCourses/LineBot
範例程式碼:
https://github.com/isdaviddong/Example-MAF-LeaveRequestToolUsing
留言