昨天 Day 1 給了地圖,也給了一個定位:Portal 是對外入口,自己不產生答案,只做身分、安全、路由、整合這四件橫切的事。今天把鏡頭拉遠一格,看它站在整個系統的哪個位置——它跟誰協作、為什麼需要單獨成為一層,而不是直接塞進後端引擎裡。把這張位置圖弄清楚,後面 28 天每次講到「這該誰來做」,你心裡都有個座標可以對。
本篇結構:
第一天我刻意只講 Portal 自己,今天得補上它的鄰居,因為「對外入口」這個角色,只有放在一張協作圖裡才講得清楚。
這套企業 AI 助理平台不是單一服務,至少有三個自家角色在分工:
| 角色 | 定位 | 職責 |
|---|---|---|
Portal |
對外入口 | 行員的請求一律先到這裡,負責身分、安全、路由、整合 |
Engine |
後端 AI 引擎 | 真正「會用工具、會推理、會調度知識」的腦子;意圖複雜、需要查資料、需要操作行員記憶的問題,最後都在這裡處理 |
KM |
知識庫 | 文件、條文、各種可被檢索的內容存在這裡,提供向量檢索能力 |
關鍵的協作關係有一條容易被誤會:Portal 並不直接走業務介面去碰 KM。真正的知識檢索鏈是 Engine 連 KM——Engine 在回答時自己決定要不要查、查什麼。Portal 唯一碰 KM 的場合,是管理人員從後台對知識庫做管理操作(新增、修改那類),而那是用反向代理「原樣轉發」過去的,Portal 不解讀內容、不參與檢索。換句話說,Portal 在知識這條鏈上只是個轉接站,不是參與者。
除了這三個自家角色,Portal 還會直接對外打兩種第三方服務。這兩個是「外部能力」,不是自家系統的一環:
| 第三方服務 | 用途 |
|---|---|
| LLM 供應商 | 直連 openai-http 或 gemini-http 的 REST |
maps 地圖服務 |
查分行位置與營業時間 |
這幾個自家服務各自獨立部署、跑在 GCP 的 Cloud Run 上,彼此用 HTTP 互打——後面講到的「跨服務互信」「各自發版」「多實例」,前提都是這個分散式部署形態(基座細節 Day 4 連同技術選型一起講)。
把上面的關係畫成資料流,位置感會清楚很多:
行員小林
│ 「我的員編是 123456,AD 帳號被鎖了,
│ 順便想查內湖分行的營業時間。」
v
┌─────────────────────────────────────┐
│ Channels(網頁聊天 / 截圖 / 語音) │ 多模態前端通路
└─────────────────────────────────────┘
│ 蓋上 SSO 身分(corpId),忽略前端自稱
v
┌─────────────────────────────────────────────────┐
│ Agent Portal │
│ 身分 · 安全 · 路由 · 整合 │ ← 幾乎不放業務邏輯
│ 無狀態、不存對話歷史 │
└─────────────────────────────────────────────────┘
│ │ │ │
v v v v
Engine KM LLM 供應商 maps
(AI 引擎) (知識庫) (openai/ (地圖服務)
│ 業務知識 ↑ 檢索 gemini…)
└───────────┘
(檢索鏈在後端,Portal 不在這條線上)
讀這張圖有三個重點:
Portal,它是唯一的對外收口;行員不會、也不該直接打到 Engine 或 KM。Portal 往下游發散出去(Engine/KM 管理代理/LLM/maps),它的工作是「把對的請求送到對的地方,再把回來的東西組好」。Engine ── KM 的橫線是業務檢索鏈,Portal 站在線外——這正是「業務知識不在 Portal 身上」的視覺化。拿小林那題走一遍就具體了:請求進 Channels,Portal 先用 SSO(single sign-on,單一登入)解出他的 corpId(前端自己宣稱的身分一律不信),把輸入裡的「員編 123456」遮成 ***。接著判斷這題同時有 IT 與地點兩種意圖——地點意圖它可以自己叫 maps 查內湖分行,IT 那段則交給 Engine 去處理。最後把兩邊湊成一個帶引用來源的答案回給小林,順手留一筆稽核。整段裡 Portal 沒有「懂」任何業務,它只是把流程管得又穩又安全。
把這段攤成時序,「兩條路分頭跑、最後合流」的形狀就出來了:

那問題來了:既然 Portal 自己幾乎不做業務運算,為什麼不把這些事散到各個前端,或乾脆併進 Engine?這就是「需不需要一層 BFF(Backend for Frontend)」的核心。我的答案是需要,理由有三條:
| 理由 | 說明 |
|---|---|
| 前端多、後端協定該收斂 | 把面向前端的形狀統一收在一層,後端只面對一個乾淨一致的呼叫方 |
| 橫切的事要有強制執行的單點 | 不管請求從哪個通路進來,都一定會過同一套關卡,安全規則無法被繞過 |
| 下游該專心做它擅長的事 | Engine 收到的永遠是已驗明正身、已過安全處理的請求,可以專心算 |
先講結論。行員可以用網頁打字、傳截圖、講語音,這些通路(Channels)對「一次互動長什麼樣」的期待都不同;要是讓每個前端各自直接對接 Engine、各自處理身分與安全,同一套規則就會被重寫好幾遍、而且必然漂移。多模態這幾條通路怎麼共用一套後端,是後面 Day 29 的主題,這裡先記住這個伏筆。
再看強制執行的單點。身分、內容安全、稽核這幾件事,最怕的就是「某個入口忘了做」。把它們釘在 Portal 這一層,不管請求從哪個通路進來,都一定會過同一套關卡——SSO 解身分、守門(guardrail)擋注入與遮 PII(即個資)、留稽核。安全規則只有在「無法繞過」時才真的有效,而 BFF 就是那個無法繞過的收口。
最後是讓下游專心。Engine 的本業是 AI 推理與工具調度,不該再分心去管「這個前端的 cookie 怎麼解」「企業這套 SSO 長怎樣」。把身分與通路適配留在 Portal,Engine 收到的永遠是一個已經驗明正身、已經過安全處理的請求,它可以假設輸入是乾淨的,專心算它的。
用 Day 1 那個比喻收一下:Portal 是大樓的警衛兼總機。(大家都愛用這個比喻) 你總不會讓每個樓層各自在門口擺一套安檢、各自驗證件——警衛集中在一樓做這件事,樓上才能專心辦公。BFF 就是那個一樓。
這個「Portal 幾乎不放業務邏輯」的決定,好處上面講完了,但它不是白拿的,誠實講幾個代價與邊界:
| 代價/邊界 | 重點 |
|---|---|
| 多一跳 | 中間隔了一層,網路多一段往返、架構多一個要維運的服務——也是 Portal 非選 reactive 非阻塞不可的原因 |
| 邊界要守得很自律 | 別讓「就一點點」的業務狀態累積,否則 Portal 會長成第二個 Engine |
| 「整合」這個例外不純粹 | 薄編排(湊幾個來源的結果)可以放,但一旦記東西、算領域規則就該往下游推 |
最直接的代價是多一跳。本來行員直接問 Engine 一次就好的事,現在中間隔了一層 Portal,網路上多一段往返、架構上多一個要維運的服務。而且中間多出來的是一層整天在等下游回應的服務,這一層絕不能用「一個請求佔死一條執行緒」的方式去等——這正是 Portal 非選 reactive 非阻塞不可的原因(少數執行緒掛著等一大堆下游回應),這條線會在第二章 Day 5 到 Day 7 展開。
第二個代價是邊界要守得很自律。「業務留後端」這句話講起來痛快,實作時天天都會遇到誘惑:某個小判斷,是不是順手在 Portal 做掉就好?一旦開始累積這種「就一點點」的業務狀態,Portal 就會慢慢長成第二個 Engine,當初分層的好處全部抵銷。所以團隊需要一條能反覆自問的判準:
寫任何東西前先問自己:這該放
Portal,還是Engine/KM?只要它牽涉到業務狀態、領域運算、需要被檢索的知識,答案幾乎都是後者。Portal只留下身分、安全、路由、整合這四件橫切的事。
第三,要老實說有個例外並不純粹:Portal 為了「整合」,確實會做一點很薄的編排——例如小林那題裡,自己叫 maps 查地點、再把它跟 Engine 的回覆湊起來。這算不算業務邏輯?我的界線是:只要它不持有業務狀態、不沉澱領域知識,只是「把幾個來源的結果組裝成一個回覆」,就還在「整合」的範圍內,可以放。一旦開始記東西、開始算領域規則,就該往下游推。這條界線不是非黑即白,但有這把尺,至少每次猶豫時有個依據可對。
不過得補一個比「持不持有狀態」更準的判準,因為光用「有沒有記東西」這把尺,會放過真正會讓 Portal 變胖的那類東西——無狀態的領域決策。下面這幾樣都是不持有狀態的純函式,「有沒有記東西」剛好量不到它們,但它們一旦長出來,Portal 照樣會變成第二個 Engine:
maps 管」,這本身就是一種業務知識;更準的維度是「變更的理由」:這段邏輯哪天要改,是因為業務規則變了,還是因為橫切關注點(身分、傳輸、稽核格式)變了?前者就不該待在 Portal,哪怕它無狀態、看起來只是個小判斷。
而且光靠「自律」和金句其實擋不住胖化——真要守得住,得有架構上的約束:依賴方向檢查(Portal 不得 import 領域型別),甚至一條會在 CI 自動擋下違規的架構檢查(所謂 fitness function)。判準給方向,約束才給保證。
明天 Day 3,我們拿一個你可能聽過的東西來對照——LiteLLM 這類 AI Gateway。Portal 跟它像在哪、又在哪些治理能力上走得更遠,這組對照會幫你把「平台 BFF」和「純 gateway」的差別釘死在心智模型裡。