AI 互動教室 ‹ 生成式 AI 導論
下載 .py 單獨開啟實驗場 ↗ 留言回報
GENAI BASICS · 05 · AGENT 與協定生態

AI Agent 與 MCP:
模型長出手腳

上一課的模型只會「想」,這一課它長出手腳。但「Agent 呼叫工具」不是魔法—— 模型只是吐出一段 JSON 文字,動手的從頭到尾是你的程式。 按「下一步」把一次真實互動一步步播出來(模型輸出為實測紀錄,天氣是教學用模擬資料):

實測紀錄:qwen3.5-2b、temperature=0、2026-08。

右邊的實驗場是真的 Python(在你的瀏覽器裡跑,不用安裝任何東西)。 首次載入約需 30–60 秒,正好夠你讀完第 1 節。每一格程式碼都能改、能重跑, 改壞了重新整理就復原——這是你的沙盒,盡量玩。

01 · AI AGENT

Agent:會拆任務、用工具、看回饋的迴圈

一句話重點:AI Agent = 模型(大腦)+ 工具(手腳)+ 迴圈(身體)—— 能自主拆任務、呼叫工具、根據執行結果決定下一步的系統。

純聊天模型只能靠訓練時背下來的知識答題;Agent 多了三件事: 決策(這個問題需不需要查工具?)、行動(發出工具呼叫)、 回饋(拿到結果後修正或收尾)。開場那個播放器就是最小的完整迴圈—— 連「什麼是光合作用」它判斷不用查工具、直接回答,也是決策的一部分。

整個迴圈的骨架用虛擬碼寫出來只有五行——注意模型從沒真的「執行」任何東西

while True: reply = 呼叫模型(messages) # 模型只會產生文字 if 不是工具呼叫(reply): break # 沒有 JSON → 它決定直接回答 result = 執行工具(解析JSON(reply)) # 動手的是你的程式 messages += [reply, result] # 結果塞回對話,讓模型看到
02 · TOOL / FUNCTION CALLING

Tool Calling:模型用嘴巴呼叫、你用程式執行

一句話重點:模型呼叫外部工具的機制——模型輸出結構化的呼叫請求(JSON), 執行與回填結果都是你的程式的事

我們在開場用的是「手工版」:system prompt 裡寫規則、要模型只輸出一行 JSON。 正式的 API 把這件事標準化了——你用 schema 宣告工具,模型回專門的 tool-call 欄位。 兩大家的寫法(真實 API):

# OpenAI:tools 是 function 清單 resp = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "台北天氣如何?"}], tools=[{ "type": "function", "function": { "name": "get_weather", "description": "查詢城市目前天氣", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"], }, }, }], ) resp.choices[0].message.tool_calls # 模型的呼叫請求在這
# Anthropic:input_schema 直接放頂層 resp = client.messages.create( model="claude-opus-5", max_tokens=1024, messages=[{"role": "user", "content": "台北天氣如何?"}], tools=[{ "name": "get_weather", "description": "查詢城市目前天氣", "input_schema": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"], }, }], ) # 回應裡 type=="tool_use" 的區塊就是呼叫請求

不管哪一家,水電工程都一樣:解析 → 執行 → 把結果塞回 messages → 再呼叫模型。 右邊 2️⃣ 還會算給你看:因為 API 無狀態,每一輪都要重送全部歷史—— agent 的上下文帳就是這樣滾大的。

03 · MCP

MCP:AI 工具界的 USB 接口

一句話重點:MCP(Model Context Protocol)是工具接入的開放標準—— 把「M 個應用 × N 個工具」的客製配接地獄,變成「M+N」份標準接口。

上一節的 get_weather 只活在你自己的程式裡; 想讓 Claude Desktop、IDE、別人的 agent 也能用它,難道每家都寫一次配接? MCP 的答案:工具包成 MCP server(寫一次,誰都能接), 應用實作 MCP client(寫一次,什麼工具都能接)。 右邊 3️⃣ 把 4×6=24 條客製配接線 vs 4+6=10 條標準線畫給你看。

用 FastMCP 把函式包成 server 只要一個修飾器——docstring 就是給模型看的說明書, 寫得好不好直接決定模型用不用得對:

from fastmcp import FastMCP mcp = FastMCP("weather") @mcp.tool def get_weather(city: str) -> dict: """查詢城市目前天氣,回傳氣溫、天氣狀況與降雨機率。""" return weather_db[city] mcp.run()

想真的動手架一個?本站的 MCP server 實作課(LLM 應用開發系列)從零寫到部署。

04 · 生態系

生態系名詞一次看:A2A、AG-UI、Skills、Multi-Agent

一句話重點:MCP 管「Agent 連工具」;A2A 管「Agent 連 Agent」、 AG-UI 管「Agent 連使用者介面」——各管一段線路的協定。

Agent Skills 是另一種打包能力的方式:把「怎麼做某件事」的知識寫成 SKILL.md(說明文件+腳本),agent 需要時才載入全文—— 這叫漸進式披露,工具說明書不用一開始全塞進上下文:

--- name: brand-guidelines description: 產出行銷素材時套用公司的品牌規範(何時用:寫文案、做簡報) --- # 品牌規範 主色 #1A73E8、標語一律「...」、禁用詞清單如下…

模型平常只看得到 namedescription 兩行;判斷用得上,才把整份文件讀進來。

Multi-Agent 則是讓多個 agent 分工協作(一個查資料、一個寫報告、一個審稿)。 常見框架的長相(真實 API):

# CrewAI:用角色描述定義 agent from crewai import Agent researcher = Agent( role="研究員", goal="蒐集主題的最新資料", backstory="你是嚴謹的產業分析師", ) # LangGraph:把 agent 流程畫成狀態圖 from langgraph.graph import StateGraph graph = StateGraph(State) graph.add_node("research", research_node) graph.add_edge("research", "write")

新手判斷準則:一個 agent+多個工具能解的,就別急著上 multi-agent—— 多 agent 代表多倍的上下文成本與更難除錯的訊息流,是「需要才加」的架構。

05 · 速查

本課名詞速查卡

發講義用的濃縮版——一個名詞一句話:

AI Agent 能自主拆任務、呼叫工具、根據執行回饋決定下一步的系統——模型是大腦,迴圈是身體
Tool / Function Calling 模型呼叫外部工具的機制:模型輸出 JSON 呼叫請求,執行與回填是你的程式
MCP AI 工具界的「USB 接口」:工具包成 server、應用實作 client,M×N 配接變 M+N
A2A / AG-UI 分別管「Agent 連 Agent」與「Agent 連 UI」的協定——跟 MCP 各管一段線路。
Agent Skills 用 SKILL.md 打包可重用能力,靠漸進式披露(先看兩行摘要、用到才載全文)省上下文。
Multi-Agent 多智能體分工協作(CrewAI/LangGraph/AutoGen)——威力大、成本與除錯難度也大,需要才加
06 · 實戰

換你動手

LEVEL 1

在右邊 1️⃣ 把 CALL 的城市改成「台中」,看管線查到不同資料;再改成資料庫沒有的城市——管線怎麼處理?為什麼錯誤也要回給模型?

LEVEL 2

看 2️⃣ 的上下文帳,回答:如果你的 agent loop 忘了把工具結果塞回 messages,模型第二次呼叫時會看到什麼?會發生什麼事?

LEVEL 3

設計一個計算機工具 calc(expr):寫出它的說明書(給模型看的)、呼叫 JSON 格式(在實驗區用 json.loads 驗證),並想清楚哪些問題「該」與「不該」觸發它。

卡住了?三題在 notebook 最後一格都有折疊解答——先自己做,再打開對照。

07 · 驗收

情境測驗

離開前試試看:下面的情境都真的會遇到。每題選一個你認為的最佳做法,選了馬上看得到解釋。

Q1 情境題

公司有 3 套 AI 助理(客服、內部知識庫、IDE 外掛),要接進 5 個內部系統(訂單、庫存、HR、行事曆、監控)。工程師報告:「每套助理對每個系統都要寫一次串接,共 15 份配接程式,維護不動了。」最合適的方向是?

這就是 MCP 要解的 N×M 配接地獄:讓「工具端寫一次、應用端寫一次」取代「每對組合寫一次」。關鍵收益在增量成本——第 6 個系統上線時,MCP 架構只要多一份 server,舊架構要多寫 3 份配接。A 是砍需求不是解問題;C 只是把 15 份程式放整齊,維護量沒變;D 方向錯得深——模型「知道」系統規格也拿不到即時資料(今天的庫存、現在的訂單),存取即時/私有資料正是工具存在的理由,何況重訓模型的成本遠高於寫接口。

Q2 錯誤診斷

同事寫的 agent loop 如下。實測時模型第一輪正確輸出了工具呼叫 JSON、工具也成功執行,但模型接下來不是又喊一次要呼叫同一個工具,就是憑空編一個天氣。bug 在哪?

while True: reply = call_model(messages) if not is_tool_call(reply): break result = run_tool(parse_json(reply)) # 有執行、有拿到結果 messages.append({"role": "assistant", "content": reply}) # 然後直接進下一輪…

順著訊息流走一遍就看到了:loop 把模型的呼叫(assistant)塞回去了,卻沒把 result 塞回去。模型是無狀態的——它只知道 messages 裡有什麼,工具在你程式裡跑得再成功,沒寫進對話就等於沒發生,於是它只能再喊一次(重複呼叫)或硬答(幻覺)。修法:append 完 assistant 後,再 append 一則帶工具結果的訊息。A 描述的是症狀不是病因(加上限只會讓它「早點失敗」);B 是真實世界該防的另一個坑,但題目說了第一輪解析成功;D 恰好說反——API 無狀態,正因為它不會自己記住,你才要把每一則都塞回去。

Q3 情境題

你要做一個「查訂單狀態、查退貨政策、算運費」的客服 agent。同事提議:「上 Multi-Agent 架構吧——訂單 agent、政策 agent、運費 agent,再加一個總指揮 agent 分派任務。」你該怎麼判斷?

架構選型的原則是從簡單的開始:這三個能力都是「一次工具呼叫拿結果」的形狀,一個 agent 配三個工具就能決策要用哪個——正是本課播放器示範的迴圈。Multi-agent 才有的代價:每個 agent 各自維護一份滾大的 messages(上下文成本翻倍)、agent 之間的訊息流更難追蹤除錯。它的主場是「子任務本身就需要多輪推理與各自的長上下文」(例如一個查資料、一個寫長報告)。A 是把架構當信仰;C 答不了「我的訂單到哪了」——即時資料必須查工具;D 拿協定當架構——A2A 解的是「agent 之間怎麼講話」,不解「該不該拆成多個 agent」。

Q4 錯誤診斷

你把天氣工具包成了 MCP server,模型卻常常在該查天氣時不查、直接瞎猜。檢查程式發現工具長這樣。最該修的是什麼?

@mcp.tool def gw(c: str) -> dict: """util v2""" return weather_db[c]

模型決定「要不要用工具」的唯一依據,就是工具的名字、參數名與說明文字——它看不到你的程式碼實作。gw(c)+「util v2」提供的資訊量是零,模型自然不知道這工具能查天氣,只好用背下來的知識瞎猜。命名清楚、docstring 寫明「查詢城市目前天氣,回傳氣溫、天氣狀況與降雨機率」,行為立刻改變——「改一句說明書、模型行為就變」是 agent 開發最划算的一根槓桿。A 無中生有,結構化的 dict 對模型完全可讀;B 搞錯層次,OpenAI 與 MCP 的工具一樣靠 description 決策,換協定救不了空白說明書;C 是好習慣,但解的是執行期錯誤,不是「模型不來呼叫」。

Python 環境載入中(首次約 30–60 秒)…讀完第 1 節它就好了