昨天 Day 20 我們收掉了第五章守門的最後一道——confused deputy 防護。那道閘強制把工具呼叫的操作身分覆寫成登入者本人,從根本擋掉「誘騙模型代查他人記憶」的越權。整個第五章(Day 16 到 Day 20)談的都是「攻擊與風險怎麼擋」,問題走到這裡,該擋的注入擋過一輪、該遮的個資也遮了。但要說準確一點:它只是通過了目前這幾道守門的檢查,不等於就「可信」——那些守門都有盲點(Day 16、17、20 反覆講過),內容仍是使用者給的不可信輸入,真正可信的來源始終只有 SSO 身分與受控設定。從今天起第六章換一個層次:一個過了守門、但本質仍不可信的問題,接下來該怎麼被「答好」。而答好的第一步,不是急著去查資料、也不是急著呼叫模型,而是先想清楚一件事——這題該交給誰回答。今天就講這道分流。
本篇結構:
先把場景擺清楚。Portal 自己不產生答案,這件事前面講過很多次,但「不產生答案」不等於「只有一條路把問題往外送」。實際上 Portal 手上握著好幾種去處,分屬兩條性質不同的軌:
| 軌 | 形態 | 怎麼運作 | 出處 |
|---|---|---|---|
| SDK 軌 | 行程內的內建助理 | 有專門處理 IT 疑難的、有處理行務問答的、也有接了地圖能力查分行據點的,是 Portal 行程內、靠依賴反轉支撐、由可抽換零件組起來的流程 |
Day 12–15 |
| Agent 軌/MCP(Model Context Protocol,讓模型呼叫外部工具的協定) | 後端獨立部署的 AI 引擎 | 把整題轉交出去,由一個遠端的 LLM 自己決定該呼叫哪些工具 | Day 27 |
問題就出在這裡:同一個聊天框、同一個 /chat 端點,進來的可能是「我密碼忘了怎麼重設」、「請假流程在哪簽」、「離我最近的分行幾點關門」,也可能是一段把這幾件事混在一起講的話。如果沒有一層先做判斷,就會落到兩種都不好的極端:
所以需要一層意圖路由(intent routing):在問題清洗完、準備生成答案之前,先研判「這句話想做什麼」,再據此指派給最合適的去處。它的位置很關鍵——夾在守門(Day 16–20)和檢索生成(明天的 Day 22)之間,是處理鏈從「防守」轉向「服務」的那個轉軸。
機制本身刻意做得樸素。對小林那句貫穿全場的話:
我的員編是 123456,AD 帳號被鎖了,順便想查內湖分行的營業時間。
提醒一下,這句話走到意圖路由這一站時,員編 123456 早在 Day 17 的 PII(即個資)遮罩就已經變成 *** 了,路由看到的其實是遮罩後的版本。但這不影響意圖判斷,因為「AD 帳號被鎖」「分行營業時間」這些語意線索都還在。
路由先對這句話跑一輪意圖偵測,標出它命中了哪幾種意圖:
意圖偵測結果(correlation id = a1b2c3d4)
it = true ← 命中關鍵語意:AD / 帳號 / 鎖 / 解鎖 / 登入
geo = true ← 命中關鍵語意:分行 / 據點 / 營業時間 / 地址
→ 判定:雙意圖(IT + 地點),交給內建助理處理
對應到日誌,大概會看到這樣一行:
2026-06-22 09:15:03.418 INFO [req=a1b2c3d4] IntentRouter : intent it=true geo=true → assistant=builtin
判定出來之後,這題就被指派給那個內建的、能同時處理 IT 與地點的助理。注意這裡的設計取向:偵測的取向是「逐意圖各自打勾」,不是「二選一」——一個問題可以同時是 IT 問題、又是地點問題。小林這句正是雙意圖的典型,it=true 又 geo=true,兩個旗標同時亮起。這個結果不是判斷完就丟掉,它會一路帶著走,變成下游決定「要查哪幾路資料」的依據。
那「指派給內建助理 vs 轉交後端引擎」這個更大的分岔,又是怎麼決定的?這兩個層次刻意分得很開:
| 內建助理 vs 後端引擎 | 碰了哪些領域(it/geo) |
|
|---|---|---|
| 由誰決定 | 由請求顯式表態(帶一個 header 明確指定) | 由意圖路由的語意比對研判 |
| 預設 | 預設交給內建助理跑那套自己排好的流程 | 逐意圖各自打勾,無預設 |
| 性質 | 一個更上層的選擇,不靠語意去賭 | 路由真正在做的細活 |
| 展開於 | Day 27(那條路怎麼接、為什麼要分兩軌) | 下游 Day 22 據此決定查哪幾路 |
換句話說,意圖路由真正在做的細活,是在「內建助理」這條路徑內,判斷一段話碰了哪些領域;至於要不要整個轉交給遠端引擎,那是一個更上層、由請求顯式表態的選擇。
清洗過的問題(已過守門)
│
▼
┌──────────────┐
│ 意圖路由 │ 研判 it? geo? …
└──────────────┘
╱ ╲
(預設) ╱ ╲ (header 顯式指定)
▼ ▼
內建助理(SDK 軌) 後端 AI 引擎(Agent 軌 / MCP)
自己排好的流程 LLM 自主決定呼叫哪些工具
│
▼
依 it/geo 旗標決定下游查哪幾路 → Day 22
最值得拆開講的取捨,是「這個意圖判斷該由誰來做」。
一個很自然的反問是:LLM 不是最擅長理解語意嗎?為什麼不乾脆把整句話丟給模型,讓它自己決定要不要查 IT 知識庫、要不要查地圖?這正是 Agent 軌的做法——把工具遞給模型,由它自主決策。它確實更聰明、更能應付刁鑽的問法。
但內建助理這條路徑,刻意把「初步意圖判斷」留在 Portal 自己手上、用樸素的語意線索比對,而不是先花一次模型呼叫去問「這題屬於什麼類」。理由有三層:
req=a1b2c3d4 的日誌一眼就看得出當時判成什麼意圖(Day 9 講過 correlation id 把散落的足跡串回來的價值,這裡就是一個受益點);交給模型則多一層不確定,同一段話可能因為模型版本飄移而判出不同結果。代價當然有,也得誠實講。樸素的語意比對應付不了太刁鑽或太口語的問法——「我那個網域帳戶登不進去」未必能命中「AD 帳號被鎖」那組線索(這跟 Day 16 提示注入用句式比對遇到的侷限是同一類問題:規則認得出已知句式,認不出沒見過的變體)。明天 Day 22 會看到,下游的向量檢索其實能用語意相近度補上一部分這種模糊匹配的能力;而判得太寬、把不相干的意圖也打了勾,後果就是多查了一路無關資料。這也正好是明天要談的另一個主題:查回來的無關內容會稀釋上下文,所以「不該查就不查」本身就是品質設計。意圖路由打的旗標準不準,直接決定了下游那幾路檢索值不值得發。
也就是說,今天這道分流並不是孤立的一站。
it=true, geo=true這兩個旗標一旦定下來,就成了明天那兩路並行查詢要不要發、發哪幾路的開關。意圖路由把「該交給誰」回答完,答案的下半場——「該去哪裡找料、又該避開哪些不必找的料」——就交棒出去了。
明天 Day 22,我們順著小林這對 it=true / geo=true 旗標走進去,看 Portal 怎麼把 IT 知識庫和分行地圖兩路查詢並行發出、用 zip 把總延遲壓到較慢那一路的耗時,又怎麼靠「條件式 RAG」做到不該查的那一路根本就不發。