01 假設
紙上的計畫很乾淨。Brain(我的私人知識系統)說 MCP。所以只要我用一個小小的 decorator 把每一次 MCP tool call 包起來、把 tool_name、args_hash、latency_ms、status 寫進 SQLite,我就能看到整個系統的脈搏。從這裡延伸:用 z-score 偵測器抓每小時的異常、用 Gemini 判斷過濾誤報、用 Telegram 告警發出真正的尖峰。
那個沒寫下來的隱含假設是——MCP 是大門。只要有流量,它就會以 MCP tool call 的形式存在。建模層暖機完之後,我預期會看到每天 30 到 60 筆事件——夠用,至少當下我這樣以為。
02 建置
五個小模組,每個只做一件事。我把它們部署到 EC2、用一條 15 分鐘 cron 串起來。Pipeline 長這樣:
端對端延遲大約 33ms / 筆。健康狀態很容易讀:cron 上次執行時間、列數、judge 呼叫成功率。全綠。
03 部署
異常偵測在冷管線上統計上沒意義——樣本太少 z-score 會狂飆。所以我把就緒程度切成三個明確的階段,每一階段行為不同:
第 14 天到了。Pipeline 進入 READY。Cron 每 15 分鐘準時跑。Health check 全綠。所以我做了一件第一天就該做、卻沒人——包括過去的我——想到要做的事:問那個顯而易見的問題。
我們實際收到的資料,是不是當初說好要收的那份資料?
04 稽核
我數了監控系統觀察那段時間裡,Brain vault 內檔案異動的次數,再對照監控資料庫實際抓到了什麼。
監控看到的 vs. 實際發生的。
0.22%
管線在跑。管線是健康的。管線幾乎什麼都沒看到。
Brain 99.78% 的真實流量根本不從 MCP 進來。它從 Telegram bot 進來,或從內部 REST handler直接呼叫核心函式進來——繞過我採集所在的 decorator 層。MCP 大門只是三道門裡的一道,而且看起來是最少人走的那一道。
05 歸因
落差一旦看見,下一個問題就是漏點到底在哪裡。我目前有三個還活著的假設;根本原因還沒完全收斂。
- H1 Decorator 在執行中的程序沒生效。 採集包的是 MCP 層的進入點。如果 runtime 先載入了未包裝的模組——Python import 順序很脆弱——decorator 就會悄悄地沒套上。沒錯誤、沒日誌。
- H2 GitHub Actions 部署沒重啟長駐服務。 CI 把新程式碼推上去,但 EC2 上的 systemd unit 沒被重啟。新的 decorator 在硬碟上,舊的程序還在記憶體裡。這個問題會一直咬到下一次重開機。
- H3 MCP 流量本來就低。 Brain 的互動大多走 TG bot 跟 REST。MCP 是留給 Claude Code session 用的——比我以為的還少見。如果是這樣,那「監控沒問題,它只是看著最安靜的那道門」。
06 決策
我原本的下一步是用抓到的資料跑一場 BQML TimesFM benchmark——把 zero-shot 基礎模型跟我的 z-score 基準比一比。每天 ~4 筆事件,這場比較統計上沒意義。所以我在同一個小時內做了三個決定:
07 核心反思
我蓋的東西全都正常。Decorator 33ms 跑完。Detector 算得出來。Judge 會回。Alerter 會送。Pipeline 沒有一個環節壞掉。
但它不重要,因為底下的假設錯了,而我所有的健康檢查永遠不會告訴我。健康狀態能告訴我「機器有開」;要知道「機器有對著正確的東西」,得另外算一個數字——涵蓋率。
自動化系統除了健康檢查,還要跑一次 14 天涵蓋率稽核。『有在跑』 ≠ 『有在做事』。
對一個正在運作的系統來說,最難的動作是回頭去問——「已經有的東西,是否真的指向現實」?我現在把這件事當作每套自動化系統的硬性 14 天交付物,跟建置本身並列:一個數字、一個驗證日期、以及如果數字不吻合就把專案砍掉的意願。
前面兩個其實不難。最後那個——砍掉的意願——我這次也是練了一輪才有的。