iT邦幫忙

0

Agent Plugin 壞一個元件,不該拖垮整個 Agent

  • 分享至 

  • xImage
  •  

Plugin 已經被 client 找到,其中一個 MCP server 卻在 handshake 時失敗。結果整包 skills 都從 Agent 的能力清單消失。這種處理看似保守,其實是把故障邊界畫錯了。

Agent Plugins 1.0 把 plugin.jsonskills/mcp.json 和 client 自訂內容放進同一個 package。封裝讓團隊能用一致的目錄整理交付內容,安裝與分發則不在規格範圍內。Package 裡的東西放在一起,不代表它們必須一起成功,也不代表它們共享同一種復原方式。

維運時需要追的是一個錯誤究竟會停在整包、單一元件,還是執行階段。

先把故障分成三層

第一層是 package。Root manifest 無法解析、必要欄位無效,client 連這個 plugin 是什麼都無法確認,拒絕整包很合理。這類錯誤發生在 discovery 與 validation 階段,標準元件還不該進入載入流程。

第二層是 component。v1 的標準元件是 skills 與 MCP servers。單一 skill 格式錯誤,或某個 MCP entry 無效時,失敗範圍應盡量留在該元件;其他可用元件仍可繼續載入。某種元件目錄不存在,並不等於 plugin 無效。不是每個 plugin 都必須同時帶 skill 和 MCP server。

第三層是 runtime。MCP subprocess 啟動後怎麼隔離、憑證怎麼給、執行期間能碰哪些檔案,以及 client-specific hook 如何復原,都不會因為 package 符合規格就自動得到答案。這部分要由 client 與團隊自己的執行環境負責。

如果監控只留下一行「plugin load failed」,這三層就又被揉回同一團了。

先把 blast radius 寫成表格

在寫 retry 之前,我會先替 plugin 做這張矩陣:

故障 預期載入結果 還能相信的能力 至少要留下的證據 復原責任
plugin.json 致命驗證錯誤 拒絕整包 plugin manifest 路徑、驗證錯誤、規格版本 package 維護者
單一 skill 格式無效 略過該 skill,繼續處理其他元件 已成功載入的 skills/servers skill 識別、解析錯誤、實際載入清單 skill 維護者
單一 MCP entry 無效或 transport 不支援 略過該 entry,繼續處理其他 servers/components 不依賴該 server 的能力 entry 識別、失敗階段、其他 server 狀態 MCP 設定維護者
MCP 啟動、驗證或 handshake 失敗 該 server 不可用,其他元件仍可載入 需由測試確認降級後的任務路徑 stderr/連線錯誤、handshake 階段、降級標記 runtime 維護者
client extension hook 失敗 依該 client 的規則處理 portable core 不能代為承諾 client 名稱與版本、extension log、fallback 結果 client 整合維護者

「其他元件仍可載入」很常被誤讀。它只描述 loading 結果,不代表原本的使用者任務做得完。假如 skill 的最後一步必須呼叫壞掉的 preview server,介面上看得到 skill,不等於它能完整執行。

所以矩陣要同時記錄 loaded components 與 degraded capabilities。只記前者,會把半套能力誤報成健康。

用一個 UI review plugin 看差異

假設團隊有一個 ui-prototype-review plugin:

ui-prototype-review/
├── plugin.json
├── skills/
│   ├── compare-genui/
│   │   └── SKILL.md
│   └── check-accessibility/
│       └── SKILL.md
├── mcp.json
└── com.example.ide/
    └── preview.json

compare-genui 保存比較 UI pattern 的流程,也可以把 生成式 UI 資源合集 列為公開資料的查找起點。它是一份人為整理的多語系資源目錄,不是 Agent Plugin、MCP server,也不提供執行期安全保證。

mcp.json 另外宣告一個可選的預覽或截圖工具;com.example.ide/ 則是假想的 IDE 專用 preview hook。這三者服務同一個 review 工作流,故障語意卻不相同。

公開資源暫時連不上,skill 仍可能靠既有步驟與團隊內部資料完成比較。MCP preview server handshake 失敗時,文字檢查也許能繼續,畫面截圖則必須標成 unavailable。IDE hook 壞掉時,另一個 client 可能根本不會讀取那個 namespace。

「Plugin 還在」只能當載入狀態,不能當任務狀態。

Path containment 只管 package 內的路徑

Agent Plugins 規格要求 plugin 提供的相對路徑不能逃出 plugin root。這可以阻止 manifest 用 ../../ 指向 package 外的檔案,也是必要的解析邊界。

這條邊界不等於 subprocess sandbox。MCP server 啟動後收到的 runtime input、處理程序可讀取的檔案、環境變數裡的憑證與網路權限,仍受作業系統、容器、client 與部署設定控制。通過 path containment 測試,只能證明 package 內的檔案解析沒有越界;它證明不了執行中的處理程序被隔離。

如果安全檢查表把兩者合成一個「sandbox: pass」,那個勾勾很容易讓人過度信任。

先跑四個 fault injection

這類 plugin 不需要一開始就建龐大的測試平台。先固定四個 case,就能抓出不少邊界錯置。

Case 1:破壞 root manifest

刪掉必要欄位,或放入 client 無法接受的規格版本。測試應確認整包被拒絕,任何標準元件都沒有進入可用清單,而且錯誤明確指向 manifest validation。

Case 2:只弄壞第二個 skill

check-accessibility/SKILL.md 格式無效,保留 compare-genui 正常。除了看到錯誤,還要確認第一個 skill 仍可被發現,壞掉的 skill 沒有悄悄混進能力清單。

Case 3:讓 MCP handshake 失敗

使用錯誤的驗證資料或測試端點,刻意讓 preview server 在連線或 handshake 階段失敗。其他元件應繼續載入;進入 review 任務時,介面與 log 都要清楚標示「預覽能力降級」,不能等到最後一步才丟出模糊的 task failed。

Case 4:讓 IDE hook 失敗

在支援該 namespace 的 client 裡觸發 hook 錯誤,再到不讀取該 extension 的 client 重跑一次。兩邊的結果未必一致,這正是測試目的。Portable core 沒有替 client-specific 行為定義統一 fallback,團隊不能自行腦補。

留一份團隊自己的 evidence contract

每次 fault injection 建議至少保存以下欄位:

fault: mcp-preview-handshake-failed
expected_scope: component
observed_loaded_components:
  - skill:compare-genui
  - skill:check-accessibility
degraded_capabilities:
  - visual-preview
reported_error: "authentication failed before handshake completed"
recovery_owner: devex-runtime

這不是 Agent Plugins 官方 schema,也不該塞回 plugin.json。它是團隊的測試紀錄,用來核對原本只應影響單一元件的故障,實際上有沒有拖垮整包,以及系統降級後還有哪些能力可信。

同一份紀錄也能避免 retry 掩蓋問題。若 client 重試三次後成功,最終狀態可以是 healthy,但前兩次失敗仍該保留。否則 intermittent failure 只會在使用者抱怨時才存在。

能被載入,離可靠還很遠

Plugin 的成熟度不該用「支援幾個 client」衡量。更有用的標準是:任一元件故障時,團隊能指出失敗停在哪一層、哪些能力仍然有效、哪一筆證據證明了這件事。

Agent Plugins 1.0 已經替 package 與標準元件畫出一部分邊界。Runtime 隔離、client extension、權限與任務降級仍是團隊自己的工作。把這些缺口寫進 fault matrix,並真的破壞元件跑一次,才算知道這包 plugin 壞起來會長什麼樣子。

參考資料


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言