Context Engineering 深度解析:Tobi Lutke 說對了,Prompt Engineering 已經不夠用
這是「Agentic Engineering 實戰手冊」系列的第四篇。上一篇:工具全景圖
「你不是在寫 Prompt,你是在設計 Agent 的世界觀。」
有一次我花了 30 分鐘寫了一個超完美的 prompt,結果 agent 產出的 code 完全不符合專案慣例。為什麼?因為我忘了在 CLAUDE.md 裡寫明我們用 Tailwind 不用 styled-components。
Prompt 本身無可挑剔——任務描述清楚、驗收條件明確、連 edge case 都考慮到了。但 agent 一拿到任務,就開心地寫了一堆 styled.div 和 css template literal。理由很簡單:它的 training data 裡,styled-components 是一個非常流行的選擇。在沒有額外資訊的情況下,它做了一個「合理」的預設判斷。
那個 prompt 沒問題。問題出在 context。
這個領悟改變了我對 AI coding 的整個理解。Prompt Engineering 教你怎麼「問問題」。Context Engineering 教你怎麼讓 agent 「理解你的世界」。這個差別,決定了 agent 產出的品質上限。
Prompt Engineering 已死?不,它進化了
2025 年 6 月,Shopify CEO Tobi Lutke 在 X 上發了一條被廣泛轉發的推文:
「我不再稱它為 Prompt Engineering。正確的詞是 Context Engineering——為 LLM 任務精心策劃完美的 context,這是一門充滿細節的藝術。」
Lutke 的意思不是 prompt 不重要了,而是我們一直把注意力放錯了地方。
傳統的 Prompt Engineering 關注的是「怎麼跟 AI 說話」——用什麼語氣、加什麼前綴、Chain of Thought 怎麼寫。這些技巧在聊天場景下確實有效。但在 agentic workflow 裡,你的 prompt 只是 agent 接收到的資訊的一小部分。
想像你新到一家公司上班。你的主管跟你說「幫我修這個 bug」(這是 prompt)。但你能不能修好,取決於:你有沒有公司的 codebase 存取權(codebase indexing)?你知不知道公司的 coding convention(project config)?你能不能跑測試確認修好了(external tools)?你知不知道這個 bug 之前有人試過什麼方法(conversation history)?
Prompt 是你說的話。Context 是你說話時的整個環境。
Anthropic 在其開發者文件裡給了一個精確的定義:
Context Engineering 是「策劃最小的高訊號 token 集合,最大化你期望結果的可能性。」
注意兩個關鍵詞:最小的和高訊號的。不是塞越多越好,是要精準地提供 agent 需要的資訊——不多不少,剛剛好。
Andrej Karpathy 後來也呼應了這個概念。在他定義 Agentic Engineering 的時候,他把 Context Engineering 列為最核心的技能之一,因為:
「Agent 的行為品質,完全取決於它能看到什麼。你給它看到的世界越精確,它做出的決策就越好。」
如果 Post 1 說的「Agentic Engineering 是一門學問」是論點,那 Context Engineering 就是這門學問裡最重要的那一章。
Context 六層模型
我在一年的實踐中,整理出一個 context 的六層框架。從最穩定(幾乎不變)到最動態(即時產生),每一層需要不同的維護策略:
Layer 1: System Instructions — 幾乎不變
這是模型的「基本人格」,通常由工具廠商設定。例如 Claude Code 的 system prompt 定義了它是一個軟體工程 agent、可以使用哪些工具、行為準則是什麼。
你的角色:這層你幾乎無法控制,但了解它的存在很重要。不同工具(Claude Code vs Cursor vs Codex)的 system instructions 不同,這解釋了為什麼同一個 prompt 在不同工具裡會有不同表現。
最佳實踐:不要跟 system instructions 打架。如果你的 CLAUDE.md 裡寫了跟 system instructions 矛盾的指令,結果是不可預測的。了解你的工具的預設行為,然後在上面疊加,而不是覆蓋。
Layer 2: Project Config — 每個專案設定一次
這是 CLAUDE.md、.cursorrules、AGENTS.md 這些設定檔。它們定義了專案的「房子規則」:用什麼語言、什麼框架、什麼命名慣例、怎麼 build、怎麼 test。
我的真實例子:我的 bobo-blog-2026 的 CLAUDE.md 長這樣(摘要):
## Commands
npm run dev # Start dev server at localhost:4323
npm run build # Build production site to ./dist/
## Architecture
Stack: Astro 5 + MDX + Tailwind CSS 4 + TypeScript
## Conventions
- Language: lang="zh-TW" (Traditional Chinese Taiwan)
- Component files: PascalCase (e.g., PostCard.astro)
- Use existing CSS custom properties over hardcoded values
就這麼簡單。但少了這些,agent 可能用 Next.js 的方式寫 Astro code、用 CSS-in-JS 寫 Tailwind 專案、用英文寫中文部落格。
最佳實踐:從少開始,需要時再加。第一版只需要 build/test 指令和核心技術棧。當你發現 agent 重複犯同一種錯的時候,那就是該加一條 rule 的時機。
Layer 3: Codebase Indexing — Agent 自動探索
這是 agent 對你的程式碼庫的理解。好的 agent 工具會自動做這件事——讀取檔案結構、分析依賴關係、識別設計模式。Claude Code 在開始工作前會自動 glob 和 grep 來了解 codebase。
為什麼它重要:如果 agent 不知道你已經有一個 formatDate() utility,它就會自己寫一個新的。如果它不知道你的 API 有統一的 error response 格式,它就會自己發明一個。
最佳實踐:保持 codebase 的結構清晰。好的資料夾命名、一致的設計模式、有意義的函數名——這些不只幫人類理解 code,也幫 agent 更準確地索引和推斷。
Layer 4: Conversation History — 每個 Session 累積
這是你跟 agent 的對話紀錄。隨著一個 session 的進行,context window 裡會累積越來越多的對話、程式碼片段、工具呼叫結果。
陷阱:conversation history 是最容易失控的一層。一個長 session 跑下來,context window 可能有 70% 都是過時的對話。Agent 可能在第 50 輪對話時,還在參考第 5 輪的過時資訊做決策。
最佳實踐:
- 長任務拆成多個 session,而不是一個超長 session
- 利用 context compaction(Claude Code 會自動壓縮舊對話)
- 重要決策在 CLAUDE.md 或 plan 檔案裡持久化,不要只靠對話記憶
Layer 5: External Tools — 按需載入
這是 MCP(Model Context Protocol)servers、API 回應、外部文件等。Agent 可以透過 tools 即時查詢資料庫、呼叫 API、讀取 Notion 文件。
為什麼革命性:傳統的 LLM 只能用 training data 裡的知識。MCP 讓 agent 可以「伸手到外面」取得即時資訊。你的 agent 不再受限於它的知識截止日期,它可以查詢你的 production database、讀取你的 Jira ticket、甚至操作你的 Chrome 瀏覽器。
最佳實踐:不要一次掛太多 MCP servers。每個 tool 的 schema 描述都會佔用 context window。我的經驗是一個 session 掛 3-5 個最常用的就好,其他的需要時再啟用。
Layer 6: Runtime State — 即時產生
這是測試結果、error logs、git diff、build output 等即時產生的資訊。Agent 跑一次 npm run test,失敗的測試結果就變成新的 context,引導它修正方向。
為什麼關鍵:Runtime state 是 agent 「自我修正」的基礎。沒有它,agent 就是在瞎猜。有了它,agent 可以進入一個 write → test → fix → test 的迴圈,逐步收斂到正確的解。
最佳實踐:確保你的 test、lint、type check 指令是可以讓 agent 執行的。如果跑測試需要手動設定環境變數或啟動 Docker container,agent 就無法利用 runtime state 來自我修正。
六層總覽
| Layer | 內容 | 變動頻率 | 維護責任 |
|---|---|---|---|
| 1. System Instructions | 模型行為規範 | 幾乎不變 | 工具廠商 |
| 2. Project Config | CLAUDE.md、rules | 每專案一次 | 你 |
| 3. Codebase Indexing | 檔案結構、patterns | 隨 code 變動 | Agent 自動 |
| 4. Conversation History | 對話、先前回應 | 每 session 累積 | 自動 + 你管理 |
| 5. External Tools | MCP、API、外部文件 | 按需載入 | 你設定 |
| 6. Runtime State | 測試、logs、diff | 即時產生 | 自動 |
CLAUDE.md:從 10 行到 200 行的演化史
我用 Claude Code 一年了。如果要選「一件最影響生產力的事」,答案不是學會什麼進階 prompt technique,而是認真維護我的 CLAUDE.md。
這是它的演化歷程:
V1(2025 年初):3 行
npm run dev
npm run build
npm run test
就是三個指令。Agent 知道怎麼啟動專案、怎麼 build、怎麼跑測試。其他的?全部自己猜。結果可想而知——每次 session 開頭都要花 10 分鐘跟 agent 解釋同樣的事情。
V2(2025 年中):40 行
## Commands
npm run dev / npm run build / npm run test
## Architecture
- Astro 5 + TypeScript + Tailwind
- File-based routing in src/pages/
## Conventions
- PascalCase components
- Use CSS custom properties
- lang="zh-TW"
加了架構說明和 coding conventions。立竿見影——agent 不再寫出 Next.js style 的 code 了。
V3(2025 年末):100 行 + 多層架構
開始用 global CLAUDE.md + per-project CLAUDE.md + rules files。全域設定管通用的 coding philosophy(偏好 composition over inheritance、test-driven 等),專案設定管具體技術棧。
V4(2026 年現在):200 行 + skills + hooks + memory
完整系統:
- Global CLAUDE.md(~100 行):開發哲學、通用 conventions、CI/CD 習慣
- Project CLAUDE.md(~50 行):每個 repo 的技術棧、build 指令、特殊模式
- Skills(23 個):可重用的 agent 能力模組,用
/skill-name觸發 - Hooks:pre-commit review、deploy 前檢查等自動化流程
- Memory system:跨 session 的持久化記憶
從 3 行到這個規模,不是因為我喜歡寫設定檔,而是因為每一行都是用踩坑換來的。Agent 連續三次在 Astro component 裡寫 React 的 useState?加一條 rule。Agent 總是忘記我們的 API response 格式?加一條 rule。
更詳細的設定檔架構設計,請看 CLAUDE.md 大師班。
Context Window 管理:什麼該塞、什麼該留
Anthropic 內部有一個概念叫 “Goldilocks Zone”——context 不能太多也不能太少,要剛好。
太多的問題:agent 的注意力會被稀釋。如果你把整個 repo 的所有檔案都 dump 進去,agent 反而抓不到重點。研究顯示,當 context 裡有大量無關資訊時,LLM 的準確率會顯著下降——這被稱為「Lost in the Middle」效應。
太少的問題:agent 缺乏做正確決策的資訊,只好自己猜。而它猜的依據是 training data,不是你的專案實際情況。
Token Budget 分配建議
這是我在實踐中摸索出的大致比例:
| Context 類型 | 建議佔比 | 說明 |
|---|---|---|
| System Instructions | ~5% | 工具預設,你無法控制 |
| Project Config | ~10% | CLAUDE.md + rules |
| Codebase Indexing | ~30% | 相關檔案的 code |
| Conversation History | ~35% | 對話 + 先前結果 |
| External Tools | ~10% | MCP 結果、API 回應 |
| Runtime State | ~10% | 測試結果、error logs |
注意 conversation history 佔了最大比例——這也是最容易失控的部分。
Progressive Disclosure 策略
不要一次給 agent 所有資訊。像剝洋蔥一樣,需要時再給:
- Session 開始時:只載入 CLAUDE.md 和 task spec
- Agent 開始探索時:讓它自己 grep/glob 找到相關檔案
- 遇到問題時:提供 error logs、test results 等 runtime context
- 需要外部資訊時:透過 MCP 即時查詢
這跟 Just-in-Time Manufacturing 的邏輯一樣——需要的時候才載入,而不是預先囤貨。
Sub-Agent 架構:保護主 Context
當一個大任務需要探索很多檔案的時候,不要在主 session 裡全部做完。用 sub-agent:
主 agent(main context)
└── 派出 sub-agent 1:研究 codebase 結構
└── 派出 sub-agent 2:探索相關 API
└── 派出 sub-agent 3:分析 test patterns
Sub-agent 各自帶著自己的 context window 工作,完成後只回報「結論」給主 agent。這樣主 agent 的 context window 不會被探索過程的細節填滿。
我在寫這個系列的時候就是這樣操作的——一個主 agent 負責寫作,三個 sub-agent 分別負責不同主題的研究,每個 sub-agent 完成後把研究結果摘要回報。主 agent 的 context 始終保持乾淨。
常見的 Context 設計錯誤
一年下來,我(和我觀察到的其他人)最常犯的五個 context 錯誤:
錯誤 1:塞太多——資訊過載
症狀:Agent 拿到一個 200 行的 CLAUDE.md + 50 個檔案的 codebase dump,然後做了一個看起來隨機的決策。
原因:LLM 有一個已知的 “Lost in the Middle” 問題——context window 中間的資訊比頭尾更容易被忽略。當你塞了太多資訊,重要的指令可能剛好落在被忽略的區域。
修正:刪掉一切不是當前任務「必要」的資訊。CLAUDE.md 是你的「always-on」context,應該精簡。任務特定的資訊應該在 prompt 裡給,不是在 CLAUDE.md。
錯誤 2:塞太少——Agent 自己發明
症狀:Agent 完美地完成了任務,但用了一個你們從不使用的 library、一種你們從不使用的設計模式、或一個跟現有 code 完全不一致的命名風格。
原因:沒有足夠的 context,agent 只好依賴 training data 中最常見的模式。而最常見的模式不一定是你的專案的模式。
修正:當你發現 agent 連續做了「合理但不是我想要的」選擇,那就是該加 context 的時機。記錄下來,加到 CLAUDE.md 或 rules file。
錯誤 3:塞錯東西——花 Token 在無關資訊上
症狀:你把一大段 design doc 貼給 agent 來修一個 CSS bug,結果 agent 花了大量 token 分析 design doc 裡的商業邏輯,然後建議你改 backend API。
原因:LLM 會試圖利用所有給它的資訊。你給了它 design doc,它就覺得你希望它考慮 design。即使 bug 只是一個 CSS z-index 問題。
修正:Context 要跟任務相關。修 CSS bug 就給 CSS 相關檔案和 error description。不需要的資訊不只浪費 token,還會誤導 agent 的注意力。
錯誤 4:不更新——用過時的 Context
症狀:Agent 用了你三個月前的 API endpoint(已經改名了)、用了一個你兩個月前棄用的 component、或遵循一個你上個月修改的 convention。
原因:CLAUDE.md 寫了之後就沒再更新。Rules file 裡的指令跟現在的 codebase 已經不一致。
修正:把 CLAUDE.md 的維護當成程式碼的一部分——它應該被 commit 進 git、被 review、被定期更新。我的習慣是每月花 30 分鐘 review 一次設定檔,清掉過時的內容。
錯誤 5:重複資訊——多個來源說不同的話
症狀:Global CLAUDE.md 說「用 tabs 縮排」,project CLAUDE.md 說「用 2 spaces 縮排」。Agent 隨機選一個,或者更糟——在同一個檔案裡兩種都用。
原因:多層設定檔架構沒有清楚的優先順序定義。
修正:建立明確的優先順序:project 設定覆蓋 global 設定。避免在多個地方重複定義同一件事。一條 rule,一個權威來源。
一個 Context 設計的真實 Before/After
讓我用一個具體的案例來展示 context quality 的影響。
任務:在 Astro 部落格加一個「相關文章」推薦功能。
Before(只有 Prompt,沒有 Context)
幫我在部落格文章頁面底部加一個「相關文章」區塊,
根據 tags 推薦 3 篇相關文章。
Agent 的結果:寫了一個 React component(我用 Astro)、用 fetch 從不存在的 /api/posts 取資料(我是 static site)、CSS 完全沒用 Tailwind(我整個專案都是 Tailwind)。
功能邏輯是對的。技術選型全錯。花了 40 分鐘重寫。
After(完整的 Context Stack)
CLAUDE.md 已經有:
Stack: Astro 5 + MDX + Tailwind CSS 4 + TypeScriptsrc/content/blog/是部落格文章目錄Content Collections API用getCollection('blog')取文章- Component 使用
.astro格式
加上精確的 Prompt:
在 BlogLayout.astro 底部加一個「相關文章」區塊。
- 用 Astro Content Collections API 的 getCollection('blog') 取文章
- 根據 tags 的交集數量排序,取前 3 篇
- 使用現有的 PostCard.astro component 呈現
- 排除當前文章本身
- 用 Tailwind grid 佈局
Agent 的結果:一個 Astro component,用 getCollection('blog') 取資料,tag 交集排序邏輯正確,用了現有的 PostCard.astro,Tailwind grid layout。20 分鐘完成,第一次就能用。
差別不在 prompt 的措辭技巧。差別在 agent 能看到的「世界」。
Takeaway
-
Context Engineering 是 Agentic Engineering 的核心技能——你的 context 品質直接等於 agent 產出品質。投資在 context 設計上的每一分鐘,都能省下 agent 犯錯後的收拾時間。
-
Context 有六層,每層需要不同的維護策略——從幾乎不變的 System Instructions 到即時產生的 Runtime State,理解每一層的角色和最佳實踐,才能精準地給 agent 它需要的資訊。
-
「剛好夠」比「越多越好」重要——學會在 token budget 內精準投放 context。太多會稀釋注意力(Lost in the Middle),太少會讓 agent 自己亂猜。Progressive disclosure + sub-agent architecture 是你管理 context 的兩大武器。
上一篇:工具全景圖 下一篇:Spec-Driven Development