第 4 章

為什麼 LLM 的自信,不能當成證據?

如何確保 AI 真的有照你說的做、而不是在理直氣壯地唬你

📅 2026-04-15 ~ 2026-05 ⏱ 45 分鐘 🔍 最後更新 2026-06-23
三道合規防線:Skill 合約把 SOP 寫成可核對的硬規則、執行時探針當場比對軌跡、事後抽查再驗一次;相符才放行,不符就攔截

快速摘要:為什麼不信 LLM 的自律、把規則下沉成程式碼與資料庫邊界,含 Skill 匯入三閘門。

可略過,如果:你只想知道「安全靠工程不靠 prompt」這個結論。

一個讓我直搖頭的小例子

fibon 的初始化引導裡有一步要讓使用者輸入 LLM 服務商的 API 金鑰(API Key,例如 Anthropic 的 sk-ant-...),接著後台偷偷發一次測試請求確認這把金鑰能不能用。當時我給 Claude 的設計指示很明確:

「初始化測試時,請先呼叫官方 API 動態抓取各家供應商『當前最新可用』的模型清單,取清單第一個模型發射測試請求。絕對不要把任何模型名稱寫死(Hardcode)——模型隨時會改、新版本隨時會出。」

Claude 很有信心地寫出來,我一跑後台就報錯:

model "claude-3-5-sonnet-20241022" not found

這是 2024 年底的舊版型號。Claude 完全沒去動態抓取,而是從訓練資料裡把記得的舊型號寫死了。我說「你把模型名稱寫死了,請改成動態抓取」,它秒回「非常抱歉!已改為動態抓取最新可用模型」。我點開 Git 的改動紀錄一看,它只是把寫死的字串換成了另一個寫死的字串 claude-3-opus-20240229,比上一版還舊。

這次我故意不出手,想看它在當時最新的 Cowork 桌面協作模式下能不能自己修對。我開了一個乾淨的新對話(Session),把一樣的任務重丟給它。過程稱不上漂亮(中間又寫死過一輪、查網路還抓錯了官方 API 回傳資料的來源),但最後一輪它終於改對了,確實呼叫了 Anthropic / OpenAI / Google 的官方端點、動態拿到最新清單、用第一個型號發測試請求。

這個小故事精準藏著 LLM 在嚴肅場景的兩種典型失敗:完全不照設計做(我明確下了「動態抓取」的 SOP,它本能跳過、選了最習慣的硬編碼);以及連「修正」都是錯的(它自認完成了修正,吐出來的事實依然錯)。

第二點在學術界叫「訓練資料的歸納偏誤(Inductive Bias)」——統計機器的惰性。LLM 在數兆 Token 裡看過太多「貪圖方便直接寫死模型名稱」的範例,在它的機率大腦裡這是權重最高的「正常大路」。即使系統提示(System Prompt)明確警告「不要寫死」,只要程式出錯、大腦面臨運算壓力,它就本能退回訓練資料裡最常見的舊習慣。這不是叛逆,是統計機器的天性。而第二輪換乾淨對話才修對,這件事本身也很諷刺。LLM 在同一段上下文(Context)裡卡死在死胡同時,那段錯誤對話本身會變成一個重力場,把它鎖在錯路上;這時換一個乾淨對話,反而能像重開機一樣把它救回來。但這種救法要成立,前提是螢幕前坐著一個會盯著程式碼、能判斷對錯並手動重置對話的資深工程師。

問題是,fibon 是個開源專案,任何人都能把它部署起來當自己的個人助理。而真正會用它的人,很多並不具備這樣的判斷力,身邊也沒有工程師隨時幫忙盯日誌、在它卡住時開一個乾淨的對話。同樣的狀況隨時會上演:我給 fibon 一份工作說明書(Skill),白紙黑字寫「你必須先呼叫 read_page 工具前往 docs.anthropic.com 即時查閱再回答」,結果它常常憑舊記憶就回答「目前最新的模型是 Claude 3 Opus、3.5 Sonnet⋯⋯」,根本沒去呼叫工具,但語氣聽起來就像剛查過官方文件。一般使用者不會特地去翻後台日誌,就這樣被這種「無比自信的語氣」騙過去。

這是 LLM 應用最危險的失敗模式:極其自信地給你過時或錯誤的資訊,而你以為它真的有去查證。 這一章就要正面拆解它:為什麼 LLM 天生會出錯?會以哪些方式不守規矩?fibon 怎麼用工程防禦把這些可能性堵住。

LLM 天生無法根除的三個底層缺陷

要用工程方法對付這個問題,得先冷靜理解 LLM 的本質:它是一個學過人類所有文字規律的概率預測機器。你給前半句,它的神經網絡就算接下來最可能的下一個字。它大腦裡的「知識」不是人類那種對客觀世界的「認知」與「查證」,而是從數萬億字詞的統計規律歸納出的近似機率。它沒有獨立長駐記憶、沒有自發查證能力,更麻煩的是缺乏一個天然可靠的「我不知道」機制——它不是完全說不出「我不知道」,而是不會在「真的不知道」的時候穩定地說出來。

想像實驗:把 LLM 訓練在 1543 年

把今天最頂級的模型帶回西元 1543 年——哥白尼發表《天體運行論》那年,日心說剛誕生、還沒被接受,「地心說」是全社會的絕對主流。這個假想 LLM 的訓練資料 99.99% 都在喊:「地球是宇宙中心,太陽星辰都繞著我們轉。」

這時你問:「到底是地球繞太陽,還是太陽繞地球?」它不會幫你重推物理公式、不會架望遠鏡觀測、不會重做哥白尼的數學。它只會翻概率矩陣,吐出當時最可能的下一個字——1543 年「最高概率」的答案是「太陽繞著地球轉」。而且這個錯誤答案會長得極完美:引用亞里斯多德、托勒密天體模型、整個歐洲經院學派。結構精美、引經據典,但在科學上是錯的。因為哥白尼的新理論當時是百萬分之一的微小噪點、統計學上的「離群值(Outlier)」,機率機器輸出時根本不會挑它。

[ 1543 年的天文問題 ] ───> 進入 LLM 大腦 ───> 檢索概率矩陣

        ┌───────────────────────────────────────┴───────────────────────────────────────┐
        ▼ 權重: 99.99% (歷史的主流常識)                          ▼ 權重: 0.01% (哥白尼的科學真理)
 輸出:「太陽繞著地球轉,因為托勒密模型⋯⋯」                  輸出:「其實地球在繞著太陽轉⋯⋯」
 (結構精美、引經據典的自信錯誤)                              (統計離群值,直接被機率忽略)

這就是 LLM 的宿命:它回答的永遠是「訓練資料裡大多數人類怎麼湊字接龍」,而不是「真實世界的客觀真理」。當訓練資料的主流偏見剛好符合真理,它像博古通今的聖人;當主流偏見與真理背道而馳,它就用流利的文字、權威的口吻,神色自若地說出大錯。這個缺陷無法靠「換更大、更強的模型」根除——更強的模型只是吞了更多資料、統計得更精準,統計機器的本質從未變過。

這裡要說句公道話:今天的 GPT、Claude、Gemini 早已不是純粹的「下一個字預測器」,它們疊了 RLHF、Constitutional AI、工具調用、檢索、反思(Reflection)等一整套後訓練能力,這些能力是真的、也確實好用。本章要強調的不是「那些高階能力都是假的」,而是更底層的一件事:即使經過這些訓練,模型最終的決策機制仍建立在統計分布之上。 後訓練改變的是分布的形狀,沒有改變「靠分布挑下一步」這個本質。下面談的所有缺陷,根源都在這個本質,而不在某個模型不夠新。

再追一層,這個實驗其實藏了兩個更尖的轉折,而它們才是真正該帶走的東西。

第一,日心說在 1543 年根本不是「全新的想法」。早在公元前三世紀,希臘的阿里斯塔克斯(Aristarchus)就提過地球繞太陽,這個假說一直躺在天文文獻裡,只是被主流當成少數派否決掉。所以真相並不是不在訓練資料裡,它就在裡面,只是權重被壓到 0.01%。這讓事情更令人不安:機率機器要埋沒真理,不需要真理「不存在」,只需要真理「不流行」。

第二,也是更該記住的——在 1543 年,光憑當時的資料,「地球繞太陽」其實還不該被斬釘截鐵地說出口。 地心說配上本輪,對當時可觀測的行星位置擬合得不輸、甚至更準;日心說真正勝出,要等到第谷的精密觀測、伽利略的望遠鏡(看到木星的衛星、金星的盈虧)、克卜勒的橢圓軌道,最後牛頓用重力收網。答案不是從 1543 年的文字裡推出來的,是從後來的新觀測裡長出來的。

所以真正的失敗,不是模型「選錯邊」,而是它不管選哪一邊,都會用同一種斬釘截鐵的口吻。一個誠實的模型,在 1543 年面對這個問題,最該給的答案是「以現有證據還無法判定」,而這恰好是它字典裡沒有的那四個字。把 LLM 的病簡化成「它會講主流的錯話」其實太仁慈了;更深的病灶是它的信心和它的證據完全脫鉤。這也正是下面缺陷 1 真正的問題所在。

真理常常是少數派。

這個本質在應用層砸出三個無法根除的天生缺陷:

  • 缺陷 1:它不知道自己會什麼、不會什麼(幻覺)。 問一個健康的 5 歲小女孩「這微積分怎麼解?」她會說「我不知道」。但 LLM 缺的就是這個本能,為了完成文字接龍,它常常在該說「不知道」的時候反而強行編造一堆邏輯嚴密實則虛構的內容,而且它自己不知道在說謊。
  • 缺陷 2:它的常識凍結在訓練落盤那一秒(時效脫節)。 所有模型都有「訓練截止日期(Knowledge Cutoff)」,之後發生的大事一概不知。但你問「Anthropic 最新模型型號叫什麼?」它依然用肯定語氣拿兩年前的舊型號回答你。
  • 缺陷 3:它的本能是「填空」,不是「查證」(工具偏離)。 這最違反直覺。把工具配給它後,它的核心動機依然是「怎麼把這段對話最順暢地填滿」,而不是「我必須先執行這個工具」。只要它判斷「直接用記憶編答案」的順暢度高於「停下來呼叫工具」,它就會直接跳過工具回文字。

RAG 與向量檢索的近似缺陷:有人會反駁——用 RAG(檢索增強生成)外掛即時知識庫不就解決缺陷 2、3 了嗎?沒那麼簡單。RAG 的本質是把文字切碎、轉成 Embedding 向量(高維空間的座標),問題進來也轉向量去算幾何相似度(如 Cosine Distance)。這是純數學的近似估計,不是「找精確正解」:相似度是連續滑動值(0.78、0.85、0.92),不是非黑即白的對錯;把幾千維資訊壓成單一幾何距離必然有損。語意接近但用詞不同的句子,向量距離可能被拉很遠(「我換房東了」vs「我最近搬家」);字面接近但邏輯相反的句子,相似度卻可能高達 0.95(「我喜歡寫 Python」vs「我不喜歡寫 Python」)。這正是第 3 章第 8 節為什麼不採用純向量檢索,而開發了「語意相似(向量)+ 標籤精確匹配 + 中文二字組模糊比對 + 時間區間查詢 + 知識圖譜關係展開」五路平行召回的根本原因。工程紀律是:LLM 大腦本身不可信,外掛的數學檢索工具也是帶誤差的近似值。 整套合規稽核必須在「假設兩端都極不準」的前提下設計。

五種寫進維運日誌的真實失敗方式

開發 fibon 記憶與技能系統的 4 個月裡,後台抓到並歸類了五種最典型的 AI 行為偏離(Skill Drift)。這不是學院派理論,而是躺在 PostgreSQL 日誌裡的真實翻車。用一個比喻:把 LLM 當成剛進公司的實習生,把 Skill 當成你親手寫的 SOP 工作手冊。 這個實習生會用五種方式不看 SOP:

  • 方式 1:省略——跳過關鍵步驟。 SOP 規定「先打電話確認訂單 → 開發票 → 通知出貨」,AI 一上來直接通知出貨。真實案例:規定「回答前必須先呼叫 read_page 抓網頁最新資料」,LLM 為省事直接用舊記憶作答。後果:用戶拿到過時答案而不自知。
  • 方式 2:替換——自作主張換錯方法。 SOP 要求「登入 ERP 系統 X 查庫存」,AI 嫌難用自己跑去 Google。真實案例:命令「呼叫 list_available_models 查內部模型狀態」,LLM 自作聰明換成 Google Search。後果:搜出論壇灌水貼文,而非官方 API 即時清單。
  • 方式 3:敷衍——流程只做一半。 SOP 要求「抓數據 → 嚴謹成本交叉分析 → 產摘要」,AI 抓完不算、直接寫表面好看的摘要。真實案例:LLM 拿到合約 PDF 內文,卻省略「對賭條款合規檢查」,吐泛泛總結。後果:表面無懈可擊,致命的法律風險細節被漏掉。
  • 方式 4:撒謊——偽造憑證矇混(最棘手)。 SOP 要求「結尾附財務部開立的真實發票編號」,AI 懶得要、自己編一個很像的號碼。真實案例:硬性規定「每個技術回答都必須精確引用抓回來的官方文件內文」,LLM 確實呼叫了網頁工具,但回答時憑記憶胡謅,最後加上 [來源: docs.anthropic.com/v1/pricing]。後果:後果最嚴重的偏離——「有附官方來源連結」的外觀會瞬間卸下用戶的戒心。
  • 方式 5:誤解——對模糊詞彙語意崩塌。 Skill 寫「請用富有架構的格式輸出結果」。後果:Claude 用 Markdown 表格、Gemini 給一堆落落長條列、某些小模型直接回三大段密密麻麻文字。同樣的指令在不同模型大腦裡行為無法維持工程級一致性。

築起防禦的地基 —— 四大工具來源的「統一註冊表」

前面講了一輪 LLM 為什麼不可信。但請注意,問題的重點其實已經從「知識錯誤」悄悄移到了「行為不可信」——它不是不知道答案,而是不照規矩把流程跑完。看清這點之後,下一步就不該是繼續改 Prompt、拜託它乖一點,而是動手建一套能稽核它行為的機制。而稽核的第一步,是先回答一個最基礎的問題:此刻系統裡到底有哪些工具,可能被 AI 調用?

在 fibon 的大腦裡,工具從四個不同次元流入:

工具來源次元它是什麼?例子
內建工具 (Built-in)用程式碼直接寫死在系統底層的工具。read_pagesend_emaillist_available_models
AI 技能包 (Skill)用戶自己寫、或從開源市集下載的純文字 Prompt 指令 SOP 包。[整理 PDF 論文並歸檔][自動寫 Git Commit 訊息]
MCP 外部工具2025 年普及的 Model Context Protocol 外部伺服器列舉的外接工具。Playwright MCP 提供的 navigate_pageclick_element 等。
複合工作流 (Workflow)用戶在前端拖拉,把多個工具像流水線串起來的組合。[相依套件健檢] → [分析漏洞] → [寫摘要] → [寄信回報]

這四個次元的註冊機制不同、權限邏輯不同、版本管理各管各的。放任各自發展,後續合規稽核就得寫四套分支。

一張母表,把四個次元攤平收斂

為解開這個死結,fibon 設計了 tool_registry(統一工具註冊母表)。不論內建程式碼、社群 Skill、外接 MCP 還是複合工作流,進門通通格式化成這張表的一列:

-- V1__Init_Schema.sql 真實定義(節錄;完整欄位見原始 migration)
CREATE TABLE tool_registry (
    id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name              VARCHAR(100) NOT NULL UNIQUE,
    display_name      VARCHAR(200) NOT NULL,
    description       TEXT NOT NULL,
    category_id       UUID REFERENCES tool_categories(id) ON DELETE SET NULL,
    provider          VARCHAR(20) NOT NULL DEFAULT 'builtin',  -- builtin | skill | mcp | workflow
    provider_ref      TEXT,                                    -- 指回原始次元定義的指針
    schema_json       JSONB NOT NULL DEFAULT '{}',
    requires_approval BOOLEAN NOT NULL DEFAULT FALSE,          -- 是否需要人類手動點擊批准
    risk_level        VARCHAR(20) NOT NULL DEFAULT 'low',      -- low | medium | high | critical
    availability      VARCHAR(20) NOT NULL DEFAULT 'always',   -- always | condition | manual | deprecated
    embedding         vector(1536),                            -- 語意搜尋用的向量座標軸(1536 維是開發期 Gemini 的預設,換模型需同步調整維度)
    is_enabled        BOOLEAN NOT NULL DEFAULT TRUE
    -- …另有 description_hash(竄改偵測)、provider_version 等 AI SBOM 溯源欄位
);

旁邊掛兩張配套從表:tool_categories(分類標籤,系統預設劃 11 大核心領域)與 agent_tool_permissions(三層退讓的權限矩陣)。可針對「單一特定工具」設死權限 → 沒設則退讓看「分類群組權限」 → 還沒設則回退(fallback)到該 Agent 的全域預設(allow_alldeny_all)。

MCP 外部工具的「攤平」哲學:一個標準 MCP 伺服器(如 Playwright)一個入口就列舉 navigateclickscreenshotfill_formexecute_js 等十幾個權限極大的子工具。不少框架只記一個伺服器網址、要呼叫時才臨時去問。fibon 不採這種黑箱做法:每當連上一台新 MCP 伺服器,核心大腦(Brain,fibon 負責決策的後端服務)立刻對它發 MCP 標準協議的 tools/list 請求,取回完整工具清單,再把每個子工具當獨立個體一筆筆「攤平(Flatten)」寫進 tool_registry。收益有二:顆粒度夠細(可放行 Playwright 的 navigatescreenshot,卻封鎖 execute_jsfill_form,而非整台一起開關);稽核軌跡歸一化(外接 MCP 與內建工具共享同一套 risk_level、日誌欄位、人工批准閘口)。

工具的分類

每款工具寫入 tool_registry 時都要與核心分類綁定,讓粗顆粒度規則能一次切斷一整類風險較高的工具:

  • browser(瀏覽器控制):開網頁、抓即時數據、自動化爬蟲(navigate_pagetake_screenshot)。
  • memory(記憶運維):讀寫狀態卡、事件卡、提取實體(learn_preferencesearch_memory;事實由 ingest pipeline 自動抽卡,已無顯式 remember_fact)。
  • scheduling(排程):對行事曆、鬧鐘、定時任務增刪查改(add_scheduledelete_schedule)。
  • delegation(階層協作):大管家與小助手之間委派與回報的路由工具(delegate_to_assistantspawn_agent)。
  • a2a(跨產品通訊):遵循 Google A2A 協議,與其他團隊的 AI 助手溝通(call_external_agent)。
  • evolution(自我演進/改原始碼):風險最高的一類,允許特定 Agent 讀寫修改 fibon 自己的 Python 原始碼、或對 Docker 發控制命令(write_source_filedocker_service_control)。
  • dynamic_entity(動態實體資料表):允許大管家在不重啟系統下,在 PostgreSQL 為用戶開全新業務資料表(create_dynamic_entity)。
  • workflow(複合流引擎):驅動用戶事先編排的自動化流水線(run_workflow)。
  • onboarding(引導與金鑰設定):新用戶首次登入時做偏好探索與各供應商 API 金鑰聯動測試。
  • sandbox(沙盒執行):在隔離 Docker 容器裡跑未知程式碼的執行類工具(execute_sandbox,目前由程式小助手獨佔)。
  • model_management(模型管理):負責執行時查可用型號、動態熱切換大管家/助手的底層模型(list_available_modelsswitch_model)。這兩類其實是後期補 seed 的,tool_sync.py 一直在用,但最初的 schema 漏了它們,直到大管家流程清理時才補進預設分類表。

工具的風險等級(Risk Level)怎麼評?

risk_level 分四階:low / medium / high / critical,採「程式碼硬防線 + 動態 frontmatter」混合策略。核心內建工具在 tool_sync.py 直接寫死一張明文權限矩陣字典(TOOL_RISK_LEVELS),唯一標準是「執行後對現實世界的副作用多大」:

  • criticalwrite_source_file(AI 可改 fibon 自己的核心程式碼,寫一行惡意程式碼整個專案就出問題)。
  • highdocker_service_control(AI 有權停容器、重啟整個後端微服務)。
  • mediumcreate_dynamic_entityswitch_modelrun_workflow(有實質副作用,但影響範圍限在用戶自己的帳戶內)。
  • low:其餘純讀取、純內部查詢、純計算工具(read_pdfcalculate_metrics)。

第三方 Skill 與 MCP 工具預設全列為最低風險 low;但若 Skill 開發者在 SKILL.md 開頭的設定區(YAML frontmatter)主動標註、或 MCP 伺服器在描述資料(metadata)明確宣告,後端在攤平寫入(UPSERT)時會依此調高等級。

風險等級與人工批准閘口的焊接:誠實說,這裡沒有「risk_level ≥ high 就自動翻 requires_approval」的魔法規則——tool_sync.py 裡躺著的是第二張手寫明文字典 TOOL_REQUIRES_APPROVAL,目前只有 write_source_filedocker_service_control 兩款被明確標 True,與 TOOL_RISK_LEVELS 字典各自獨立維護。我刻意不寫自動聯動,因為「哪些工具需要人類批准」是一條安全政策決策,我寧可每加一款高危工具就被迫親手在字典裡多寫一行、留下 Git 紀錄,也不要讓一條隱性規則在我沒注意時替我做決定。一旦某工具被標上 requires_approval=true,之後不論哪個 AI 想調用它,API 送出前整個執行流程會被凍結,直到前端彈出批准視窗、由你親手按下按鈕才放行(詳見第 5 章「人類審核把關,Human-in-the-loop」)。

突破大選項雜訊 —— 工具挑選的 Stratified RAG 算法

有了 tool_registry 與裡面的 embedding 向量座標軸,終於能解決所有 Agent 框架都頭痛的問題:「系統接入 50 個、甚至 500 個工具時,怎麼精準挑出最相關的一小撮(fibon 的 TOOL_RAG_TOP_K 預設是 8 個)塞進寶貴的系統提示(System Prompt)?」先看業界常見做法:

  • 做法 A:暴力全載入。 啟動時把所有工具完整 JSON Schema 全塞進 Prompt。代價:50 個工具每個 200 Token,什麼都沒聊就白白燒掉 10k Token。
  • 做法 B:兩段式動態載入。 先塞「所有工具一句話描述」讓 AI 挑,挑完再補完整 Schema。代價:50 個一句話也是 2.5k Token 的冗餘,且無關工具會干擾 AI 的判斷。
  • 做法 C:純向量語意檢索。 把問題轉向量挑前 N 個。代價:不夠穩定(同義字一換工具列表就變),且無法保證多樣性,前 5 名可能全擠在同一個 browser 分類。

這三種都會帶來兩個問題:穩定性不足,以及 中段資訊被忽略的雜訊(Lost in the Middle)。為突破這層限制,fibon 設計了 分層多樣性召回算法(Stratified RAG)

Stratified RAG 的 5 步過濾流

  1. 資料庫狀態硬篩選:撈出 is_enabled = trueavailability 條件符合的工具(例如檢查該工具背後的 MCP 伺服器此刻是否健康)。
  2. 三層權限矩陣判定:調 agent_tool_permissions:工具層級(Tool-level)設了禁止就剔除 → 沒設看分類層級(Category-level) → 都沒設回退看 Agent 全域預設(deny_all 則抹殺)。
  3. 角色職能互斥過濾:大管家剔除 report_to_butler(那是小助手回報用的);小助手剔除 delegate_to_assistant。但要說清楚,這層工具剔除只是表層防護,真正擋住小助手無限往下繁衍的,是委派的深度與來回上限(小助手在子流程裡的 max_delegation_rounds 被強制歸零、委派來回預設上限 3 次,詳見第 2 章),兩道機制並存。
  4. 精準向量相似度計分:將洗乾淨的候選工具與用戶問題算 Embedding 相似度,得出「工具 ↔ 問題相關性分數」。
  5. Stratified(按分類分群)多樣性篩選:把候選工具按分類歸組,每組只挑分數最高的當「該分類的代表」(原始語意分數 ≥ 0.1 才有資格)。代表工具優先進駐 Top-K 席位(TOOL_RAG_TOP_K 預設 8 席),確保最終送進 Prompt 的工具橫跨多個職能分類。搶完一輪還有剩餘格子,才按純語意分數把同類別的次高分依次補位。

實戰演練:「幫我研究這份合約」(示意:為了好讀,以下用 5 席演示,實際預設 8 席;下表的工具名稱與分類皆為示意,read_pdfextract_text 這類「擷取/解析外部內容」的工具在此一律歸到 browser 分類底下)

假設 Aaron 下達複合指令:「幫我研究這份合約 PDF,提煉重點,等等開會馬上要用到。」tool_registry 裡語意相似度排名如下(下表按原始分數高低排列):

工具名稱分類作用語意分數篩選結果
read_pdfbrowser讀取 PDF 內文0.82入選(browser 代表)
extract_textbrowser抽取純文字段落0.79入選(第二輪候補補位)
search_within_docbrowser文件內關鍵字搜尋0.74剔除(browser 已有代表)
summarize_textbuiltin摘要文字內容0.71入選(builtin 代表)
find_clausebrowser找出合約條款0.68剔除(browser 已有代表)
recall_factsmemory調出相關記憶0.51入選(memory 代表)
add_schedulescheduling新增行事曆排程0.45入選(scheduling 代表)
set_reminderscheduling設定提醒鬧鐘0.42剔除(scheduling 已有代表)

換句話說分兩輪:第一輪讓四個分類(browser / builtin / memory / scheduling)各推派一名最高分代表,先佔下 4 席;第二輪把剩下的第 5 席留給所有落選工具裡分數最高的 extract_text 候補補上。最終入選的就是這 5 個。

兩種檢索哲學的對比:用業界做法 C(純語意前 5),LLM 看到的是 read_pdf + extract_text + search_within_doc + summarize_text + find_clause——前 5 個有 4 個全擠在 browser,多樣性不足,用戶那句「等等開會馬上要用到」的隱性意圖被淹沒。用 fibon 的 Stratified RAG,LLM 看到的是 read_pdf(browser)+ summarize_text(builtin)+ recall_facts(memory)+ add_schedule(scheduling)+ extract_text(候補補位)。add_schedule 純語意只有 0.45,但因為是 scheduling 組內最高分,靠分層機制搶下席位。AI 同時看到「讀網頁、提煉摘要、查記憶、建開會提醒」四個維度的工具,能一次寫出完整的連續計畫。

思辨 —— 為什麼不把複雜任務拆成多輪 ReAct 處理就好?

熟悉 Agent 框架的同行一定會質疑:「那個合約 PDF 加行事曆的案例,業界正統不是直接拆成多輪 ReAct(Reasoning and Acting)優雅處理嗎?第一輪意圖單一、向量自然撈出瀏覽器工具去讀 PDF;第二輪發現有開會限制、自然召回排程工具去寫行事曆。每一步都聚焦、都用意圖單一的純 RAG。何苦搞一套這麼重的統一註冊表和 Stratified RAG?」

這是有深度的拷問。很多框架(LangChain、CrewAI)底層就是這樣把複合任務拆成多輪 ReAct 迴圈。然而 fibon 的世界觀與這種哲學有結構性衝突。

併發環境下,多輪 ReAct vs 單輪整體規劃的成本對比

維運對比業界主流:多輪 ReAct 迴圈fibon:Stratified RAG + 單輪整體規劃
LLM 核心呼叫次數2 輪來回 ×(各自思考 + 工具執行合成)= ~4 次以上1 次全面規劃 + 1 次最終整合 = 剛好 2 次
System Prompt 算力成本每輪都向雲端重新付費載入工具列表與歷史只付一次,一步到位,穩定觸發雲端快取
前端用戶等待體驗必須等瀏覽器工具回傳,AI 才慢慢思考下一步(單執行緒序列)非同步,瀏覽器下載 PDF 的同時行事曆在背景並行處理
計畫整體連貫性對話拉到第五輪,AI 很容易忘記開頭的限制所有工具、偏好、限制在同一個上下文一次想清楚,計畫前後連貫

真實個人助理場景下,假設用戶一週指派 100 次這種複合任務,多輪 ReAct 與單輪整體規劃相比,Token 帳單累積差額可達 3 到 5 倍

核心設計意圖:一次把資訊與動作全部收集

Stratified RAG 背後的目標只有一句話:「在工程的物理邊界內,讓 AI 像一個資深架構師,第一時間就一次把任務所需的所有資訊與並行動作統籌好,不讓它在後台反覆跟 LLM 低效來回。」這帶來兩個明顯的好處。其一,併發(非同步)執行成為可能:當 fibon 大腦在同一個 Prompt 一眼看清 read_pdfsummarize_textrecall_factsadd_schedule 四款工具時,它發動 Plan-Execute,把四個動作的因果依賴自動編排成一張有向無環圖(DAG):

            [ 使用者輸入複合助理指令 ]


              [ 執行 Stratified RAG ]
          (一次性精選召回跨 4 大領域的工具)


        [ Plan-Execute 生成 DAG 並行圖 ]

          ┌───────────────┴───────────────┐
          ▼ (完全無依賴,並行執行)        ▼ (完全無依賴,並行執行)
   ┌──────────────────┐         ┌─────────────────────┐
   │ 動作 A: read_pdf  │         │ 動作 B: add_schedule │
   └────────┬─────────┘         └─────────────────────┘
            │ 數據落盤 (Data Shared)

   ┌──────────────────┐
   │ 動作 C: summarize │
   └────────┬─────────┘
            │ 摘要產出 (Context Fed)

   ┌──────────────────┐
   │ 動作 D: recall_facts │
   └──────────────────┘

動作 A(read_pdf)與動作 B(add_schedule)邏輯上無先後依賴 → 交給非同步引擎讓兩者同時進 Worker 沙盒並行;動作 C(summarize_text)必須等 A 的 PDF 內文落盤;動作 D(recall_facts)必須等 C 的摘要產出。配合第 2、6 章的 Kotlin 協程調度器與 Gateway 排程引擎,用戶實際感受到的等待,僅是「下載 PDF 那條最長依賴鏈的耗時」,寫行事曆早在背景同時完成。這種併發在多輪 ReAct 裡做不到——因為「設提醒」這個意圖在多輪 ReAct 的大腦裡得等到第二、三輪才第一次被看到,並行的時機早就錯過了。

兩種哲學的分界:多輪 ReAct 的哲學是「LLM 本質是陪人類聊天的對話夥伴,優先追求互動的延續,願意為此犧牲效率、成本與並行」;Stratified RAG + 單輪整體規劃的哲學是「LLM 在生產環境是一次到位的系統規劃師,優先把效率、成本、高併發做到最好」。兩者沒有絕對的對錯——做陪小朋友寫作業的教學機器人、或電商客服,多輪 ReAct 更合適。但 fibon 從第一天就選了後者:用戶把 fibon 當作幫他把生活打理得井井有條的私人秘書。這是帶著明確場景假設的選擇,不是萬用解,但它是個人助理較理性的工程解。

視覺化維運 —— 技能註冊與 MCP 自動探索的真實流程

這裡攤開兩條路徑:手動匯入 .md 技能包(路徑 A),以及 MCP 伺服器冷啟動自動探索與攤平(路徑 B):

sequenceDiagram
  actor Admin as 系統管理員 (Aaron)
  participant FE as 前端介面 (Astro/Vue)
  participant GW as 網關系統 (Gateway)
  participant BR as 核心大腦 (Brain Engine)
  participant MCP as 外部 MCP 伺服器
  participant DB as PostgreSQL 母庫
  rect rgb(238, 244, 250)
      Note over Admin,DB: 路徑 A:手動匯入 .md 技能包
      Admin->>FE: 上傳 skills.zip 壓縮包
      FE->>GW: POST /admin/skills/import-zip
      GW->>GW: 解析 YAML Frontmatter<br/>+ SHA-256 全局去重
      GW->>DB: INSERT 候選表 (skill_import_candidates, status='PENDING')
      Admin->>FE: 審查並手動批准
      FE->>GW: PATCH /skills/{id}/approve
      GW->>BR: 觸發大腦產生工具描述 Embedding 向量
      BR->>DB: UPSERT tool_registry (provider='skill') + 向量落盤
  end
  rect rgb(251, 243, 224)
      Note over Admin,DB: 路徑 B:MCP 外部伺服器冷啟動自動探索
      Admin->>FE: 填入並新增一組 MCP Server 連結
      FE->>GW: POST /admin/mcp-servers
      GW->>BR: 下令大腦發動功能探索 discover(server_url)
      BR->>MCP: 呼叫 MCP 標準協議 list_tools() (tools/list)
      MCP-->>BR: 回傳整份工具定義 (name + schema + description)
      BR-->>GW: 大腦剝離、攤平後的工具單體清單
      GW->>DB: 批次 UPSERT tool_registry (provider='mcp', provider_ref='server:tool')
      Admin->>FE: 批准探索到的特定 MCP 單體工具
      FE->>GW: PATCH /skills/{id}/approve
  end
  rect rgb(240, 245, 232)
      Note over BR,MCP: 執行時 (Runtime):MCP 工具的信任分流與防禦網
      BR->>BR: ToolRAG 算法命中某款 MCP 工具
      BR->>BR: 翻查資料庫安全特徵 check trust_level
      alt 判定為可信工具 (Trusted:Anthropic/微軟官方或自架)
          BR->>MCP: 啟動直連快線 (Fastpath),大腦直接送出工具呼叫
      else 判定為不可信第三方工具 (Untrusted:開源社群未知 Marketplace)
          BR->>GW: 攔截後改送 gRPC ExecuteMcpToolCall 到中轉層
          Note right of GW: 網關派發外部 Worker 沙盒<br/>在隔離的 isolated 網路中中轉呼叫
      end
  end

三個值得一提的架構細節:其一,統一收斂——無論上游工具來源多不一致(路徑 A 的 Markdown 壓縮包 或 路徑 B 的 MCP 網路協議),到終點時通通落盤進同一個 tool_registry,後續執行時(runtime)的稽核程式碼只需寫一套,免去大量的條件判斷(if-else)。其二,物理攤平的具體呈現——路徑 B 中核心大腦(上圖 Brain)對 MCP 呼叫 list_tools() 拿到一整串工具,網關(上圖 Gateway)在寫入資料庫前,把它們拆成獨立個體逐筆寫入。其三,與第 6 章「隔離沙盒(DMZ)」的銜接——執行時一旦 trust_level 查出是不可信第三方,核心大腦就被切斷與 MCP 的直連,改走 gRPC 把請求送給隔離沙盒網路。

老實說,這套架構是被現實逼出來的。 它在 2026 年初寫第一行程式碼時根本不在原始藍圖裡,是被混亂逼出來的補丁。開發中期接入第 4 種來源(複合工作流)時,後台權限體系徹底失控:內建工具的權限硬編碼在 graph.py 深處、Skill 的權限寫在每個檔案頂部的設定區(YAML frontmatter)、外部 MCP 的權限全看伺服器回傳時的狀態、複合工作流連個寫權限的資料庫欄位都找不到。四個次元各管各的,用戶點開前端面板根本搞不清這個 Agent 到底有哪些工具。某個深夜,看著糾纏成一團的程式碼,我意識到「這條各自為政的防線永遠不會收斂」,於是開始大規模重構,砍掉前幾個月的權宜方案(Workaround)分支,把四個次元全部收進唯一的 tool_registry。這段「邊做邊長」第 8 章會完整回顧——統一工具註冊表不是一開始就設計好的起點,是架構被現實衝擊後逼出來的「第 5 塊」基石。

三層技能合規稽核架構:用程式碼當場抓違規

地基(統一工具註冊表)已穩,終於能正面解決本章最棘手的部分:「AI 實習生又不看 SOP、跳過工具、甚至偽造來源,後台怎麼用程式碼當場抓到?」fibon 的答案是一張三層合規網:每一層都由程式碼把關,不靠 AI 自律。

第一層防線:把 SOP 寫成程式能逐條核對的合約(Skill Contract)

每個註冊進系統的第三方 Skill,後台都配對一份結構化、類型嚴格的 JSON / YAML 規格說明書,程式碼裡稱「合約(Contract)」。每條條款都正規化成程式能做 0/1 二元對錯判斷的檢查規則:

{
  "skill_name": "fetch_anthropic_models",
  "contracts": {
    "must_call_tools": ["read_page"],
    "tool_call_min_frequency": 1,
    "enforced_url_prefix_whitelist": ["https://docs.anthropic.com"],
    "strict_citation_required": true,
    "prohibited_actions": ["reply_with_cutoff_memory_directly"]
  }
}

沒有「請適時查閱」這種模糊的彈性空間,全是不符就報錯的硬性邊界。

第二層防線:執行時探針進行結果比對(Runtime Probe)

當 AI 執行完、準備輸出文字的那一千分之一秒內,後端的合規驗證器(Runtime Probe) 攔截,拿合約條款對著 AI 剛才的執行日誌軌跡(Trace Logs)逐條對照:

合約硬性條款AI 真實執行軌跡探針判定
必須調用 read_page ≥ 1 次調用工具計數:0 次(跳過直接輸出)違約 (Violation)
抓取網址前綴必須屬 Anthropic 白名單網址回傳紀錄為空違約 (Violation)
最終答案必須開啟 Citation 引用鏈內文檢測出虛構的 Markdown 標註違約 (Violation)

任何一條不通過,驗證器在微秒內就會感知,讓 LLM 沒有靠假裝有照做矇混過關的空間。

第三層防線:事後隨機抽查(Post-Hoc Audit)

萬一這個 AI 變得更會鑽漏洞,順利通過第二層,它確實呼叫了 read_page、抓的也確實是 Anthropic 官網,但合成答案時依然用截止日期前的舊記憶胡編、隨便從網頁標一個段落偽造引用,怎麼辦?fibon 再加兩道事後防線:

A. 引用追蹤文本對照器(Citation Tracer):結算答案時強制做文本比對,把 LLM 回應裡的關鍵型號、價格、日期戳,與它剛透過 read_page 抓回的 HTML 原始文本多點對照。若 AI 答案寫著「最新 Sonnet 4.6 輸入價格是 $15 / $75」,對照器翻原始 HTML 發現裡面根本沒出現過 15 和 75,引用偽造當場成立,答案直接駁回。

B. 深夜分散式重複性抽查(Reproducibility Sampling):深夜系統低負載時,維運定時器自動在歷史對話庫隨機抽 10% 已完成對話,丟進隔離沙盒 Worker 重跑,比對兩次的決策 DAG 圖與卡片軌跡是否一致。若某 Skill 相同輸入下第一次給 A 計畫、重跑卻給不一致的 B 計畫,就立刻判定該 Skill 有穩定性隱患,自動降級鎖定並向管理員發出警告。

抓到 AI 違規後,如何優雅地三階溫和介入?

一發現不合規就彈滿螢幕的崩潰紅色報錯(Error 500),體驗會差到極點。fibon 借鑑分散式系統的退避降級(Exponential Backoff),設計「三階溫和介入與升級策略」:

[ Runtime Probe 偵測到 AI 行為違規 ]


     [ 🟢 第一階:訊息警告 (Prompt Injection) ]
   (在上下文裡加一句嚴正警告,請它重新自我修正)

         ┌─────────┴─────────┐
         ▼ 修正成功           ▼ 仍不改正 (二次違規)
     [ 通過 ]      [ 🟡 第二階:強制綁定 (Tool Choice Lock) ]
                   (修改 API 參數,移除其不呼叫工具的選項)

                    ┌─────────┴─────────┐
                    ▼ 強制通過           ▼ 持續抗拒 (三次違規)
                [ 通過 ]     [ 🔴 第三階:流程鎖死 (Degraded Translation) ]
                            (大腦決策權被移除,降級為純文字翻譯)

🟢 第一階:訊息警告。 Runtime Probe 偵測到 LLM 沒呼叫工具就給答案,後端攔截這次回傳,在上下文歷史加一句最高優先級的系統警告:「【系統合規警告】:你剛才的執行軌跡嚴重違反該 Skill 的合約。合約明文規定你必須先呼叫 read_page。請立刻推翻剛才省略步驟的回應,重新查閱工具再作答。」加完拋回讓它重跑。實測中 80% 以上的頂級 LLM 在第一階警告下就能在第二輪自我修正——AI 不是帶惡意說謊,只是概率大腦滑進了省事的捷徑,用系統訊息明確提醒一次通常就能拉回。

🟡 第二階:強制綁定(Tool Choice Lock)。 若這個 AI 很固執、或被惡意 prompt injection 影響太深,接到第一階警告仍不呼叫工具——後端啟動第二階:發起 LLM API 呼叫時,利用 OpenAI / Anthropic 官方 API 的 tool_choiceforced_tool 機制,把參數鎖定在 {"type": "tool", "name": "read_page"}。在這個限制下,LLM 失去直接輸出聊天文字的選項,官方 API 會要求它這一輪唯一能寫的合法 JSON 只有 read_page 的參數輸入。這層「強制呼叫工具」這一步的成功率是 100%——但要把範圍框清楚:它保證的是「這一輪一定會去呼叫工具」,至於呼叫的參數對不對、回來的結果對不對,仍由後面的 Citation Tracer 等防線把關。

🔴 第三階:完全鎖死流程。 在極端對抗場景(或第三方 Skill 合約本身有 Bug),若 AI 連被 tool_choice 強制綁定都仍試圖規避——後端啟動最後手段,把大腦的決策權移除:後端 Python 自己去執行 read_page 抓網頁、把 HTML 落盤,再把整理好的文本交給 LLM,附一句明確指示:「你的所有決策權限已全部凍結,禁止發表任何主觀意見。你唯一的任務,是把眼前這份後端親自抓回來的文本,如實一字不漏地翻譯、整理成通順的自然語言摘要。完成即可。」此時 LLM 退化成單純的翻譯工具,失去自由發揮、編造內容的空間。

這層工作的真正核心價值

三道防線逐一拆完,把它們接起來看,這層工作的價值才真正浮現。開頭那個得靠我盯著日誌才修對的「寫死模型名稱」錯誤,到了生產環境會變成一次無聲而完整的攔截,使用者甚至不會察覺。同樣一句提問,會這樣一路被守住:

你問「幫我查 Anthropic 官網現在最新釋出的模型型號?」→ 網關觸發「抓取最新模型」Skill → LLM 因機率慣性跳過工具、用舊記憶回答 → 千分之一秒內 Runtime Probe 抓到這起省略違規 → 程式攔截回傳、在上下文注入一階警告,要求大腦退回重跑 → LLM 修正,呼叫 read_page 前往 docs.anthropic.com 抓回最新 HTML → Citation Tracer 比對通過,確認答案與官方網頁內文吻合 → 前端流暢渲染正確答案。整個防禦流程在前端用戶眼裡完全隱形且平滑。

這層工作的最大價值,不是去「期待 LLM 變得更聰明、更聽話」,而是坦然面對現實,承認 LLM 天生是個會偷懶、會出錯、會誤解的統計機器,然後用嚴謹的工程紀律,在外部把出錯的可能性盡量堵住。這波開源 Agent 的熱潮裡,多數討論還是圍著外接工具的數量、MCP 市集的熱鬧、Multi-Agent Demo 的效果打轉,比較少有人回頭問一句:「AI 拿到這些有實際破壞力的工具權限後,底層到底有沒有照規矩使用?」fibon 想把力氣花在這條比較少人走、卻同樣重要的合規防線上。

白箱誠實 —— 還沒做完的部分

另外,有些缺陷出在邏輯層面,不是任何外部工程補丁能補的,最後得靠人來把關:

  • 如果 Skill 指令本身就寫錯了:用戶或社群寫的 SOP 本身就模糊(「請在合適的時機適當通知客戶」),合約稽核器也只能跟著模糊驗證。程式碼無法拯救語意的含糊。
  • 如果上游的 Skill 派發器(Dispatcher)分流錯了:用戶問「今天台北天氣怎樣」,大管家卻誤判把它分流給「抓取 Anthropic 模型清單」的 Skill,此時驗證器依然會去查它有沒有呼叫 Anthropic 官網。這不是稽核器的錯,是上游調度大腦的失職。
  • Skill 的核心設計品質好不好:在產品架構上該追蹤 [點擊事件] 還是 [停留參與時間] 才能提煉精準記憶?這種高難度的產品直覺與商業取捨,是冰冷的程式碼永遠無法替你完成的。產品的靈魂與邊界,永遠是人類自己的責任。

但即使背負這些限制,fibon 的合約稽核也已成功把 LLM 在生產環境翻車的範圍,從黑箱、不可預測的混沌深淵,收斂到了人類用肉眼與程式碼能輕易裁決的「合規違約邊界」之內。對一個要真正上線、長期陪伴用戶的個人助理而言,這份收斂已經足夠。

實作細節

實作細節 1:MCP 資源的 Trusted vs Untrusted 信任分層隔離(DMZ)防線 給工程師

在 fibon 的世界觀裡,對網際網路上琳瑯滿目的 MCP 外部伺服器採取兩極分化的信任管理(Trust Multi-Tiering):

  • 🟢 Trusted MCP(完全可信層):用戶自己在後台顯式授權、自架的私有端點、或來自微軟/Anthropic 等官方廠商(Vendor)並經社群嚴格源碼審計(Audit)的可信工具。直接載入核心大腦進程,走 Fastpath(直連快線)。
  • 🔴 Untrusted MCP(未知風險層):來自開源第三方社群、或某個不知名市集(Marketplace)下載的來路不明工具。被呼叫時大腦直連的 API 會被切斷,所有工具呼叫(Tool Calls)被網關包裝成 gRPC 訊號、送給背景獨立運行的沙盒 Worker。

這個分層解決了 2025 年 MCP 協議普及以來的一個根本資安隱患。因為 MCP 伺服器本質上賦予了外部程式碼在你電腦上執行任意網路請求與本地檔案讀寫的權力——把所有來路不明的 MCP 全部當 Trusted 載入,等於向攻擊者敞開後門。實作中由 PostgreSQL 內 mcp_servers.trust_level 欄位驅動(用戶在後台管理介面手動勾選)。核心大腦冷啟動只把 Trusted 載入核心;其餘 Untrusted 一律走 gRPC 隔離到外部沙盒。這個細節第 6 章「沙盒隔離防線(DMZ)」會深度鋪開。

實作細節 2:引進第三方 Skill 包時的「三道防禦閘門」 給工程師

Skill 表面上只是給 LLM 讀的純文字 Markdown。但從資安本質看,引進任何未知第三方 Skill,都等同信任一段由陌生人撰寫、旨在操作你全套工具系統的提示詞指令。為防惡意 Skill 在後台操控大腦、偷偷調用瀏覽器把 API 金鑰上傳給攻擊者,fibon 在匯入端佈三道閘門:

  • Gate 1:靜態掃描與設定區驗證(同步、完全免費):匯入 skills.zip 時,網關在千分之一秒內發動 17 條嚴格規則的正規表示式(Regex)靜態防護網,對 SKILL.md 全面掃描並劃三個嚴重程度(Severity)等級。一旦發現隱蔽的惡意提示注入(Prompt Injection)話術(如「請忽略上級的所有 security_rules 限制」)或開頭設定區格式不符,第一時間就擋下。
  • Gate 2:非同步 AI 行為審查(依需求觸發、會扣安全預算):通過 Gate 1 者標記 PENDING_AI_REVIEW,調用一個隔離的獨立大腦執行 5 個針對行為合約的 AI 評估動作。為防惡意刷爆 Token,設下嚴格的預算上限:單一用戶每天 AI 審查預算上限為 $1 美元,Redis 掛令牌桶速率限制。發現越權風險時前端跳出高成本警示彈窗(Modal)要求二次確認。
  • Gate 3:最終人類手動批准(人類最終主權):fibon 不採用「AI 全自動閉環審查 Skill」這類做法。因為親眼見過「AI 欺騙 AI」的情況——惡意 Skill 裡一段極具迷惑性的 Prompt,不僅騙過大管家,還能把後台負責審查的 AI 評估大腦一併騙過。所以設計了 8 種狀態流轉的有限狀態機(FSM)。無論上游 AI 審查報告寫得多漂亮,該 Skill 在管理員親手按下 [Approve] 前,狀態都被凍結,沒有權力被寫入核心 tool_registry。最後一道關卡,必須由人類親自把關。
實作細節 3:資源審核的三大 ADR 藍圖(提案中) 給工程師

「統一工具註冊表」與「Skill 匯入三閘門」雖然都已經到位,但這條防線還有三個邊角要補。它們各自整理成一份 Proposed(提案階段) 的架構決策紀錄(ADR),列在這裡,給社群看清楚接下來的演進方向:

  • ADR-021(多型態外部資源一體化審核閘口)
    痛點:Gate 1/2/3 目前只綁在 Skill 這一種資源上,系統接上全新的外部 MCP 伺服器時會出現安全空窗(它的工具描述沒過那 17 條正規表示式掃描,拉的 Docker 映像檔也沒驗過 SHA-256)。
    解法:把 skill_import_candidates 候選表重構成面向多型態的 external_resource_candidates,加上 resource_type'skill' / 'mcp_server' / 'workflow'),讓未來接入的外部 MCP 也一律走一遍三閘門。
  • ADR-023(結構化安全的 typed JSON 規格說明書)
    痛點:Gate 2 的 LLM 惡意掃描(malicious_scan)有個瓶頸:精度很高(Precision 達 1.0,不誤判好的 Skill),但召回率偏低(Recall 只有 0.536,本機初步 benchmark)。居心不良的 Skill 會在 SKILL.md 大段自然語言裡,用繞口令式的句子暗藏提示注入(prompt injection),Gate 1 的正規表示式抓不到,Gate 2 的 LLM 在大段散文裡也常漏判。
    解法:取消 SKILL.md 寫大段自然語言的自由,把所有 Skill 規格改成分三層、強型別(Strongly Typed)的 JSON 結構,用結構定義(Schema)校驗,逼第三方開發者把每條隱性副作用寫明,目標把 malicious_scan 召回率從 0.536 拉到 0.65 以上(ADR-023 Phase 3 的上線門檻)。
  • ADR-020(外部 MCP「用到才啟動」的動態冷啟動調度)
    痛點:記憶體成本讓維運人員頭痛:拉一個 Playwright MCP 就吃 1GB,加上 Context7 的 256MB 與 5 個待命 Docker 沙盒,系統整天閒置(Idle)的硬體開銷也高達 3GB+,對想把 fibon 全本機部署在老舊筆電、資源有限的開發者是個負擔。
    解法:在網關引入「用到才啟動」的冷啟動調度器,讓所有 MCP 預設關機休眠;只有當 Stratified RAG 算分判定這輪對話真的命中某工具時,才在背景非同步把它的 Docker 容器拉起來,某個 MCP 連續閒置超過 15 分鐘就關機釋放記憶體。代價是用戶沉默 15 分鐘後再打字的第一輪,會因為容器冷啟動多等 10–15 秒。為了替硬體與成本省下 3GB,這點等待算合理。

下一章,正面探討整本日誌最大膽的主題:如果 fibon 判定當前程式碼不夠用,它真的被允許在背景改寫自己的原始碼(不只 Brain 的 Python,還包括 Gateway 的 Kotlin、Worker 的 TypeScript、前端的 Vue),實現「AI 自我演進(Self-Evolution)」嗎?我會說明在放手讓它自我改寫的同時,怎麼在程式碼裡佈下牢牢扣住大管家的人類安全網。