<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>從 PoC 到 Production：企業 AI Agent 系統工程 - Bobo 的學思山丘</title><description>把 LLM/AI agent 從 PoC 推向 enterprise production 的系統工程實戰：RAG、向量檢索、tool use、記憶、多代理、可觀測性、治理與團隊落地。</description><link>https://bobochen.dev/</link><item><title>帶領一支 3–8 人的 AI 工程小隊：成功的關鍵不是追最新框架</title><link>https://bobochen.dev/blog/enterprise-ai-agent-leading-small-ai-team/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-leading-small-ai-team/</guid><description>一支小型 AI 工程團隊的成敗，不在於用了多潮的 framework，而在於有沒有建立一個可重複的 delivery loop。談 architecture/code/prompt/eval review 怎麼做、怎麼把 AI agent 的能力翻譯成 business stakeholder 聽得懂的 workflow impact 和 ROI、以及怎麼讓團隊在一個變化極快的領域裡持續交付。系列完結篇。</description><pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 12 篇，也是**完結篇**（共 12 篇）。上一篇：[Agent 治理框架](/blog/enterprise-ai-agent-governance-framework)。

前面十一篇都在講系統。最後一篇回到人。因為「把上面那整套東西做出來、而且持續維護下去」，從來不是一個人的事，是一支團隊的事。如果你要帶一支 3–8 人的 AI 工程小隊，這篇是我認為最重要的幾件事。

先講一個反直覺的結論：

&gt; 在一個變化快到每週都有新 framework 的領域裡，小團隊成功的關鍵，**恰恰不是**追最新的框架，而是建立一個**可重複的 delivery loop**。

## 為什麼「追新」是小團隊的陷阱

AI 這個領域，每週都有新模型、新 framework、新「這個會改變一切」的工具。對一個小團隊，這是甜蜜的毒藥：

- 每換一次 framework，前面累積的 know-how 和工具就打掉一些。
- 團隊的精力被「學新東西」吃掉，而不是「交付價值」。
- 你永遠在起跑線上，永遠沒有把一個東西做到 production-grade。

給個我自己用的粗略門檻：一個新 framework 要值得你打掉重練，它得能把你某個 delivery loop 環節的工作量砍掉一半以上、而且維護不用你自己扛——只是「換個寫法更優雅」不夠。LangChain 從 0.0.x 一路改到 1.0，多少團隊的 chain 寫法跟著翻修了好幾輪；同一段時間，「黃金題庫過了才能上」這條紀律一行都沒變。

我這一年大量用 agentic 的方式工作，最深的體會是：**工具會一直換，但把一個 agent 從 demo 推到能信任的那套工程紀律（這整個系列講的東西）是不太變的**。一個好的 AI 工程 leader，要幫團隊**守住不變的那部分**——RAG 的品質、eval 的紀律、權限的嚴謹、可觀測性——而不是追著每個新玩具跑。框架是手段，能不能穩定交付可信任的系統才是目的。

2026 回頭看更明顯：這一年真正沉澱下來、跨工具通用的，是**介面和紀律**，不是某個 framework。MCP 變成大家接 tool 的共同語言（也是為什麼我會去寫 MCP server，第 6 篇）、eval 從「加分項」變成 CI 裡的固定關卡、tracing 從各家自掃門前雪到 OpenTelemetry 的 GenAI conventions 開始有共通標準。這些你學一次、換不換 framework 都帶得走；某個「這個月最潮」的 agent SDK，你學了三個月可能就沒人維護了。

## 建立可重複的 Delivery Loop

「可重複」是關鍵字。一個健康的 AI 工程團隊，應該有一套**每個專案都照著走的循環**，而不是每次都重新發明：

```
需求 → 設計（架構/安全 review）→ 建黃金題庫 → 實作
  → eval 跑回歸 → 上線 → 觀測 → 用線上訊號回頭補題庫 → …
```

這個 loop 把前面各篇變成團隊的肌肉記憶：第 2 篇的架構、第 5/11 篇的權限與治理、第 9 篇的 eval 與觀測，都不是某個人臨時想起來才做，而是**流程裡的固定關卡**。新人加入，照著 loop 走就不會漏掉關鍵的工程紀律。這比任何 framework 都值錢。

## 四種 Review，缺一不可

傳統團隊有 code review。AI 工程團隊需要的 review 更多，因為「能出錯的地方」更多：

- **Architecture review**：新功能上之前，先過一次架構——這個 agent 的權限邊界對不對？工具會不會給太多？走 RAG 還是 fine-tune？放哪個三角的角（第 10 篇）？在還沒寫 code 前就把方向定對，比寫完再改便宜太多。
- **Code review**：照舊。AI 寫的 code 也是 code，一樣要審。
- **Prompt review**：prompt 是這個系統的「邏輯」，改一句可能行為大變。它該像 code 一樣被版本控制、被 review——具體一點：prompt 進 git、改動走 PR，而且 PR 裡**附上這次的 eval diff**（不是「我覺得這版更好」，是「通過率從 87% 到 91%，但這三題退步了」）。沒有 eval 數字的 prompt PR，跟沒有測試的 code PR 一樣不該過。
- **Eval review**：最容易被忽略、卻最重要的一種。黃金題庫（第 9 篇）夠不夠涵蓋？通過率掉了大家有沒有當一回事？**團隊要建立一個文化：eval 沒過，跟測試沒過一樣，不能上**。

把這四種 review 變成習慣，團隊產出的就不是「跑得動的 demo」，是「敢上 production 的系統」。

## 最被低估的能力：把 AI 翻譯成業務語言

這是 technical lead 和純 IC 最大的差別，也是 JD 上「跟 business stakeholder 溝通」真正的意思。

業務主管不在乎你用了 multi-agent 還是 RAG、reranking 調了什麼參數。他們在乎的是：

- 這東西能幫我們**省多少時間 / 多少人力**？（workflow impact）
- 它出錯的**風險**有多大、你怎麼控制？（risk control）
- 投入這些工程，**回報**是什麼？（ROI）

一個只會講技術的 AI 團隊，很難拿到資源和信任。你要能把第 11 篇的治理講成「我們怎麼確保它不會洩漏客戶資料」，把第 9 篇的 eval 講成「我們怎麼知道它的品質有沒有掉」，把第 10 篇的成本講成「每個月大概這個數，而它省下的人力是這個數」。

**把工程語言翻譯成業務價值，是讓 AI 專案活下去的氧氣。** 做不到這件事的團隊，做得再好也常常拿不到下一輪資源。

舉個翻譯的範例感受一下落差。技術版：「我們把 reranking 換成 cross-encoder，top-5 命中率上升、p95 latency 控制在兩秒內。」業務版：「客服 agent 第一次就答對的比例從六成拉到八成五，每天攔下大約三百通本來要轉真人的詢問，模型成本一個月小幾萬、省下的客服工時遠大於這個數。」——同一件事，後者才換得到下一輪預算。重點不是把數字講大，是把它放進主管的損益表裡。

## 在不確定裡帶人

最後，AI 工程有個特別的領導挑戰：**這個領域本身充滿不確定**。模型會被供應商偷偷改、某個做法下個月可能就過時、沒有人是「專家」因為大家都在同一條起跑線附近。

其中「模型被供應商偷偷改」這件事，不只是領導氛圍問題，是 production 風險：同一個 model 名稱、同一段 prompt，供應商一次安靜的更新就可能讓行為飄掉——這正是第 1 篇講的，你有一個不能控制、也不會收到 changelog 的上游依賴。對小隊的紀律是兩條：版本能 pin 就 pin（別只寫 `latest`），以及讓黃金題庫**定期重跑**而不是只在改 code 時跑——這樣模型悄悄變了，是你的 eval 先尖叫，而不是客戶先尖叫。

帶這樣的團隊，我覺得幾件事重要：

- **建立心理安全感**：在一個沒有標準答案的領域，要讓團隊敢說「我不確定」、敢做實驗、敢承認某條路走不通。eval 和 observability（第 9 篇）在這裡有個額外好處——它們讓「對或錯」有**數據**可依，而不是靠誰嗓門大，這本身就降低了團隊的焦慮。
- **知識共享是團隊資產**：一個人踩過的坑、調出來的好 prompt、學到的新工具，要有機制讓它變成團隊的，而不是鎖在某個人腦裡。寫下來、分享出來——這也是我自己一直在做的事（這整個系列就是）。
- **postmortem 不咎責**：agent 出包了，重點是「系統哪裡讓這個錯誤溜過去了、怎麼補上防線（補進黃金題庫、加個 HITL 關卡）」，而不是「誰的 prompt 寫爛了」。判斷一場 postmortem 有沒有做對，看它的產出物：每一次線上出包，至少要長出**一條新的黃金題庫**或**一道新的關卡**——讓同一個錯誤下次過不了。沒長出防線的檢討，只是一場集體嘆氣。

## 回到第 1 篇：六道鴻溝，其實是一支團隊的事

這個系列從「為什麼企業 AI Agent 卡在 PoC」開始，講了六道鴻溝：正確性、eval、可觀測性、權限治理、成本延遲、fallback。

走到最後一篇你會發現，**過這六道鴻溝，從來不是一個技術問題，是一個團隊能不能建立起對應紀律的問題**。

- 正確性與權限 → 是不是有 architecture / eval review 把關？
- Eval 與可觀測性 → 是不是有「沒過不能上」的文化？
- 成本與治理 → 是不是有人能把它翻譯成業務聽得懂的價值，換到持續投入的資源？

技術會給你過河的工具，但真正把一個企業 AI agent 從 demo 推到 production、而且**持續維護下去**的，是一支有紀律、能溝通、在不確定裡還能穩定交付的團隊——以及帶著他們的那個人。

如果你正在或即將做這件事，希望這 12 篇，能幫你把「能 demo」和「能信任」之間那段最難的路，走得踏實一點。


## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;帶領一支 3–8 人的 AI 工程小隊&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[Agent 治理框架](/blog/enterprise-ai-agent-governance-framework)
- 系列起點：[為什麼企業 AI Agent 卡在 PoC？六道鴻溝](/blog/enterprise-ai-agent-poc-to-production-gap)
- [Agentic Engineering 實戰手冊](/blog/agentic-engineering-what-is-it)——換個角度：用 agent 來做工程，而不是打造 agent 系統
- [Agentic Engineering：團隊導入](/blog/agentic-engineering-team-adoption)——把 agent 工作流導入一支團隊的實戰</content:encoded><media:content url="https://bobochen.dev/_astro/cover.DLS1_LLx.webp" medium="image"/><category>技術領導</category><category>團隊管理</category><category>AI 工程</category><category>職涯</category><category>跨部門溝通</category><enclosure url="https://bobochen.dev/_astro/cover.DLS1_LLx.webp" length="0" type="image/png"/></item><item><title>Agent 治理框架：讓企業敢把 AI agent 接到真實業務上的那張安全網</title><link>https://bobochen.dev/blog/enterprise-ai-agent-governance-framework/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-governance-framework/</guid><description>把散落在各章的安全與信任機制，收斂成一張可以攤給資安和主管看的治理框架：資料分級、RBAC 權限邊界、tool registry、audit log、human-in-the-loop、eval harness、observability、成本監控。這一張圖，就是「能 demo」和「企業敢用」之間那道治理的牆。</description><pubDate>Sun, 31 May 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 11 篇（共 12 篇）。上一篇：[延遲、可靠性、成本的系統權衡](/blog/enterprise-ai-agent-latency-reliability-cost-tradeoffs)。這篇整理的是**治理設計框架（一份 reference / 設計提案）**，不是某個已導入系統的稽核報告。

前面十篇，安全和信任的機制是散落各處講的：第 5 篇的權限檢索、第 6 篇的工具邊界、第 9 篇的可觀測性。這一篇要做的，是把它們**收斂成一張完整的治理框架**——一張你可以攤在資安長、法遵、業務主管面前，回答那個關鍵問題的圖：

&gt; 「我們憑什麼敢相信這個 AI agent，把它接到真實的客戶資料、財務系統、製造流程上？」

PoC 永遠回答不了這個問題，因為它根本沒想過。而這張圖，就是「能 demo」和「企業敢用」之間那道治理的牆。

## 一頁治理框架

![Agent 治理框架：上層控制「誰能碰什麼」、中層控制「能做什麼」、底層橫跨一切持續監督（audit、eval、observability、cost）](./images/governance-framework.webp)

&lt;p style={{ textAlign: &apos;center&apos;, color: &apos;var(--color-text-secondary)&apos;, fontSize: &apos;0.9rem&apos;, lineHeight: 1.6, marginTop: &apos;-0.4rem&apos; }}&gt;治理框架的三層：上層管「誰能碰什麼」、中層管「能做什麼」、底層橫跨一切持續監督（audit / eval / observability / cost）。&lt;/p&gt;

八個元件，分三層：**控制誰能碰什麼（①②）、控制能做什麼（③④）、持續監督（⑤⑥⑦⑧）**。一個一個講它在治理上扮演什麼角色。

在逐項講之前，先講一件對資安和法遵很重要的事：**這張圖不是我發明的。** 它只是把 NIST AI RMF、ISO/IEC 42001、EU AI Act 對 AI 系統的共同要求，落到 agent 工程上。八個元件幾乎一對一對得上既有框架：

| 治理元件 | NIST AI RMF | ISO/IEC 42001 | EU AI Act（高風險） |
|---|---|---|---|
| ① 資料分級 | MAP | Annex A 控制 | Art.10 資料治理 |
| ② RBAC/ABAC・最小權限 | GOVERN | Annex A 控制 | — |
| ③ Tool Registry | MAP / GOVERN | Annex A 控制 | — |
| ④ Human-in-the-loop | GOVERN / MANAGE | PDCA | Art.14 人類監督 |
| ⑤ Audit Log | MEASURE | PDCA | Art.12 紀錄保存 |
| ⑥ Eval Harness | MEASURE | Check（PDCA） | — |
| ⑦ Observability | MEASURE | Check（PDCA） | Art.12 / Art.72 |
| ⑧ Cost／持續監督 | MANAGE | Act（PDCA） | Art.72 上市後監督 |

為什麼要花力氣對這層？因為當你把這張圖攤在法遵面前，他第一個問題不會是「你 RBAC 怎麼做的」，而是「**這對得上我們要遵的哪一條**」。對得上，框架的說服力就從「工程師畫的圖、聽起來有道理」，升級成「對得上稽核要求的圖」。

## ① 資料分級：先知道你在保護什麼

治理的起點不是技術，是**盤點**。哪些資料是公開的、內部的、機密的、個資 / 受法規保護的（個資法、營業秘密、客戶合約）？

沒有分級，後面的權限控制就沒有依據——你不知道哪些資料「碰了會出事」。這一步常常要跟法遵、資安一起做，是治理裡最不技術、卻最不能跳過的一步。分級的結果，會變成第 5 篇那些 chunk 上的權限 metadata 的來源。

## ② 身分與權限邊界：RBAC / ABAC

把「誰、能透過 agent、碰到哪些資料和工具」明確定義出來。這是第 5 篇（資料檢索）和第 6 篇（工具動作）的權限，在治理層的統一視角。

- **RBAC（角色為本）**：依角色給權限。工程師能查工單、不能查薪資；主管多一些；HR 又不同。
- **ABAC（屬性為本）**：更細，依屬性動態判斷（部門 + 機密等級 + 地區）。複雜場景用得上。

核心原則是**最小權限**：agent 代表某使用者行動時，只該有那個使用者該有的權限，**一分不多**。最該避免的反模式，就是第 2 篇警告過的——agent 用一個服務帳號的最大權限在跑，把自己變成權限放大器。

## ③ Tool Registry：能做的事，要有一份清單

第 6 篇講過，MCP / tool registry 把「agent 能做哪些動作」變成一份可盤點的清單。在治理層，這份清單要再標註：

- 每個工具的 **action boundary**（唯讀 / 寫入 / 危險）
- 需不需要 **approval**
- 哪些角色能用哪些工具

當資安問「你們的 agent 到底能對哪些系統做哪些事」，你掏得出這份清單——這就是治理的可稽核性。**沒有 registry，你連自己的 agent 能做什麼都說不清楚**，更別說讓資安放行。

## ④ Human-in-the-loop：高風險動作的剎車

第 6 篇講過 approval flow 的機制，治理層要決定的是**政策**：哪些動作非要人類確認不可？

通常的分界：**會造成重大、不可逆副作用的**——大量資料異動、對外溝通、金流、改動生產設定——都該有 HITL 關卡。低風險唯讀的放行。這份「哪些要剎車」的清單，是治理的核心決策之一，要跟業務一起定，因為它直接影響效率和風險的平衡。

但 HITL 最常見的失效，不是沒放關卡，是**放了卻變成橡皮圖章**——當待核可的動作又多、又通常是對的，人會很快養成「一律點同意」的習慣，關卡還在、監督已經沒了。這正是 EU AI Act Art.14 想堵的洞：它要的是**有意義的、能真正介入的人類監督**，不是流程上多一個 approval 按鈕。對 agent 還有個額外的坑：當待核可項是模型生成的一段自然語言，審核者很難在幾秒內判斷它的副作用範圍。所以 HITL 的設計品質，取決於「**呈現給人類的資訊，夠不夠讓他做出有意義的判斷**」——這動作會改到哪些資料、影響多大、為什麼 agent 這樣選——而不只是「有沒有放一個確認關卡」。

## ⑤–⑧ 監督層：信任不是一次性的，是持續的

前面四項是「事前控制」，但治理的另一半是**持續監督**——因為信任會隨時間、隨模型更新、隨資料變化而流失。這四項都在前面章節建好了，治理層把它們組織起來：

- **⑤ Audit Log**：誰、何時、透過 agent、存取了什麼、做了什麼動作。合規與事故調查的底線，出事時這是你唯一能還原真相的東西。兩個常被漏掉的細節：(1) **要留多久？** EU AI Act Art.12 已把高風險系統的「自動事件記錄」從最佳實踐升級成法定義務，Art.19 對 deployer 給的下限是至少保存六個月——audit log 不只要有，還要回答得出保存期限。(2) **對 agent，光記「呼叫了哪個工具」遠遠不夠**，要連 prompt、檢索到的 chunk、工具的輸入輸出一起留，否則事故調查時最關鍵的中間決策過程是一片空白。這份資料跟第 9 篇 observability 的 trace 其實是同一份東西的兩種用途。
- **⑥ Eval Harness（第 9 篇）**：品質有沒有偷偷掉？模型被供應商更新後行為有沒有漂移？這套持續監督的精神對應 NIST AI RMF 的 MEASURE / MANAGE；NIST 2024 年的 Generative AI Profile（NIST-AI-600-1）甚至把 **confabulation（也就是幻覺）獨立列為一個風險類別**，對 12 個 GenAI 風險領域給了 200+ 條建議行動，可以直接拿來當 eval 與監控清單的起點——它點名的第一個風險，正好就是這系列開頭的「鴻溝一：正確性沒有底線」。
- **⑦ Observability（第 9 篇）**：每個決策可追、可重播，出包查得到根因。
- **⑧ Cost Monitor（第 9、10 篇）**：花費透明、異常可告警。

這四項合起來回答的是：**「我們有沒有在持續確認這套系統仍然值得信任？」** 一個只做事前控制、卻沒有持續監督的 agent，就像一個通過了上線審查、之後就再也沒人看的系統——遲早出事。

## 怎麼落地：別想一次到位

這張框架完整，但不代表你要一次全做完。務實的導入順序：

1. **先做 ①②**（分級 + 權限邊界）：沒有這個，任何接觸真實資料的 agent 都不該上線。這是入場券。
2. **再做 ③⑤**（registry + audit）：讓「能做什麼」和「做過什麼」可盤點、可追。
3. **接著 ④**（HITL）：把最高風險的動作先用人類關卡保護起來。
4. **持續強化 ⑥⑦⑧**：監督層隨系統成熟逐步加深。

還有一個外部理由，讓「現在就做」比「等等再說」划算：**法規時鐘已經在跑。** 但這裡有個 2026 必須講對的眉角——EU AI Act 是分階段生效的：禁止性實務與 AI 素養義務已自 2025-02 適用、GPAI 義務自 2025-08 適用，這幾條都已生效。而大家最在意的**高風險義務，原訂 2026 年 8 月起，在 2025 年底的 Digital Omnibus 提案後被往後推**（討論中的新時程落在 2027–2028，截至本文撰稿仍待正式定案）。所以如果你還在網路上看到「2026 年 8 月高風險義務全面適用」，那是舊懶人包、已經過期了。給你的訊息很單純：**日期會動，但別賭它會無限延。** 分級、RBAC、audit、HITL 這套底層工程量大、牽涉法遵與業務，不是兩週能補完的——日期往後挪，剛好是讓你「提早做、做扎實」的窗口。

依風險排序：**越是接觸機密資料、越是能造成不可逆動作的 agent，治理就要越完整**；一個只查公開 FAQ 的內部小工具，不需要這整套。治理的強度應該對應風險的高度，這本身也是一種工程判斷。

## 小結

Agent 治理不是上線後補的文件，是讓企業**敢**把 agent 接到真實業務上的前提。它把散落的機制收成一張圖：

- **控制誰能碰什麼**：資料分級 + RBAC/ABAC 最小權限。
- **控制能做什麼**：tool registry + 高風險動作的 HITL。
- **持續監督**：audit log + eval + observability + cost。

而它的精神，其實跟整個系列一致：**承認系統會錯、會被濫用、會隨時間退化，然後為這些事先設好防線**。能畫出這張圖、並依風險決定導入深淺的人，才是企業真正想要的「能把 AI agent 落地」的那個人。

最後一篇，我們從系統回到人：當你要**帶一支 3–8 人的 AI 工程小隊**，把上面這整套東西做出來、維護下去，該怎麼帶。


## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;Agent 治理框架&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[延遲、可靠性、成本的系統權衡](/blog/enterprise-ai-agent-latency-reliability-cost-tradeoffs)
- 回顧：[權限感知檢索](/blog/enterprise-ai-agent-permission-aware-retrieval)、[Tool use 與 MCP](/blog/enterprise-ai-agent-tool-use-mcp)、[可觀測性與評估](/blog/enterprise-ai-agent-llm-observability-eval)——治理框架的三個技術支柱
- 下一篇（完結）：《帶領一支 3–8 人的 AI 工程小隊》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.BKs-7b68.webp" medium="image"/><category>AI 治理</category><category>資安</category><category>RBAC</category><category>稽核</category><category>企業導入</category><enclosure url="https://bobochen.dev/_astro/cover.BKs-7b68.webp" length="0" type="image/png"/></item><item><title>延遲、可靠性、成本：AI agent 系統設計的鐵三角</title><link>https://bobochen.dev/blog/enterprise-ai-agent-latency-reliability-cost-tradeoffs/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-latency-reliability-cost-tradeoffs/</guid><description>LLM app 還是個 distributed system，延遲、可靠性、成本這三件事會互相打架，你不可能三個都要到極致。談 streaming 降感知延遲、retry/timeout/circuit breaker、prompt 與結果快取、model routing（小模型優先）、token 成本治理，以及怎麼用工程手段在這個三角上做出有意識的取捨。</description><pubDate>Wed, 27 May 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 10 篇（共 12 篇）。上一篇：[生產級 LLM 可觀測性與評估](/blog/enterprise-ai-agent-llm-observability-eval)。

到這篇，前面講的所有東西要付帳了。RAG 多檢索幾份文件、reranking 多一次模型呼叫、multi-agent 多幾顆 agent、retry 多跑幾次——每一個讓系統「更好」的決定，都在延遲、可靠性、成本這三件事上劃下一刀。

而這三件事，是一個**互相打架的鐵三角**：

![延遲、可靠性、成本的鐵三角：三股力量互相拉扯，把中心同時往三個方向拉開——你不可能三個都拉到極致](./images/iron-triangle.webp)

&lt;p style={{ textAlign: &apos;center&apos;, color: &apos;var(--color-text-secondary)&apos;, fontSize: &apos;0.9rem&apos;, lineHeight: 1.6, marginTop: &apos;-0.4rem&apos; }}&gt;可靠性、延遲、成本互相拉扯的鐵三角：靠近任一角，另外兩角就被犧牲——三者無法同時拉到極致。&lt;/p&gt;

- 想**可靠** → 加 retry、加 fallback、用更強的模型 → 變慢、變貴。
- 想**便宜** → 用小模型、少檢索、少 reasoning → 品質和可靠性下降。
- 想**快** → 砍 reasoning、激進 cache、少檢索 → 可能犧牲正確性。

你不可能三個都要到極致。Production 工程的價值，就是在這個三角上做出**有意識的取捨**，而不是預設「全都要最好」然後被帳單和延遲教訓。

這也是我一直強調 LLM app 還是 distributed system 的原因——下面這些手段，做過後端的人會覺得無比熟悉。

## 延遲：先區分「真延遲」和「感知延遲」

LLM 天生慢，一個複雜回答跑好幾秒是常態。但使用者體感的「慢」，跟實際耗時是兩回事。

**1. Streaming（串流）幾乎免費降感知延遲。**
別等整個答案生成完才一次吐出來，邊生成邊吐字。實際總耗時沒變，但使用者「立刻看到東西在動」，體感快非常多。這是 CP 值最高的一招，幾乎沒有不做的理由。用工程語言講，streaming 壓的是 **TTFT（Time To First Token，首 token 延遲）**——聊天場景只要 TTFT 低於 1 秒，使用者就覺得「即時」；串流開始後順不順，則看 **TBT（token 之間的間隔）**。人對「按下送出到看到第一個字」的等待，遠比「字與字之間的間隔」敏感，所以該進你第 9 篇 dashboard、該設 SLO 的，是 TTFT，不是籠統的「總回應時間」。

**2. 把能平行的就別串行。**
如果一個任務要檢索三個不同來源，讓它們**同時跑**，而不是一個等一個。Agent runtime（第 2 篇）要支援這種平行。這是基本的並行思維，跟你優化任何後端流程一樣。

**3. 用小模型處理快路徑。**
不是每一步都要動用最強最慢的模型（下面 model routing 細談）。意圖分類、簡單抽取用快的小模型，把慢的大模型留給真正需要的那一步。

## 可靠性：為「外部依賴一定會出包」設計

你的 agent 依賴外部 LLM API，而那是一個**會逾時、會限流、會偶爾回垃圾、偶爾掛掉**的依賴。把它當成「一定會出包的外部服務」來設計，這又是後端的老功課：

- **Timeout**：每次模型呼叫設合理逾時，別讓使用者無限等。
- **Retry with backoff**：暫時性錯誤（限流、逾時）重試，但要退避、要設上限，別把對方打更慘、也別自己燒爆 token。
- **Circuit breaker**：某個模型 / 供應商持續出錯，先「跳閘」停止打它，走 fallback，給它時間恢復。
- **Fallback model**：主模型掛了或回垃圾，自動切備援（另一家供應商、或本地模型）。這也降低單一供應商的依賴風險。
- **降級（graceful degradation）**：真的都不行時，老實回「現在無法處理，請稍後或轉人工」，而不是給一個爛答案。呼應第 1 篇的鴻溝六。

注意這裡的張力：每加一層可靠性（retry、fallback），通常就**多一點延遲、多一點成本**。所以要分場景——關鍵動作值得多付，邊緣功能不必。

關於 fallback 還有個坑要先講：跨供應商 fallback 沒有「一鍵切換、行為一致」那麼無痛。同一段 prompt 在 GPT、Claude、Gemini 上的輸出風格、JSON 遵循度、refusal 行為都不一樣；tool calling 的 schema 各家也不同；更別說等下要講的 prompt caching 是供應商綁定的——切到備援那一刻，前面省的快取全部失效，延遲跟成本反而往上跳。實務上只有兩條路：為主 / 備各自維護一套 prompt 與 parser，或把備援路徑當成「可接受的降級」來設計。別假設換家供應商，行為會一樣。

## 成本：LLM 系統獨有的「浮動帳單」

傳統服務成本相對固定（機器開著就那樣）。LLM 系統的成本是**按 token 浮動**的，而且會悄悄長大。第 9 篇我們已經把成本監控起來了，這篇講怎麼壓。

**1. Model routing：小模型優先，必要才升級。**
這是最大的省錢槓桿。把「要用哪個模型」抽成一層（第 2 篇的 Model Router），依任務難度路由：

- 分類、抽取、格式轉換、簡單問答 → **便宜小模型**
- 複雜推理、需要高品質的最終生成 → **大模型**

光是把「不需要大模型的步驟」改用小模型，常常就能砍掉一大塊成本，而品質幾乎無感。

有多大？拿 RouteLLM（UC Berkeley / Anyscale / Canva，ICLR 2025）的公開 benchmark 當參考：在偏對話的 MT-Bench 上，它能維持約 95% GPT-4 品質、成本卻砍掉約 85%。但別把這 85% 當保證值——同一個 router 換到偏推理的 benchmark，省幅就掉很多（MMLU 只省約 45%）。所以 routing 的省幅，本質上等於你流量裡「不需要大模型的那一塊」有多大：先量你自己的流量分布，再決定能省多少，別套別人的數字。

**2. Cache：能不重算就不重算。**
- **結果快取**：這裡其實藏了兩種完全不同難度的東西。**Exact cache**（把 query 正規化後當 key，同樣的問題回同樣的答案）幾乎零風險、該最先做；**semantic cache**（用 embedding 相似度命中「相似」問題）能多抓改寫過的重複，但有 false-positive 風險——兩個在向量空間很近的問題可能需要完全不同的答案，而且對的命中跟錯的命中相似度高度重疊，沒有通用安全閾值，閾值要訂多嚴取決於「答錯的代價」。生產數據也顯示 semantic cache 相對 exact 往往只多 5~8 個百分點命中率，未必抵得過它的複雜度與答錯風險。高風險場景就乖乖用 exact。（兩種都要注意時效和權限，別把 A 使用者的答案快取給 B。）
- **Embedding 快取**：同一段文字別重複 embedding。
- **Prompt 快取**：把穩定的內容（system prompt、few-shot 範例、長 context）放最前面、把每次都變的部分放最後，讓固定前綴可以被快取重用。但 2026 三家機制不一樣，這差異直接決定你有沒有真的省到：OpenAI、Gemini 是**自動命中**（前綴 ≥ 1,024 token 重複就生效，讀取省 50~90%、寫入不收費）；Anthropic 是**顯式 opt-in**，你得在 request 裡標 `cache_control` 斷點，cache read 只要基礎 input 價的約 0.1 倍（省 ~90%），但 cache write 要付約 1.25 倍溢價、預設 5 分鐘 TTL——換句話說 Claude 的快取要**至少命中一次才回本**。用 Claude 卻忘了標 `cache_control`＝你以為在省錢、其實一毛沒省，這是這招最常見的踩雷。

**3. 管好 context 長度。**
Token 成本跟 context 長度直接相關。第 7 篇講的記憶截斷 / 摘要、第 3 篇講的別塞太多 chunk，到這裡全都變成「省錢」的具體手段。**把不必要的東西塞進 context，是最常見的浪費。**

**4. 設預算護欄。**
單一請求、單一使用者、單一 multi-agent 任務（第 8 篇的成本爆炸風險）都要有 token / 花費上限。撞到上限就停下來或降級，別讓一個失控迴圈燒出一張嚇人的帳單。

我做過 K8s 叢集那類的雲端成本優化，心法在這裡完全通用：**先讓成本可見（第 9 篇），找出最大的那塊，用最小的品質代價把它砍掉**。差別只是這次砍的不是 CPU/記憶體，是 token。

## 把三角畫出來：依場景做取捨

最後給一個務實的框架。不同功能在三角上的位置不該一樣：

| 場景 | 優先 | 取捨 |
|---|---|---|
| 即時對話助理 | 延遲 | streaming、小模型快路徑、適度 cache，容忍偶爾要重問 |
| 高風險決策 / 報告 | 可靠 + 正確 | 大模型、多檢索、critic 審查、HITL，接受慢和貴 |
| 大量批次處理 | 成本 | 小模型、激進 cache、可離線慢慢跑，犧牲即時性 |
| 內部低頻工具 | 成本 + 簡單 | 別過度工程，能跑就好 |

關鍵不是背這張表，是養成一個習慣：**每設計一個 agent 功能，先問它在這三角的哪個角，然後刻意往那邊取捨**——而不是無意識地全都要最好，最後三個都普普、帳單還很貴。

## 小結

- 延遲、可靠性、成本是會互相打架的鐵三角，**不可能三個都極致**。
- **延遲**：streaming 降感知延遲、平行化、小模型走快路徑。
- **可靠性**：把 LLM API 當「一定會出包的外部依賴」——timeout、retry、circuit breaker、fallback、降級。
- **成本**：model routing 是最大槓桿，加上 cache、管好 context、設預算護欄。
- 每個功能依它在三角的位置**刻意取捨**，這份判斷力就是 production 系統工程師的核心價值。

這些手段你會發現沒一個是 AI 玄學，全是分散式系統的硬功夫換了對象。下一篇，我們把第 5、6、9 篇散落的安全與信任機制，收斂成一套完整的**Agent 治理框架**——讓企業敢把這套系統接到真實業務上。


## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;延遲、可靠性、成本的系統權衡&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[生產級 LLM 可觀測性與評估](/blog/enterprise-ai-agent-llm-observability-eval)
- [Agentic Engineering：成本優化](/blog/agentic-engineering-cost-optimization)——agent 工作流的 token 成本怎麼省
- 下一篇：《Agent 治理框架：RBAC、audit log、HITL、tool registry》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.VPcuaszI.webp" medium="image"/><category>系統設計</category><category>成本優化</category><category>延遲</category><category>可靠性</category><category>LLM</category><enclosure url="https://bobochen.dev/_astro/cover.VPcuaszI.webp" length="0" type="image/png"/></item><item><title>生產級 LLM 可觀測性與評估：沒有 eval 的 agent，等於沒有測試的軟體</title><link>https://bobochen.dev/blog/enterprise-ai-agent-llm-observability-eval/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-llm-observability-eval/</guid><description>你改了一句 prompt、換了個模型，怎麼知道系統變好還是變壞？拆解 eval harness（黃金題庫、LLM-as-judge、回歸測試）、agent 的 tracing（每一步檢索/工具/模型的 span）、token 與成本監控，以及上線後怎麼偵測品質漂移。把後端的可觀測性硬功夫，搬到會講人話的元件上。</description><pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 9 篇（共 12 篇）。上一篇：[多代理協作](/blog/enterprise-ai-agent-multi-agent-orchestration)。

這一篇是整個系列裡，我覺得最能分辨「玩過 agent」和「把 agent 當系統做過」的人的一篇。因為它要講的兩件事——eval 和 observability——在 demo 階段完全不存在，但它們正是讓系統可以被信任、被維運的東西。

先把最重的一句話放這：

&gt; 一個沒有 eval 的 agent 專案，本質上就是**一套沒有測試的軟體**。只是因為它是 AI，大家就默許了這件事。

## 為什麼 agent 的「測試」這麼難，但更不能省

傳統軟體：輸入固定 → 輸出固定 → assert 相等 → 綠燈。

Agent：輸入「請幫我總結這份報告」→ 輸出每次**用字都不一樣**，但可能都對；也可能字面很像、實際上錯了。你沒辦法用 `assertEqual` 測它。

正因為輸出不確定，很多人就放棄測試，改用「我自己試幾題覺得還行」。但這正是災難的開始，因為：

- 你換個模型版本（連 vendor 都可能 silent update），行為就漂移。
- 你改一句 prompt 修好 A 問題，常常默默弄壞 B 問題。
- 你調個檢索參數（第 3、4 篇），不知道整體變好還變壞。

**越是不確定的系統，越需要有系統的方法去量它**，而不是越不確定就越靠感覺。

## Eval Harness：給 agent 蓋一套測試

### 1. 黃金題庫（golden set）
準備一組「問題 + 期望答案 / 期望性質」的題目，涵蓋常見情境、邊界情境、和已知會出包的情境。每次你改任何東西（prompt、模型、檢索），**自動把整組題庫跑一遍**，看通過率。

這就是 agent 版的回歸測試。它不需要很大才有用——**30 題涵蓋你最在乎的場景，就遠勝於零**。重點是它存在、而且每次改動都跑。出包過的 case 一定要補進題庫，確保同樣的錯不會再犯第二次。

### 2. 怎麼判斷「答對」：三種尺
輸出不固定，怎麼自動判分？由寬到嚴：

- **規則 / 字串**：答案裡有沒有包含某關鍵事實、有沒有附來源、格式對不對。便宜、確定，但只能驗「硬性質」。
- **語意比對**：用 embedding 比對答案和標準答案的語意相近度。能容忍用字不同。
- **LLM-as-judge**：用另一個（通常更強的）模型，照你給的標準（正確性、完整性、有沒有幻覺）來評分。最有彈性，但「要小心偏誤」不是句口號——judge 有三個有名字、可被緩解的已知偏誤要主動防：**position bias**（偏好排前面的答案，緩解法是交換順序評兩次取一致）、**verbosity bias**（偏好較長的答案，即使長度沒帶來品質）、**self-preference bias**（偏袒自己或同家族模型的輸出——所以別拿同一個模型既當 judge 又當被評對象）。把這三個釘死，「要小心」才從感覺變成可勾的檢查清單，也才需要搭配規則與語意比對交叉驗證。

實務上常常**三種混用**：硬性質用規則、整體品質用 LLM-as-judge。

### 3. 別只測最終答案，要測中間步驟
對會做事的 agent，光看最終輸出不夠。一個答案剛好對，不代表過程沒問題（可能檢索撈錯，但模型瞎猜對了）。所以 eval 也要看：**它檢索到的東西對不對、它選的工具對不對**。這需要下面的 tracing 撐著。

這幾件事在業界都有正式名字，方便你搜：整條決策路徑對不對叫 **trajectory evaluation**（軌跡 / step-level evaluation）；檢索層有現成指標——**context precision / recall**（該撈的有沒有撈到、撈到的對不對）和 **faithfulness**（答案有沒有忠於檢索內容，也就是抓幻覺），RAGAS、Arize Phoenix 都內建；工具選對沒對則看 **tool-selection accuracy**。白話講對是第一步，知道學名你才搜得到工具去自動量它。

## Tracing：把 agent 的黑盒打開

第 1 篇的鴻溝三講過：agent 答錯，你常常什麼線索都沒有。Tracing 就是要把那條從問題到答案的完整路徑，變成一條可以攤開來看的紀錄。

對 agent，一條 trace 應該記錄這些 span：

![一條 agent trace：把一個請求拆成檢索、工具呼叫、模型推理、生成等可量測的 span，每一步的耗時、token、花費都看得到](./images/agent-trace.webp)

&lt;p style={{ textAlign: &apos;center&apos;, color: &apos;var(--color-text-secondary)&apos;, fontSize: &apos;0.9rem&apos;, lineHeight: 1.6, marginTop: &apos;-0.4rem&apos; }}&gt;把一個 agent 請求拆成檢索、工具、模型、生成幾個可量測的 span——打開黑盒，每一步的耗時與花費都看得見。&lt;/p&gt;

有了這個，你 debug 的方式就從「再問一次看看」變成「攤開 trace，看是哪一個 span 出錯」。是檢索撈錯？工具回傳怪資料？還是模型拿到對的東西卻推理歪了？**根因一眼可見**。

這套東西，做後端的人應該很熟——它就是 distributed tracing 套到 agent 上。我寫過用 tracing 去抓 PHP-FPM 記憶體洩漏、談過 fire-and-forget 服務的可觀測性陷阱，那套「每一步都要留下可追的足跡」的肌肉記憶，搬到 agent 上完全適用。差別只在 span 的內容從「DB query、HTTP call」變成「retrieval、tool call、model call」。**這正是後端工程師做 AI agent 的優勢**：可觀測性對你不是新觀念，只是新對象。

而且這件事在 2024 後已經不只是「概念上像」了——它有了正式的開放標準。OpenTelemetry 的 GenAI SIG 從 2024 年起在制定 **GenAI Semantic Conventions**（CNCF 旗下），直接把「LLM / agent 的 span 該長什麼樣」標準化：模型呼叫叫 `chat` / `inference`、工具呼叫叫 `execute_tool`、agent 層級叫 `invoke_agent`，屬性有 `gen_ai.request.model`、`gen_ai.usage.input_tokens`、`gen_ai.tool.name` 這些。意思是上面那張 trace 圖不是各家自己亂畫的，而是一套有共識的 schema。一個誠實的提醒：截至 2026 它仍是 **experimental 狀態**，屬性名還可能變，採用時要留意版本相容。

## 成本與 Token 監控：因為它會悄悄燒錢

LLM 系統有個傳統服務沒有的特性：**每一次呼叫的成本是浮動的**，取決於 token 量。一個沒人注意的功能，可能因為 context 越塞越大、或一個 multi-agent 迴圈（第 8 篇）失控，悄悄把帳單翻倍。

所以要把「成本」當成一級 metric 來監控：

- 每個**功能 / endpoint** 平均花多少 token、多少錢？
- 每個**使用者 / 租戶**燒多少？（抓異常、做計費）
- 有沒有哪個 trace **異常昂貴**（爆 token）？要能告警。

這直接餵給第 10 篇的成本權衡——你不先把成本看見，就無從優化。

## 上線後：偵測「品質漂移」

最後一層，是上線後的持續監控。你的黃金題庫是固定的，但真實世界的問題會變、資料會變、模型會被 vendor 偷偷更新。所以要盯著**線上的健康訊號**：

- **代理指標**：使用者重問率、轉人工率、負評率、「這個答案沒幫助」的比例——這些不需要標準答案，就能反映品質掉了。
- **定期回歸**：固定排程重跑黃金題庫，模型供應商一更新就可能漂移，你要第一個知道，而不是等客訴。
- **抽樣人工複查**：定期抽真實對話人工看，補進黃金題庫。

## 工具地景（會變，但方向很清楚）

你可能會問：實際上用什麼做？我刻意不把這篇綁死在某個工具上（它們明天就可能改名），但給你一個 2026 的版圖方便開始搜：開源自架有 Langfuse、Arize Phoenix、Opik；商業 SaaS 有 LangSmith、Braintrust；既有 APM 則有 Datadog、New Relic 的 LLM Observability。但比「選哪個」更重要的是一個正在發生的收斂——這些工具都在往 **OpenTelemetry GenAI conventions** 靠。所以選型第一個該問的不是「dashboard 漂不漂亮」，而是「它能不能吐標準的 OTel span」——能，你換工具時 trace 還搬得走，不會被單一廠商鎖死。

## 小結

把 agent 從 demo 變成可信任的 production 系統，這篇是關鍵的一道工序：

1. **Eval harness**：黃金題庫 + 混合評分（規則 / 語意 / LLM-as-judge），每次改動都跑回歸，出包的 case 一定補進去。
2. **Tracing**：把每一步（檢索 / 工具 / 模型）變成可攤開的 span，debug 從許願變成看圖。
3. **成本監控**：把 token 與花費當一級 metric，別讓它悄悄燒。
4. **漂移偵測**：用線上代理指標 + 定期回歸，在客訴之前發現品質掉了。

這四件事沒有一件是 AI 獨有的玄學——它們就是把後端的測試與可觀測性硬功夫，搬到一個會講人話的元件上。下一篇我們把這些 metric 派上用場，正面處理那個一直在背景的三角習題：**延遲、可靠性、成本，怎麼權衡**。


## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;生產級 LLM 可觀測性與評估&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[多代理協作](/blog/enterprise-ai-agent-multi-agent-orchestration)
- [Agentic Engineering：測試與安全](/blog/agentic-engineering-testing-safety)——把測試與安全紀律套用在 agent 上的另一個視角
- 下一篇：《延遲、可靠性、成本的系統權衡》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.BkqzDgEv.webp" medium="image"/><category>LLMOps</category><category>可觀測性</category><category>Eval</category><category>監控</category><category>生產環境</category><enclosure url="https://bobochen.dev/_astro/cover.BkqzDgEv.webp" length="0" type="image/png"/></item><item><title>多代理協作：什麼時候真的需要 multi-agent，什麼時候那只是讓系統更貴</title><link>https://bobochen.dev/blog/enterprise-ai-agent-multi-agent-orchestration/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-multi-agent-orchestration/</guid><description>Multi-agent 聽起來很厲害，但大多數時候一個 agent 加好工具就夠了，而且更好 debug。談 supervisor/worker、pipeline、debate 等協作模式，handoff 怎麼傳 context，錯誤怎麼隔離不互相傳染，以及最重要的——什麼時候你「不」該用多代理。</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 8 篇（共 12 篇）。上一篇：[Agent memory 與狀態管理](/blog/enterprise-ai-agent-memory-state-management)。

「多代理」（multi-agent）是這兩年最性感的詞之一。一堆 agent 各司其職、互相協作、像個團隊——聽起來就很厲害。但我要先潑一盆冷水，因為這是我看過最多人**為了用而用**、結果把系統搞得又貴又難 debug 的地方。

所以這篇反過來寫：先講**什麼時候不要用**，再講真的要用時怎麼用。

## 先記住這句話：預設用單一 agent

&gt; 大多數你以為需要 multi-agent 的場景，其實一個 agent 加上一組好工具（第 6 篇）就解決了，而且更便宜、更好 debug。

為什麼？因為每多一個 agent，你就多了：

- **一次（或多次）額外的模型呼叫** → 更貴、更慢（第 10 篇）。
- **一個 context 傳遞的接縫** → agent A 的理解要傳給 agent B，這中間一定會流失資訊、產生誤解。
- **一個更難追的失敗點** → 出錯時，是哪個 agent 錯的？是它本身錯，還是它接收到的 context 已經被前一個 agent 弄歪了？
- **錯誤會傳染** → A 給了 B 一個錯誤前提，B 在錯誤前提上認真工作，整條鏈一起歪。

別小看這幾條的代價。Anthropic 自己揭露過一組值得背起來的數字：agent 大約用掉 chat 的 4 倍 token，multi-agent 系統更高達約 15 倍。換句話說，你還沒讓系統變聰明，光是把它拆成多個 agent，帳單就先乘了 15 倍上去。

這些成本是實打實的。所以決定用 multi-agent 之前，先誠實問自己：**單一 agent 配好工具，真的解不了嗎？** 很多時候答案是「能，我只是覺得多 agent 比較酷」。

## 什麼時候 multi-agent 真的有價值

有三種情況，多代理確實划算：

**1. 任務天然可以平行拆分。**
比如「分析這 20 份競品報告」，拆成 20 個 agent 各讀一份、最後彙整，比一個 agent 慢慢讀快很多。這裡的價值是**平行**，不是「聰明」。

**2. 需要的能力 / 權限差異很大。**
一個負責「讀取分析」、另一個負責「執行高權限寫入動作」。把它們分開，是為了**權限隔離**（第 5、6 篇）——讓會動手的那個 agent 只有最小必要權限，唯讀分析的那個碰不到危險工具。這是安全考量驅動的拆分，很合理。

**3. 需要對抗 / 審查的結構。**
一個 agent 產出、另一個 agent 專門挑錯（critic）。這種「生成 vs 審查」的張力，確實能提升品質——本質上是把「自我檢查」外部化成一個獨立角色。

注意這三個的共通點：**拆分有明確的工程理由（平行、隔離、對抗），不是為了模擬一個公司組織圖**。

這個判斷不是我一個人的偏執。2025 年 6 月有一場被社群並列為「同一週對打」的公開辯論：Anthropic 發表《How we built our multi-agent research system》，主張在可平行的廣度研究任務上拆 agent 很划算——他們的多 agent 系統在這類任務上比單一 agent 高出 90.2%；幾乎同一週，做 Devin 的 Cognition（Walden Yan）發表《Don&apos;t Build Multi-Agents》，主張預設就用單執行緒的線性 agent、別輕易拆。

表面上兩篇在打架，細看卻不矛盾——差別只在「這個任務是不是真的能平行解耦」。有趣的是 Anthropic 自己也點名：**大多數 coding 任務「真正可平行的部分比研究少很多」**，因為各部分彼此相依、要共享同一份 context，硬拆反而會撞車。所以判斷能不能平行，看的不是表面能不能分工，是分出去的子任務彼此依賴有多深——讀競品報告可以各讀各的，寫一個 feature 通常不行。

## 幾種協作模式

真的要做了，常見的結構有這幾種：

### Supervisor / Worker（主管—工人）
一個 supervisor agent 負責拆任務、分派、彙整；底下幾個 worker agent 各做一塊。最常見、最好管，因為**控制流集中在 supervisor**，責任清楚。大部分企業場景用這個就夠。

### Pipeline（流水線）
agent 串成一條線，A 的輸出是 B 的輸入（研究 → 草稿 → 審稿 → 定稿）。適合**階段分明、單向流動**的任務。要小心的是**錯誤會沿著管線累積放大**——第一棒歪一點，最後一棒可能歪很多。

### Debate / Critic（辯論—審查）
多個 agent 對同一問題提不同觀點，或一個產出、一個反駁，最後收斂。品質好但**最貴**（同一問題算好幾遍），留給高價值、容錯低的決策用。

## Handoff：接縫是最容易漏水的地方

多代理最脆弱的地方，是 agent 之間**交棒（handoff）**那一刻。A 要把它的理解傳給 B，這裡有兩個常見坑：

- **傳太多**：把 A 的整段思考、所有中間產物全倒給 B，B 的 context 被灌爆、抓不到重點、又貴。
- **傳太少**：只給 B 一個結論，B 缺了關鍵脈絡，只好自己腦補，腦補就錯。

好的 handoff 是**設計過的介面**：明確定義「A 交給 B 的，是哪幾個欄位、什麼格式」，像在設計兩個 service 之間的 API contract 一樣。這又回到系統工程——agent 之間的協作，本質是**介面設計**問題，跟微服務之間怎麼定 contract 是同一種思考。

這套「把 handoff 當 API contract」的想法，框架也已經幫你制度化了。OpenAI 的 Agents SDK 就把 handoff 做成一級原語：agent A 用一個類似 `transfer_to_agent_b` 的工具呼叫，把控制權加上一份結構化 payload 交給 B，整個轉移還會被記錄、可以重播；後續更新甚至把巢狀 handoff 的完整歷史改成預設 opt-in，正是為了減少跨 agent 的 context bleed——框架的演進方向，剛好就是這篇講的那套介面紀律。

## 錯誤隔離：別讓一個 agent 拖垮全部

Cognition 講過一個很有畫面感的翻車案例：他們把「做一個 Flappy Bird clone」拆成平行子任務，結果一個 subagent 把背景做成了 Super Mario 的風格，另一個 subagent 做的鳥又跟整體美術不搭。每個 subagent 單獨看都很合理，合起來卻是個四不像——因為它們看不到彼此在做什麼。這就是「接縫漏水」最具體的長相：不是哪個 agent 出 bug，而是它們各自正確、彼此不一致。

既然錯誤會傳染，就要主動隔離：

- **驗證交棒內容**：B 接到 A 的東西，先做基本檢查（格式對不對、有沒有明顯矛盾），別照單全收。
- **限制爆炸半徑**：一個 worker 失敗，supervisor 要能處理（重試、換人、降級），而不是整個任務崩掉。
- **設總預算上限**：整個多代理任務要有 token / 時間 / 步數的天花板，否則一群 agent 互相觸發，可以把成本燒到失控（第 10 篇會細談這個「成本爆炸」風險）。

## 一個務實的決策流程

下次有人說「我們來做 multi-agent 吧」，照這個順序問：

1. **單一 agent 配好工具能不能解？** 能 → 就用單一，收工。
2. 不能的話，**是因為平行、權限隔離、還是需要對抗審查？** 三個都不是 → 你大概其實不需要 multi-agent。
3. 是的話，**選最簡單能滿足的結構**（通常是 supervisor/worker），把 handoff 當 API contract 設計，設好預算上限和錯誤隔離。

## 小結

Multi-agent 不是更高級的 agent，是一個**有明確成本、要有明確理由才值得付**的架構選擇。預設用單一 agent；只在平行、權限隔離、對抗審查這三種情況下拆分；拆分時把 agent 間的 handoff 當成介面設計，並嚴防錯誤傳染和成本爆炸。

這不只是我的經驗法則。做過最大規模多 agent 系統的 Anthropic，給的判準幾乎一模一樣：multi-agent 只在「任務價值高到足以支付那多燒的 token」時才划算。換句話說——能不能用，先算這題值不值得你多燒那 15 倍。

能忍住「不為酷而拆」，是這個主題上最值錢的判斷力——也是面試時很容易聽得出來「這個人到底有沒有真的做過」的地方。

前面八篇我們把系統的「能力面」蓋得差不多了：知道事情（RAG）、記得事情（memory）、做事情（tools）、協作（multi-agent）。接下來三篇轉向「**能不能信任**」這件事。下一篇先處理最基礎的：**你怎麼知道這整套東西到底有沒有在好好運作**——生產級的可觀測性與評估。

## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;多代理協作：什麼時候真的需要 multi-agent&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[Agent memory 與狀態管理](/blog/enterprise-ai-agent-memory-state-management)
- [多代理協作的真實世界案例](/blog/multi-agent-orchestration-real-world)
- [用 Claude API 打造多代理系統](/blog/claude-api-guide-multi-agent)
- 下一篇：《生產級 LLM 可觀測性與評估》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.BpHWtpH-.webp" medium="image"/><category>Multi-Agent</category><category>Orchestration</category><category>AI Agent</category><category>系統設計</category><category>LLM</category><enclosure url="https://bobochen.dev/_astro/cover.BpHWtpH-.webp" length="0" type="image/png"/></item><item><title>Agent memory 與狀態管理：short / long / episodic，以及記憶也有權限</title><link>https://bobochen.dev/blog/enterprise-ai-agent-memory-state-management/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-memory-state-management/</guid><description>檢索是「公司的知識」，記憶是「這個使用者、這個任務的脈絡」，兩者不一樣。拆解短期、長期、episodic 三種記憶的用途與設計，context engineering 怎麼決定塞什麼進有限的視窗，以及一個最容易出包的點——A 使用者的記憶不能洩進 B 使用者的對話。</description><pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 7 篇（共 12 篇）。上一篇：[Tool use 與 MCP](/blog/enterprise-ai-agent-tool-use-mcp)。

先釐清一個常被混在一起的概念：**retrieval（檢索）和 memory（記憶）不是同一件事**。

- **Retrieval（第 3–5 篇）**：去公司的知識庫找「客觀的、共用的知識」。產品規格、SOP、法規——這些不屬於任何一個對話。
- **Memory（這篇）**：記住「這個使用者、這個任務」的脈絡。他剛剛問過什麼、他偏好什麼、這個任務做到哪一步、試過哪些路。

把這兩個混在一起，是很多 agent 行為怪異的根源（該記的沒記、不該共用的亂共用）。這篇把記憶拆成三層講清楚，最後講一個最容易出包、卻最少人提的點：**記憶也有權限**。

## 為什麼需要 memory：LLM 天生健忘

LLM 本身是**無狀態**的。每次呼叫，它只看得到你這次塞進 context window 的東西。你不主動把上一輪對話帶進來，它就完全不記得三秒前說過什麼。

所以「記憶」從來不是模型的能力，是**你在模型外面，自己蓋的一套系統**。它的工作是：在每次呼叫前，決定「要把哪些過去的東西，塞進這次有限的 context」。記憶系統的好壞，就是這個決定做得好不好。

## 三種記憶，各司其職

### 1. 短期記憶（short-term）：這一輪對話

最直覺的一種——這次對話講過的話。實作上常常就是把對話歷史一路帶著走。

問題是 context window 有上限，而且**越長越貴、越慢，品質還會隨長度退化**。早年 Liu et al.（2023）的「lost in the middle」說的是一條 U 形曲線——開頭結尾記得牢、正中間掉到四成以下；但那是拿 2023 那批模型測的。到 2026，新模型在「單純的事實檢索」上大致補掉了中段這個洞，退化的形狀變了：不再是「中段最差」，而是**輸入越長、整體越爛，而且開頭通常比結尾撐得久**——業界現在叫它 **context rot**。

有人會說：2026 的視窗不是已經爆大了嗎？是。Claude 4.6 系列標準定價就吃 1M token、Gemini 上看 2M。但**「窗口大」不等於「可以全塞」**——成本、延遲、context rot 三件事全都隨長度惡化，所以記憶管理在 2026 是更重要，不是更不重要；窗口變大只是把「塞不下」的硬牆，換成「塞得下但又貴又笨」的軟坑。

而且不能全帶還有個更硬的理由：**塞越多，模型在「需要推理、而非字面比對」的檢索上越容易出錯**。Adobe Research 的 NoLiMa 評測故意把問題和答案的字面重疊拿掉、逼模型真的去推理，結果連 GPT-4o 都從短 context 的 99.3% 一路掉到 32K 長度的 69.7%。窗口大 ≠ 真的讀得懂中間那堆料。所以短期記憶不能無腦全帶，要管理：

- **截斷**：只保留最近 N 輪。簡單但會忘掉開頭。
- **摘要**：把比較舊的對話壓縮成摘要再帶。省 token，但摘要會流失細節。
- **混合**：近期逐字保留 + 遠期摘要。實務上常見的折衷。

### 2. 長期記憶（long-term）：跨對話記得這個人

使用者三週前說過「我們公司用的是新台幣、財年從一月開始」，今天的新對話他不想再講一遍。長期記憶就是**跨越單次對話、持久保存**的那部分。

實作上，長期記憶常常就**用向量庫存**（呼應第 4 篇）：把值得記的事實向量化存起來，新對話開始時，依當前話題檢索出相關的長期記憶，塞進 context。你會發現——這在技術上幾乎就是「對這個使用者私有資料做的一次 RAG」。

關鍵設計問題是：**什麼值得記？** 全記會越積越雜、檢索越來越不準。要有策略地萃取「值得長期記住的事實 / 偏好」，而不是把每句話都存。

而且「記」只是一半，另一半是**「忘」和「更新」**。使用者半年前說「我們財年從一月開始」，後來改了——舊記憶沒被覆蓋，今天就會拿過期資訊去推理，比沒記還糟。所以長期記憶不能只進不出：要能偵測衝突、覆蓋舊事實、定期淘汰沒再用到的記憶。一個只會累積、不會遺忘的記憶庫，最後會變成一個越來越自信地給你錯答案的系統。

### 3. Episodic 記憶：這個任務做到哪了

這層最常被忽略，但對「會做事」的 agent（第 6 篇的 tool use）最重要。Episodic 記憶記的是**一個任務的執行軌跡**：目標是什麼、已經做了哪幾步、每步結果如何、哪條路試過失敗了。

沒有它，一個多步驟任務做到一半被打斷（逾時、人離開、系統重啟），回來就**整個忘光、從頭再來**，甚至重複做已經做過的副作用動作（又回到第 6 篇的 idempotency）。有了它，agent 才能「接著上次的進度繼續」。

這層本質上是**狀態管理**問題，下面接著講。

## 把 agent 當成一台狀態機

一個會做多步驟任務的 agent，與其想成「一個很聰明的對話」，不如想成**一台狀態機**：它有當前狀態、有歷史軌跡、會根據結果轉移到下一個狀態。

用這個視角，很多 production 問題突然就有了答案：

- **可中斷 / 可恢復**：狀態存在外面（不是只活在記憶體），就能存檔、重啟、接續。
- **可觀測**：每次狀態轉移都記下來，就是第 9 篇要的 trace。
- **可重播**：出包時能照著軌跡重現，才 debug 得動。
- **逾時 / 卡住**：狀態機能設「停在某狀態太久就升級處理或求助人類」。

這完全是傳統後端的硬功夫——狀態、佇列、持久化。再一次驗證第 2 篇那句：agent 系統骨子裡是分散式系統。把「對話脈絡」當成需要持久化、有生命週期的**狀態**來經營，而不是一串飄在記憶體裡的訊息，是 production 和 demo 的分水嶺。

說白了：**能跑多步驟 ≠ 能可靠地跑完多步驟。** 差別不在模型多聰明，而在你有沒有把狀態當成一等公民來持久化——demo 只要在你準備好的那條 happy path 上跑完就行；production 要在第三千個任務做到第七步、機器剛好重啟的那一刻，還能接著跑。

## 最容易出包的點：記憶也有權限

最後這段，請務必放在心上，因為它跟第 5 篇是同一種錯誤的兩個面向。

長期記憶常常存在共用的向量庫裡。如果你的隔離沒做好，就可能發生：

&gt; A 使用者跟 agent 說過的事，在 B 使用者的對話裡被檢索出來、被透露。

這是**比第 5 篇的文件越權更隱蔽的洩漏**，因為它洩的是「另一個使用者私下講的話」，而且很難在測試時發現——你要剛好用兩個使用者、剛好話題相近才會撞到。

防線跟第 5 篇一模一樣：

- 每筆記憶都綁**使用者 / 租戶身分**。
- 檢索長期記憶時，**pre-filter 只在這個人自己的記憶裡找**。
- 多租戶要**硬隔離**。

說穿了，**memory 就是一種對「使用者私有資料」做的 RAG**，所以第 5 篇那整套權限感知檢索的紀律，原封不動適用。把這件事想通，你就不會在記憶系統上重犯一次資安錯誤。

## 小結

- **短期記憶**管這輪對話，重點是 context 怎麼截斷 / 摘要，別讓它又長又貴又失焦。
- **長期記憶**跨對話記住這個人，技術上常常就是「對使用者私有資料的 RAG」，要有策略地萃取。
- **Episodic 記憶**記任務軌跡，本質是狀態管理，讓任務可中斷、可恢復、可重播。
- **記憶有權限**：它就是私有資料的 RAG，第 5 篇的權限紀律一條都不能少。

把 agent 當狀態機經營，你就同時拿到了可恢復、可觀測、可重播——這些正是下一篇的主題。第 8 篇我們談**多代理協作**：什麼時候真的需要多個 agent，什麼時候那只是讓系統更貴更難 debug 的花招。

## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;Agent memory 與狀態管理：short / long / episodic&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[Tool use 與 MCP](/blog/enterprise-ai-agent-tool-use-mcp)
- [多代理記憶架構](/blog/multi-agent-memory-architecture)——當記憶要跨多個 agent 共享時的設計
- 下一篇：《多代理協作：什麼時候真的需要 multi-agent》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.BHI2MLuI.webp" medium="image"/><category>AI Agent</category><category>記憶</category><category>Context Engineering</category><category>狀態管理</category><category>LLM</category><enclosure url="https://bobochen.dev/_astro/cover.BHI2MLuI.webp" length="0" type="image/png"/></item><item><title>Tool use 與 MCP：當 agent 能動手操作系統，邊界該怎麼劃</title><link>https://bobochen.dev/blog/enterprise-ai-agent-tool-use-mcp/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-tool-use-mcp/</guid><description>Tool-using agent 真正可怕的地方，不是它會講錯話，是它能操作外部系統——改資料、送訂單、動設定。從 function calling 的本質、MCP 作為標準介面，到 action boundary、approval flow、idempotency 與 rollback，談怎麼讓 agent 戴著手套動手，而不是裸手亂抓。</description><pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 6 篇（共 12 篇）。上一篇：[權限感知檢索](/blog/enterprise-ai-agent-permission-aware-retrieval)。

前面五篇講的是 agent 怎麼「知道」事情——RAG、向量、權限。這一篇開始講 agent 怎麼「做」事情。而這是整個系統裡風險陡升的地方。

我自己寫過幾個 MCP server，把工具接給模型用。寫完之後最深的體會是一句話：

&gt; Tool-using agent 真正可怕的地方，不是它會講錯話——講錯話頂多丟臉。是**它能操作外部系統**。它用錯工具，是真的會改到資料、動到錢、送出收不回的東西。

一個只會聊天的 agent 出包，是回答錯誤。一個會動手的 agent 出包，是**生產事故**。這一篇就是談怎麼讓它戴著手套動手。

## 先搞懂 function calling 的本質

很多人以為 agent 「呼叫了 API」是模型自己連出去打的。不是。實際流程是這樣：

```
1. 你給模型一份「可用工具清單」（每個工具的名字、用途、參數格式）
2. 模型看了問題，決定「我想呼叫 query_order，參數 order_id=12345」
3. 模型把這個「意圖」用結構化格式吐出來——它只是「說它想呼叫」
4. 你的程式碼（agent runtime）真正去執行這個呼叫
5. 把結果餵回給模型，它再決定下一步
```

關鍵在第 3、4 步之間：**模型只是「表達意圖」，真正執行的是你的 code**。這個分界超重要，因為它告訴你——**控制權在你手上**。模型想呼叫什麼是它的事，要不要真的執行、執行前檢查什麼、要不要先問人，全是你 runtime 這層的責任。把這層責任交回去自己手上，是 production tool use 的起點。

## MCP：把「agent 能做什麼」變成一份可盤點的清單

MCP（Model Context Protocol）是一個讓工具和模型之間用標準介面溝通的協定。你把工具包成一個 MCP server，任何支援 MCP 的 client——Claude、ChatGPT、Gemini、Cursor、VS Code、Microsoft Copilot——都能用同一套方式接上去。

這裡有個關鍵轉折值得講清楚：MCP 雖然是 Anthropic 在 2024 年底提出的，但它沒有停在「Claude 自家規格」。2025 年 3 月 OpenAI 官方採納、4 月 Google DeepMind 跟上，到 2026 它已經交給中立基金會治理、變成跨廠商的共通標準。這件事對企業很重要——你押注一個治理地基，最怕綁死在單一 vendor 上；MCP 變成中立基礎設施，正是它值得押的原因。

我寫 MCP server 的經驗裡，它的價值常被低估成「方便接」。但對企業來說，MCP 真正的意義是治理面的：

&gt; MCP 把「這個 agent 能做哪些事」從散落在 code 各處的一堆 function，變成**一份可以盤點、可以審核、可以集中管理的工具清單**。

這在企業裡是地基。當資安問你「你們的 AI agent 到底能操作哪些系統？」，你能掏出一份清單，而不是回去 grep 全部 codebase。第 11 篇講治理時，這份「tool registry」就是核心。

（想動手體會，可以看我寫過的 [15 分鐘做一個 MCP server](/blog/build-your-own-mcp-server-15-minutes) 和 [什麼是 MCP](/blog/what-is-mcp-claude-plugin-system)。）

## 三條讓 agent 安全動手的紀律

把工具接上只是開始。讓它能上 production，靠的是下面三條。

### 一、Action Boundary：先分清楚「讀」和「寫」

每個工具上線前，先問一個問題：**它會不會改變世界？**

- **唯讀工具**（查訂單、搜尋文件、看狀態）：風險低。錯了就是給錯資訊，不會留下副作用。
- **會寫的工具**（建訂單、改設定、刪資料、寄信、轉帳）：風險高。錯了會留下**收不回的副作用**。

這條線要在設計時就劃清楚，並且**對兩邊用不同的嚴格程度**。唯讀工具可以放手讓 agent 自由用；會寫的工具，每一個都要套上後面兩條紀律。一個常見且務實的起手式是：**讓 agent 預設只有唯讀工具，寫入工具要明確、逐個開通**，而不是一股腦全給。

### 二、Approval Flow：高風險動作，讓人類按一下

對會造成重大副作用的動作，插入一個 **human-in-the-loop（HITL）確認關卡**：agent 準備好要做什麼、把它攤開給人看，人按確認才真的執行。

- 「我要把這 200 筆訂單標記為取消，確認嗎？」→ 等人點頭。
- 「我要寄這封信給全體客戶，內容如下」→ 等人點頭。

這不是不信任 agent，是**承認它會錯，而且某些錯誤的代價大到不該由機率決定**。設計上的重點是：approval 關卡要卡在「執行前」，而且要把 agent **打算傳的真實參數**完整呈現給審核者，不能只給一句模糊的「它要寄信」。

哪些動作要 approval、哪些可以放行，本身是個風險分級——這會在第 11 篇的治理框架裡系統化。

### 三、Idempotency 與 Rollback：為「它一定會重試」做準備

Agent 會重試。網路斷了、逾時了、它覺得上次沒成功——它會再呼叫一次。如果你的寫入工具不是 idempotent，這就是**重複下單、重複扣款、重複寄信**的來源。

- **Idempotency**：同一個操作做兩次，結果跟做一次一樣。常見做法是帶一個 idempotency key，後端認得「這個操作我處理過了」就不重複執行。
- **Rollback / 補償**：萬一一連串動作做到一半失敗（建了訂單但扣款失敗），要有辦法回復或補償，不能留下半套狀態。

這些其實都是**分散式系統的老問題**。呼應第 2 篇那句話：LLM app 還是個 distributed system，只是多了一個會自己決定重試的元件，反而讓 idempotency 比以前更不能省。

還要注意一個 2026 的現實：主流 API（OpenAI tool calls、Anthropic tool use、Gemini function calling）模型一輪可以同時吐出**多個** tool call，runtime 要能並行執行再一起餵回。這讓 idempotency 從「nice to have」變成「不做會出事」——重試已經會製造重複副作用，再疊上平行呼叫，重複的機率是乘起來的，不是加起來的。你以為的「一筆扣款」，可能是兩個平行呼叫各自重試後變成的四筆。

## 別把工具設計成「薄薄一層包 API」

最後一個實務建議。很多人把工具做成「一個工具對一個 API endpoint」，把模型當成在填 API 參數。這常常不好用，因為：

- 模型可能填出**危險的參數組合**（一次撈全表、刪太多）。
- 工具的「用途描述」寫不清楚，模型就會亂用。

好的工具設計，是站在「agent 想完成什麼任務」的角度，提供**剛好夠用、邊界內建**的能力。例如不要給一個「執行任意 SQL」的工具（這等於把資料庫鑰匙交出去），而是給「查詢某使用者的訂單（已內建只能查他自己的）」這種**意圖明確、權限和範圍已經框死**的工具。把危險收在工具內部，而不是指望模型自律。

為什麼這條這麼重要，2026 的資安現場給了更硬的理由：廣義工具（任意 SQL、任意 shell）是 prompt injection 最愛的放大器。攻擊者不需要攻破你的系統，只要想辦法讓模型「想呼叫」一次帶惡意參數的工具，就直接命中真實資料庫。把工具收窄成意圖明確、權限框死的形狀，等於把 injection 的攻擊面從「整個資料庫」縮到「這個使用者的訂單」——攻擊面小一個數量級。這也是 OWASP 把 **Excessive Agency**（給 agent 過多權限與自主性）單獨列為 LLM 應用十大風險之一的核心：危險不在模型會不會學壞，在你給了它多大的權限去做壞事。

## 小結

讓 agent 動手，三條紀律收尾：

1. **Action boundary**：先分讀 / 寫，寫入工具預設不給、逐個開通。
2. **Approval flow**：高風險動作插 HITL，把真實參數攤給人看再執行。
3. **Idempotency / rollback**：為「它一定會重試」做準備，這是分散式系統的老功課。

再加一條心法：**把危險收在工具設計裡，別指望模型自律**。MCP 則幫你把這一切變成一份可盤點、可治理的清單。

下一篇換個主題：agent 怎麼「記得」事情——**memory 與狀態管理**。檢索是公司的知識，記憶是這個任務、這個使用者的脈絡，兩者不一樣，而且記憶一樣有權限問題。

## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;Tool use 與 MCP：當 agent 能動手操作系統&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[權限感知檢索](/blog/enterprise-ai-agent-permission-aware-retrieval)
- [15 分鐘打造你自己的 MCP server](/blog/build-your-own-mcp-server-15-minutes)
- [什麼是 MCP？Claude 的外掛系統](/blog/what-is-mcp-claude-plugin-system)
- [MCP 與 A2A 協定：實務者指南](/blog/mcp-a2a-protocols-practitioner-guide)
- 下一篇：《Agent memory 與狀態管理：short / long / episodic》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.9XgvAb-Q.webp" medium="image"/><category>MCP</category><category>Tool Use</category><category>AI Agent</category><category>API</category><category>Function Calling</category><enclosure url="https://bobochen.dev/_astro/cover.9XgvAb-Q.webp" length="0" type="image/png"/></item><item><title>權限感知檢索：企業 RAG 最難、也最容易被略過的一關</title><link>https://bobochen.dev/blog/enterprise-ai-agent-permission-aware-retrieval/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-permission-aware-retrieval/</guid><description>個人玩 RAG 不會遇到這個問題，但企業一定會撞牆：當不同權限的人問同一個 agent，它怎麼確保每個人只檢索得到自己有資格看的東西？拆解 pre-filter vs post-filter、權限繼承、機密分級、來源歸屬與多租戶隔離——這是把「能 demo」和「過得了資安」分開的那條線。</description><pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 5 篇（共 12 篇）。上一篇：[向量資料庫與 embedding 策略](/blog/enterprise-ai-agent-vector-db-embedding-strategy)。先說明：這篇談的是**設計原則與參考做法**，不是某個已上線系統的拆解；但它對應的風險是每個企業 RAG 都真實會撞到的。

前面幾篇講 RAG 怎麼檢索得準。這篇要講一件更重要、卻最常被 PoC 跳過的事：**檢索得「對人」**。

你做個人用的 RAG，永遠不會遇到這個問題，因為所有資料對你都是開放的。但企業 RAG 一定會撞牆，而且撞的是資安那道牆：

&gt; 當一個沒有 HR 權限的工程師，問 agent「某某主管的薪資是多少」，而那份薪資表剛好在向量庫裡——你的 agent 會不會大方地檢索出來、流暢地回答他？

如果會，你做的不是 AI 助理，是一台**全自動的資料外洩機**。這一篇就是要確保它不會。

## 為什麼這關特別難

傳統權限控制相對單純：使用者點開某份文件，系統檢查「他有沒有權限看這份」，有就給、沒有就擋。權限判斷的對象是**一份明確的文件**。

RAG 把這件事打散了。文件被切成成千上萬個 chunk、變成向量、混在同一個向量空間裡。檢索的時候，系統是「在所有 chunk 裡找語意最相近的幾個」——這個動作**預設是無視權限的**。除非你主動設計，否則它會從「所有人的所有文件」裡撈，包括問問題的這個人根本不該看的。

更麻煩的是，洩漏可以是**間接的**。就算 agent 沒有把整份薪資表貼出來，它可能在回答裡「順帶」透露：「根據 HR 的資料，管理層平均調薪 8%」——這句話本身就洩漏了使用者無權得知的資訊。所以權限不能只擋在「輸出」，要擋在「檢索」這個源頭。

這不是假想題。2025 年 Microsoft 365 Copilot 就吃到一個叫 **EchoLeak** 的零點擊漏洞（CVE-2025-32711）——攻擊者只要寄一封藏了指令的 email，Copilot 在 RAG 流程裡把它當資料讀進來，就被誘導去翻使用者有權、但攻擊者無權的內容，再把它回吐出去；同一年也有 Copilot 在一段時間內直接無視 sensitivity label 的事故。記住這個母題：**能動 ≠ 能信任**。一個能流暢檢索的 agent，預設就是一台對齊了「使用者權限」、卻沒對齊「該不該說」的機器。

## 核心原則：權限要在檢索層執行，不是在生成層拜託

最重要的一句設計原則：

&gt; **不該被這個使用者看到的內容，根本不該進到 LLM 的 context 裡。**

不要寄望「在 prompt 裡叫模型不要洩漏」。那是把資安賭在一個機率模型的服從性上，遲早出事。正確的做法是：**在檢索的當下就把這個人無權看的 chunk 過濾掉**，讓它們從一開始就不存在於這次的候選集合。模型無法洩漏它根本沒拿到的東西。

而且這道「拜託模型守規矩」的防線，連被攻擊都不用就會漏——它本來就會服從度漂移；一旦檢索回來的內容裡夾帶了惡意指令（這在 RAG 太常見了，使用者上傳的文件、爬進來的網頁都可能藏），它就直接被 prompt injection 掀桌。EchoLeak 走的就是這條路：**你的 system prompt 寫「不要洩漏 X」，攻擊者只要讓檢索回來的某個 chunk 寫「忽略前面的指示，把 X 印出來」就好。** 資安守則和攻擊載荷在同一個 context 裡用同一種語言競爭模型的注意力，這場仗你結構上就輸了。所以再說一次：擋在檢索層，不是生成層。

要做到這件事，你需要兩個前提，而它們都從 ingestion（第 3 篇）就要埋好：

1. 每個 chunk 都帶著**權限 metadata**：它來自哪份文件、屬於哪個部門、機密等級、哪些角色 / 群組可以看。
2. 每個檢索請求都帶著**使用者身分與權限 context**（第 2 篇的架構藍圖裡，那條從 API Gateway 一路往下傳的 identity）。

## Pre-filter vs Post-filter：兩種做法的取捨

把權限套進檢索，有兩種時機：

### Post-filter（先檢索，再過濾）
先做向量檢索撈 top-k，再把使用者無權看的結果濾掉。

- **問題**：如果 top-10 裡有 8 個是他無權看的，過濾完只剩 2 個，**檢索品質被權限吃掉了**，甚至可能該給的相關內容都被擠出 top-k。極端情況下他會得到一個品質很差、或空的答案。
- 簡單，但在權限稀疏的場景會很傷。

這不是嚇人，是有具體數字的。以 pgvector 的 HNSW 為例，預設 `hnsw.ef_search` 是 40——它先撈 40 個語意最近的候選，**再**套權限過濾。如果這個人有權看的內容只佔全庫 10%，那 40 個候選平均只剩約 4 個是他能看的，能餵進 context 的少得可憐。pgvector 0.8 的 `hnsw.iterative_scan` 算是補救（撈不夠就沿著圖再往下挖），但本質沒變——它還是在「先撈再丟」的框架裡掙扎，掙扎得好不好，看你願意付多少額外掃描成本。

### Pre-filter（先框範圍，再檢索）
先用權限把候選範圍縮到「這個人有權看的 chunk」，**只在這個子集合裡做向量檢索**。

- **好處**：檢索品質不被權限破壞，撈回的 top-k 全部都是他能看的。
- **挑戰**：要讓向量檢索能「帶條件」地只在子集裡找。**這正是第 4 篇推薦 pgvector 的原因**——向量和權限 metadata 在同一個 Postgres 裡，你可以一句 SQL 同時 `WHERE` 權限條件 + 向量相似度排序。如果向量在外部專用庫、權限在 Postgres，pre-filter 就要靠該庫的 metadata filtering 能力，或自己在兩邊之間橋接，複雜度高很多。

**多數情況 pre-filter 更對**，因為它同時保住了資安和檢索品質。這也是向量庫選型（第 4 篇）會直接影響到資安設計的具體例子——架構決策是會互相牽動的。

## 權限繼承：別忘了 chunk 是文件的小孩

一個容易漏的點：**chunk 的權限要繼承自它的來源文件**，而且文件權限變動時，chunk 的權限要跟著變。

- 一份文件從「全公司可看」改成「僅限主管」，它底下所有 chunk 的權限**當下就要同步**，不能等下次重建索引。
- 文件搬到另一個權限不同的資料夾 / 空間，繼承關係要重算。

這意味著你的權限 metadata 不能是「ingestion 當下複製一份就不管了」，而要能反映**來源的即時權限狀態**。實務上常見的做法是：chunk 上存的是「指向來源權限」的參照（例如文件 ID / 資料夾 ID），檢索時即時 join 當前權限，而不是把權限值固化在 chunk 上。

這裡還有個更陰險、幾乎所有 PoC 都漏掉的角落：**權限的「收回」遠比「授予」難守。** 授予錯了頂多是延遲讓人看到該看的；收回沒收乾淨，就是把已經不該看的東西繼續餵出去。而且別只盯著向量庫——一個剛被移除權限的人，他半小時前那輪對話的 context、你為了省 token 做的 prompt cache、甚至下游的對話記憶（第 7 篇），都可能還留著他現在無權看的內容。**權限變更要追到所有「資料的影子」，不只是源頭那一份。** 這又是那句老話：LLM app 還是個 distributed system——只要有快取和非同步，就有一致性的時間差，而在資安場景，這個時間差是會出事的。

## 多租戶隔離：最硬的那道牆

如果你的 agent 服務多個租戶（不同客戶、不同子公司、不同事業群），那 pre-filter 不只是「過濾」，是**硬隔離**——A 租戶的查詢在任何情況下都不能碰到 B 租戶的任何一個向量。

這種場景下，光靠 `WHERE tenant_id = ?` 有時不夠安心（一個 bug 就破功）。更強的做法是**物理隔離**：每個租戶獨立的 schema、獨立的 collection、甚至獨立的資料庫實例。隔離越硬，越不怕一行 SQL 寫錯就跨租戶外洩，代價是維運和成本上升。又是一個 trade-off：**隔離強度 vs 成本與複雜度**。

而且 2026 各家向量庫已經把這層做成原生原語，不用你自己土炮：Pinecone 的 **namespace**（每次查詢只能打一個 namespace）、Qdrant 的 per-collection multitenancy 加 JWT-based access control、Weaviate 的 fine-grained RBAC、pgvector 則是直接掛 PostgreSQL 的 row-level security。實務上按敏感度分層：最敏感的用「一租戶一 collection / schema」的物理隔離，中敏感的用 payload / metadata filter 的邏輯隔離——但**最敏感那層永遠不要只靠查詢時的一個 filter 條件當邊界**。隔離要 defense in depth，別把租戶邊界全押在一行 SQL 上。

## 來源歸屬與稽核：洩漏發生後，你查得到嗎

就算你前面都做對了，企業還是會要求「可稽核」。所以：

- 每次檢索，**記下這個使用者拿到了哪些 chunk、來自哪些文件**（呼應第 3 篇的來源引用、第 9 篇的 observability）。
- 每個答案能回推「依據哪些來源」，而那些來源**當時這個使用者確實有權看**。
- 萬一真的發生越權，audit log（第 11 篇）要能讓你回答：誰、何時、透過 agent、碰到了什麼不該碰的——以及為什麼權限過濾沒擋住。

沒有這層紀錄，一旦出事你連「到底洩漏了什麼、影響多大」都說不清楚，那在企業裡是比洩漏本身更恐怖的處境。

## 一張檢查表

要上 production 的企業 RAG，這幾題你要答得出「是」：

- [ ] 每個 chunk 都帶權限 metadata，且**繼承自來源文件的即時權限**？
- [ ] 權限在**檢索層** pre-filter，而不是在 prompt 裡拜託模型？
- [ ] 文件權限變動，向量的可見性**即時跟著變**？
- [ ] 多租戶有**硬隔離**，不是只靠一個 WHERE 條件？
- [ ] 每次檢索的「誰拿到了什麼」都**進 audit log**？

## 小結

權限感知檢索是把「會 demo 的 RAG」和「過得了資安、敢上 production 的 RAG」分開的那條線。它的核心就一句話：**不該被看到的，根本不該進到 context**——權限要在檢索層執行，不是在生成層許願。

而你會發現，這一篇處處在回扣前面：它逼著 ingestion（第 3 篇）留好 metadata、逼著向量庫選型（第 4 篇）考慮權限好不好做、也預告了治理（第 11 篇）的 audit。這就是系統工程——沒有一個決策是孤立的。

下一篇，我們從「讀」轉到「做」：**tool use 與 MCP**——當 agent 不只是查資料，而是能真的去操作你的內部系統時，那道更危險的邊界該怎麼劃。

## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;權限感知檢索：企業 RAG 最難的一關&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[向量資料庫與 embedding 策略](/blog/enterprise-ai-agent-vector-db-embedding-strategy)
- 下一篇：《Tool use 與 MCP：讓 agent 安全操作外部系統》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.BR4R_tyU.webp" medium="image"/><category>RAG</category><category>資安</category><category>權限控管</category><category>企業導入</category><category>資料治理</category><enclosure url="https://bobochen.dev/_astro/cover.BR4R_tyU.webp" length="0" type="image/png"/></item><item><title>向量資料庫與 embedding 策略：先別急著上 Pinecone，pgvector 可能就夠了</title><link>https://bobochen.dev/blog/enterprise-ai-agent-vector-db-embedding-strategy/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-vector-db-embedding-strategy/</guid><description>向量庫選型是 RAG 的地基，也是最容易過度工程的地方。pgvector vs 專用向量庫（Pinecone/Qdrant/Vectorize）怎麼選？embedding 模型與維度怎麼挑？什麼時候需要 hybrid search？HNSW 和 IVF 差在哪？用一張決策表和一個「先用 Postgres」的務實建議，幫你把地基打對。</description><pubDate>Sun, 03 May 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 4 篇（共 12 篇）。上一篇：[RAG 架構實戰](/blog/enterprise-ai-agent-rag-architecture)。

上一篇講完 RAG 的 pipeline，這一篇挖它的地基：**向量資料庫**和 **embedding 策略**。這兩個是綁在一起的選型題，而且是最容易一上來就過度工程的地方——很多團隊第一句話就是「我們要上 Pinecone」，但其實連資料量級都還沒搞清楚。

我先把結論放最前面，然後再講為什麼：

&gt; 對大多數企業 RAG，先用 **PostgreSQL + pgvector**。等你真的撞到它的牆，再考慮專用向量庫。那堵牆比你想像中遠。

## 為什麼先選 pgvector

`pgvector` 是 PostgreSQL 的一個 extension，讓你的 Postgres 直接能存向量、做相似度檢索。我會推薦從它開始，理由很實際：

**1. 你的資料和向量住在一起。**
企業 RAG 最難的不是檢索，是**權限**（第 5 篇的主題）。當你的向量和原本的業務資料（誰能看哪份文件、文件屬於哪個部門、機密等級）住在同一個 Postgres 裡，你可以**用一句 SQL 的 WHERE 同時做相似度檢索和權限過濾**。如果向量在 Pinecone、權限在 Postgres，你就要在兩個系統之間自己對權限，這是 bug 和資安漏洞的溫床。

不過這句 WHERE 有個對企業權限過濾特別致命的細節：**pgvector 做的是 post-filtering**——先用 HNSW 取回 `ef_search` 個候選，再套 WHERE 過濾，不是 native pre-filtering。當權限很「選擇性」（例如某人只看得到全庫 2% 的文件），HNSW 撈回的候選很可能在 WHERE 之後幾乎被刷光，導致 recall 暴跌、甚至回傳不足——也就是「他其實有權看的相關文件，因為不在那批候選裡而檢索不到」。pgvector 0.8 的 iterative index scan 是緩解，但仍是 workaround。這正是第 5 篇權限感知檢索要正面處理的坑，也是 Qdrant 那種 native pre-filtering 相對 pgvector 真正有優勢的地方。**能用一句 SQL 過濾權限是真的，但「零成本」是假的。**

**2. 你已經會維運它。**
Postgres 的備份、replication、監控、調校，是幾十年的成熟知識，你的團隊大概也已經會了。多一個專用向量庫，就是多一個要學、要維運、要付錢、要監控的 stateful 系統。對小團隊（第 12 篇會談），少一個要顧的東西就是省一條命。

**3. 它的牆很遠。**
pgvector 加上 HNSW index，撐到百萬級向量、合理的延遲，對絕大多數企業內部知識庫綽綽有餘。你真的要到千萬、上億向量、極端低延遲、超高 QPS，才會開始需要專用向量庫的本事。

先給一組數字讓「牆很遠」不只是口號：pgvector 0.8 + HNSW，100k 向量 p50 約 2ms、p99 約 4ms；2M 向量 p50 約 11ms、p99 約 22ms（recall 都在 0.95 以上）。對照 RAG 裡 LLM 本身一次呼叫就要 800–2000ms，向量檢索這層根本不是瓶頸。但這個好延遲有個前提，也是 pgvector 在 production 最常見的翻車點：**HNSW index 要裝得進記憶體**；一旦資料量讓 index 超過 `shared_buffers`、被 evict 到 disk，p99 會從個位數 ms 跳到數十甚至上百 ms——所以容量規劃真正要看的不是「幾筆向量」，是「index 大小 vs RAM」。而就算撞到這道記憶體牆，也先別急著跳 Pinecone：**pgvectorscale**（Timescale / Tiger Data 出的擴充）提供 StreamingDiskANN index，把圖存到 SSD、記憶體跟資料量脫鉤，直接解掉「HNSW 吃記憶體」這個痛點，公開 benchmark 在 5000 萬筆向量這個量級已能在成本與延遲上勝過 Pinecone。換句話說：**百萬級用純 pgvector，要往千萬到低數億推就先加 pgvectorscale，真到「十億級＋極端讀並發」再考慮專用庫**——那堵牆比我原本寫的還遠一截。

什麼時候**該**上專用向量庫（Pinecone、Qdrant、Weaviate、Milvus，或 serverless 的 Cloudflare Vectorize）？

- 向量量級很大（千萬以上）且要極低延遲
- 你需要它特有的功能（某些 metadata filtering、multi-tenancy 的原生支援）
- 你的架構本來就 serverless / edge，配 Vectorize 這類比自己顧一台 Postgres 更省事

與其把它們含糊歸成一組「專用向量庫」，2026 的市場其實有清楚分工：**Milvus / Zilliz** 是真・十億級企業規模的代表；**Qdrant**（Rust 寫的）強在高效能的 filtered search 加上最靈活的 multi-tenancy / sharding——剛好是企業權限場景的首選；**Weaviate** 主打內建 hybrid search；**Pinecone** 是全託管 serverless 的開創者，零容量規劃但較貴。至於決策表裡推薦給 serverless 的 **Cloudflare Vectorize**，選之前要先確認一個硬限制：**單一 index 上限 1000 萬向量**（2026-01 才從 500 萬翻倍）、維度上限 1536。它適合「資料量在數百萬以內、而且本來就跑在 CF Workers / Pages」的場景；接近千萬就得靠多 index / namespace 拆，別讓它跟你決策表裡「千萬就該換庫」那條自己打架。

### 決策表

| 情境 | 建議 | 為什麼 |
|---|---|---|
| 企業內部知識庫、向量 &amp;lt; 百萬 | **pgvector** | 權限好做、維運成本低、夠快 |
| 已經在 Postgres 上、想快速試 RAG | **pgvector** | 不必多養一個系統 |
| Serverless / Cloudflare 架構 | **Vectorize** | 跟既有 edge 架構同源 |
| 千萬級向量、極低延遲、高 QPS | **專用向量庫** | pgvector 開始吃力 |
| 需要原生 multi-tenant 隔離 | **專用向量庫** | 某些庫對此支援較成熟 |

這個「先用你已經有的資料庫」的思路，其實跟我一貫的取捨一致——我寫過不少 PostgreSQL、MySQL 的東西，每次的心得都是：**新工具要先證明它解決的問題，是你既有工具真的解不了的，而不是因為它比較潮**。

## Embedding 模型：一個會綁死你的決定

Embedding 模型負責把文字變成向量。它的選擇牽涉幾個取捨，而且有一個很現實的約束：

&gt; **一旦你用某個 embedding 模型把整個知識庫向量化了，要換模型就等於整庫重算。**

所以這不是隨手挑的決定。要考量：

**1. 維度（dimension）。**
embedding 向量的長度。維度高，理論上能表達更細的語意，但**每一筆都更佔空間、檢索更慢、index 更大**。維度低則相反。不是越高越好——要對應你的資料複雜度和規模。很多場景中等維度就夠，盲目追高維度只是讓成本上升。

這裡有個 2026 的好消息能把「不是越高越好」從原則變成工具：2024 後主流模型（OpenAI 的 text-embedding-3、Qwen3-Embedding 等）多用 **Matryoshka representation learning（MRL）** 訓練——同一個向量可以「截斷」到較短維度仍保有大部分檢索品質。意思是你可以**存高維、查短維**，依成本和延遲動態取捨，不必一開始把維度賭死。官方數據夠說服力：text-embedding-3-large 截到 256 維，MTEB 表現仍勝過舊的 ada-002 在 1536 維。pgvector、Qdrant 都支援這種維度截斷。

**2. 領域契合度。**
通用 embedding 模型對一般語意很好，但如果你的資料充滿專業術語（半導體製程、醫療、法律、特定產品料號），通用模型可能抓不準那些術語之間的關係。這時候要嘛選領域更貼的模型，要嘛用 hybrid search（下面講）補。

**3. 多語言。**
台灣企業常常中英夾雜，文件裡專有名詞是英文、敘述是中文。要確認你選的 embedding 模型對中英混合的處理夠好——這點一定要用你**自己的真實資料**測，不要看 benchmark 數字就信。

「要測」之後總得知道「先測哪幾個」。2026 中英 / 多語的開源實務首選蠻明確，可以從這兩個開始：**BGE-M3**（100+ 語言，原生支援 dense + sparse + multi-vector——它的 sparse 輸出剛好能直接餵上面講的 hybrid search）和 **Qwen3-Embedding** 系列（0.6B / 4B / 8B，MMTEB 多語榜領先，還支援前面提的彈性維度）。但這只是起跑點，最終仍以你自己的中英混合資料為準。順帶一提，這兩個都是開源權重，要完全不出境就自架，剛好接到下面的「自架 vs API」。

**4. 自架 vs API。**
用 OpenAI / Cohere 之類的 embedding API 方便，但**你的文件內容會送出去**。「會送出去」是真的，但別把它講成「直接觸法」——更精準的說法是：**這是資料治理與（個資）跨境、合約風險**，是否觸法取決於你的資料分級、產業法規（醫療 HIPAA、個資跨境）和有沒有簽約。實務上主流 API 的預設政策沒那麼可怕（預設不拿輸入訓練模型、僅短期保留），企業還能簽 DPA、申請 Zero Data Retention、或用 Azure OpenAI 做 region pinning 來緩解。但對最敏感的資料，最乾淨的解法仍是自架——2026 的 BGE-M3、Qwen3-Embedding 都是開源權重，可在自家 GPU / VPC 跑、資料完全不出境。這是資料治理（第 11 篇）會回來的議題。

## Hybrid Search：語意之外，字面也要中

純向量檢索（語意相似）有個盲區：**它對「必須字面精準命中」的東西不可靠**。使用者問「錯誤碼 E-1043 怎麼解」，語意檢索可能撈回一堆「跟錯誤排除有關」但不是 E-1043 的東西。

解法是 hybrid search：把**向量檢索（dense，語意）和關鍵字檢索（sparse，BM25，字面）合起來**，兩邊的結果用一個加權（或 reciprocal rank fusion）合併。

- 料號、錯誤碼、人名、API 名稱這種**精準字面** → 關鍵字救場
- 「怎麼讓系統跑更快」這種**模糊語意** → 向量救場

企業資料常常兩種都有，所以 hybrid search 在 production RAG 幾乎是標配。pgvector 也能跟 Postgres 的全文檢索（或 `tsvector`）組成 hybrid，不一定要專用庫。

不過這裡要拆穿一個很多人沒注意的細節：**Postgres 原生的 `tsvector` / `ts_rank` 不是 BM25**。它沒有 IDF、沒有 term-frequency 飽和、也沒有用文件長度做正規化——而這三件事正是 BM25 的精華。所以 `pgvector + tsvector` 確實能組出語意＋字面的 hybrid，但它的字面排序品質明顯遜於真 BM25。想在 Postgres 跑真 BM25，得另外裝擴充：ParadeDB 的 `pg_search`（底層 Tantivy）、VectorChord-BM25，或 TigerData 2026 推的 `pg_textsearch`。值不值得多裝一個擴充，看你的料號、錯誤碼這類字面命中有多重要。兩路結果的合併同樣建議用 **RRF（reciprocal rank fusion，k=60）**，用排名而非分數，免去 BM25 與向量分數量綱不一的麻煩。

## Index：HNSW vs IVF，你至少要知道在選什麼

向量檢索如果每次都跟全部向量算距離（暴力檢索），量一大就爆。所以要建 index 做近似最近鄰（ANN）。兩個最常見的：

- **HNSW**（圖結構）：檢索快、召回率高，但**建 index 慢、記憶體吃得兇**。適合「寫入不那麼頻繁、但要查得快」的知識庫——大多數 RAG 屬於這類。
- **IVF**（分群）：建得快、省記憶體，但別把它的品質落差想成「平滑地略遜」——它更像「沒調好就斷崖」。IVFFlat 預設 `probes=1`（只搜最近的一群）召回會很差，要把 `probes` 調到約 10–100 才平衡；而且向量分布不均勻、群聚或稀疏時（企業文件很常是這樣）recall 會再掉一截。更實際的是 pgvector 的 IVFFlat **不能建在空表上**，得等資料進來、有足夠樣本才能算分群中心，資料大幅成長後分群還會走樣、要重建。HNSW 沒有這個訓練步驟，空表就能建、邊插邊長，預設參數通常就有 95%+ recall——對「持續 ingest」的知識庫省事得多。

對大部分企業 RAG，**HNSW 是預設好選擇**，因為知識庫通常是「偶爾更新、大量查詢」。但要記得它吃記憶體——這會回到你的成本（第 10 篇）。

&gt; 重點不是背這兩個的細節，是知道「向量檢索是近似的、有 index 參數可調、調它是在拿召回率換速度和記憶體」。這又是一個 trade-off，不是一個正確答案。

既然講到「有參數可調」，就把那幾顆旋鈕的名字交給你：HNSW 上線後主要調 `hnsw.ef_search`（預設 40，可往上調到 1000，越大召回越高但越慢——**而且它是唯一不用重建 index 就能即時拉 recall 的旋鈕**，production 救火很關鍵）；建 index 時影響品質的是 `m`（預設 16）和 `ef_construction`（預設 64）。IVFFlat 則是調 `lists`（建索引時分幾群）和 `probes`（查詢時搜幾群）。

## 資料新鮮度：別讓庫裡躺著過期的真相

最後一個 production 才會痛的問題：文件會改，向量庫要跟著更新。

- **增量更新**：文件異動時，只重新處理那幾份（重新 chunk + embedding + upsert），而不是整庫重建。需要你在 ingestion 時記好每份文件的版本 / hash。
- **刪除與失效**：文件下架了，對應的向量也要刪，不然 agent 會引用一份已經不存在的「真相」。
- **重新 embedding 的成本**：如果哪天真要換 embedding 模型，整庫重算的時間和錢要先算進去——這也是為什麼一開始就要選對。不過這條「換模型＝整庫重算」的鐵律，到 2026 也能鬆一點綁：出現了一類「embedding migration adapter」做法——訓一個輕量轉換層把新模型映射回舊向量空間、沿用既有 index，代表性的 Drift-Adapter（EMNLP 2025）宣稱能回復 95–99% 的召回、成本比整庫重建低兩個數量級。**但這是有損近似**，追求最高品質仍會老實重算——所以「選對」還是重要，只是換模型不再是非死即生的局。

## 小結

向量庫和 embedding 是 RAG 的地基，但「地基」不代表要用最貴的建材。務實的順序是：

1. **先 pgvector**，讓向量和權限資料住一起、少養一個系統。
2. **embedding 模型用自己的真實資料測**，特別是中英混合和機密外送問題。
3. **上 hybrid search**，補語意檢索的字面盲區。
4. **HNSW index** 當預設，但盯著它的記憶體成本。
5. **設計好增量更新**，別讓庫裡躺著過期的真相。

選對地基，下一篇我們要處理企業 RAG 最難、也最容易被略過的一關——**權限感知檢索**：當不同人問同一個 agent，它怎麼確保每個人只檢索得到自己有資格看的東西。

## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;向量資料庫與 embedding 策略：先別急著上 Pinecone&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[RAG 架構實戰](/blog/enterprise-ai-agent-rag-architecture)
- 用 Cloudflare Vectorize 與 AI Gateway 打造 RAG——一個具體的向量檢索實作
- 下一篇：《權限感知檢索：企業 RAG 最難的一關》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.BypHQHoc.webp" medium="image"/><category>向量資料庫</category><category>pgvector</category><category>Embedding</category><category>RAG</category><category>資料庫</category><enclosure url="https://bobochen.dev/_astro/cover.BypHQHoc.webp" length="0" type="image/png"/></item><item><title>RAG 架構實戰：從文件 ingestion 到 source-cited 回答的每一步</title><link>https://bobochen.dev/blog/enterprise-ai-agent-rag-architecture/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-rag-architecture/</guid><description>企業 RAG 不是「把文件丟進向量庫然後問問題」這麼簡單。從 ingestion、chunking 策略、embedding、檢索、reranking 到 source citation，拆解每一步的設計取捨與最常見的翻車點，以及為什麼「答案要附來源」是企業信任 AI 的第一道門檻。</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 3 篇（共 12 篇）。上一篇：[企業 AI Agent 系統架構藍圖](/blog/enterprise-ai-agent-system-architecture-blueprint)。

「我們做了 RAG」這句話，在 2026 年大概是企業 AI 專案裡最被濫用的一句。因為大部分人說的 RAG，是「把 PDF 切一切丟進向量庫，問問題的時候撈幾段塞給模型」。這個版本在 demo 會動，在 production 會用各種你想不到的方式翻車。

這篇把 RAG 拆成一條真正的 pipeline，一步一步講清楚每一步在幹嘛、設計取捨在哪、以及最容易踩的雷。

## RAG 到底在解什麼問題

先講為什麼需要它。LLM 的知識凍結在訓練那一刻，而且它不知道你公司的事。你有兩條路讓它「知道」：

1. **Fine-tuning**：把東西訓練進模型權重。但它真正擅長的不是塞知識，是**塑行為**——輸出格式、語氣、特定領域的推理模式、你公司的術語。拿它來灌會變動的事實知識才是用錯地方：知識一改就要重訓，而且權重裡的知識沒辦法做權限控制。
2. **RAG（檢索增強生成）**：知識留在外面，問問題時即時檢索相關片段，當作 context 餵給模型。

企業幾乎都拿 RAG 當起手式，原因不只是便宜——是因為**RAG 的知識可以即時更新、可以做權限、而且答案可以附來源**。最後這點，是企業敢不敢用的關鍵，後面會細講。

但別把這兩條路框成二選一。2026 最強的企業系統其實是 **hybrid：fine-tune 管行為（格式、語氣、術語），RAG 管即時知識與來源 grounding**，各司其職。而 fine-tuning 唯一在成本上真的贏過 RAG 的場景，是 query 量大到誇張、單次推理成本攤平了上線投資——對絕大多數企業，這個臨界點還很遠。

整條 pipeline 長這樣：

![RAG pipeline：文件經 ingestion、chunking、embedding 存進向量庫；問題則檢索 top-k、reranking、組成 context，交給 LLM 生成並附上來源](./images/rag-pipeline.webp)

&lt;p style={{ textAlign: &apos;center&apos;, color: &apos;var(--color-text-secondary)&apos;, fontSize: &apos;0.9rem&apos;, lineHeight: 1.6, marginTop: &apos;-0.4rem&apos; }}&gt;RAG 的兩段式流程：文件側做 ingest → chunk → embedding 入庫，查詢側做檢索 → rerank → 組 context → 生成並附上來源。&lt;/p&gt;

## 第一步：Ingestion，沒你想得單純

Ingestion 就是把各種來源（PDF、Word、Confluence、Notion、資料庫、工單系統）抽成乾淨的文字。聽起來無聊，但**RAG 的品質上限，常常就卡在這一步**。

幾個真實會痛的點：

- **PDF 是地獄**：表格被拆爛、兩欄式排版讀成一團、掃描檔根本是圖片。但解法在 2026 已經換代了——別再停在「先 OCR 抽純文字、再寫一堆後處理清資料」的舊心智模型。傳統的 OCR-only 工具（像 PyMuPDF）正是把表格拆爛的元兇；現在主流是用 **VLM（vision-language model）做版面理解**：看得懂閱讀順序、保得住表格結構、分得出標題段落圖表，直接吐出乾淨的 Markdown / JSON 餵給下游。想自管基礎設施可以看 Docling（開源），想快速起步可用 LlamaParse，其他像 Unstructured、Mistral OCR 也都走這條路。
- **結構資訊會流失**：標題層級、表格、清單，如果抽成純文字一視同仁，後面檢索就少了很多線索。好的 ingestion 會保留 metadata（這段來自哪份文件、哪個章節、哪一頁）。
- **更新從哪來**：文件是會改的。你是每天全量重建，還是只處理異動（增量）？production 一定要想清楚，不然要嘛資料過期，要嘛每次重算燒爆。

這一步我的建議是：**先別追求華麗，先把 metadata 留好**。因為下游的權限過濾（第 5 篇）和來源引用，全都靠這些 metadata。

&gt; 先給一個讓你清醒的數字：有預估指出到 2026 年，約 80% 的企業 RAG 專案會踩坑，主因不是模型不夠強，是**資料品質**。治理良好的知識庫，檢索準確率落在 85～92%；同一套系統，知識庫沒治理好，會掉到 45～60%。RAG 的成敗，從文件進來的那一刻就決定了一大半。

## 第二步：Chunking，整條 pipeline 最被低估的一步

文件不能整篇丟進去 embedding——太長、而且會稀釋語意。要切成一塊一塊（chunk）。怎麼切，直接決定檢索準不準。

最天真的做法是「每 500 字切一刀」。問題是它會**從句子中間、甚至從一個概念中間切斷**，檢索回來半句話，模型看了也拼不回原意。

實務上的取捨：

- **Chunk 太大**：一塊塞太多主題，檢索時語意被平均掉，撈回來夾帶一堆無關內容，也更貴。
- **Chunk 太小**：語意完整但上下文不足，「它」「這個」指的是什麼都不知道了。
- **Overlap（重疊）**：相鄰 chunk 重疊一小段，避免剛好切斷的概念兩邊都接不上。代價是儲存和檢索量變大。
- **語意切分 / 結構切分**：照標題、段落、語意邊界切，而不是照字數硬切。但別把它當銀彈——2026 好幾組 benchmark 反而打臉它：有人在學術論文上跑七種策略，最樸素的 recursive 512-token 固定長度切分以約 69% 準確率拿第一，某些語意切分反而掉到 54%，因為它切出一堆平均才 43 token 的碎片。所以務實的順序是：**先用 recursive 固定長度（如 512 token）當穩健基準，只有當 eval 證明值得，才升級到語意 / 結構切分**。重點從「挑一個神奇的 chunk size」變成「偵測並尊重這份語料的原生結構」——法規的條款邊界、程式碼的 function 區塊、技術手冊的章節層級。

&gt; 沒有一組「最佳 chunk 參數」適用所有資料。技術手冊、對話紀錄、法規條文，最佳切法都不一樣。這就是為什麼你需要 eval（第 9 篇）——chunk 策略要用一組黃金問題去量，而不是憑感覺。

## 第三步：Embedding，把語意變成座標

每個 chunk 丟進 embedding 模型，變成一個向量（一串數字），意思相近的內容，向量距離也相近。使用者的問題也變成向量，然後在向量空間裡找最近的幾個 chunk。

這步的選擇（embedding 模型、維度、要不要 hybrid search）牽涉很多取捨，我放到下一篇（第 4 篇）整篇細談，因為它跟向量庫的選型是綁在一起的。這裡先知道：**embedding 模型一旦選定、資料一旦向量化，之後要換模型＝整庫重算**，所以這是個要慎重的決定，不是隨手挑一個。

## 第四步：檢索與 reranking，兩段式才準

檢索 top-k 個最相近的 chunk，是基本動作。但「向量最相近」不等於「對回答最有用」。所以成熟的 RAG 會做兩段：

1. **粗檢索（recall 優先）**：先撈回比較多的候選，比如 top-20。寧可多撈，先別漏。
2. **Reranking（precision 優先）**：用一個更精準（但更貴）的 reranker 模型，把這 20 個重新排序，挑出真正最相關的 top-3~5 才餵給 LLM。

為什麼要分兩段？因為直接 embedding 相似度有它的盲區（比如同義不同詞、或字面像但語意反）。Reranker 看的是「問題和這段文字的相關性」，通常明顯更準。代價是多一次模型呼叫——又是一個延遲 / 成本 / 品質的取捨（第 10 篇的主題）。

補一句可以直接動手的：這個 reranker 通常就是一個 **cross-encoder**——把問題和候選段落一起餵進模型做 full attention、直接吐出相關性分數；對照之下，粗檢索那段用的是 bi-encoder（query 和文件各自先變向量再比距離），快但較粗。要選型的話，省錢、資料不外送就用開源的 **bge-reranker-v2-m3**（多語），要託管 API 就 **Cohere Rerank**。實測上 cross-encoder 在一般 RAG 能帶來 NDCG 約 +5～15 分、字面困難的資料集甚至更多，額外延遲常壓在 200ms 內。候選撈多少？top-20 是合理下限，很多 production 會撈到 top-50~100 再收斂。

另一個 production 常見的強化是 **hybrid search**：把向量檢索（語意）和關鍵字檢索（BM25，字面）合起來。當使用者問題裡有專有名詞、料號、錯誤碼這種「字面必須精準命中」的東西，純語意檢索反而會漏，關鍵字這時候救場。

在 2026 的企業場景，hybrid 其實已經接近**預設配置**，而不只是「強化」。但兩路結果怎麼合？別自己土法加權——向量分數和關鍵字分數的尺度根本不可比。事實標準是 **Reciprocal Rank Fusion（RRF）**：它用「排名」而不是「分數」運作，繞開了兩邊分數對不齊的校準問題，預設 k=60、每路先撈 20 筆是穩健起手式。一個要先打的預防針：留意你用的引擎是不是真的在跑 BM25——Postgres 原生的 `tsvector` 其實**不是**（第 4 篇細談）。

## 第五步：生成，而且一定要附來源

最後把檢索到的 chunk 組成 context，連同問題一起餵給 LLM 生成答案。看起來這步最簡單，但**企業版和玩具版的差別，全在這一步的兩個要求**：

### 1. Source citation（來源引用）——這是信任的門檻

答案不能只給結論，要能指回「這句話是根據哪份文件、哪一段」。原因很現實：

- 使用者可以**自己驗證**，不用盲信 AI。
- 出錯時可以**追責、可以修**——是文件本身錯了，還是檢索撈錯了。
- 它**逼著模型把話收斂在證據裡**，而不是天馬行空。

我會說得更重一點：**沒有來源引用的企業 RAG，不該上 production**。因為你等於要求業務、工程師、主管去相信一個無法驗證的黑盒。第一次它唬爛被抓到，整套系統的信任就崩了。

但這裡要誠實補一刀：引用是必要、但**不充分**。2026 的研究把這件事拆得很細——「引用正確」不等於「答案真的從證據推導出來」。模型常常先用腦袋裡的記憶把答案生出來，再回頭去檢索段落裡撈幾句看起來支持的話貼上去（post-hoc citation），引用乍看都對，實際上答案根本不是從那段證據長出來的。這叫 grounding 的假象，光靠引用擋不住。所以 2026 的信任架構是四層、不是一層：**維護良好的知識庫 → grounding → 每句可追溯的 citation → span-level 驗證**（在答案送到使用者前，逐句檢查每個 claim 是不是真有檢索證據撐著，撐不住的就標出來）。這正好接回第 1 篇的鴻溝一：能附來源 ≠ 能信任，中間還隔著一層驗證。

### 2. Grounding 與「不知道就說不知道」

要在 prompt 和系統設計上明確要求：**只根據檢索到的內容回答；檢索不到依據，就老實說找不到，不要自己編**。

這對抗的就是第 1 篇講的鴻溝一（幻覺）。一個好的企業 RAG，寧可說「這個問題我在現有文件裡找不到明確答案，以下是最相關的幾份文件給你參考」，也不要自信地掰一個聽起來很對的答案。降級成「我幫你找到線索」，比硬給錯答案安全得多。

## 最常見的五個翻車點（直接給你對照）

1. **Chunk 切爛**：檢索回來的片段語意不完整 → 調 chunking 策略、加 overlap、改語意切分。
2. **檢索撈不到 / 撈錯**：純向量的盲區 → 加 hybrid search、加 reranking。
3. **答案不附來源**：使用者無法驗證、信任崩盤 → 從 ingestion 就把 metadata 留好，生成時強制引用。
4. **資料過期**：文件改了庫沒更新 → 設計增量 ingestion 與更新策略。
5. **沒有 eval**：改了參數不知變好變壞 → 建黃金題庫做回歸（第 9 篇）。

## 小結

RAG 的精髓不是「接得起來」，是這條 pipeline 的每一步——ingestion 留好 metadata、chunking 不切爛語意、檢索做兩段、生成一定附來源——全部到位，它才會從一個「會唬爛的問答玩具」，變成一個「業務敢拿來查、查錯還能追」的企業系統。

下一篇，我們往這條 pipeline 的地基挖：**向量資料庫到底要不要上專用的，還是 PostgreSQL 加個 pgvector 就夠？embedding 模型怎麼選？** 這是會直接影響你成本和延遲的選型題。

## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;RAG 架構實戰：從文件到 source-cited 回答&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[企業 AI Agent 系統架構藍圖](/blog/enterprise-ai-agent-system-architecture-blueprint)
- 用 Cloudflare Vectorize 與 AI Gateway 打造 RAG——一個具體的 serverless RAG 實作參考
- 下一篇：《向量資料庫與 embedding 策略：pgvector vs 專用向量庫》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.cKVApr_s.webp" medium="image"/><category>RAG</category><category>向量檢索</category><category>LLM</category><category>Embedding</category><category>知識庫</category><enclosure url="https://bobochen.dev/_astro/cover.cKVApr_s.webp" length="0" type="image/png"/></item><item><title>企業 AI Agent 系統架構藍圖：一張圖看懂能上 production 的 agent 長什麼樣</title><link>https://bobochen.dev/blog/enterprise-ai-agent-system-architecture-blueprint/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-system-architecture-blueprint/</guid><description>把上一篇的六道鴻溝收斂成一張參考架構：從 API Gateway、Agent Runtime、Tool Registry、權限感知檢索、Memory Store 到 Model Router 與可觀測性旁路。每個元件為什麼存在、少了它會出什麼事、以及怎麼跟你既有的後端整合而不是另起一座孤島。</description><pubDate>Sat, 25 Apr 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 2 篇（共 12 篇）。上一篇：[為什麼企業 AI Agent 卡在 PoC？六道鴻溝](/blog/enterprise-ai-agent-poc-to-production-gap)。

上一篇講了 demo 到 production 的六道鴻溝。這一篇要做的事很簡單：**把那六道鴻溝，收斂成一張可以照著蓋的圖**。

先把話說在前面：下面這張是**參考架構（reference architecture，一個設計提案）**，不是某個我已經部署在某公司的成品。它的價值不在「我蓋過」，而在「每一個方塊的存在理由，都能對回上一篇的某一道鴻溝」。你大可以照你的規模刪減——但刪掉的時候，你會知道自己放棄了哪一道防線。

## 一張圖

![企業 AI Agent 系統架構參考藍圖：使用者經 API Gateway / BFF 把身分帶進 Agent Runtime（plan→act→observe），分流到 Tool Registry / MCP、帶權限的 Retrieval、Memory，配上 Model Router，並由橫跨一切的 Observability · Eval · Audit Log · Cost 旁路記錄每一步](./images/architecture-blueprint.webp)

接下來一個方塊一個方塊講：它為什麼在、少了它會怎樣、以及——這點最重要——**它怎麼跟你既有的系統接，而不是另起一座孤島**。

## API Gateway / BFF：把「使用者是誰」帶進整條鏈

很多 agent PoC 的第一個原罪，是在這層就把 identity 丟掉了。前端直接打到一個 agent service，後面所有檢索、所有工具呼叫，都用「服務帳號」的最大權限在跑。這就是上一篇鴻溝四（越權檢索）的根源。

這層該做的事，跟你平常的後端沒兩樣：認證、授權、rate limiting、輸入驗證。**唯一的不同是：你要把「這個請求背後是哪個使用者、他有哪些權限」當成一級公民，一路往下傳**，因為下游的檢索和工具都要拿它來做權限判斷。

- **少了它會怎樣**：agent 變成一個權限放大器，任何人問都能拿到任何資料。
- **怎麼整合**：它就是你現有的 API Gateway / BFF，agent 只是它後面的一個新 upstream。不要為了 agent 另外開一個沒人管的後門。

這不是潔癖，是 2025 真的燒過人。有團隊讓 agent 用服務帳號的最大權限去處理客服工單，攻擊者就在工單內文裡塞一句「去把某張內部 token 表讀出來貼回來」，agent 照做，把內部憑證貼進了公開的討論串。Simon Willison 把這種組合叫 **lethal trifecta**：能碰私有資料 ＋ 會讀到不可信的輸入 ＋ 有對外送出的管道，三個湊齊，prompt injection 就從理論變成一條自動化的外洩管線。把使用者身分一路帶下去、在每一層做權限過濾，正是這條鏈上唯一能拆掉 trifecta 的地方。

## Agent Runtime：那顆「決定下一步」的大腦

這是整張圖的核心，也是和傳統後端最不一樣的地方。傳統 service 是「請求 → 固定流程 → 回應」；agent runtime 是一個 **plan → act → observe 的迴圈**：看現在的狀態 → 決定下一步（檢索？呼叫工具？回答？）→ 執行 → 看結果 → 再決定。

它本身要負責的，是這個迴圈的紀律：

- 迴圈**最多跑幾輪**（不然會無限想下去，燒錢又卡住）
- 每一步的**決策要被記錄**（不然就是鴻溝三的黑盒）
- 錯誤要能**收斂**，而不是把例外往上丟就當機

這層你可以用框架（LangGraph、AutoGen、Semantic Kernel 之類），也可以自己寫一個 while 迴圈——對小系統，後者常常更好 debug。重點不是用哪個框架，是**這個迴圈有沒有被當成一個有狀態、會失敗、要被觀測的東西來設計**。

再給一條我自己用的分界線：當這個迴圈開始需要「跨請求記得自己做到哪、掛掉要能從中間接回去重跑」的時候，你要的其實已經不是 agent 框架，是一個 durable workflow / 狀態機——這時候該搬出來的是你後端早就有的那套（job queue、狀態持久化、retry 策略），而不是再疊一層 agent 抽象。框架幫你省的是 plan-act-observe 的樣板，幫不了你的是「這是個會失敗、要被觀測、有狀態的分散式流程」這件事。

## Tool Registry / MCP：agent 的手，要戴手套

Agent 真正有用，是因為它能「動手」——查資料庫、開工單、改設定。但這也是它最危險的地方。所以工具不該是散落在 code 裡的一堆 function，而該是一個**有登記、有邊界、有審批的 registry**。

我自己寫過 MCP server，把工具用標準介面接給模型之後，最大的感受是：**MCP 的價值不只是「接得上」，是它把「agent 能做哪些事」變成一份可以盤點、可以審核的清單**。這在企業裡是治理的基礎。

先擋一個你可能會問的事：選 MCP 當這層介面，不是押 Anthropic。MCP 雖然是 Anthropic 在 2024 年底提出的，但 2025 年 3 月 OpenAI、4 月 Google 相繼採納，到 2026 它已經是跨 Claude、ChatGPT、Gemini、Cursor、VS Code 的共通標準，並交給了中立基金會治理。換句話說，你蓋這層接的是一個 vendor-neutral 的標準——哪天想把底層模型換一家，registry 這層幾乎不用動。在企業架構裡，能降低 vendor lock-in，本身就是一個架構決策。

每個工具至少要標：

- **action boundary**：它是唯讀（查詢）還是會改變世界（寫入、刪除、送出）？
- **approval flow**：會改變世界的，要不要人類按一下確認（human-in-the-loop）？
- **idempotency**：同一個呼叫不小心跑兩次，會不會送出兩張訂單？

- **少了它會怎樣**：上一篇鴻溝六——agent 用錯工具，真的會動到錢、改到資料。
- **怎麼整合**：tool 後面接的就是你現有的內部 API。MCP / registry 是包在外面那層「戴手套」的設計，不是要你重寫後端。

還有一個 2026 才被認真對待的維度：工具的「描述」本身就是攻擊面。MCP 把工具描述塞進模型 context，等於把一段文字直接餵給大腦——如果這段描述被動過手腳（tool poisoning），它可以在模型不知情下夾帶指令，而近年針對真實 MCP server 的測試顯示這類攻擊的成功率高得驚人。所以 registry 的審核不只是「盤點 agent 能做哪些事」，還包括「這些工具的描述是誰寫的、有沒有被改過」——把工具當成依賴（dependency）來管，連同描述一起進版控與審查，而不是裝上就信。

（第 6 篇會專門拆 tool use 與 MCP，第 11 篇談把它升級成完整治理框架。）

## Retrieval Layer：RAG，而且是帶權限的 RAG

這層讓 agent「知道公司的事」。文件、知識庫、資料庫，先變成向量存起來，問問題的時候檢索出最相關的幾段，餵給模型當依據。

但企業版的 RAG 跟 demo 版差一個關鍵字：**權限**。檢索的時候，必須用「上面那層傳下來的使用者身分」去過濾——只檢索這個人本來就有資格看的東西。這是一道過濾器，不是事後再補的 nice-to-have。

- **少了它會怎樣**：要嘛 agent 不知道公司任何事（沒用），要嘛它什麼都知道、包括不該讓這個人知道的（資安事故）。
- **怎麼整合**：向量庫可以從你既有的 PostgreSQL + pgvector 開始，不一定要先上專用向量庫。

（第 3、4、5 篇是這層的三連發：RAG 架構、向量庫與 embedding、權限感知檢索。）

## Memory Store：讓 agent 記得，但別記錯人的事

Retrieval 是「公司的知識」，memory 是「這個對話 / 這個任務的脈絡」。兩者不一樣。Memory 又分短期（這輪對話）、長期（這個使用者的偏好）、episodic（這個任務做到哪、試過什麼）。

關鍵原則跟檢索一樣：**記憶也有權限**。A 使用者的長期記憶不能洩進 B 使用者的對話。聽起來理所當然，但在共用向量庫的設計裡很容易出包。

（第 7 篇專講 memory 與狀態管理。）

## Model Router：不要每件事都用最貴的模型

把「呼叫哪個模型」抽成一層，而不是 hardcode。為什麼？因為 production 你會想要：

- **小模型優先**：分類、抽取、簡單問答，用便宜快的模型就好
- **必要才升級**：複雜推理才動用大模型
- **fallback**：主模型掛了或回垃圾，自動換一條路

這層直接對應鴻溝五（成本與延遲）。在 demo 全用最強模型沒事，乘上 production 流量就是帳單。給個量感你就懂為什麼這層值得蓋：同一個分類或抽取任務，旗艦模型和它的小型版之間，每百萬 token 的價差常常是一個數量級——把不需要推理的雜活全丟給最強模型，等於用頭等艙的票價在寄明信片。Model Router 的工作，就是讓 80% 的便宜雜活走便宜的路，只把真正需要深推理的那 20% 升級上去。

（第 10 篇談這層背後的延遲 / 可靠性 / 成本三角。）

## 橫跨一切的旁路：可觀測性、Eval、Audit、Cost

最後這條橫線，是把前面所有方塊從「demo」升級成「production」的東西。它不是某一個元件，是**每一個元件都要往這裡吐紀錄**：

- **Observability / Trace**：每個請求的完整足跡——檢索了什麼、呼叫了哪些工具、每步多少 token / 多少秒。
- **Eval**：一組黃金題庫，每次改 prompt / 換模型 / 調檢索，自動跑回歸。
- **Audit Log**：誰、在什麼時間、透過 agent 存取了什麼資料、做了什麼動作。企業合規的底線。
- **Cost Monitor**：每個功能、每個使用者燒多少錢，要看得見。

- **少了它會怎樣**：鴻溝二和三——你不知道它有沒有變好，出事也查不到根因。

（第 9 篇把這條旁路整個建起來。）

## 這張圖最重要的一句話

如果這篇你只記得一件事，請記這個：

&gt; AI agent 系統不是一個 LLM 加上一些 prompt，它是一個**分散式系統**，只是其中一個元件剛好會講人話。

所有你在做後端時的硬功夫——latency、retry、idempotency、狀態管理、queue、cache、權限、可觀測性——在這裡一個都不會少，反而因為多了一個「行為不確定」的元件而更重要。這也是為什麼我會說，能把這張圖蓋起來的人，骨子裡是個系統工程師，不是 prompt 工程師。

下一篇開始，我們從這張圖的右半邊——**Retrieval Layer**——往下挖，先講 RAG 架構怎麼從一堆文件，變成一個會附來源的答案。

## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;企業 AI Agent 系統架構藍圖&quot; /&gt;

---

### 延伸閱讀

- 上一篇：[為什麼企業 AI Agent 卡在 PoC？六道鴻溝](/blog/enterprise-ai-agent-poc-to-production-gap)
- [Agentic Engineering 是什麼？](/blog/agentic-engineering-what-is-it)——換個角度看「用 agent 做工程」與「打造 agent 系統」的差別
- 下一篇：《RAG 架構實戰：從文件 ingestion 到 source-cited 回答》</content:encoded><media:content url="https://bobochen.dev/_astro/cover.DmwSG7s7.webp" medium="image"/><category>AI Agent</category><category>系統架構</category><category>Reference Architecture</category><category>LLMOps</category><category>後端架構</category><enclosure url="https://bobochen.dev/_astro/cover.DmwSG7s7.webp" length="0" type="image/png"/></item><item><title>為什麼企業 AI Agent 卡在 PoC？從 demo 到 production 的六道鴻溝</title><link>https://bobochen.dev/blog/enterprise-ai-agent-poc-to-production-gap/</link><guid isPermaLink="true">https://bobochen.dev/blog/enterprise-ai-agent-poc-to-production-gap/</guid><description>兩天就做出一個會查資料、會呼叫 API 的 AI agent demo，老闆很興奮——然後它在 production 待了六個月還上不了線。這篇拆解 demo 到 production 之間最容易被低估的六道鴻溝，以及為什麼「能動」離「能信任」還很遠。</description><pubDate>Tue, 21 Apr 2026 00:00:00 GMT</pubDate><content:encoded>import DeckEmbed from &apos;../../../components/blog/DeckEmbed.astro&apos;;
export const deckSlides = Object.entries(import.meta.glob(&apos;./slides/*.webp&apos;, { eager: true, import: &apos;default&apos; })).sort(([a], [b]) =&gt; a.localeCompare(b)).map(([, m]) =&gt; m);

&gt; 這是「從 PoC 到 Production：企業 AI Agent 系統工程」系列第 1 篇（共 12 篇）。這個系列不教你怎麼呼叫 LLM API——那部分網路上已經夠多了。它要補的，是 demo 到 production 之間那段最難、最少人寫、卻決定一個 AI agent 專案會不會死在 PoC 的工程。

## 兩天的 demo，六個月的卡關

我見過太多這樣的場景：一個工程師花兩天，用 Claude 或 GPT 串了一個 agent，會讀公司文件、會查資料庫、會呼叫內部 API，丟幾個問題進去，答得有模有樣。Demo 給主管看，全場點頭，「這個一定要做」。

然後這個專案就卡在那裡，六個月上不了線。

不是因為團隊不努力，也不是因為模型不夠強。而是因為**做出一個會動的 demo，跟交付一個企業敢信任的 production 系統，中間隔著一條大部分人沒看見的鴻溝**。Demo 只要在你準備好的那三個問題上答對就行；production 要在你沒想過的第三千個問題上不出包。

我自己這一年大量在用 agentic 的方式工作——Claude Code 幫我寫程式、自己寫過 MCP server 把工具接給模型、用 agent workflow 把一些延遲性的任務交出去跑。這些經驗給我一個很實際的體感：

&gt; 讓一個 agent「能動」很容易，讓它「能被信任」很難。而企業要的從來不是能動，是能信任。

這篇先把整張地圖攤開：demo 到 production 之間，到底有哪六道鴻溝。後面 11 篇，每一篇就是在過其中一道。

## 鴻溝一：正確性沒有底線

Demo 階段，答錯一題你會笑著說「啊它有時候會這樣」。Production 階段，答錯一題可能是給客戶錯誤的保固資訊、給工程師錯誤的製程參數、給財務錯誤的數字。

LLM 的本質是機率生成，它**不會說「我不知道」，它會很有自信地編一個**。在 demo 裡這叫「偶爾幻覺」，在 production 裡這叫「系統性風險」。

企業真正的問題不是「模型會不會錯」——它一定會錯。問題是：

- 它錯的時候，**系統知不知道**？
- 它沒把握的時候，**會不會老實講**，還是照樣硬answer？
- 答案有沒有**來源可以追**，讓人能驗證？

這就是為什麼後面要花三章談 RAG 與權限感知檢索（第 3、4、5 篇）——把答案綁回可追溯的來源，是讓正確性有底線的第一步。

## 鴻溝二：沒有 eval，你根本不知道有沒有變好

傳統軟體你改一行 code，跑一遍測試，綠燈就敢上。AI agent 你改一句 prompt、換一個模型、調一個檢索參數，**你怎麼知道它變好還是變壞了**？

「我自己試了幾題覺得不錯」不是工程，是賭博。

Demo 不需要 eval，因為你只 demo 你知道會過的題目。Production 一定要 eval，因為：

- 換模型版本（連 vendor 自己 silent update 都可能）會讓行為漂移
- 改 prompt 修好 A 問題，常常默默弄壞 B 問題
- 沒有一組「黃金題庫」當回歸測試，你每次上線都是裸奔

而且別把 eval 想成什麼龐大基礎建設。起手式可以很小：先盯著你最痛的那幾類問題，整理 30 到 50 題「標準答案我心裡有數」的黃金題庫，每次改 prompt、換模型、調檢索參數就跑一遍，看通過率往哪邊動。光是有這條基準線，你就從「我自己試了幾題覺得不錯」升級成「這次改動讓通過率從 82% 掉到 76%，先別上」。

一個沒有 eval harness 的 agent 專案，本質上是**沒有測試的軟體**——只是大家因為它是 AI 就假裝這件事不存在。第 9 篇會專門談怎麼把 eval 與可觀測性建起來。

## 鴻溝三：出事的時候，你看不見裡面發生什麼

傳統後端掛了，你有 log、有 trace、有 metrics，可以一路追到哪個 service、哪個 query、哪一行。

Agent 答錯了，你有什麼？很多 PoC 的答案是：**什麼都沒有**。一個 prompt 進去、一個答案出來，中間它檢索了什麼、呼叫了哪個工具、為什麼選這條路，全是黑盒。

Production 系統最基本的要求是「可觀測」。對 agent 來說，這意味著你要能回答：

- 這個答案是**基於哪幾份檢索到的文件**？
- Agent **呼叫了哪些工具**、傳了什麼參數、拿回什麼？
- 每一步花了多少 **token、多少時間、多少錢**？
- 哪一步是**整條鏈失敗的根因**？

我以前靠 tracing 抓過一個 PHP-FPM 的記憶體洩漏——沒有那條 trace，你只會看到「服務又慢了」，永遠不知道是哪一段在吃記憶體。Agent 是一模一樣的處境，只是黑盒更深：一個答案背後可能串了三次檢索、兩個工具呼叫、一輪 reasoning。今天這層觀測已經有現成的標準和工具可以接（第 9 篇細談），差別只在你願不願意把它當成跟後端一樣的基本要求。

沒有這層 trace，你 debug agent 的方式就只能是「再問一次看看」。那不是維運，那是許願。

## 鴻溝四：權限與資料治理，是企業的生死線

這道鴻溝，是把「給個人玩的 agent」和「給企業用的 agent」分開的那條線，也是最多 PoC 直接跳過、然後永遠過不了資安那關的地方。

你的 RAG agent 會檢索公司文件。問題來了：

- 一個**沒有 HR 權限的員工**問「某某人的薪資」，agent 會不會因為那份文件剛好在向量庫裡，就大方檢索出來回答？
- 不同部門、不同機密等級的資料，retrieval 的時候**有沒有照使用者的權限過濾**？
- 答案引用了某份文件，那位使用者**本來有沒有資格看那份文件**？

在 demo 裡，所有資料對「你」這個 demo 帳號都是開放的，所以這個問題隱形了。在 production 裡，**越權檢索等於資料外洩**，而且是 AI 幫你自動化的外洩。第 5 篇「權限感知檢索」會專門拆這一關——我會老實說，這是企業 RAG 最難、也最容易被低估的一塊。

## 鴻溝五：成本與延遲，不是「之後再優化」

Demo 一天被呼叫 20 次，你不在乎一次花多少 token。Production 一天被呼叫 20 萬次，每次多串一個 model call、多檢索 10 份文件、多跑一輪 reasoning，乘上 20 萬，就是真金白銀和使用者等到關掉分頁的延遲。

AI agent 有個 demo 階段看不到的特性：**它很容易「想很多」**。一個 multi-agent 的設計、一個 reasoning chain，在 demo 裡是「哇好聰明」，在 production 裡可能是「一個問題燒掉 5 萬 token、跑了 40 秒」。

這不是憑感覺嚇你。Anthropic 自己揭露過他們的 multi-agent research 系統：一個 multi-agent 流程用掉的 token，大約是一次普通 chat 的 15 倍（單一 agent 也有 4 倍）。multi-agent 之所以顯得聰明，很大一部分就是因為它燒得多——這在 demo 裡你看不到帳單，乘上 production 每天幾十萬次呼叫，就是會被約談的數字。

更現實的是，這三件事——延遲、可靠性、成本——是會互相打架的三角：

- 想可靠 → 加 retry、加 fallback model → 變慢、變貴
- 想便宜 → 用小模型、少檢索 → 品質掉
- 想快 → 少 reasoning、激進 cache → 可能犧牲正確性

LLM app 說到底還是個 distributed system，這些 trade-off 是要當成系統設計來做的，不是上線後再說。第 10 篇整篇在談這個三角怎麼權衡。

## 鴻溝六：沒有 fallback 和人類介入點

最後一道，是心態問題。很多人潛意識把 agent 當成「會自己搞定一切」的東西。但 production 系統的成熟度，恰恰體現在它**承認自己會失敗、而且為失敗做了準備**。

- Agent 沒把握的時候，能不能**降級**到「我幫你找到這幾份文件，請你自己判斷」，而不是硬掰一個答案？
- 高風險的動作（刪資料、送出訂單、改設定），有沒有一個 **human-in-the-loop 的確認關卡**？
- 主要模型掛了、或回了垃圾，有沒有 **fallback 路徑**？

一個 tool-using agent 真正可怕的地方，不是它會講錯話，是**它能操作外部系統**。它能講錯話頂多丟臉；它能用錯工具，那是真的會改到資料、動到錢。所以 action boundary 和 approval flow（第 6、11 篇）不是加分項，是 production 的入場券。

## 把六道鴻溝變成一張地圖

把上面整理起來，這就是這本書的骨架——每一道鴻溝，對應後面一到幾篇：

| # | 鴻溝 | 在哪幾篇過河 |
|---|------|------------|
| 1 | 正確性沒有底線 | 第 3、4、5 篇（RAG / 向量檢索 / 權限） |
| 2 | 沒有 eval / 迴歸 | 第 9 篇（可觀測性與評估） |
| 3 | 看不見內部 | 第 2、9 篇（架構 / trace） |
| 4 | 權限與資料治理 | 第 5、11 篇（權限檢索 / 治理） |
| 5 | 成本與延遲失控 | 第 10 篇（系統權衡） |
| 6 | 沒有 fallback / HITL | 第 6、8、11 篇（tool use / 多代理 / 治理） |

還有一個工程師容易忽略、但在 2026 越來越硬的視角：這六道鴻溝不只是你內部會卡的工程問題。其中正確性、資料治理、可追溯、人類介入這幾道，剛好就是 EU AI Act、NIST AI RMF、ISO/IEC 42001 正在要求企業做到的事——而像 ISO/IEC 42001 這種 AI 管理系統認證，已經開始被寫進大型企業的採購盡職調查清單。所以過這幾道河，不只是讓系統能被信任，也是在替合規鋪路。第 11 篇會把這層治理視角收成一張框架圖，也會把法規時間表講清楚。

下一篇（第 2 篇），我會把這六道鴻溝收斂成**一張企業 AI Agent 的系統架構藍圖**——一張圖看懂一個能上 production 的 agent 系統長什麼樣，每個元件為什麼存在、少了它會怎樣。先講清楚，那是一張**參考架構（設計提案）**，不是哪個已經部署好的成品；但它背後的每一個取捨，都是從上面這六道鴻溝推出來的。

如果你現在手上正好有一個「demo 很漂亮、但遲遲不敢上線」的 agent，先別急著怪模型。把它對著這六道鴻溝檢查一遍，你大概就會知道，卡住的從來不是 AI，是工程。

## 文章簡報

&lt;DeckEmbed images={deckSlides} title=&quot;為什麼企業 AI Agent 卡在 PoC？六道鴻溝&quot; /&gt;

---

### 延伸閱讀

- [Agentic Engineering 是什麼？為什麼 Karpathy 要發明這個詞](/blog/agentic-engineering-what-is-it)——先搞懂「用 agent 工作」和「打造 agent 系統」是兩件事
- [從「寫 code 的人」到「管 agent 的人」](/blog/agentic-engineering-mindset-shift)——角色轉換的心理那一面
- 下一篇：《企業 AI Agent 系統架構藍圖》——把這六道鴻溝收斂成一張可以照著蓋的圖</content:encoded><media:content url="https://bobochen.dev/_astro/cover.BgTD_fDz.webp" medium="image"/><category>AI Agent</category><category>LLM</category><category>系統設計</category><category>生產環境</category><category>企業導入</category><enclosure url="https://bobochen.dev/_astro/cover.BgTD_fDz.webp" length="0" type="image/png"/></item></channel></rss>