跳至內容

AI 編碼詞彙

Matt Pocock 的 AI 編碼辭典的本地每週更新鏡像,經過調整,適合在 moebis 實驗室內進行快速瀏覽。

71 個詞條每週重新整理已快取 2026年10月20日 上午8:39

AI 編碼有其專屬的詞彙,但核心概念很快就能學會。這本字典將模型、上下文、token、成本、不可預測的行為和工具工作流程背後的術語翻譯成淺顯易懂的英文,讓這項工作感覺不那麼神祕。

區段

第 1 節 — 模型

AI

一個變動的標籤,而非一項技術。「AI」不像model或token那樣指稱一個固定的事物——它指的是電腦最新且令人印象深刻的功能。目前它指的是大型語言模型。它以前曾指過非常不同的事物:

時代「AI」的含義
1950年代符號推理 — 定理證明器、西洋棋程式。
1960–70年代基於規則的符號程式 — ELIZA、SHRDLU。
1980年代專家系統 — 數千條編碼人類專業知識的手寫 if-then 規則。
1990年代博弈樹搜尋 — 深藍擊敗卡斯帕洛夫 (1997)。研究人員完全避免使用「AI」一詞
2000年代統計機器學習 — 垃圾郵件過濾器、推薦系統。當時仍作為「機器學習」而非「AI」銷售
2010年代深度學習 — 影像識別 (AlexNet, 2012)、AlphaGo (2016)。
2020年代大型語言模型 — ChatGPT (2022) 使「AI」成為聊天機器人的代名詞

指標會透過已知機制移動,有時被稱為 AI 效應:一旦某一技術可靠運作,它就會被重新命名——這「只是」搜尋、「只是」統計——而「AI」則向前推進到下一個未解決的問題。這個觀察由來已久。伯特倫·拉斐爾 (Bertram Raphael) 於 1971 年這樣表述:「AI 是我們尚不知道如何透過電腦妥善解決的問題的統稱。」拉里·特斯勒 (Larry Tesler) 大約在 1979 年的版本:「智慧就是機器還沒有做過的事情。」

這就是為什麼關於 AI 的對話經常雞同鴨講。「AI 無法推理」或「AI 被過度炒作」這類的說法帶有隱藏的時間戳記——它可能是關於專家系統、2010 年代的影像分類器,或是上個月的 LLM,而每一個參照都支持不同的結論。當關於 AI 的討論陷入僵局時,解決辦法通常是用實際指稱的精確術語來替換這個詞:模型、harness、agent或給它的context。

避免:在任何技術聲明中使用「AI」——請改為指稱你所指的部分。「AI 程式碼編寫」作為這種做法的標籤是可以的;「AI 正在產生幻覺」則不行。

用法:

「技術長想知道 AI 是否能處理分流佇列。」

「在確定範圍之前先翻譯一下——她指的是帶有票務系統存取權限的 harness 中的 LLM。『AI』本身並不是規格。」

模型

也就是參數。無狀態——只做下一詞元預測,不做其他事。「Claude Opus 4.x」和「GPT-5.x」都是模型。模型本身做不了任何代理式工作,必須由執行框架承載。

模型不能讀檔、執行命令、瀏覽網頁,或記住昨天——它只在每次模型供應商請求中接收詞元,再預測輸出詞元。所有讓你感覺像有個代理在工作的事——選擇工具、讀取結果、反覆執行直到任務完成——都是執行框架在協調一連串預測。

模型供應商會提供不同等級的模型:大型模型最聰明,但較慢且昂貴;小型模型更快、更便宜,但能力較弱。選擇等級是實際取捨——規劃與困難除錯用重量級,機械式修改用輕量級——而執行框架讓你能在工作階段中途切換。

嚴格使用這個詞,也能讓診斷更精確。「模型不擅長這件事」是一項明確主張——同個模型換了執行框架,或給了不同上下文,表現往往完全不同。責怪模型之前,先檢查它拿到了什麼:多數令人失望的輸出,追根究柢是上下文或執行框架的問題,而不是參數。

用法:

「規劃步驟要把模型從 Sonnet 換成 Opus 嗎?」

「可以試試,但這個任務主要靠執行框架出力。如果系統提示和工具不對,換模型也沒用。」

參數

模型內部的數字——通常有數十億個——在訓練中調整。模型「知道」的一切都存在其中。訓練設定它們;推論則原封不動地使用。也稱為權重。

從運作機制來看,參數負責把輸入轉成輸出。下一詞元預測是一項龐大計算:上下文視窗內的詞元輸入後,經過參數相乘,產生下一個詞元的預測。模型裡沒有事實資料庫,也沒有程式碼查詢表——只有這些數字,以讓計算傾向產生有用輸出的方式排列。模型能從訓練背出的事實,例如標準函式庫 API,就是參數知識:儲存在參數中,而非從任何地方檢索。

需要真正理解的細節是,參數在訓練後就固定了。你在工作階段做的任何事都不會改變它們——無論你的更正、展示的程式碼庫,或它從中學習的錯誤。每個工作階段都使用同一組數字。這就是模型為何無狀態、內建知識為何止於知識截止日期,以及專案特定資訊為何必須改由上下文帶入。改變參數的唯一方法是更多訓練——實際上會產生另一個模型。

用法:

「可以用我們的程式碼庫微調它嗎?」

「那會更新參數——之後就是另一個模型了。只為一個專案,幾乎總是把程式碼庫載入上下文比較便宜,而不是重新訓練。」

訓練

設定模型參數的過程:讓模型接觸大量文字,調整參數以改善下一詞元預測。這是模型供應商進行的一次性昂貴程序,包括預訓練(主要大量訓練)與後訓練(之後對指示遵循、安全等方面的精修);以本詞彙表的層次來說,無須區分。

機制是在大規模下反覆進行:給模型一段文字,讓它預測下一個詞元,依實際下一詞元微調參數,再於數兆詞元中重複。沒有任何內容以事實或規則形式儲存——模型「知道」的一切,都是改善預測的副產品,以參數知識形式壓縮在參數裡。

日常使用有兩個重要結果。訓練在某個時間點結束,因此模型有知識截止日期——它沒看過你上個月升級的函式庫版本。而訓練也不是你能做的事:當模型不了解你的程式碼庫、慣例或內部 API,解法絕不是「教模型」,而是把那些資料放進上下文,這是你能控制的輸入。

用法:

「能讓它知道我們的內部 API 嗎?」

「不能靠訓練——那是模型供應商要花幾個月做的程序。把 API 文件載入上下文吧,那才是你真正能調整的槓桿。」

推論

執行訓練好的 模型 來產生輸出 — 這是在每個 模型供應商請求 時發生的事。參數 維持固定;模型只是對給定的 上下文 進行 下一個 Token 預測。相較於 訓練 成本低廉,但它是按 Token 計費,也是使用模型的主要成本。

模型的生命週期分為兩個階段:

階段發生時間其作用參數
訓練一次,在發布前從訓練語料庫中產生參數正在寫入中
推論每次任何人使用模型時針對你的上下文執行凍結的參數以產生 Token唯讀

你在推論時所做的任何事情都不會寫回參數 — 這就是為什麼你今天修正的錯誤明天不會持續存在的原因。在你仔細解釋修正方式後,明天在 工作階段 中犯下相同錯誤的模型並沒有無視你;它是無法從交流中學習。模型是 無狀態的 — 連續性必須來自外部 — 來自 上下文視窗 或 記憶系統。

這種機制也解釋了你的計費方式。每個請求都會在完整的上下文上執行模型,因此成本隨 輸入 Token 和 輸出 Token 規模化,而執行數十次 工具 呼叫的代理會在每次來回傳輸時支付推論費用。這就是為什麼上下文大小既是一個品質問題,也是一個成本問題。

用法:

「為什麼帳單是隨使用量規模化,而不是固定的授權費用?」

「你支付的是推論費用 — 每個模型供應商請求都會在供應商的硬體上執行模型。訓練已經完成,但推論成本會按請求累積,而當呼叫工具時,單一 輪次 可以擴展為多個請求。」

思考強度

思考強度是一個用於調整 模型在回答前進行多少推理的滑桿。由 模型提供者要求按設定運作,它能控制模型在開始編寫你所看到的迴應之前所經歷的思考長度。這種思考過程就像其他事情一樣,是在 推論階段產生的;封裝工具通常會將其隱藏,但這是模型正在進行的真實工作。

更高的思考強度需要更高的成本且運行速度更慢。推理結果會以 Token的形式發出,即使你從未見過它們,也會被計費為 輸出 Token,並且是一個 Token 接一個 Token 地產生——因此調高思考強度會拉長答案到達前的等待時間,並增加帳單費用。這是在權衡更多深思熟慮與速度和成本之間的關係。

大多數封裝工具將思考強度公開為一個小型等級階梯:

層級用途
低機械式編輯、查詢、具有清晰路徑的明確變更。
中日常編碼——常見的預設值。
高棘手的錯誤、設計決策、多步驟計劃。
最大最困難的問題,此時給出錯誤答案的修正成本很高。

弄錯了的徵兆會帶來雙向影響。在困難的問題上把思考強度設定得太低,你會得到一個自信、膚淺的答案,它跳過了問題所需的推理——讀起來很好,但在稍後會讓你付出代價的方面是錯的。為了一行重新命名的程式碼將其設定為最大值,你會經歷漫長的思考,卻產生出最低設定也能做到的結果。

請將思考強度與任務相匹配,而不是與 對話階段相匹配。針對真正難以推理的部分調高它,並為周圍的機械式工作調低它。

用法:

「它一直搞砸這個併發修復——我已經解釋過三次了。」

「把思考強度調高。這是一個需要大量推理的錯誤,在預設設定下,它在承諾採用某種方法之前思考得不夠久。」

詞元

模型讀寫的最小單位。大小約等於一個詞,但並不完全相同——常見詞通常是一個詞元,罕見或較長的詞會拆成數個。上下文視窗大小、成本與延遲,都以詞元計算。

文字透過詞元切分器變成詞元:它使用一份在訓練前學得、包含數萬個片段的固定詞彙表,將任何輸入拆成詞彙表項目的序列。模型從來看不到字元或單詞——所有文字輸入時都轉成詞元,而下一詞元預測會在輸出時逐一產生詞元。

粗略來說,一個詞元約等於四分之三個英文單詞,因此一千個詞元大約是 750 個單詞。程式碼較難預測:常見關鍵字和慣用寫法能緊湊地切分,但生成的識別名稱、雜湊、base64 資料與壓縮輸出,每個「詞」可能拆成很多詞元。規律是:在切分器來源資料中經常出現的文字,編碼較短而高效;沒有的文字則被切成許多小片段。像 `a3f9c2e1` 這種雜湊未曾出現過,因此會拆成多個詞元,而 `function` 只有一個。這就是為何看似很小、卻充滿特殊字串的檔案,會占用令人意外的大量上下文視窗。

詞元是衡量其他一切的單位。成本按詞元計算——供應商分別計收輸入詞元與輸出詞元。速度是每秒詞元數,因為輸出是逐個詞元生成。上下文視窗也是固定的詞元數,因此檔案的詞元數決定能容納多少內容。

避免:「單詞」——詞元邊界不等於單詞邊界,真正重要的單位是每秒詞元數與每美元詞元數。

用法:

「這個提示會有多大?」

「用詞元切分器跑一下——結構定義很精簡,但 JSON 鍵名很奇怪,會比你想的拆成更多詞元。」

下一個 Token 預測

模型實際做的事。給定上下文,它取樣出下一個詞元,附加上去,再執行一次。每項輸出——句子、工具呼叫、一千行的檔案——都逐個詞元建立。模型沒有其他運作模式。

每一步都相同:上下文視窗的詞元經過參數運算,為詞彙表每個詞元產生機率——這個很可能是下一個,那個較不可能。從這些機率中取樣一個詞元,附加後,以稍長的上下文再次循環。同個提示在不同執行產生不同輸出,原因正是取樣步驟:非決定性內建於機制,而非後來疊上的錯誤。

記住這個機制,就能解釋原本看來奇怪的行為。模型在輸出詞元前從不檢查它是否真實,只判斷它是否可能——這是幻覺的根源。每產生一個詞元就定案,因此聽來自信的開場句,可能把後續整段答案帶偏。而輸出詞元嚴格逐個生成,也讓生成速度限制了任何代理工作的最快速度。

用法:

「代理如何『決定』呼叫工具?」

「它並不決定——從頭到尾都是下一詞元預測。工具呼叫只是執行框架從輸出串流解析出來的結構化字串。」

非確定性

同樣的輸入可能產生不同輸出。用相同上下文執行模型兩次,可能得到兩個不同答案——有時只差一個詞,有時做法完全不同。即使你的程式碼完全沒變,也會發生。

這是模型生成文字,以及模型供應商處理請求方式的特性。推論時,模型對可能的下一個詞元產生機率分布,再從中取樣——通常刻意加入一些隨機性,因為總選最有可能的詞元,會產生重複且品質較低的文字。回答前段只要有一個詞元取樣不同,就會改變後面所有詞元,這就是單一不同詞語如何變成完全不同的做法。供應商端服務又增加更多變化:請求會在共用硬體上批次處理,批次間極小的浮點差異,可能左右兩個機率相近詞元的選擇。沒有一個設定能讓這些差異全部消失。

應預期代理對同個任務會產生一系列不同結果。大多數回答的品質落在合理的鐘形曲線內——非決定性之所以還能接受,原因就在此——但兩端尾部也確實存在:有些日子模型感覺很敏銳,有些日子則像完全搞不清楚狀況。同個任務,不同骰運。這有兩個實際影響。重試是正當策略:失敗只是從分布抽到的一次結果,重新嘗試同個任務可能單純就更好。而驗證比使用決定性工具更重要——你無法測試一次代理行為,就指望它重複相同表現,因此自動化檢查必須攔下糟糕結果。

別過度替這件事編故事。人類擅長模式比對,連續幾次不佳執行,會讓人覺得是「這週模型變差了」的證據。通常只是分布使然。

用法:

「Claude 今天糟透了。他們發布了更差的版本嗎?」

「大概沒有——模型輸出是非決定性的。同個任務也會有好日子與壞日子。先明天再試,再去找原因。」

模型提供者

任何提供模型進行推論的服務。通常是遠端服務(Anthropic、OpenAI、Google),也可以是本機——在你自己電腦上執行的 Ollama、LM Studio、llama.cpp。執行框架本身不執行模型,而是請供應商執行。

供應商擁有運作機制:參數存在其硬體上,每次模型供應商請求,都是執行框架透過網路傳送詞元,再取得預測。因此,供應商是一整類常被誤歸咎於模型或執行框架之問題的來源——速率限制、容量下降與服務中斷都在這裡。代理在工作階段中途停滯,或每個回合都出錯時,值得先查看供應商狀態頁。

供應商也設定商業條件:輸入與輸出詞元的單價、前綴快取折扣,以及究竟提供哪些模型。注意,供應商與模型製作者可能是不同公司——Bedrock、Vertex 和 OpenRouter 都提供別人的模型。

本機供應商以能力換取控制權:能放進你硬體的模型遠小於前沿模型,但資料不離開機器,也沒有逐詞元帳單。

用法:

「能為隔離網路的客戶離線執行嗎?」

「把模型供應商換成本機的——在他們機器上用 Ollama 或 llama.cpp。執行框架不在乎,只是改連另一個端點。」

Harness

環繞著model並使其轉變為agent的一切:tools、system prompt、context-window management、權限、掛鉤(hooks)。Claude.ai 和 Claude Code 運行於相同的模型,但表現卻大不相同,因為它們的框架(harnesses)不同。

模型本身只做一件事:輸入文字,輸出文字。它無法讀取檔案、執行指令,或記住上一個turn。框架提供了所有這些功能。它為每個model provider request組合context,執行模型要求的tool calls,將tool results回傳,儲存session歷史紀錄,在執行高風險操作前徵求你的同意,並決定何時進行compact。代理迴圈(agent loop)——模型提出建議、框架執行、重複進行——是由框架運行的。

這對診斷問題至關重要。當兩個產品之間的行為有所不同,或是昨天與今天有所不同時,變數通常不是模型——而是框架。不同的系統提示詞、不同的工具集、更改後的權限預設值,或全新的上下文管理策略,都會在模型完全不變的情況下改變行為。這也意味著你的大部分設定都存在於框架中:AGENTS.md檔案、權限設定以及掛鉤,全都是對框架的指令,而非對模型的指令。

範例:Claude Code、Cursor、Codex CLI——以及 Claude.ai,它是一個聊天框架,而非編碼框架。

用法:

「相同的模型,為什麼 Claude Code 可以編輯檔案,而 Claude.ai 只能回答問題?」

「不同的框架——Claude Code 擁有filesystem工具、不同的系統提示詞和權限層。這裡的變數不是模型。」

模型提供者請求

從代理程式執行環境到模型供應商的一次來回。執行環境會發送目前的上下文;供應商會回傳一個回應(一個工具呼叫或最終答案)。如果代理程式呼叫了工具,單一使用者訊息就可以衍生出許多模型供應商請求——每個工具結果都會觸發另一個請求。

每個請求都承載了所有內容:系統提示詞、目前的完整對話、每一個工具結果。由於模型是無狀態的,因此供應商在請求之間不會保留任何資料——第四十次請求會重新發送第三十九次請求所發送的內容,再加上多出來的一個工具結果。前綴快取的存在就是為了讓這種重複動作符合經濟效益。

請求也是計費的單位。輸入代幣、輸出代幣以及快取折扣全都是以每個請求來計算,這就是為什麼看起來無害的問題可能會花費令人驚訝的金額:成本與你的訊息不成正比,而是與請求次數乘以每個請求所承載的上下文大小成正比。

值得將請求與輪次區分開來。一個輪次是與你的一次互動,而單一輪次——「修復失敗的測試」——會以一連串請求的形式展開:

請求模型回傳執行環境隨後
1工具呼叫:執行測試執行測試,附加失敗輸出
2工具呼叫:讀取測試檔案附加檔案內容
3工具呼叫:讀取原始碼檔案附加檔案內容
4工具呼叫:編輯原始碼檔案套用編輯,附加結果
5工具呼叫:再次執行測試執行測試,附加通過輸出
6最終答案:「已修復,測試通過」向你顯示

一個輪次需要六個請求——每一個請求都重新發送整個上下文。當你納悶代幣都去哪裡了時,請計算請求數,而不是輪次數。

用法:

「一個問題燒掉了四萬個代幣?」

「看看工具呼叫——十二次 grep、八次讀取、四次編輯。每個工具結果都會衍生另一個模型供應商請求,而且整個工作階段前綴每次都會重新發送。」

輸入權杖

執行框架在每次模型供應商請求送出的詞元——系統提示、對話歷史、工具結果,也就是模型撰寫前讀取的一切。費率低於輸出詞元,因為處理成本較低。

進行 AI 程式設計時,輸入詞元占帳單大多數。模型是無狀態的,因此每個回合都把整個工作階段當輸入重新傳送:你的第一則訊息、每次回應,以及此後每個工具結果。第五十回合的輸入包含先前四十九回合。一次模型供應商請求可能只產生幾百個輸出詞元,卻重新傳送累積歷史中的十萬個輸入詞元。

前綴快取降低成本:與先前請求完全相同的歷史,以便宜的快取詞元計費,而不是全價輸入。輸入成本仍高時,解法是縮減重新傳送的內容——在任務間清除或壓縮。

用法:

「帳單很高,但代理幾乎沒寫東西。」

「是輸入詞元——每回合都重新傳送整個工作階段。沒有前綴快取,每次請求都重新為歷史付費。」

輸出 Token

模型生成回傳的詞元。計費高於輸入詞元,通常約為五倍,因為產生它們需要更多運算。

模型寫出的所有內容都計入:你讀到的文字、產生的程式碼、工具呼叫,以及回答前進行的任何延伸思考。最後一項常讓人意外:即使執行框架通常不顯示推理詞元,它們仍按輸出計費,提高努力程度也會消耗更多。

輸出詞元也決定工作階段的步調。模型讀取輸入很快,但輸出必須逐個詞元生成,所以一個回合感覺慢時,幾乎總是在寫輸出,而不是讀輸入。等待很久,通常意味著答案會很長。

用法:

「這次重構工作階段一直燒額度,明明輸入很小。」

「代理在重寫整個檔案,而不是局部修補。輸出詞元價格約為輸入的五倍,讓它只輸出編輯內容,帳單就會下降。」

前綴快取

供應商端的儲存機制,讓連續的模型供應商請求略過共用前綴的重複處理。當請求開頭和近期某次請求相同——相同系統提示,以及到某個位置為止相同的歷史紀錄——供應商會重用先前工作,將這些詞元以低得多的快取詞元費率計價。

快取之所以划算,是因為工作階段只會持續附加。每次請求都把完整歷史紀錄當成輸入詞元重新傳送(原因見該詞條),而一般工作階段只會改變歷史紀錄尾端——每次請求就是前一次加上幾則新訊息。供應商只處理一次冗長的共用開頭,儲存結果,然後從前綴結束處繼續。沒有快取,50 個回合的工作階段就得付費,把第一回合重新處理五十次。

快取也會到期。快取項目能保持有效多久,依模型供應商而異——通常是幾分鐘,而不是幾小時。工作階段閒置超過時限後,下一次請求會以全額價格重建前綴一次,才恢復快取。這主要是執行框架開發者要考量的事;對使用者來說,可見的影響是長時間暫停後的請求,會比暫停前更貴。

用法:

「為什麼工作階段進行到一半,帳單突然暴增?」

「執行框架開始每回合都把目前時間插進系統提示。前綴快取在第一個改變的詞元就會中斷,所以之後每次請求都按全額計費。」

快取代幣

供應商從先前模型供應商請求快取的輸入詞元,因此不用重新處理。連續請求共用前綴時,供應商透過前綴快取重用工作,並以低得多的費率計收快取部分。這是讓長工作階段負擔得起的槓桿——沒有它,每個回合都得重新為完整歷史付費。

重要原因在於工作階段的計費方式。模型是無狀態的,每次請求都把整段對話——系統提示、每則訊息、每份工具結果——重新當輸入詞元傳送。到了第五十回合,每次請求都帶著五十回合歷史,每次全部按全額付費。快取改變了計算:供應商已處理過、且前綴完全一致的詞元,會按快取詞元計費,通常是輸入費率的十分之一或更低。長工作階段傳送的多半是快取詞元,帳單因此維持合理。

以下範例顯示何時會快取、何時不會。每個字母代表一塊對話內容;每次請求傳送截至當時的對話:

請求傳送已快取全額計費原因
`AB`無`AB`首次請求——沒有可比對內容
`ABC``AB``C``AB` 是前次請求的完全相同前綴
`ABCD``ABC``D`前綴仍完整
`AXCD``A``XCD`編輯把 `B` 改成 `X`;比對在此失敗

快取有個特定弱點:它比對完全相同的前綴。如果對話較前面的任何內容改變——執行框架重排內容、時間戳記更新、檔案表示方式變動——從那個位置起快取就失效,後面全部按完整輸入費率計價。快取也會在閒置幾分鐘後到期,因此長時間暫停後恢復工作階段,會重新為歷史付費一次。工作階段成本無明顯原因地上升時,比較用量報告中的快取詞元與輸入詞元——快取出問題,會先在那裡顯現。

用法:

「長工作階段成本好痛——重構一次八美元。」

「檢查快取詞元。執行框架若在回合間重排系統提示或檔案,前綴就斷了,每次請求都得重新付完整輸入費率。」

區段

第 2 節 — 工作階段、上下文視窗與輪次

無狀態

不將資訊延續下去。模型在各個模型提供者請求之間是無狀態的——每次請求都會重新發送完整的上下文視窗,因為模型沒有其他方式來查看任何內容。預設情況下,代理程式在各個工作階段之間是無狀態的:新的工作階段開始時是空白的,沒有先前工作階段的任何痕跡。與有狀態相對。

模型本身永久處於無狀態:它的參數在訓練後就被凍結,你在推論時所做的任何事情都無法改變它們。無論對話感覺起來有多像,模型不會從你的修正中學習,不記得昨天被告知過相同的事情,也沒有在試著了解你。工作階段內的連續感是由框架製造的,它保留了逐字稿並在每次請求時重新發送。模型不是在記住對話;它是在重新閱讀對話。

實際的後果是:如果你想讓某些事情在跨工作階段時被記住,你必須把它寫在代理程式讀得到的地方。這就是AGENTS.md檔案、記憶系統和交接產出物的作用——這些檔案會被載入到未來工作階段的上下文中,用來替代模型所沒有的記憶。當代理程式不斷犯下你先前已經修正過的錯誤時,問題不在於它為什麼沒學會(它辦不到),而是該把修正寫在哪裡,好讓未來的每個工作階段都能讀到它。

用法:

「為什麼每次我清除時,它就會忘記那個慣例?」

「模型是無狀態的——新的工作階段開始時是空的。如果你想保留它,請把它寫進 AGENTS.md 或框架會在工作階段開始時載入的記憶檔案中。」

上下文

代理目前能存取的相關資訊。這是抽象名詞——不是模型看到的原始輸入(那是上下文視窗),也不是持續累積的歷史紀錄(那是工作階段),而是代理知道、且與任務相關的內容。「將某項內容載入上下文」就是把它納入這個集合;「上下文工程」則是策劃這些內容的專業。

三個詞可清楚區分:

詞彙所指內容
上下文代理目前掌握、與任務相關的資訊
上下文視窗模型每次請求實際看到的詞元序列
工作階段執行框架儲存的持續對話

這種區分很重要,因為上下文衡量的是品質,而非數量。上下文視窗可以幾乎全滿,但上下文仍很差——數千詞元的過時工具輸出,沒有一個與眼前任務相關。它也可以幾乎空白,上下文卻極佳:只有那份攸關任務的型別定義。

大多數日常失敗都可追溯至上下文。代理捏造 API、違反決策,或猜測結構定義時,第一個問題應該是它當時的上下文有什麼——通常相關事實根本沒載入,或被埋在注意力衰退之下。解法是策劃:載入任務需要的,排除不需要的。

用法:

「它一直編造型別中沒有的欄位。」

「型別檔案不在上下文裡——它只看呼叫端,然後猜測。先讀入定義。」

上下文視窗

model在每個model provider request上看到的每一件事。它是有限的、特定於模型的,並且是模型感知任何事物的唯一表面。

它是一個單一的tokens序列:system prompt、目前的對話、harness回傳的每一個tool result。如果某個東西存在於該序列中,模型就可以使用它;如果不存在,模型就不知道它的存在——不是你的程式碼庫,不是你昨天編輯的檔案,也不是你在三個對話階段前給出的指令。視窗之外的任何東西都必須被帶入(通常透過tool call),然後才能影響任何事情。

有限意味著它會被填滿。每一個回合都會附加更多內容——你的訊息、模型的迴應、工具結果——而一個長的session最終會達到極限,迫使進行compaction或clearing。這也意味著視窗中的所有東西都在競爭:你載入的每一個 token 都意味著可供其餘部分使用的 token 少了一個,而你不需要的內容仍然佔據了模型的attention。實際的做法是將視窗視為一個預算——載入任務所需的內容,將其餘部分留給工具呼叫。

避免:

「記憶」——上下文視窗是工作狀態,不會跨對話階段持久保存。Memory是疊加在頂部的獨立概念。

用法:

「我可以把整個 monorepo 直接貼到提示詞裡嗎?」

「上下文視窗有 20k 個 token——這大概佔了程式庫的五分之一。挑選任務觸及的檔案,其餘的留給工具呼叫去處理。」

具狀態

將資訊延續下去。工作階段在多個輪次之間帶有狀態——隨著工作階段進行,上下文會不斷累積,這就是為什麼長時間的工作階段會陷入混亂區的原因。透過新增一個能將資訊持久儲存至環境並在未來工作階段開始時重新載入的記憶系統,可以讓代理程式在多個工作階段之間保持狀態。模型本身永遠不會有狀態;任何表面上的連續性,都是框架重新餵入上下文所致。與無狀態相對。

各層狀態存在的位置:

層級有狀態?運作方式
模型從不參數是凍結的;它只能看到每次請求中的內容
工作階段跨輪次框架將每則訊息與工具結果附加到上下文中
框架跨工作階段記憶檔案、AGENTS.md、交接產出物——寫下來,稍後重新載入
環境總是無論是否有工作階段在執行,檔案都會持續存在

每一層的狀態性都是透過重新讀取儲存在下一層的事物來建立的:工作階段之所以感覺是連續的,是因為框架將訊息歷史記錄重新發送給無狀態模型;而代理程式之所以能跨工作階段記憶,是因為框架從環境中重新載入檔案。任何狀態都不會儲存在模型本身中。

狀態並非總是需要的。所有延續下來的事物都會影響接下來的發展,因此在工作階段早期所做的錯誤假設也會一併被延續下去。清除是有意地將工作階段狀態丟棄,並從已寫下來的內容重新開始。

用法:

「它記住了我昨天的偏好——這代表模型學會了嗎?」

「不,代理程式之所以有狀態,是因為框架將它們寫入記憶檔案中,並在工作階段開始時重新載入。模型本身完全沒接觸到昨天的內容。」

代理程式

一個配備了 tools、system prompt 和 context window 的 model,並透過 harnessed 進行包裹,與使用者進行 turns 互動。[Claude Code 是一個 agent。Cursor 是一個 agent。Claude.ai 是一個 agent。] 代理程式(agent)是你實際與之對話的對象——它是動態的模型,為特定目的而配置。

與本字典中的大多數術語不同,「agent」並未命名機械零件。模型是一份包含 parameters 的檔案;harness 則是你可以指向的軟體。代理程式兩者都不是——它是你正在對話的單位。人們不斷將 AI擬人化,而代理程式就是擬人化的單位:你委託的事物、讀取你的訊息並回答的事物,以及「它又把組建搞砸了」當中的那個「它」。當你說代理程式做了某事時,你的意思是模型加 harness 做了這件事,但你將這個組合視為單一參與者來對待。

這個概念比這波 AI 熱潮還要古老。軟體代理程式——你委託其達成目標、代表你行動的程式——只要有 AI 的歷史,就一直是個概念。

避免使用: 「the AI」、「the bot」(太模糊——它們隱瞞了你指的是參數還是包裝後的東西)。

用法:

「你這次遷移是用哪個 agent?」

「本地用 Claude Code,UI 工作用 Cursor——底層是相同的模型,不同的 harness。」

系統提示詞

執行框架放在每次模型供應商請求之前的指示——也就是代理的常設任務簡報:它是誰、如何行動、能呼叫哪些工具、遵循什麼慣例。通常在整個工作階段保持穩定。

系統提示由執行框架供應商撰寫,而不是你;程式設計框架中的系統提示很龐大——常有數萬個詞元的行為規則、工具說明與邊界情況處理,而且每個回合都按輸入詞元付費。你的常設指示也會一起帶入:AGENTS.md 這類檔案會在工作階段開始時,載入到系統提示旁,因此模型在看到你的訊息前,就先一起讀過供應商與你的簡報。

因為每次請求都相同,它構成前綴快取的開頭——這也是執行框架在整個工作階段固定它,而不邊做邊改的部分原因。

模型受訓時會優先遵循系統提示,而非使用者訊息。因此,當代理堅持你從沒要求的慣例,或怎樣都改不了輸出格式時,通常是它在遵守系統提示,而你的訊息在這場爭論中輸了。有些執行框架可自訂,讓你完整存取系統提示,讀到代理真正被告知的內容,並加以修改。

用法:

「兩個執行框架,同個模型,同個提示,行為卻完全不同。」

「系統提示不同。一個偏向簡短程式編輯,另一個偏向解釋——差異就在那裡,在你的訊息到達之前就存在了。」

工作階段

與 agent 的一次有界互動運行。從空開始,累積訊息、tool results 以及讀取的檔案,並在 cleared、關閉或 compacted 成一個新工作階段時結束。工作階段就是 填滿 context window 的東西:如果上下文視窗是盒子,工作階段就是慢慢填滿它的東西。對於單一上下文視窗而言過大的工作

階段的訊息歷史記錄是代理程式的工作記憶。由於 model 是 stateless 的,因此它似乎記住的一切——你要求了什麼、測試說了什麼、它在三個回合前決定了什麼——都在訊息歷史記錄中,隨著每個 model provider request 重新發送。任何不在工作階段中的東西對代理程式來說都不存在。

該記憶隨工作階段結束而結束。新的工作階段從零開始:昨天工作階段結束時非常熟悉你的程式碼庫的代理程式,今天早上對此一無所知。生存下來的是 filesystem ——在一個工作階段期間寫入的檔案可以被下一個工作階段讀取,這正是 handoffs、memory systems 和 AGENTS.md 所依賴的。

你選擇工作階段何時結束。工作階段中的所有內容都會影響每個後續的 turn,因此在一個工作階段中完成的無關任務會留下會影響下一個答案的殘留物。每個工作階段一個任務可保持上下文相關;完成任務是清除的自然點。

用法:

「一個工作階段在崩潰之前可以運行多久?」

「取決於工作——專注的重構比開放式研究能保持更長時間的敏銳度。一旦工作階段臃腫,就進行交接或壓縮,不要勉強推進。」

回合

一個使用者訊息加上代理程式為回應所做的一切,直到它將控制權交還給使用者為止。包含一個或多次模型供應商請求——如果代理程式呼叫了工具,則會有很多次。釐清問題會結束該輪次;你的回覆則會開啟下一輪。階層為工作階段 > 輪次 > 模型供應商請求。

讓輪次值得被命名的原因在於,它的長度是由代理程式決定,而不是你。你交出一個訊息;代理程式決定在交出控制權之前要串接多少個工具呼叫。一個輪次可以是一句式的回答,也可以是二十分鐘的閱讀、編輯與執行測試。從兩個角度來看,這都是同一個特性:長輪次是讓暫時離開(AFK)工作得以運作的原因,而長輪次也是事情在無人監督的情況下出錯的地方——當代理程式交出控制權時,它可能已經背離了你的本意很遠。

輪次也是引導的自然單位。輪次內的所有事情都在沒有你的情況下發生;輪次之間的間隙就是你重新導向的地方。大多數執行環境會軟化這一點:你可以在輪次進行中斷開以停止代理程式並重新導向它,或者在它工作時輸入訊息,該訊息會在輪次完成時被讀取。如果你發現自己經常對輪次的結束位置感到不滿意,解決方法通常是要求較短的輪次——先擬定計畫,一次一步——用自主性換取更多可以進行引導的間隙。

用法:

「一個輪次花了兩分鐘?」

「它在那一個輪次中進行了十四次工具呼叫——每一次都是獨立的模型供應商請求。在代理程式最終將控制權交還給你之前,延遲會不斷累積。」

區段

第 3 節 — 工具與環境

環境

代理作用的世界——執行框架之外,代理透過工具結果感知、透過工具呼叫改變的一切。執行框架運行代理;環境則是代理工作的地方。`AGENTS.md` 這類檔案存在環境中,執行框架則負責把它載入上下文視窗。檔案系統是最常見的環境,但不是唯一一種(資料庫、遠端 API、瀏覽器工作階段都能是環境)。

代理只有在查看時才看得到環境。它對環境所知的一切都來自工具結果,因此它的認知是一組快照,每份只在擷取當下準確。如果檔案在代理讀取後改變——你手動編輯、建置步驟重新生成——代理仍會根據舊副本推理,直到某件事促使它重讀。代理自信描述一個早已變樣的檔案,通常就是這種情況:環境變了,快照沒變。

環境也是會持續存在的層——唯一始終有狀態的一層。工作階段結束時,其上下文就消失,但寫入環境的檔案會保留,供下次工作階段讀取——這就是記憶系統、交接產物與 `AGENTS.md` 所仰賴的機制。代理明天仍應知道的任何事,都必須進入環境。

你決定環境有多大。沙箱縮小環境,限制代理可觸及的範圍;新增工具則擴大環境,把資料庫或 API 納入。邊界內是代理能感知和改變的內容;邊界外的一切,對代理而言都不存在。環境為支援代理工作而設置得如何,就是程式碼庫的 AX。

避免:用「環境」指執行環境或執行框架本身——執行框架是包裝層,環境是工作空間。

用法:

「代理看不到測試環境的資料庫結構。」

「把它接進環境——給代理一個對測試環境限定唯讀的 `psql` 工具。執行框架沒問題,只是沒有可操作的對象。」

檔案系統

代理程式從中讀取、寫入並在其中執行的檔案與目錄樹狀結構——這是編碼代理程式的預設環境類型。AGENTS.md、技能、原始程式碼、建構腳本和工具設定都存放在檔案系統中。當框架「在你的專案中啟動」時,它就是將代理程式指向一個檔案系統。

代理程式僅透過工具呼叫與其互動——讀取檔案、寫入檔案、執行 Shell 命令。在工具呼叫載入它之前,磁碟上的任何內容都不在上下文視窗中,這讓代理程式能夠在遠大於視窗的儲存庫中工作:檔案系統容納所有東西,上下文只保留當前任務已讀取的內容。有些框架預設會將當前目錄的檔案名稱載入到上下文視窗中——不是內容,只是樹狀結構——它們充當上下文指標:代理程式可以看到存在什麼並讀取它需要的檔案。

而且它是與你共享的。代理程式編輯的檔案與你在編輯器中開啟並在 git 中進行 diff 的檔案是相同的——檔案系統是共同的工作區,你可以在這裡審查代理程式做了什麼。

用法:

「為什麼它沒有載入我的 AGENTS.md?」

「它是在不同的檔案系統上執行的——沙箱掛載的是父目錄,而不是專案根目錄。重新指向框架。」

工具

公開供[代理程式 (agent)]](#harness) 呼叫的函數——Read、Write、Bash、Search。工具是代理程式感知[環境 (environment)]](#agent) 並對其採取行動的方式:它除了透過[工具結果 (tool results)]](#environment)之外無法看見環境,除了透過[工具呼叫 (tool calls)]](#tool-result)之外無法改變環境。每個工具呼叫都會消耗額外的[模型提供者要求 (model provider request)]](#tool-call),因為結果必須先傳回給模型,模型才能決定下一步要做什麼。

多數編碼代理程式隨附的工具:

工具它的功能
Read將檔案內容傳回為工具結果
Write在[檔案系統 (filesystem)]](#model-provider-request)中建立或編輯檔案
Bash執行 Shell 指令並傳回其輸出
Search尋找在整個程式碼基底中符合某個模式的檔案或文字

一個工具由三件事定義:名稱、功能描述以及參數的結構描述 (schema)。控制代碼在每個要求中將這些定義傳送給[模型 (model)]](#filesystem) ,模型選擇工具的方式與它產生其他所有內容的方式相同——透過寫入[Token (tokens)]](#model) (在此情況下為帶有引數的結構化呼叫)。模型本身絕不會執行任何操作;控制代碼會讀取呼叫、執行函數並傳回結果。

工具清單決定了代理程式能做什麼。一個能力強大但工具集狹隘的模型只是一個狹隘的代理程式:它會透過它擁有的任何工具來路由所有事情,這就是為什麼代理程式如此高度依賴 Bash 的原因——Shell 是一種能夠觸及大部分系統的工具。若要乾淨俐落賦予代理程式某種能力,請為它新增一個工具;[MCP (MCP)]](#token)是從控制代碼外部外掛工具的標準。

工具定義在每個要求中都會佔用[上下文 (context)]](#mcp) ,因此在呼叫任何工具之前,大型工具集就已經有了常態成本——而且許多描述類似的工具會讓模型更難挑選出正確的工具。

用法:

「代理程式可以直接查詢 Staging 嗎?」

「在控制代碼中新增一個](#context) 工具,並將其範圍設定為對 Staging 進行唯讀存取。如果沒有對應的工具,代理程式對檔案系統之外的一切都是盲目的。」 `psql` 針對開源編碼代理程式 OpenCode 背後公司的規模化蒸餾攻擊,洩漏了儲存的 OpenAI …

工具呼叫

模型產生的輸出,指出工具名稱與引數——只是結構化文字。它本身不會做任何事;執行框架必須讀取並執行。模型會在一次模型供應商請求中產生它。

工具呼叫的生命週期:

步驟執行者發生的事
1模型從系統提示的說明得知有哪些工具
2模型發出呼叫——工具名稱加上引數,通常是 JSON——然後停止
3執行框架解析呼叫,並依權限模式檢查
4執行框架獲准才執行
5執行框架在下一次請求中,以工具結果傳回執行結果

代理工作的一個回合,通常是許多這類往返串接而成。

呼叫和其他輸出一樣,都是由下一詞元預測產生,因此也可能像任何模型輸出一樣出錯:不存在的路徑、命令不支援的旗標,或看似合理卻不正確的引數。執行框架執行的是寫下的內容,而不是原本的意思——路徑打錯不一定會妥善報錯,可能直接改到錯誤檔案。

用法:

「它說跑了測試,但檔案時間戳記沒變。」

「看看對話紀錄——它真的發出了工具呼叫,還是只描述有執行?模型會產生呼叫,但執行框架如果沒有執行,就什麼也沒發生。」

工具結果

執行框架執行工具呼叫後傳回的內容——檔案內容、命令輸出、錯誤。這是代理觀察環境的唯一管道。它會在下一次模型供應商請求中傳回模型,由模型決定如何處理。工具呼叫與工具結果是同一次交換的兩端,都在同一個回合內。

工具結果的生命週期:

步驟執行者發生的事
1執行框架執行工具呼叫——執行命令、讀取檔案
2執行框架擷取結果:輸出、內容或錯誤
3執行框架將它當成訊息附加至上下文
4執行框架在下一次模型供應商請求中,將完整上下文傳給供應商
5模型讀取結果並決定:再呼叫工具,或給最終答案

結果會在工作階段剩餘期間留在上下文中。工具結果通常是程式設計工作階段上下文的大宗:每次讀檔、執行測試和搜尋都完整加入,失去用處後仍持續占用詞元。幾個大型結果——冗長測試紀錄、整份讀入的生成檔案——會比對話本身更快把工作階段推向上下文視窗的邊緣。

因為模型只看得到結果,所以無法檢查背後環境。輸出若遭截斷、命令悄悄失敗,或執行框架傳回錯誤而不是內容,模型只會根據拿到的東西推理。代理對你的系統理解似乎有誤時,就該檢查工具結果:紀錄中某處會有一個結果,描述了與你知道的事實不同的情況。

用法:

「它推理時好像以為檔案是空的。」

「工具結果傳回的是權限拒絕,而不是內容。模型只看見錯誤字串——它沒有其他方式看檔案。」

MCP

模型上下文協定 (Model Context Protocol)。 一種將外部工具伺服器插入 harness 的協定 — agent 如何獲得超越 harness 內建的 tools。agent 從不「呼叫 MCP」;它呼叫工具,而 harness 剛好從 MCP 伺服器獲得了該工具。也公開資源(唯讀資料)和提示(可重複使用的範本),但工具提供是主要用途。

該協定解決了整合問題。沒有標準的話,每個 harness 都需要自己的 Linear 整合、自己的 Slack 整合、自己的資料庫整合 — 針對每一個分別編寫和維護。透過 MCP,整合只需編寫一次作為伺服器,任何相容 MCP 的 harness 都可以使用它。harness 連接到伺服器,伺服器宣告它提供哪些工具,這些工具就會與內建工具一起提供給 agent。

代價是付出 context。伺服器宣告的每個工具都以定義的形式出現 — 名稱、描述、參數架構 — 並且 model 只能呼叫它知道的工具。簡單的做法是預先將每個定義載入 context window:安裝幾個大方的伺服器,session 在你輸入任何內容之前就會開始帶有數千個 tokens 的工具架構,將 attention budget 花在任務永遠不會使用的工具上。

許多 harness 現在透過工具搜尋來緩減這個問題:上下文持有的不是完整的定義,而是可用工具的 context pointer — agent 透過名稱或目的搜尋工具,並且只在需要時才載入其定義。如果你的 harness 沒有這樣做,預付成本仍然適用,並且只啟用專案實際需要的伺服器是值得的。

用法:

"agent 需要從 Linear 讀取票證。"

"將 harness 設定為使用 Linear MCP server — 它將 Linear API 公開為 agent 可以呼叫的工具。省去了你編寫自訂工具包裝器的麻煩。"

權限請求

執行框架在執行未預先核准的工具呼叫前,向使用者顯示的內容。模型產生工具呼叫後,執行框架不立即執行,而是暫停詢問。核准就執行;拒絕則由執行框架把拒絕以工具結果回報模型。這是執行框架讓人類參與迴路、介入高風險或敏感操作的機制。

權限請求的生命週期:

步驟執行者發生的事
1模型產生工具呼叫
2執行框架依權限模式及已儲存核准檢查
3執行框架已預先核准:立即執行。否則:暫停並顯示請求
4使用者單次核准、核准工作階段剩餘期間,或拒絕
5執行框架執行呼叫,或將拒絕作為工具結果傳回

拒絕請求能引導代理。模型會像讀取其他工具結果一樣讀取拒絕並回應——嘗試其他做法,或詢問你的偏好。多數執行框架允許拒絕時附帶訊息,讓請求成為引導點:「不要那樣,改用遷移腳本」會在模型決定下一步的當下到達。

代價是,每項請求都得同步等待你。代理會阻塞到你回答;你在旁觀看時沒問題,不在時就麻煩——不斷觸發請求的代理,無法留著離席工作。權限模式就是調節鈕:哪些呼叫自由執行、哪些先問,最好再有沙箱,讓擴大自由執行範圍也安全。

用法:

「它卡在權限請求上十分鐘了——我剛才在開會。」

「這就是人類參與的代價。預先核准安全工具,讓請求只在真正有風險的呼叫時觸發。」

權限模式

代理模式中負責權限把關的部分——哪些工具呼叫會觸發權限請求,哪些能自動執行。這是模式系統最初的用途,之後執行框架才開始在上面綁定行為指示。

執行框架提供一系列階梯式模式:

模式讀取寫入與 shell典型用途
唯讀/規劃自動封鎖研究、規劃、審查
預設自動詢問日常受監督工作
自動編輯自動編輯自動,shell 詢問可信任儲存庫、機械式修改
「Yolo」/全自動自動自動沙箱、離席執行

選擇哪一階,是安全與中斷之間的取捨,兩種失敗方式都感受得到。太嚴,你就成為瓶頸:代理每隔幾秒就為無害讀取暫停,你開始不加思索地核准,而核准也失去意義——橡皮圖章集兩者之弊,只有干擾,沒有保護。太鬆,代理就會編輯你原本想先看的檔案,執行你原本想先看的命令。

寬鬆設定最適合沙箱,因為錯誤工具呼叫的影響範圍受控。在沙箱之外,多數人會選擇自動核准讀取,並對不可逆操作保留人類參與。

用法:

「每次 grep 都停下來,離席執行完全泡湯。」

「放寬唯讀工具的權限模式,寫入與 shell 繼續詢問。研究工作階段的大多數權限請求只是干擾。」

代理模式

一個用於形塑agent在執行階段運作方式的預設集——將permission mode與注入system prompt中的行為指令結合在一起。範例:對有風險的呼叫進行提示的預設值、封鎖編輯並引導代理進行研究的計畫模式(plan mode)、自動批准編輯的接受編輯模式(accept-edits)、自動批准一切的繞過權限模式(bypass permissions)(俗稱 YOLO 模式)。可以在mid-session切換。

這種綑綁正是區分模式與純粹權限設定的關鍵。權限模式只是一個閘道:它決定哪些tool calls可以通過。單獨一個閘道會製造出一個想要編輯卻無法編輯的代理——它提出寫入請求,遭到封鎖,然後嘗試另一種方式。注入的指令消除了這種欲望:計畫模式不只是封鎖編輯,它告訴代理目前處於規劃階段,因此它會進行讀取、提問和提出建議,而不是與閘道拔河。引導與閘道指向同一個方向。

實際上,隨著你在任務進展中的信任度改變,你會切換模式。同一個任務可以經歷多種模式:在方法仍在形塑時使用計畫模式,在最初的微妙編輯時使用預設提示,一旦代理表現出對變更的理解則使用接受編輯模式,在sandbox內進行AFK執行時則使用繞過模式。切換模式對你來說毫無成本:對話將在原處繼續,並帶有新的權限和新的指令。如果你發現自己在沒有閱讀的情況下批准了每一個提示,則說明模式設定得比你的實際信任度更嚴格;如果你不斷拒絕編輯,則說明設定得太寬鬆。

供應商術語:Claude Code 稱這些為「權限模式」,Codex 稱它們為「批准模式」——兩者都早於行為綑綁。

用法:

「我只是想要一個計畫,它卻一直在編輯檔案。」

「切換到計畫模式——它會封鎖寫入並停留在研究階段。」

「那稍後的 AFK 執行呢?」

「使用繞過模式,但只能在沙箱內部。」

沙盒

一個隔離的 environment,agent 在其中運行——例如容器、虛擬機器、用完即焚的 filesystem,或是權限受限的 shell。這能限制代理程式操作的影響範圍:即使代理程式執行了具破壞性的指令或抓取了惡意內容,損害也能被控制住。這正是讓 AFK 變得切實可行的安全基礎。

沙箱與 permission mode 從兩端解決了同一個問題。權限機制在操作執行前會先進行詢問;而沙箱則限制了操作一旦執行後所能觸及的範圍。權限機制需要你 in the loop——每一個提示都是一次中斷——而一個不斷詢問的工作階段幾乎談不上是自主運作的。沙箱消耗的是基礎設施而非注意力:隔離越強,需要提出的問題就越少。

隔離分為不同的等級:

等級它是什麼它包含的內容
受限 shell圍繞每個指令的作業系統級限制對專案外部的寫入、網路存取
容器全新檔案系統、未掛載憑證、用後即丟代理程式對自身機器所做的任何事情
虛擬機器 / 雲端完全獨立的機器,通常由運行平台提供一切,包括核心層級的逃逸

任何沙箱都無法包含的事項:合法離開沙箱的操作。擁有你的 git 憑證的代理程式可以執行 push;具備網路存取權的代理程式可以呼叫生產環境 API。在決定將其隔離得有多嚴密之前,請先決定什麼該跨越邊界。

用法:

「我想讓它在 bypass-permissions 的情況下運行一整夜,但我還沒準備好這樣做。」

「把它放進沙箱裡——全新容器、不掛載憑證、無對外網路。最壞的情況下,它也只是炸毀了自己的檔案系統,而你只要把容器丟棄即可。」

區段

第 4 節 — 失敗模式

逢迎

過度順從的 模型 輸出。原因在於 訓練:模型被塑造成偏好人類喜愛的答案,而人類傾向於喜歡附和勝過被指出錯誤。因此模型學到了順從會獲得獎勵——即使這種附和並不正確。

表徵為:

  • 在壓力下妥協 ——當你說「你確定嗎?」時,會推翻正確答案。
  • 讚美糟糕的輸入 ——在分析之前,就贊同你那漏洞百出的計畫非常出色。
  • 有偏見的框架 ——當你暗示這是你寫的時候,審查偏向正面;當你暗示是別人寫的時候則偏向負面。相同的產出,不同的評判。
  • 模仿 ——將你的錯誤重複回傳給你作為確認。

診斷測試: 如果沒有你的引導,模型會這樣說嗎?如果唯一改變的是你的語氣或框架,那是逢迎,而不是真正的分析轉變。

修正: 隱藏你的偏好。以中立的方式措辭提示——「檢視這段程式碼」而不是「這段程式碼好嗎?」。

避免: 將任何剛好討好你的錯誤答案稱為「逢迎」。沒有診斷測試,這個詞的價值並不比「錯誤」更高。

用法:

「它說我的重構計畫看起來很棒,然後我問『你確定嗎?』它就把整套說詞收回了。」

「典型的逢迎——它先是因為你聽起來很有信心而同意,然後又因為你聽起來懷疑而妥協。計畫的品質沒有變,變的是你的語氣。 清除 並在不透露任何傾向的情況下重新詢問。」

幻覺

自信地給出錯誤的 模型 輸出。有兩種不同原因與修正方法的類型:

類型出錯之處原因修正
事實性關於世界的虛構或錯誤事實——不存在的函數、錯誤的 API 簽章、偽造的引文參數化知識 缺口,通常超出 知識截止點載入正確的 上下文知識
忠實度輸出偏離了所載入的上下文知識、使用者的指令或模型先前的推理注意力退化;在 呆滯區 中惡化清除 或 壓縮

下一個 Token 預測 無論底層事實是否真實,都能產生流暢的輸出——模型內部沒有訊號表明它不知道某事,因此虛構的方法會以與正確方法相同的自信語氣出現。幻覺程式碼按其結構來看是合理的:如果它存在的話,API 就會是那個樣子,這正是它能夠滑過快速瀏覽層級審查,且僅在執行時失敗的原因。

你需要知道你看到的是哪種類型,因為針對其中一種類型的修正會讓另一種類型惡化。事實性意味著知識缺失:修正方式是添加上下文——文件、型別定義、檔案。忠實度意味著知識存在,但在爭奪注意力的競爭中落敗:修正方式是移除上下文。如果將忠實度誤診為事實性,你就會貼入更多文件,這會擴大上下文並使偏移更嚴重。當代理程式出錯時,在決定面臨什麼問題之前,請先檢查正確的資訊是否已經存在於上下文中。

避免: 將「幻覺」作為「錯誤」的純粹同義詞——未指明類型時,該術語沒有診斷價值。

用法:

「它在綱要上幻覺出了一個 `parseAsync` 方法。」

「事實性還是忠實度?」

「這個方法存在於我貼上的文件中——它只是在第四十 輪 後停止讀取它們了。」

「那就是忠實度。壓縮並重新載入,不用費心新增更多文件。」

參數知識

模型從訓練中「知道」、儲存在參數裡的內容。在訓練時便固定——模型看不到自己的參數,也無法更新。細節在壓縮中流失:數十億事實擠進固定數量的參數,罕見內容變得模糊。它是常見主題流暢表現的來源,也是冷門主題捏造內容的來源。與上下文知識相對。

參數知識不以事實形式儲存。訓練從未給模型資料庫供查詢;它調整參數,直到模型能良好預測文字,而能良好預測某主題文字的模型,行為就像知道該主題。知識可靠度取決於某事在訓練資料中出現的頻率:有數百萬個例子的主題能準確再現,只有少數例子的主題,模型則根據相似主題的樣貌猜測。對模型來說,再現與猜測是同一個過程,因此它分不清自己在做哪個。捏造答案與正確答案一樣流暢。幻覺就是模型猜錯。

參數知識也會老化。參數在知識截止日期就停止改變,因此那天之後發布或更名的函式庫不在其中,改過的 API 也仍被記成舊形式。

無論是太罕見或太新這兩種缺口,解法都相同:無法把知識加入參數,所以必須改以上下文知識提供。

用法:

「它寫 React 完美無缺,卻會編造我們內部 SDK 的方法。」

「React 在參數知識中很密集——有數百萬個訓練例子。你的 SDK 沒有,所以模型填入看似合理的形狀。把 SDK 文件載入上下文。」

知識截止

模型的參數知識所涵蓋的最後日期。截止日之後的函式庫、API 與事件,除非文件以上下文知識載入,否則都是捏造陷阱。每個模型版本都有自己的截止日期。

截止日期源自模型的製作方式:訓練將文字快照融入模型參數,之後參數便固定不變。模型不知道自己的知識有邊界——被問到截止日之後的事時,它不會拒絕,而是從最接近的已知內容推測。陷阱因此不易察覺:根據舊版函式庫寫的程式碼看似合理,通常也能編譯,卻會在已改變的部分失敗。

解法始終相同:把最新資訊放進上下文。載入更新紀錄、指向已安裝版本的型別定義,或讓代理從網路讀文件。上下文裡有資訊,總比參數裡沒有好。

用法:

「它一直寫 v3 SDK 語法——我們用的是 v5。」

「v5 在知識截止日期後才推出。把 v5 更新紀錄載入為上下文知識,否則它會一直根據舊版參數知識編造。」

上下文知識

agent](#agent) 可以直接從目前 context 讀取的事實——使用者的任務、agent 已讀取的檔案、tool results,以及在 session 開始時載入的 AGENTS.md 內容。相對於 parametric knowledge:parametric 是從參數中回憶出來的;contextual 則是從 window 中讀取出來的。當 agent 根據 contextual knowledge 工作時,Hallucinations 的發生率會大幅降低——答案就在眼前,而不是從模糊的記憶中撈取。

在這兩種類型的知識中,只有 contextual knowledge 是在你掌控之中的。參數是凍結的,因此要讓 model 具備它所缺乏的知識——內部 SDK、在 knowledge cutoff 之後發布的程式庫、昨天做出的決定——唯一的辦法就是將其放入 context 中。許多實務上的 AI 編碼工作歸根究柢就是:在模型需要時,把正確的事實呈現在它眼前。

當 contextual knowledge 與 parametric knowledge 衝突時,通常是 contextual 獲勝。貼上目前的 API 文件,模型就會遵循文件,而不是它對舊 API 的陳舊記憶——不過舊版本仍然可能會滲透進來,特別是在漫長 session 的深處。如果載入了文件後,agent 仍然不斷回復到過時的模式,這就是 parametric knowledge 洩漏到了 contextual 之外;重申修正內容或將其移近工作內容會有所幫助。

與 parametric knowledge 不同,使用 contextual knowledge 是需要付出代價的。載入 window 中的所有內容都會消耗 tokens 並競逐模型的 attention budget,因此載入越多並不代表自動越好——目標是讓相關的事實進入 window,而不是所有的事實。

只有在與 parametric knowledge 對比時才使用這個詞;否則直接說 context 即可。

避免使用:「工作記憶」——contextual knowledge 是現在在 window 中的內容;memory system 則是將跨 session 內容帶入其中的機制。規模不同,切勿混淆。

用法:

「為什麼我貼上文件時它就能完美搞定 API,不貼就會胡言亂語?」

「有了文件,這就是 contextual knowledge——照著頁面讀。沒有的話,這就是 parametric,而那些罕見的端點就會變得模糊。」

注意力關係

預測每個詞元時,模型會考量上下文中其他每個詞元——有些權重很大,有些幾乎沒有。兩個詞元之間的配對,稱為注意力關係;有意義的配對(「her」與「Sarah」,或 `getUser()` 呼叫與其 `function getUser` 定義)會比無關配對更強烈地互相影響。N 個詞元的上下文,大約有 N² 個關係。

模型表面上的理解就存在這些配對中。它能解析代名詞,是因為「her」和「Sarah」的注意力關係很強。它用正確引數呼叫函式,是因為呼叫位置與先前讀過的定義之間的關係在起作用。這些都不是查詢所得——每次模型供應商請求,每個配對都會重新計算。

N² 值值得仔細想想,因為成長速度比直覺快:

上下文大小配對數(約 N²)
1,000 個詞元約 100 萬
10,000 個詞元約 1 億
100,000 個詞元約 100 億

每個配對也不只計算一次。模型有多個注意力頭——前沿模型的確切數量未公開,但五十至一百個是合理猜測——每個頭都計算每段關係的自己的版本。因此,上表每個配對都在每個頭中重複。配對數量非常龐大。

對任何特定任務而言,只有少數關係重要。你的指示與它所管轄程式碼之間的配對,是少數重要關係之一;池中幾乎其他一切都是雜訊。而兩者成長速度不同:重要關係大致固定,總池量卻隨上下文大小呈平方成長。1,000 個詞元時,你關心的配對是百萬分之一;100,000 個詞元時,變成百億分之一。這是注意力預算背後的算術,而重要關係分得的占比過薄時,感受到的就是注意力衰退。

用法:

「它一直把差異中兩個 `user` 符號搞混——看來進入笨拙區了。」

「對,各呼叫位置與宣告的注意力關係正在互相干擾——詞元形狀相同,繫結不同。改掉其中一個名字,配對就會清楚。」

注意力預算

每個 token 都有有限的影響力預算,可以用來分配到 context 的其餘部分。對 one relationship 的強烈影響會留給其他人更少的影響力。這個預算是針對每個 token 的,不會隨著上下文增加而增長,這就是為什麼長 sessions 會被稀釋的原因。

把它想像成訊號和雜音。你的指令是一個固定音量的訊號;context window 中的每一個其他 token 都是互相競爭的聲音。指令從未變小——它仍然存在,字元對字元地存在——但隨著上下文增長,周圍的房間變得更大,訊號雜訊比隨之下降。在 10k token 上下文中曾是最響亮的東西的指令,在 150k 時變成了背景嗡嗡聲。這就是 attention degradation 背後的機制:模型並未忘記;訊號在雜音中迷失了。

這種症狀讀起來像是抗拒——代理程式在早期同意了一個限制,然後卻偏離了它,而重新貼上該限制只會短暫地起作用。原因不是指令;而是視窗中與之競爭的所有其他東西。

你可以控制的是進入上下文的內容。不服務於任務的內容並非中立的——它是覆蓋在所有有用內容之上的雜音。保持視窗很小,當累積的上下文不再符合其價值時進行 clear,並重申重要的限制,而不是相信它們早期的提及會持續有效。

用法:

「為什麼它一直忽略我貼在頂部的綱要?」

「我們已經身處 dumb zone——每個 token 的注意力預算都是固定的,但上下文持續增長。綱要上的訊號現在正與數千個較新的 token 競爭。」

注意力退化

隨著 session 增長,每個 token 的 attention budget 會分散到更多競爭者身上。任何單一 meaningful relationship 的訊號都會縮減;來自無關 context 的雜訊會湧入。相同的 model,相同的 parameters — 只是同一個盤子要餵飽更多張嘴。聰明區/笨拙 zone effect 的原因。

它表現為模型在對話中段變差:它遵循了一小時的約束開始失效,它重新詢問被告知過的事情,它寫出的程式碼忽略了稍早讀取過的檔案。模型沒有任何改變 — 唯一的變數是它現在所關注的上下文數量。

這是漸進式的,這也是為什麼很難在對話內部察覺的原因。沒有錯誤,也沒有閾值;每個 turn 都只比前一個稍微差一點,當錯誤變得明顯時,你已經在笨拙區待了一陣子。

你的復原方式是移除上下文,而不是加入更多。重新貼上被忽略的指令只會在同一個擁擠視窗中增加另一個競爭者,且只能提供短暫的幫助。有效的方法是:clear 並僅重新載入任務所需的部分,或者 compact,或者 hand off 給一個新的對話。將指令遵循能力的下降視為關於上下文長度的訊號,而不是關於模型的訊號。

用法:

「它已經深陷笨拙區 — 發明了類型檔案中不存在的泛型。」

「注意力退化。類型定義仍在上下文中,但其訊號已被我們之後新增的所有內容所埋沒。請清除並重新載入。」

智慧區域

在 session 的早期,agent 處於「聰明區」——敏銳、專注、記憶力良好。隨著工作階段增長,它會漂移到「笨拙區」:變得更草率、健忘、犯更多錯誤——以及更多的忠實性 hallucinations。相同的 model,相同的 harness——只是有更多的 context。這是 attention degradation 的實際感受。在前沿模型上,笨拙區通常從大約 125K-150K tokens 開始——儘管這仍有爭議。當工作階段膨脹時進行 Clear 或 compact;不要硬撐。

這種下降是漸進式的,這使得它很容易被忽略。沒有錯誤訊息,也沒有明顯的界線;代理程式只是開始表現得稍微差一點,然後是明顯變差。常見的徵兆:它忘記了你在二十個回合前給它的指令,重複它已經修正過的錯誤,或者自信地斷言上下文相矛盾的事項。因為這種下滑是平穩的,通常的反應是硬撐並重新解釋——這會增加更多上下文並使問題惡化。

這些區域不會追蹤 context window 的限制。工作階段可能已經深入笨拙區,而視窗的大部分仍然是空的:限制是 harness 拒絕繼續的地方,但品質在那之前很久就已經下降了。圍繞著聰明區進行規劃,而不是視窗——任務的實際預算是在其內部運作良好的 token,而不是它在技術上可以容納的 token。

聰明區是一個預算,無關的工作會消耗它。在工作階段中完成的每個任務都會消耗 token,因此在同一個工作階段中啟動第二個任務意味著在更接近笨拙區的地方啟動它。每個工作階段執行一個任務,可以讓每個任務都利用工作階段中最敏銳的部分。當單一任務大於一個聰明區時,請將其分割:在自然的邊界進行 hand off 或壓縮,並讓一個全新的工作階段來處理接下來的部分。

用法:

「它在前三個元件上表現完美,卻把第四個搞砸了。」

「你已經不在聰明區了——同樣的模型,只是現在深入笨拙區。壓縮並重新載入計畫,下一個元件就會順利完成。」

區段

第 5 節 — 交接

清除

結束目前的 對話階段並開始一個新的對話階段。下一則訊息將以一個空的對話階段和一個空的 上下文視窗開始。通常由使用者驅動。

清除是污染上下文的解藥。一個對話階段會累積所有東西:失敗的嘗試、錯誤的方向、過時的 工具結果、放棄的計劃。模型在每個 回合都會重新閱讀所有這些內容,而糟糕的歷史記錄會拖累新工作。在冗長的對話階段深入發展時,代理會變得更加模糊且更不聽話——你清楚給出的指示被忽略了,品質下滑,而催促它做得更好也沒有幫助,因為它正在涉足的噪音仍然存在於它的 上下文中。清除可以消除噪音。

清除不會抹去對話。大多數 封裝工具會將對話記錄保留在你的電腦上,因此抄本仍然可以閱讀或恢復。消失的是代理的工作狀態:模型是 無狀態的,所以新的對話階段對舊對話階段所知的一切一無所知。如果對話階段包含下一個階段需要的決策或進度,請先讓代理寫下一個 交接產物,然後透過指向它來開始新的對話階段。

比較 壓縮,它會將對話階段摘要到新的上下文中,而不是以空白開始。清除是更直截了當的工具:沒有任何東西被延續,包括垃圾。

用法:

「它一直卡在失敗的測試中循環。」

「直接清除它——用計劃文件和測試檔案開始一個新的對話階段。與現有的上下文抗衡沒有意義。」

接力

把代理的上下文,從一個工作階段轉移到另一個。承載機制各異——書面的交接產物、記憶體內摘要(壓縮)等等。這與清除不同,後者完全不轉移。原因也各異:切換角色(規劃者 → 實作者)、啟動離席執行、分散到平行工作階段,或騰出上下文視窗空間。

接收方工作階段從零上下文開始——模型是無狀態的,新工作階段看不到舊工作階段的任何內容。下一個工作階段需要的東西,都必須明確攜帶,其餘全部消失。「沒有回頭詢問的途徑」是影響承載方式的限制:新工作階段無法問舊工作階段當時的意思,因此攜帶內容必須能獨立成立。

機制形式特性
交接產物環境中的檔案在任何工作依賴它之前,你能閱讀並修正;可在多個工作階段重用
壓縮上下文視窗內的摘要自動且便宜;較難檢查;提供給單一後繼工作階段

不良交接最明顯的失敗是重新爭論:新工作階段重啟舊工作階段已定案的決策,因為攜帶內容記錄了決定什麼,卻沒有記錄為什麼。判斷交接品質,要看一個零上下文的工作階段能用它做到什麼。

用法:

「規劃工作階段越來越重——我應該繼續嗎?」

「做個交接。把決策寫進文件,清除,然後在新的工作階段讀取文件並開始實作。」

主要來源

原始形式的真實來源——程式碼、對話紀錄、原始日誌、實際的 API 回應。這不是對事物的描述,而是事物本身。與次要來源相對。

如果你想知道你的程式碼庫在做什麼,程式碼就是主要來源。文件、架構圖和 README 都是對它的描述——在編寫時準確,之後則隨時間逐漸過時。當代理程式自信滿滿地對你的專案斷言錯誤的事情時,要問的問題是它依據的是哪個來源:讀取文件的代理程式會繼承文件的過時性;讀取程式碼的代理程式則是在讀取當前的真實情況。

成本是阻止主要來源成為預設選項的原因。將其載入上下文視窗成本高昂——完整檔案、完整記錄、每一個計入輸入且競爭注意力預算的權杖。你付出的代價換來的是完整性:沒有任何內容被其他人對重要性的判斷所預先過濾。上個月寫的摘要無法包含今天變得重要的細節;但主要來源仍然包含。

當精確度很重要時——確切的簽章、實際的錯誤、引發問題的那一行——請尋求主要來源。管理上下文的大部分工作,在於決定何時為主要來源付費,以及何時次要來源就已足夠。

用法:

「代理程式說重試邏輯會以指數方式退避,但我看它一直在猛烈呼叫端點。」

「它是從設計文件中讀到這一點的。讓它指向實際的重試模組——當行為重要時,請從主要來源著手。」

第二手來源

對primary source的描述,距離一步之遙 — 描述程式碼的文件、描述抄本的摘要、描述搜尋結果的報告。載入context window的成本比它所描述的來源更便宜,且依建構具有損耗性:寫下它的人決定了什麼是重要的,而他們放棄的任何內容對於只有摘要的讀者來說都是不可見的。

許多context工程都是次要來源的製造。Compaction將session歷史記錄轉化為種子化下一個對話的摘要。Subagent在嘈雜的搜尋上燃燒自己的上下文並傳回簡短的報告。Handoff artifact將對話的決策濃縮成下一個對話讀取的文件。Memory systems將對話學到的東西提煉成筆記。每一個都做出相同的權衡:以忠實度換取餘裕。

次要來源會在兩種情況下失敗。它們是有損的 — 遺失綱架決策的壓縮摘要、未提及邊界條件的報告。而且它們會漂移 — 主要來源變更而描述沒有跟上,因此文件以本季的信心描述上一季的架構。當agent根據在任一方面失敗的次要來源採取行動時,它會自信地根據錯誤的資訊進行運作;解決方法是將其送回主要來源。

這兩種失敗都沒有讓次要來源成為錯誤。上下文視窗是有限的,而主要來源是昂貴的;沒有摘要、報告和交接文件,任何大型的東西都裝不下。技巧在於知道哪些細節可以在損失中存活下來 — 並且在無法存活時針對主要來源進行驗證。製作精良的次要來源攜帶了指向其原始來源的context pointer — 命名它所來自的抄本的摘要、命名它所描述的檔案的文件 — 因此當描述不夠時,讀者可以跟隨指標,而不是根據損失進行運作。

用法:

「交接文件說驗證已完成,但新的對話不斷發現損壞的權杖重新整理。」

「這份文件是次要來源 — 上一個對話寫下的是它相信的,而不是真實的。讓新的對話執行驗證測試並信任主要來源。」

接力工件

用作[交接 (handoff)]傳遞機制的文檔](#handoff) — 由一個[工作階段 (session)]寫入[環境 (environment)]](#environment) 中,供另一個工作階段讀取。[規格 (Specs)]](#session) 、[票證 (tickets)]](#spec)以及計畫文檔全都是交接成品。

編寫交接文檔的原因是:[模型 (model)]](#ticket)是[無狀態的 (stateless)]](#model) ,因此工作階段中的任何內容在[清除 (clearing)]](#stateless)它之後都不會保留。決策、限制、未完成的計畫——隨著承載它們的[上下文 (context)]](#clearing) 一起消失。環境會持續存在。將重要的狀態寫入檔案中,能將其移至下一個工作階段可以讀取的位置。

這個成品是[二手來源 (secondary source)]](#context) ——它是對工作階段工作的記錄,而不是工作本身。這就是為什麼它足夠小,足以向全新工作階段進行簡報,這也是它可能誤導人的原因:它記錄了寫入階段當時的信念,而它遺漏或弄錯的任何內容對讀者而言都是不可見的。在任何聲明重要的情況下,下一個工作階段應該對照[一手來源 (primary source)]](#secondary-source) (程式碼、測試)來驗證它,而不是直接繼承。

好的成品的編寫對象是零上下文的工作階段。使用具體的檔案路徑,而不是「我們討論過的檔案」。記錄決策內容與原因,這樣下一個工作階段就不必重新爭論。記錄已完成與未完成的事項。告知寫入階段該成品的去向會很有幫助:「為一個對此工作一無所知的全新工作階段編寫交接文檔」。

另一種傳遞機制是[壓縮 (compaction)]](#primary-source) ,它會在記憶體中進行摘要。此成品有兩個優點:它存放在磁碟上,你可以在任何事物依賴它之前進行讀取和修正;並且它可以重複使用——同一個規格可以向五個平行的工作階段進行簡報。

用法:

「我要如何在規劃[代理程式 (agent)]](#compaction)和實作代理程式之間分配這個任務?」

「讓規劃人員編寫一個交接成品——包含檔案路徑、決策、限制。實作人員的工作階段以指向該成品的指標開頭,並以它作為簡報來進行工作。」](#agent) [環境 (environment)]

Spec

一個描述多session工作內容的handoff artifact——說明正在建立什麼,而不是每個 session 如何完成各自的部分。隨著工作進展而變動。由tickets組成。

規格書的存在是因為 session 是一次性的,而大型工作不是。任何需要消耗一個以上context window心力的工作,都需要一個在context之外的歸宿——位於 agent 的environment中、能夠在clearing後存活的地方,無論那是 repo 中的檔案、GitHub issue,還是 agent 可以存取的 issue tracker。規格書就是那個歸宿:目標、限制、迄今做出的決定,以及帶有狀態的 ticket 清單。任何新的 session 都能讀取它,並在不繼承先前 session 累積雜訊的情況下,知道目前的工作進度。

規格書有其辨識度高的風格,大多繼承自團隊原本記錄事物的方式。「產品需求文件」(PRD)偏向面向使用者的內容與原因——功能、行為、驗收標準。「設計文件」或「RFC」則偏向技術層面——選定的方法、被否決的替代方案、取捨。規模較小時,帶有 ticket 檢查清單的簡單 `plan.md` 就能為多 session 功能發揮相同的作用。風格不如角色重要:對agent而言,這些都是同一件事——它在每個 session 開始時讀取的持久意圖陳述。

用法:

「這全部應該在同一個 session 內完成嗎?」

「不,把它寫成規格書——拆分成 ticket,每個 ticket 在各自的 session 中執行。試圖在單一 context 中完成整件事,在不到一半的時候就會進入dumb zone。」

票券

一個 handoff artifact,其範圍界定了單一的 session 工作。它可以獨立存在,或是作為 spec 的子項掛在其下。票證(tickets)可以封鎖同級票證,也可以被同級票證封鎖,因此工作順序是從其相依性圖表中推導出來,而不是透過線性計畫。

其定義上的限制是規模:單一工作階段。票證應該要在工作階段超出 smart zone 之前完成——而且這個限制是可以測試的。如果你票證上的工作階段在工作完成之前經常退化,那麼票證就太大了;請將它們拆分。如果每個工作階段在進行五分鐘的工作之前,大部分的 context 都花在設定上,那麼它們就太小了;請將它們合併。

一個好的票證是寫給沒有其他背景資訊的讀者看的。目標、驗收標準,以及指向相關檔案和決策的 context pointers——足夠讓工作階段在不需要重新推導上一個工作階段已知內容的情況下開始工作。

相依性圖表也是解鎖並行處理的關鍵。獨立票證(圖表的葉節點)可以同時在各自的工作階段中執行。這是同時執行多個代理程式的有效方法。在 software factory 中,票證被標記為就緒本身就是啟動其工作階段的觸發器。

用法:

「關於遷移規格書,我該從哪裡開始?」

「看看票證圖表——Schema 的變更會封鎖資料回填(backfill),資料回填會封鎖 API 切換。挑選一個葉節點並在上面執行一個工作階段。」

壓縮

在記憶體中完成的 handoff:前一個 session 的歷史紀錄會被總結,並由該總結來引導一個新的工作階段。依設計具備破壞性(Lossy):轉錄稿是 primary source,總結則是 secondary source——以細節換取記憶體空間。由使用者手動觸發,或透過 autocompact 自動觸發。

其機制:context window 是有限的,而一個長的工作階段會填滿它——每一個 tool result、每一次讀取的檔案、每一個錯誤的轉折都會留在歷史紀錄中。當它變得笨重時,harness 會要求 model 總結工作階段,丟棄原始歷史紀錄,並用總結來引導一個新的工作階段。任何未能進入總結的內容都會從上下文中消失。有些 harness 會在磁碟上保留舊的轉錄稿,並在總結中留下指向它的 context pointer 來減緩這個問題——次級來源會連結回其主要來源,因此總結遺失的細節可以透過重新讀取原始資料來恢復。

總結是由模型編寫的,因此可以透過提示詞(prompted)來控制。「保留 Schema 決策」會讓產生的成品更有目的性。時機也很重要——在階段邊界、計畫敲定後進行壓縮,而不是在任務進行到一半時。

對比於 clearing,後者會放棄一切並從冷啟動開始:壓縮試圖將要點帶過來;清除則押注於它們已經寫在某個更好的地方。

用法:

「Context 變得有點重了,但我還要通過測試。」

「在開始之前進行壓縮——將必須存活的內容寫入總結提示詞中,這樣新的工作階段就能保留 Schema 決策並捨棄探索過程。」

自動緊湊型

當上下文視窗接近滿載時,由執行框架自動觸發的壓縮。

執行框架會監看上下文視窗使用量。超過門檻——通常約 80%——就暫停,請模型摘要目前工作階段,再以摘要初始化新工作階段。工作接著繼續,彷彿什麼都沒發生。

但其實發生了。壓縮會遺失資訊,自動壓縮還會在你沒選定的時機遺失。手動壓縮通常發生在階段分界,你能告訴模型該保留什麼。自動壓縮則在任務中途、只要達門檻就啟動——可能正重構到一半,讓摘要自行決定哪些決策值得留下。典型症狀是:代理自信繼續,卻悄悄忘了你一小時前確立的限制,直到工作開始違反限制,你才察覺。

防禦方法是別讓它觸發。注意上下文指標,在自然分界手動壓縮,或把決策寫進磁碟上的計畫文件或交接產物,讓任何摘要都無法弄丟。多數執行框架也能自訂緩衝——把門檻提前、延後,或完全關閉自動壓縮——讓你調整觸發前保留的餘裕。

用法:

「它似乎不記得我們先前對結構定義的決定。」

「回合之間觸發了自動壓縮——早期決策被摘要,應該漏了些東西。重新載入計畫文件,或下次手動壓縮,自己控制保留內容。」

區段

第 6 節 — 記憶與引導

記憶體系統

一個嘗試讓 agent 在不同的 sessions 之間保持 stateful的系統。在工作階段期間將資訊持久化到 environment 中,並在後續工作階段開始時將其重新載入到 context window 裡,因此當使用者 clearing 工作階段後,代理程式仍能維持連續性。

記憶系統分為兩部分。寫入路徑:在工作階段中,代理程式會將學到的內容(你表達的偏好、關於專案的事實)記錄為環境中的檔案。讀取路徑:在工作階段開始時,harness 會將這些檔案或其索引載入回上下文視窗中。許多 harness 都內建了自己的記憶系統——Claude Code 的 `/memory` 就是其中之一——但你也可以自己建構:一個筆記目錄加上 AGENTS.md 中的一條查閱指示。

這適用於任何常駐載入內容的相同權衡取捨。記憶會不斷累積,因此大多數系統會載入單行索引,並將主體內容留在 context pointers 後方,而不是全部內嵌。而且記憶是 secondary sources,因此會出現漂移:3 月記錄的事實,在專案已經往前推進後的 6 月載入時,仍帶有相同的信心水準。記憶系統需要像 AGENTS.md 一樣進行修剪。

用法:

「我一直得重新告訴它我用的是 Postgres,而不是 MySQL。」

「連接記憶系統——在第一個 turn 將它學到的內容寫入 filesystem,並在工作階段開始時重新載入它。model 本身是 stateless的;記憶層偽造了連續性。」

AGENTS.md

中的一個檔案,[控制代碼 (harness)]](#environment) 會在[工作階段 (session)]](#harness) 開始時將其載入[上下文視窗 (context window)]](#context-window) 中——這是專案對[代理程式 (agent)]](#session) 的長期簡報。這是跨控制代碼的慣例;某些控制代碼也有自己的變體(Claude Code 的變體是 CLAUDE.md)。

因為它會自動載入,所以這是避免在不同工作階段中重複自己的方法之一。[模型 (model)]](#agent)是[無狀態的 (stateless)]](#model) ——你在一個工作階段中給出的修正,在下一個工作階段中就消失了,最後你得對每個新工作階段重複說明專案使用的是 pnpm、測試是以特定旗標執行的、某個目錄是自動產生的且不應被更動。當你已經為同一件事修正過代理程式兩次時,該修正就是 AGENTS.md 的候選行。

適當的內容是代理程式無法從程式碼中推導出來的任何事物:建置與測試指令、程式碼基底未明確顯示的慣例、嚴格限制(「絕不要編輯產生的客戶端」)。內容應簡短且具陳述性——它是簡報,而不是說明文件。

其權衡取捨在於其中的所有內容隨時都在載入中。指令會不斷累積,其中多數與任何特定任務無關,而冗長的 AGENTS.md 不僅消耗 Token,還會自我稀釋——上下文中的指令越多,模型遵循其中任何一條指令的可靠性就越低。

應避免:

將 AGENTS.md 用於應該[漸進揭露 (progressively disclosed)]](#stateless) 的內容——其中的任何內容在每個[回合 (turn)]](#progressive-disclosure) 、每個工作階段中都要付出 [Token (token)]](#token) 成本,無論該工作階段是否需要它。風格指南可以改放在[技能 (skill)]](#turn)或[上下文指標 (context pointer)]](#skill) 後面;請將 AGENTS.md 保留給適用於所有地方的內容。

用法:

「為什麼每個工作階段一開始就燒掉了 4k 個 Token?」

「檢查 AGENTS.md——有人把整個風格指南貼在裡面,而不是把它放在技能後面。」](#context-pointer) [控制代碼 (harness)]

漸進式揭露

只載入agent現在需要的context,並透過context pointers指向其餘部分。這借鏡自 UI 設計,意思是只向使用者顯示與其目前任務相關的控制項,並將其餘部分隱藏在點擊之後。

這項技術的存在是因為上下文的成本是雙重的。前端載入的每個token在每個turn中都被計費為input tokens,且無論代理程式是否需要,每個 token 都會消耗attention budget。塞滿完整風格指南、部署執行手冊和資料庫慣例的AGENTS.md會降低代理程式處理所有這些事務的能力——對當前任務重要的指令被無關的指令稀釋了。蛛絲馬跡就是代理程式忽略了你明知在其上下文中的規則:它們在裡面,但被埋沒了。

漸進式揭露顛棄了這種做法。保持常駐載入層很小——每個主題一句話,並指向詳細資訊所在的位置。代理程式在編寫元件時會讀取風格指南,在部署時會讀取部署執行手冊,而在修復測試時兩者都不讀。Skills是內建於harness中的模式:每個session載入簡短描述,只有在觸發時才載入完整指令。

用法:

「我應該把整個風格指南傾倒到 AGENTS.md 中嗎?」

「不用——漸進式揭露。將風格指南作為代理程式實際需要編寫元件時才載入的技能來參考。AGENTS.md 在每個 turn 都要支付 token 成本。」

上下文指標

文件中的一個提及點指向另一個提及點,因此agent可以將其拉入context window,僅在任務需要時才調用。progressive disclosure這個單元就是建立在基礎之上的。

使用指標(而不是內嵌內容)的原因是成本。指標是上下文視窗中的一行。其背後的檔案可能有數千個tokens,但在代理真正跟隨該指標之前,這些 token 是免費的。如果在AGENTS.md中內嵌一個 2,000 token 的執行手冊,那麼每個session都要為其付費;將其替換為「部署流程:參見 `internal/deploy.md`」,則只有執行的 session 才會載入它。當任務匹配時,代理會透過tool call跟隨指標。

一個指標要能運作需要兩個部分:穩定的路徑,以及足夠的描述,讓代理知道跟隨它是值得的。裸露的路徑是代理沒有理由跟隨的指標;沒有內容提示的「參見 `internal/deploy.md`」會被需要它的 session 跳過。編寫該行時應符合任務呈現的方式:「發布、部署或復原 — 請先閱讀 `internal/deploy.md`」。

只要你仔細觀察,指標無處不在:AGENTS.md 中的行、skill描述(工作具(harness)載入描述;skill 本體在其後面等待)、目錄列表中的檔名、文件之間的連結。

指標也可以將secondary source繫結回衍生出它的primary source — 命名原始逐字稿的壓縮摘要、描述其來源檔案的文件。這使得次要來源的資訊遺失是可以復原的:當摘要證明不夠用時,代理會跟隨指標並閱讀原文,而不是從摘要保留的內容中工作。

避免:「reference」— 太過枯燥;無法傳達跟隨它會帶入更多上下文的意思。「Portal」— 太過華麗。

用法:

「AGENTS.md 變得越來越龐大了。」

「其中大部分應該是上下文指標,而不是內容。保持常駐規則內聯;將部署執行手冊和樣式指南轉為 skills,並留下一個上下文指標。」

技能

一個打包為單元的教導能力——用於把一項任務做好的指令與資源,保留在環境中,直到上下文指標將其拉入當前任務的上下文視窗。這是漸進式揭露在框架中的單位。

技能是一個開放標準,定義於 agentskills.io——最初由 Anthropic 開發,自此被大多數主要框架採用,因此編寫一次的技能可以在它們之間通用。格式是一個包含以下內容的資料夾:

  • 一個 `SKILL.md` 檔案——詮釋資料(至少包含名稱和描述)加上指令本身
  • 選用:代理程式可以執行的腳本
  • 選用:指令指向的範本與參考資料

預設情況下,只有名稱和描述位於上下文中。當代理程式的任務相符時,它會載入其餘部分。在此之前,該技能幾乎不佔用任何空間——無論其完整指令有多大,都只需一兩句話的權杖。

這將技能與 AGENTS.md 區分開來,後者無論任務為何都會被載入到每個工作階段中。技能是在出現特定類型的工作時(發布、搭建新服務、編寫遷移)才會被讀取,其餘時間則被忽略。

避免:「工具」——工具是代理程式呼叫的東西;技能是它讀取的指令。

用法:

「我應該把部署手冊放在哪裡?」

「作為一個技能——代理程式僅在任務涉及部署時才載入它。如果在 AGENTS.md 中,對於我們每週使用一次的東西,它會在每個輪次上消耗權杖。」

子代理

由另一個代理透過tool call產生的agent。在其自己的context window的自己的session中執行,並回報單一tool result。與handoff不同 — 父系明確期望有回傳;handoff 沒有回傳路徑。無法產生進一步的子代理 — 樹狀結構只有一層深。子代理的存在是為了隔離context,而不是為了組合階層。

重點是將嘈雜的工作排除在父系的上下文之外。廣泛的搜尋或冗長的檔案讀取遠征會產生頁面的工具結果,其中大部分只有在找到答案時才重要。在父系內部執行,所有內容都會在對話的其餘部分留在父系的上下文中。在子代理內部執行,雜訊會填滿一個拋棄式的視窗 — 只有最後的報告才會進入父系的上下文。報告是secondary source:父系獲得的是子代理對其所發現內容的描述,而不是原始結果,因此報告遺漏的任何內容對父系來說都是不可見的。

子代理也可以同時執行 — 父系可以一次將多個子代理散開到獨立的工作片段上。

用法:

「grep 結果正在炸毀我的上下文。」

「產生一個子代理來進行搜尋 — 它將在雜訊上燃燒它自己的上下文視窗,並回報你實際需要的兩個檔案路徑。」

區段

第 7 節 — 工作模式

人在迴圈(Human-in-the-loop)

一種工作模式,其中一個或多個人類在session期間與agent進行配對——即時進行檢閱、重新導向或協同合作。人類全程參與,而不只是單純把關個別動作。

這與AFK工作形成對比,在後者中,代理程式在無人看管的情況下運行,而你事後再評估結果。人在迴圈中(Human-in-the-loop)意味著在問題代價還小時就攔截它們:你看到代理程式拿錯了檔案、看錯了需求,或是開始走向死胡同,於是你用一句話就能重新引導它——而不是發現在那個錯誤上已經建立了一個充滿自信、長達二十分鐘的工作成果。代理程式無法可靠地知道自己何時偏離正軌;若放任不管,它們往往會繼續往前衝,而不是停下來詢問。

哪種模式合適取決於工作內容。規格明確、低風險且易於驗證的任務適合AFK。至於模稜兩可、不可逆,或是你很難檢閱最終成果的任務——例如資料庫結構遷移(schema migration)、棘手的設計決策,或是任何觸及生產環境的事情——則適合留在迴圈中。這項判斷基本上取決於:走錯路的代價有多大?你又會多晚才發現它?

有些工作本質上就在迴圈中,因為你的反應就是輸入內容。Grilling只有在你親自在場回答問題時才行得通;prototyping也只有在你親自在場對產出做出反應時才有效。

留在迴圈中需要消耗你的注意力,這是稀缺資源。提升代理程式使用效率的一部分工作,是透過計畫、automated checks以及最後的human review,安全地將更多工作移出迴圈,而不是全程監督。軟體工廠(software factory)透過從觸發條件開始啟動工作階段,將此概念進一步推進,因此甚至連啟動工作都不需要你參與。

用法:

「這要放著讓它AFK跑一整夜嗎?」

「不行,這是資料庫結構遷移——保持人在迴圈中。我想看每一個步驟,如果它選錯了要回填資料的欄位,我好進行導向。」

AFK

鍵盤外(Away from keyboard)。一種工作模式,指使用者啟動一個 session 並讓 agent 無人看管地運行。AI 編碼的產出倍增器 — 當你在睡覺、吃飯或處理其他事情時,許多 AFK 工作階段可以並行運行。通常需要寬鬆的 permission mode 加上 sandboxing 才是安全的。

當你不在場時,代理會以不同的方式處理模稜兩可的情況。當你在觀察時,一個模稜兩可的決定會作為一個問題浮現,你來回答它;一旦你走開了,代理就會選擇一個預設值並繼續運行,之後的每一個決定都建立在該猜測之上。典型的失敗是回來時發現數小時完成的、自信的工作,是建立在前十分鐘所做的一個錯誤決定上。這項工作並不馬虎 — 它是連貫的,只是對錯誤的事情保持連貫。

由於你在運行期間無法提供輸入,請在運行前後提供。之前:事先解決模稜兩可的情況 — 一場 grilling 工作階段、一份書面的 spec — 這樣代理單獨填補的空白就會減少。期間:automated checks 和 automated review 代替了你沒有給予的注意力,對可以用機械方式捕捉的問題進行快速失敗。之後:運行以可審查的事物結束 — 一個 PR,而不是已經合併的變更。AFK 並不消除 human review;它將所有審查延遲到最後,這就是為什麼最後到達的東西必須值得審查的原因。這也是為什麼 AX 在 AFK 運行中最為重要的原因 — 在無人看管的情況下,環境是代理獲得的唯一支援。

避免使用:「背景代理」("background agent")— 以機器為中心(「在背景運行」)而不是以人類模式為中心(「使用者已離開」)。AFK 指出了重要的事實:使用者沒有在看。

用法:

「我正在讓這個 AFK 運行 — 三個在沙盒中運行的代理進行重構,早上再審查 PR。」

「Bypass permissions?」

「對,唯讀 filesystem,無網路。」

自動檢查

在 environment 中執行的確定性驗證——測試、型別檢查、Linter、建置、pre-commit 鉤子。通過/失敗,沒有主觀判斷。這是 agent 無需牽涉其他人即可進行自我修正的信號。不穩定的測試(flaky test)是壞掉的檢查,而不是非檢查;自動檢查在 [設計上] 是具備確定性的。

自我修正以循環的方式運作。代理程式進行變更,以 tool call 執行檢查,而失敗輸出會落在其 context window 中——包含檔案與行號的型別錯誤、帶有預期與實際值的失敗斷言。這對代理程式來說已經足夠修正問題並再次執行檢查,周而復始直到通過,過程中沒有人類介入。確定性正是讓循環值得信賴的原因:相同的程式碼總是產生相同的判定,因此通過是有意義的。不穩定的檢查會破壞這點——代理程式會「修正」本來沒問題的程式碼,或者在真正失敗後繼續重試。

這就是為什麼好的檢查是程式碼庫 AX 的很大一部分。處在具有嚴格型別、快速測試套件和 linter 的儲存庫中的代理程式,在你看到之前就能攔截大部分自己的錯誤;而在沒有這些東西的儲存庫中的代理程式,會直接出貨它產生的任何東西。這種差異在 AFK 運行中最為重要,此時檢查是運行期間發生的唯一驗證。但檢查只能攔截它所斷言的內容——綠色檢查代表斷言的屬性成立,並不代表程式碼是正確的。主觀判斷上的落差正是 automated review 和 human review 派上用場的地方。

避免: 「回饋迴圈(feedback loop)」/「背壓(backpressure)」——兩者都將檢查與審查混為一談。避免:「測試」——測試是自動檢查,但並非所有自動檢查都是測試。

用法:

「代理程式在 AFK 運行中不斷出貨有問題的程式碼。」

「有哪些自動檢查連線到了 sandbox?」

「只有單元測試。」

「加上型別檢查和 lint——它在 PR 落地之前就會從中自我修正。」

自動審查

審查另一個代理工作的agent,通常使用不同的model或system prompt。非決定論的:它會形成判斷。可在任何地方執行 — PR 合併前、提交歷史記錄的後置、對話中途作為subagent。CI 中的 LLM-as-judge 是自動化審查,而不是automated check;斷言 做什麼 決定了類別,而不是它在哪裡執行。

與工作代理的分離正是它起作用的原因。要求寫程式碼的代理去審查它自己的工作起不了什麼作用 — 產生錯誤的session也包含了產生該錯誤的推理,而代理會將自己的結論讀回作為確認。擁有全新context window的審查者沒有這種依附:它以陌生人的方式看待 diff,這正是審查所依賴的。不同的模型或審查專用的系統提示進一步強化了這一點 — 不同的盲點,以及針對你實際關心的事物(安全性、API 契約、效能)而非模糊的「尋找問題」所劃定的系統提示範圍。

它介於其他審查層之間。自動化檢查是決定論的,並能抓出可以透過機械方式斷言的問題;human review成本高昂且擴充性最差。自動化審查位於中間:它以機器成本抓出具判斷性質的問題 — 誤導的函數名稱、遺漏的邊界條件。因為它是非決定論的,它可能會遺漏事情並標記出非問題;把它當作在人類查看之前提高底線的過濾器,而不是取代底線的閘門。

避免: 「AI 審查」/「代理審查」 — 太過模糊,無法與工作代理本身區分開來。

用法:

「我們從AFK執行中收到了太多糟糕的 PR。」

「在合併前新增一個自動化審查步驟 — 不同的模型、獨立的系統提示,範圍限定在安全性和合約變更。」

人工審查

使用者閱讀代理產生的程式碼,並形成判斷。讀差異或變更檔案才算;讀代理描述自己做了什麼不算——敘述不是產物。描述是由受審方撰寫的次級來源;差異才是第一手來源,審查意味著閱讀它。

代理提升了程式碼產量,因此審查成為瓶頸。一個實用想法是分層採取不同審查策略。自動化檢查攔截機械式錯誤,自動化審查攔截可描述的問題,人類審查則保留給只有你能判斷的事——這項變更是否正確、做法是否適合程式碼庫、它究竟是否該存在。

愈早審查,成本也愈低。工作開始前讀計畫,或途中讀小幅差異,只需幾分鐘;離席執行結束後再挖掘完成的分支,會花更久。審查關卡放在哪裡,是人類參與的決策,不是事後補想。

避免:單說「程式碼審查」——無法區分人類或自動化。

用法:

「我人工審查過離席執行的輸出。」

「你讀的是差異,還是只有摘要?」

「差異。摘要說刪除了無用程式碼——結果那個函式其實有被生成檔案呼叫。」

氛圍程式設計

一種工作模式,其中使用者在沒有經過human review的情況下接受agent的程式碼。Diff被視為不透明的——重點在於程式是否能運作,而不是裡面寫了什麼。Automated review與automated checks可能仍在執行,但氛圍編碼(vibe coding)對兩者皆未置可否。

這個詞源自 Andrej Karpathy,他在2025年初創造了這個詞:「完全順從氛圍」,並且「忘記程式碼本身的存在」——描述你想要的,接受回傳的內容,並透過執行它來進行評估。

氛圍編碼以檢查換取速度。閱讀diff通常是代理驅動工作中最慢的步驟,因此捨棄它就能消除主要的瓶頸。對於失敗代價低廉的程式碼——prototypes、一次性腳本、內部工具——這是一個合理的權衡。風險會隨著程式碼的壽命與利害關係而擴大。

代價會在之後出現。透過氛圍編碼產生的變更會累積到一個沒有人讀過的程式碼庫中,而行為又是唯一被檢查的事物——因此任何行為無法浮現的問題,例如寫入記錄檔的機密、遺漏的邊界情況(edge case),或是默默出錯的資料處理,都會在未被察覺的情況下上線。當有人第一次對系統進行除錯時,也就是第一次有人閱讀這些程式碼的時候。隨著人工審查消失,任何仍在執行的自動化驗證——測試、型別、自動化審查——就成了程式碼通過的唯一關卡。這種態度套用到整個程式碼庫,或其中的一部分,而其變更來自software factory時,這就是一個dark factory。

避免:將「vibe coding」當作「低品質AI編碼」的同義詞——這個詞指的是審查態度,而不是產生的程式碼。

用法:

「你有看它在驗證流程裡改了什麼嗎?」

「氛圍編碼的——登入還能用,這就是我有檢查的全部了。」

「推送前先讀一下diff,靠感覺搞驗證就是機密外洩到日誌檔的原因。」

設計概念

使用者與代理對正在打造之物所共享的理解,但獨立於任何資產。這是 Brooks 的用語(The Design of Design):對話、交接產物與程式碼,都是試圖捕捉或達成設計概念的資產,但它們都不是概念本身。設計概念的品質,能從建立它的對話品質感受到。

這個詞指出一種熟悉挫折背後的落差:代理完全照你要求寫出來,結果仍然不對。常見原因是,你還沒完全想清楚自己要什麼。你腦中的設計概念尚未完整——提示描述了已想通的部分,卻沒提還沒想通的部分。代理因為沒有可對齊的東西,便用自己的假設填補沉默。沒有任何機制故障。沒有共享的設計概念,是因為當時根本還沒有完整概念可供分享。

你能像與同事合作一樣,判斷設計概念是否已共享:對方開始用你會採取的方式,回答你還沒問的問題。在那之前,工作就是對話——盤問是刻意進行的版本——而太早撰寫規格,只會把不一致封存成更持久的資產。設計概念也會隨學習而移動;資產落後於它,因此忠實呈現上週理解的規格,仍可能誤導這週的工作階段。

用法:

「它完全照我要求寫,結果還是不對。」

「你們還沒共享設計概念——它在用假設填空。繼續談,直到取消、退款、部分履約在你們之間都對齊了,再讓它寫規格。」

燒烤

一種與代理程式共同開發設計概念的技術:代理程式以蘇格拉底式的方式對使用者進行訪談,一次一個決策,並為每個決策提出建議答案。放慢對完成計畫的衝刺速度——在概念穩定之前,不會編寫任何交接產出物。

這項技術的存在是因為代理程式會默默地填補空白。當被要求根據兩行提示詞編寫規格說明時,代理程式不會停下來處理你尚未做出的決策——它會挑選預設值並將其寫入。結果看起來很完整,而且猜測與選擇無法區分,所以你很晚才會發現它們:在審查時,或者當建構的功能以你從未選擇的方式處理邊緣情況時。盤問顛覆了這一點——代理程式必須提問,而不是猜測。

這是一種人在迴圈中的技術:你的答案就是輸入。當對話中無法回答某個問題時——你必須親眼看到該事物——請切換到原型製作。

用法:

「它直接去寫規格說明,結果把取消邏輯搞錯了。」

「先盤問它——在它將任何內容提交到文件之前,讓它向你詢問部分取消、退款和時間安排。在對話中解決比在程式碼中解決更便宜。」

原型製作

當對話無法充分呈現細節、需要一個實際成品來討論時,讓代理快速做出粗略版本。

盤問透過對話釐清設計決策。對話成本低,卻無法呈現所有細節:有些問題不能只靠文字回答——互動感受如何、API 的設計在實際呼叫程式碼中是否順手、版面能否承受真實的資料量。訪談碰到某個問題,而你的誠實答案是「我不知道,得看到才知道」。過了這個點,討論就只會打轉。不如讓代理把東西做出來,親自看看,再帶著答案回到對話。

代理降低了製作成本,因此這個做法才變得實用。以前要花一天才能做出的粗略模型,如今幾分鐘就能完成,值得經常採用。這是一種人類參與的技術:原型存在的目的,就是讓你實際體驗並給出反應。

通常不會只看一次就結束。圍繞原型反覆迭代——給出反應、要求修改、再次回應——讓每一輪都能對照真實成品釐清另一個決策,細節程度也比單靠對話更高。

原型不必每個部分都很粗糙。你可以把正在評估的部分做到正式產品的品質;決策確定後,剛才試用的元件或 API 就能移入真正的程式碼庫。因此,原型也是規格不可或缺的參考材料。

用法:

「我們已經花半小時爭論,這個設定精靈應該放在一頁,還是分成三個步驟。」

「光說無法定案——讓代理把兩種版本都做成原型。我們實際點過,五分鐘就知道了。」

DX

開發者體驗 — 程式碼庫及其工具鏈讓人類能夠順利完成工作的容易程度。良好的 DX 包含快速的回饋、清晰的錯誤訊息、能解答你心中疑問的文件,以及一次就成功的設定。這個術語早於 AI 編碼;它收錄在此字典中主要是作為 AX 的對照。

DX 是人與程式碼庫之間的互動 — 僅此而已。這兩個受眾之間的主要差異在於,人類是具狀態的而代理程式是無狀態的。人類學習一次程式碼庫並將該知識帶入之後的每一天,這就是為什麼糟糕的 DX 能夠存活的原因:他們透過批次推送來繞過緩慢的 CI,透過在 Slack 上問一次來繞過缺失的文件,透過記住東西的位置來繞過令人困惑的結構。因應措施累積下來,團隊最終能在一個與他們對抗的程式碼庫中維持生產力。

代理程式面對同一個程式碼庫時,卻沒有任何累積。在各個工作階段之間保持無狀態,代理程式每次都從頭重新學習程式碼庫 — 它受益於快速的測試套件和清晰的錯誤訊息,但它昨天弄懂的任何事情都會消失,除非它被寫入環境中,而代理程式只能透過工具結果來感知該環境。這就是 AX 所指的差距:當開發者是代理程式時仍能存活的 DX 部分,加上人類沒有的考量,例如保持上下文視窗乾淨。

重疊之處意味著 DX 投資通常能免費改善 AX — 嚴格的型態、快速的測試和可預測的結構對兩者都有幫助。分歧之處意味著它並不總是如此:一份精美的上手文件對人類有一週的幫助,但對代理程式完全沒有幫助,除非可以從 AGENTS.md 存取它。

用法:

「我們的 DX 很好 — 新進員工在一週內就能展現生產力。」

「有生產力是因為有人在那週陪著他們。代理程式沒有那一週;請分開檢查 AX。」

AX

代理程式體驗(Agent experience,簡稱 AX)——環境為代理程式在程式碼基底中做好工作而設定的完善程度。這是對應於DX(開發者體驗)的代理程式端。當同一個代理程式在某個儲存庫表現良好而在另一個儲存庫表現糟糕時(相同的模型,相同的測試工具鍊),差別通常就在於 AX。本能會讓人怪罪模型或重寫提示詞;但解決方案往往在於儲存庫本身。

良好的 AX 有三個主要面向:

面向良好的 AX 長什麼樣子
自動化檢查快速、具決定性的自動化檢查(型別、測試、程式碼檢查),代理程式可以在沒有人類介入的情況下進行自我修正
架構代理程式無需閱讀所有內容即可導覽的程式碼基底:可預測的結構、大量隱藏在小型介面後方的行為、能明確表達功能名稱的命名
自由上下文保持精簡的AGENTS.md、技能和工具,以便將大部分的上下文視窗留給任務使用,讓代理程式保持在智慧區,而不會陷入癱瘓

AX 與 DX 重疊——良好的檢查和乾淨的架構對雙方都有幫助——但牠們分道揚鑣。人類可以容忍部落知識、緩慢的 CI 以及「去問莎拉關於計費模組的事」;代理程式不行。代理程式無法從 IDE 工具提示或漂亮的儀表板中獲益;牠們需要以文字形式呈現在工具結果中的失敗。程式碼基底可能具有良好的 DX 但糟糕的 AX。

避免:將 AX 視為 DX 的同義詞——不同的受眾需要不同的投資。

用法:

「這個代理程式在 API 儲存庫中寫出優秀的程式碼,但在前端儲存庫中寫出垃圾。」

「API 儲存庫有嚴格的型別和快速的測試套件;前端兩者皆無,且有四十個隨時載入的技能。這是 AX 的差距,而不是模型的問題。」

軟體工廠

一種工作系統,其中代理程式工作階段是由觸發條件(建立問題、排程、CI 失敗、另一個工作階段結束)而非由人類啟動,因此更多工作可以在離線(AFK)狀態下運行,而人類的注意力則花在保留的人在迴圈中決策上。

如果沒有工廠,每個工作階段的啟動都是因為有人啟動了它。即使是完全離線的工作,也必須等待有人開啟工作階段、將其指向票券並使其開始運行。團隊希望交付的成果超出了這種方式的限制。工廠將人類從啟動工作階段中解放出來,但不一定從其他任何事情中解放出來。

常見的觸發條件及其啟動的工作階段:

觸發條件它啟動的工作階段範例
建立或標記問題探索、臭蟲修復、實作標記為 `ready-for-agent` 的問題會獲得一個開啟 PR 的工作階段
排程(cron)定期維護每晚修復一個 Linter 規則
CI 失敗或監控警報診斷、嘗試修復主分支上的建置失敗會獲得一個找到破壞性提交並提出修復方案的工作階段
另一個工作階段結束後續工作一個代理程式開啟的 PR 會觸發自動化審查,其評論會觸發修復工作階段

工廠不必涵蓋整個軟體流程。一個執行某種工作階段並開啟一個可審查 PR 的 cron 作業就是一個工廠。從這麼小的規模開始很有用:一個狹窄的迴圈會產生小型的、相似的 PR,而審查這些 PR 可以顯示在擴大迴圈之前,該迴圈值得多少信任。

人類可以坐在工廠的任何位置——編寫和標記觸發工作階段的問題、在實作開始前批准計畫、在合併前進行人工審查。決定哪些決策保持人工是主要的設計問題。一個或部分程式碼庫中,沒有人類審查工廠的輸出結果,這就是黑暗工廠。

用法:

「誰修復了所有 `no-floating-promises` 違規?」

「工廠。Cron 作業每晚挑選一條 Linter 規則,開啟一個 PR。我早上審查一下就行了。」

熄燈工廠

software factory 在其中寫入程式碼且沒有人類閱讀的程式碼庫(codebase)或其一部分。沒有 human review。人類仍然可以編寫啟動工作的問題(issues)。但是沒有人讀取產生的程式碼。這個名稱來自「關燈」(lights-out)工廠,這些工廠在現場沒有人的情況下製造東西。

黑暗工廠(dark factory)是針對某個程式碼區域的 vibe coding,而不是針對單一變更。當你進行 vibe coding 時,你選擇不閱讀你要求的變更。但你知道該變更存在。在黑暗工廠中,團隊針對整個區域做出一次性的選擇。在那之後,沒有人會要求或看到每一項變更。變更的到來速度就跟觸發新工作的速度一樣快。

當某個東西損壞時,問題就浮現了。你不知道是什麼變更了,因為沒有人讀過這些變更。你必須對團隊中沒有人讀過的程式碼進行除錯。原因可能在許多變更中的任何一個裡,而且每一個都通過了檢查。

Automated checks 和 automated review 是唯一的關卡。如果它們沒有發現問題,問題就會進入程式碼中。

避免: 僅僅因為工廠在沒有人監看的情況下運行,就將程式碼庫稱為「黑暗的」。如果 agent sessions 在 AFK 狀態下運行且人類審查了他們的 PR,那是軟體工廠。這不是黑暗工廠。

用法:

「誰修改了計費服務中的重試邏輯?團隊裡沒有人記得這件事。」

「計費服務是一個黑暗工廠。代理程式合併了所有通過 CI 的變更。沒有人讀過那個變更。」

Instagram