Kvmzen 部落格
← 返回技術實踐

AI Agent 為什麼離不開 JSON?從 Tool Calling、Function Calling 到 MCP 的完整資料流解析

AIAgent ·約 14 分鐘閱讀

AI Agent 為什麼離不開 JSON?從 Tool Calling、Function Calling 到 MCP 的完整資料流解析

症狀:JSON 明明可以解析,Agent 卻仍然選錯工具、API 被拒絕,或拿到 MCP 結果後無法繼續。
最快解法:把問題拆成五層,依序驗證 JSON 語法、Schema、工具選擇與權限、呼叫關聯、結果消費,不要只檢查「是不是合法 JSON」。

這篇適合三類讀者:
Agent 開發者需要理解呼叫鏈中 JSON 的實際角色;排障工程師需要定位參數、狀態與結果錯誤;平台架構師則需要設計統一事件、日誌和 Schema 版本。

JSON 不是推理引擎,而是可驗證的資料邊界

AI Agent 並不是靠 JSON 完成推理,而是靠 JSON 及 Schema 在模型、編排器、工具和 API 之間傳遞機器資料。模型負責理解任務和提出工具呼叫,應用程式負責驗證、授權與執行,協定負責傳輸,業務系統則負責最後的狀態判定。

以「替客戶建立工單」為例,一次完整鏈路通常是:

  1. 使用者提出自然語言需求。
  2. 模型根據工具名稱、描述與輸入 Schema 產生工具呼叫。
  3. 編排器解析工具名稱和參數,執行本地函式或遠端 API。
  4. 執行器回傳成功或結構化錯誤。
  5. 編排器以原始呼叫 ID 將結果放回對話狀態。
  6. 模型讀取工具結果,產生下一個動作或最終回答。
  7. 業務層驗證工單是否真的建立,而不是只相信模型文字。

OpenAI 的工具呼叫資料通常包含工具名稱、JSON 格式的 arguments 和 tool call ID;Google 的 Function Calling 流程則明確要求由你的應用程式執行函式,再把結果送回模型。你可以參考 OpenAI Function Calling API 參考Google Gemini Function Calling 官方文件 對照各自欄位,不要把不同平台的訊息格式直接混用。(platform.openai.com)

先分清楚四個責任層

  • 模型生成層:產生工具名稱、參數和下一步意圖。
  • 應用執行層:驗證參數、認證、授權、呼叫 API。
  • 協定傳輸層:保存訊息順序、呼叫 ID、結果格式。
  • 業務驗證層:確認資源真的建立、更新或刪除。

只要你把這四層混在同一個 agent_error 欄位裡,日誌就只能告訴你「失敗」,不能告訴你到底是誰的責任。

「能解析」仍然不代表呼叫成功

第一層:JSON 合法,但 Schema 不合規

以下資料在語法上是合法 JSON:

{
  "ticket_id": 123,
  "priority": "urgent"
}

但如果 Schema 要求 ticket_id 是字串、priority 只能是 lownormalhigh,這個請求就會在結構驗證階段失敗。常見問題包括:

  • 必填欄位遺失;
  • 字串、數字、布林值型別錯誤;
  • 陣列元素格式不一致;
  • 出現執行器未預期的額外欄位;
  • Schema 版本更新後,舊工具仍送出舊欄位。

因此,驗證順序應是「先 JSON parser,再 JSON Schema validator」。不要使用 json.loads() 成功作為放行條件。不同模型平台也只支援各自文件定義的 Schema 子集;即使名稱都叫 JSON Schema,嚴格模式可接受的關鍵字未必相同。OpenAI 官方文件也提醒,嚴格工具呼叫只支援部分 JSON Schema,且應在你的程式中再次驗證 arguments。(platform.openai.com)

第二層:Schema 合規,但工具選錯

假設你同時提供:

  • create_ticket
  • update_ticket
  • search_ticket

三個工具,而模型選了 update_ticket。即使參數完全符合 Schema,執行結果仍可能錯誤,因為模型的「工具語意判斷」出錯。

這時繼續收緊欄位型別通常沒有幫助。你應該檢查:

  • 工具名稱是否直接描述動作,不要使用過度相似的名稱;
  • 描述是否寫明「何時使用」及「何時不要使用」;
  • 候選工具範圍是否過大;
  • 使用者目前是查詢、建立還是修改;
  • 工具是否明確標示唯讀、破壞性或需要確認。

這也是 Tool Calling 的核心邊界:Schema 管理「參數長什麼樣」,工具描述和上下文管理「應該呼叫哪一個」。

第三層:參數正確,但 API 執行被拒絕

API 拒絕不一定是模型錯。至少要分開記錄:

  • 認證失敗,例如 API Key 過期;
  • 授權不足,例如帳戶沒有修改資源的權限;
  • 資源狀態不允許,例如工單已關閉;
  • 網路、DNS、逾時或上游服務不可用;
  • 業務規則不符合,例如重複訂單或超過限額。

執行器不能只回傳「request failed」。應該產生模型和人都能讀懂的結構,例如:

{
  "ok": false,
  "error": {
    "code": "RESOURCE_STATE_INVALID",
    "retryable": false,
    "message": "ticket is already closed"
  }
}

其中 code 用於程式分支,retryable 用於決定是否重試,message 才是提供模型理解的補充說明。這比讓模型從 HTTP 狀態碼或一段堆疊追蹤中猜原因可靠得多。

五層故障分流表

下面這張表可用來建立你的第一版排障分流規則:

檢查層 典型症狀 應保存的欄位 修正方向
JSON 語法 解析器直接報錯 原始 arguments、解析錯誤位置 修正序列化或串流拼接
Schema 缺欄位、型別錯誤 Schema 版本、驗證差異 更新工具定義或參數映射
工具選擇 呼叫了不相關工具 候選工具、描述、上下文 縮小工具範圍、重寫描述
執行與權限 API 401、403 或業務拒絕 權限決策、資源狀態、錯誤碼 在執行器處理,不交給模型猜
狀態與結果 重複執行、結果錯配 interaction ID、call ID、結果版本 修復歷史順序與關聯鍵

這個分法的價值在於,你可以先回答「失敗發生在哪一層」,再決定要改提示詞、Schema、執行器,還是狀態儲存。不要一看到工具失敗就降低模型溫度或無限重試。

呼叫 ID 遺失會破壞長任務狀態

在單一工具的簡單流程中,呼叫 ID 遺失可能只造成一次回傳錯誤;但在並行工具或長任務中,後果會嚴重得多。

例如模型同時呼叫:

[
  {"id": "call_a", "name": "get_user", "arguments": {"id": "u1"}},
  {"id": "call_b", "name": "get_orders", "arguments": {"user_id": "u1"}}
]

如果執行器只保存工具名稱,沒有保存 call_acall_b,兩個結果回來後就可能互相配錯。常見結果是:

  • 模型把訂單清單當成使用者資料;
  • 同一個工具因為「沒有收到結果」而再次執行;
  • 編排器無法判定哪些工具已完成;
  • 長任務在中途停止,重試後又重複修改資源。

Google 的新式互動流程要求在回傳 function result 時帶回對應的 call_id;OpenAI 的工具訊息也使用 tool_call_id 關聯結果。Anthropic 的工具使用則要求 tool_result 緊接在原本的 tool_use 之後,並以 tool_use_id 配對。這些名稱不同,但責任相同:結果必須可追溯到唯一一次呼叫。(ai.google.dev)

第二步:保存完整狀態,而不是只保存最後一句話

若你採用無狀態模式,每次後續請求都要由客戶端保留完整歷史,包括使用者輸入、模型產生的工具呼叫,以及工具結果。Google 官方文件特別列出這個要求;缺少其中一段,模型就可能看不到先前的呼叫上下文。(ai.google.dev)

建議至少保存以下欄位:

{
  "trace_id": "trace-...",
  "interaction_id": "interaction-...",
  "tool_call_id": "call-...",
  "tool_name": "get_orders",
  "schema_version": "orders.v3",
  "status": "executed",
  "result_hash": "sha256:..."
}

不要只記錄最終回答。真正能幫你重現問題的,是每一個模型輸出、執行決策、權限結果和工具回傳。

MCP 結果返回後仍要做下游驗證

Model Context Protocol 對工具結果提供兩種重要路徑:

  • content:可包含文字、圖片、資源連結等內容;
  • structuredContent:供程式和客戶端消費的結構化 JSON;
  • outputSchema:描述結構化結果應符合的格式。

MCP 規範指出,如果工具提供 outputSchema,伺服器必須提供符合該 Schema 的結構化結果;客戶端則應進行驗證。為了相容較舊的客戶端,工具在提供結構化內容時,也應保留序列化後的文字內容。(modelcontextprotocol.io)

所以,不要假設收到 structuredContent 就代表下游一定能用。你還要檢查:

  1. 客戶端是否真的支援該欄位;
  2. structuredContent 是否符合當前 outputSchema
  3. 文字 content 是否能作為相容降級;
  4. 結果是否包含 isError 或等效錯誤狀態;
  5. Schema 版本是否和消費端一致。

MCP 版本與提案可能持續調整,尤其是 outputSchema 對 JSON Schema 子集的支援範圍。部署前應以 MCP Tools 規範MCP Schema Reference 作為實作依據,不要把某個 SDK 的型別定義當成所有客戶端的共同標準。(modelcontextprotocol.io)

FAQ:排查 JSON 資料流時最容易混淆的問題

AI Agent 為什麼普遍使用 JSON?

JSON 能讓欄位、陣列和巢狀物件保持明確邊界,方便模型輸出後由程式驗證,也方便日誌系統保存和重播。但 JSON 只解決「怎樣表示資料」,並不解決工具選擇、權限、資源狀態或業務正確性。

Function Calling 的 JSON 是模型直接執行的嗎?

不是。模型只產生函式名稱和參數,實際執行者是你的編排器或應用程式。執行前必須驗證 Schema、檢查認證與授權,執行後再把結果連同原始呼叫 ID 傳回模型。

MCP 工具結果如何讓模型繼續工作?

MCP 伺服器回傳工具結果後,客戶端會將結果放入後續模型互動。結構化資料可放在 structuredContent,人類可讀內容則放在 content;兩者都應保留,讓不同客戶端有降級處理空間。

JSON 已經合法,Agent 為什麼仍會失敗?

合法 JSON 不等於符合 Schema,也不等於工具選擇正確。你還要檢查必填欄位、型別、列舉值、工具描述、認證、授權、資源狀態和業務規則,並把每一層的錯誤分開記錄。

呼叫 ID 不見了,怎樣判斷是否已經重複執行?

先比對 trace ID、工具名稱、參數雜湊和執行器的冪等鍵。如果只有模型訊息沒有執行事件,不能直接判定已成功;對有副作用的工具,應在執行器保存唯一請求鍵,避免重試造成重複建立或修改。

第三步:建立可重播的統一事件日誌

你可以把所有平台轉成內部統一事件,但不要抹掉原始欄位。推薦事件至少分成:

  • model_tool_proposed:模型提出工具名稱、原始參數和模型回應 ID;
  • schema_validated:使用哪個 Schema 版本、驗證成功或失敗;
  • permission_decided:使用者、服務帳戶、資源和授權結果;
  • tool_executed:開始時間、結束時間、重試次數和執行結果;
  • protocol_returned:原始 call ID、MCP 結果欄位和訊息順序;
  • business_verified:資源最終狀態,以及是否真的完成任務。

可勾選的驗收清單

  • [ ] 每次工具呼叫都有唯一 trace_idtool_call_id
  • [ ] 原始 arguments 與解析後物件分開保存。
  • [ ] 每次驗證都記錄 Schema 名稱與版本。
  • [ ] 工具選擇錯誤和參數驗證錯誤分成不同錯誤碼。
  • [ ] API 401、403、逾時和業務拒絕不共用同一個失敗狀態。
  • [ ] 並行工具結果回傳前,已用呼叫 ID 完成配對。
  • [ ] MCP 結果同時保留 contentstructuredContent 和錯誤狀態。
  • [ ] 具副作用的工具具備冪等鍵或去重策略。
  • [ ] 日誌可依 trace ID 重播完整對話與執行鏈。
  • [ ] 涉及 macOS 工具時,同時記錄遠端環境、權限提示和依賴版本。

如果你正在建立驗收規則,可以先閱讀 Kvmzen 繁體中文幫助中心,把權限、遠端連線與環境重現條件一起納入平台作業文件。

你應該採用的六步落地流程

第一步,先固定一個可重現任務,例如查詢資料、建立資源或執行 macOS 指令,不要一開始就用多工具複合流程。

第二步,故意注入四類故障:Schema 缺欄位、權限拒絕、呼叫 ID 遺失、MCP 結果與 outputSchema 不匹配。

第三步,確認每類故障是否落到不同事件和錯誤碼,而不是全部變成「Agent failed」。

第四步,加入並行工具測試,檢查結果順序改變時,編排器是否仍能用 ID 正確配對。

第五步,測試重試與中斷恢復。特別是建立、刪除、付款或修改檔案等有副作用操作,必須確認重試不會重複執行。

第六步,將平台原始訊息保存在冷資料區,內部統一事件則提供查詢介面。這樣既能跨平台分析,也不會因欄位正規化而失去原始證據。

當前環境與 Mac 方案,差異在可重現性

如果你的 Agent 依賴 macOS 指令、Xcode、AppleScript、iOS 模擬器或本機權限,目前環境常見的缺點是:開發者各自使用不同版本、權限狀態難以複製、錯誤日誌分散在本機,而且排障時還要等待同事釋放設備。Windows 或 Linux 雲端主機雖然適合一般 API 編排,但遇到 macOS 專屬工具時,往往需要額外轉接層,增加權限和狀態差異。

若你要持續重現跨層呼叫故障,租用 Kvmzen 的 Mac 環境會更適合短期測試、隔離依賴和遠端協作;你可以先從 Mac 雲端租用方案確認環境,再把固定的 Schema、事件日誌與測試案例部署上去。若團隊需要比較自購設備與遠端環境,也可先參考 Mac mini 價格與方案資訊,再按任務週期、硬體介面需求與長期負載作決定。

如果你的工作是全年穩定重負載、必須接實體 USB 或特殊周邊,自購 Mac 仍可能更合理;但若目標是隔離環境、臨時重現問題或驗證一條 MCP 與 Function Calling 呼叫鏈,遠端 Mac 通常能讓你更快建立一致的測試條件。

限時特惠

不只是一台 Mac,是你在雲端的開發基地

獨享算力 · 全球節點 · 按月訂閱 · 無需購置硬體

返回首頁
限時優惠 點擊查看套餐