Agent、Harness、Tool、MCP 這幾個詞在不同框架的文件裡指的範圍不太一樣,同一個詞在甲專案是協定規範,在乙專案是產品名稱,查資料時很容易把兩件事看成同一件。在我們開始之前,先把六個基礎名詞定義清楚,並一併釐清 Skill 與 Plugin 的差異。
這些名詞沒有唯一權威的定義,取捨方式是不去爭論哪個定義最正確,而是選能拿來做判斷的定義。
以自我迴歸(autoregressive)方式預測下一個 token 的模型
單次呼叫在數學上是純函式(pure function):
f(context) → tokens
它沒有狀態,也沒有產生副作用(side effect)的能力:
連續對話之所以看起來有記憶,是因為呼叫端每次都把先前的訊息一併重送進去。
同樣的輸入在不同時間得到不同結果,那個「不同」一定來自模型以外的地方。
能夠在迴圈中呼叫工具、觀察執行結果、據此決定下一步的系統
最小結構是三步一循環,觀察 → 決策 → 行動,行動產生的結果回到觀察,成為下一輪的輸入。
跟對話式介面的差異不在模型強弱,而在兩件事:
拿 ChatGPT 網頁版當例子,貼一段程式碼請它解釋,那是對話式介面,它自己搜尋網頁、讀取結果、再決定要不要繼續搜尋,那就是 agent。
同一個模型,差別在外層。
包覆 Model 的執行框架,決定它看得到什麼輸入、被允許呼叫什麼、輸出如何被驗證
這個詞在軟體測試領域已經有既定用法,兩者結構相同,目的不同:
| test harness | agent harness | |
|---|---|---|
| 受測體 | 受測程式 | Model |
| 做的事 | 提供輸入、擷取輸出、比對預期值 | 供給輸入、接收輸出、決定接下來怎麼處理 |
| 目的 | 跑完一輪,判定通過或失敗 | 讓執行持續下去,驗證失敗時決定重試、改路徑或中止 |
受測程式本身不需要知道 harness 存在,Model 也一樣。
一個具名的函式宣告,包含名稱、參數 schema 與用途描述
最常見的誤會是以為工具由模型執行,實際上模型不執行工具,流程分四步:
第 3 步是授權邊界唯一能存在的位置。如果模型能直接執行,就沒有任何地方可以插進去擋。
工具宣告是資料(一段 JSON schema),工具執行是程式碼,兩者在不同的地方。
Model Context Protocol,一份以 JSON-RPC 為基礎的協定規範,定義 client 與 server 之間如何列出工具、呼叫工具、回傳結果
它是規範文件,不是產品,也不是函式庫。實作有很多套,官方維護 Python 與 TypeScript SDK,社群另有其他語言的實作。
所以「安裝 MCP」這個說法不對,實際安裝的是:
MCP 要解決的是 M×N 問題:
| 情境 | 需要幾份介接程式碼 |
|---|---|
| 沒有 MCP,M 個 agent 框架各自接 N 種工具 | M×N |
| 有 MCP,工具側實作 server、agent 側實作 client | M+N |
兩邊各做一次就好,換掉 agent 框架時,工具側不必重寫。
模型單次推論可接受的 token 上限
這個名詞看起來最單純,實際上它不是一個數字,是三個數字取最小值:
| 層 | 由誰決定 | 出問題時的現象 |
|---|---|---|
| 模型能力 | 模型權重與位置編碼的訓練範圍 | 超出後輸出品質下降,不報錯 |
| 伺服器配置 | 推論伺服器啟動時的執行期參數 | vLLM 直接回傳錯誤,Ollama 不報錯,直接截掉超出的部分 |
| API 協定 | 端點是否接受該參數 | 參數送出後被忽略,看起來像沒生效 |
三層任何一層卡住,實際可用的就是那一層的數字。常見的組合是模型檔宣告 128K、推論伺服器啟動參數壓在 32K、而設定用的那個 API 端點根本不解析該參數,最後真正能用的是 32K。
所以 context window 這個數字只有指明層級時才有意義,否則兩邊談的可能不是同一個值。
Skill 的定義各家一致,plugin 不是。這個詞至少有兩種用法:
所以「Skill 與 Plugin 的差異」這個問題,要先確認對方講的是哪一種 plugin。取程式碼擴充這種來對照:
| Agent Skill | Plugin(程式碼擴充) | |
|---|---|---|
| 本質 | 檔案形式的指令集與資源 | runtime 內的程式碼 |
| 載入時機 | 模型讀取時進入 context | 行程啟動時載入 |
| 消耗 | 佔用 context window | 佔用記憶體,不佔 context |
| 出事範圍 | 模型不照做,其餘功能正常 | 可能導致 runtime 無法啟動 |
| 可攜性 | 複製檔案即可移轉 | 綁定該 runtime 的擴充介面 |
Skill 改變模型知道什麼,Plugin 改變 runtime 能做什麼
這句話只在程式碼擴充那種用法下成立。plugin 當打包單位時,skill 可以裝在 plugin 裡面一起散布,兩者不是對立選項。
MCP server 是第三種擴充方式,跟這兩者都不同。
從這個層級可以看出 Agent 底下的兩個分支能各自替換:

| 名詞 | 一句話定義 | 容易搞錯的地方 |
|---|---|---|
| LLM | 無狀態的 token 預測函式 | 以為它自己記得先前的對話 |
| Agent | 具備觀察決策行動迴圈、能產生副作用的系統 | 把單次問答也叫 agent |
| Harness | 決定 Model 的輸入、授權與輸出驗證的執行框架 | 跟測試領域的 test harness 混為一談 |
| Tool | 具名的函式宣告 | 以為工具是模型自己執行的 |
| MCP | 工具介接的協定規範 | 當成可以安裝的產品 |
| Context Window | 單次推論的 token 上限 | 只看模型宣告的數字 |
把 agent 接上一台地端推論伺服器時卡了很久,原因跟名詞有關。
那個模型檔宣告支援 128K,agent 這端要求至少 64K,照理說綽綽有餘,實際跑起來每次都在 32K 被截斷。我以為是參數沒帶對,反覆改送出去的 num_ctx,改了幾輪完全沒有變化。
後來拆開看,是兩件事同時發生:
問題不在我不會調參數,在於我把「模型支援 128K」和「這個端點願意給我 128K」當成同一句話。這兩件事在 context window 底下屬於不同層,名詞沒分清楚,debug 的方向從第一步就偏了。
換另一組名詞,agent 工程的四個範式,以及 Loop Engineering、Spec-Driven Development、Verifier Loop 之間的關係。