AI 領域精選文章翻譯
by Prithvi Rajasekaran (Anthropic Labs)
原文連結: Harness design for long-running application development
作者:Prithvi Rajasekaran,Anthropic Labs 成員
過去幾個月,我一直在研究兩個相互關聯的問題:讓 Claude 產出高品質的前端設計,以及讓它在無人介入的情況下完整建構應用程式。這項工作源於早期在前端設計技能和長時間運行的編碼代理 harness 上的努力——我和同事透過提示工程與 harness 設計,將 Claude 的表現大幅提升,但兩者最終都遇到了瓶頸。
為了突破瓶頸,我在兩個截然不同的領域尋找新穎的 AI 工程方法:一個由主觀品味定義,另一個由可驗證的正確性與可用性決定。從生成對抗網路(GAN)獲得靈感,我設計了一個包含生成器(generator)與評估器(evaluator)代理的多代理架構。要建立一個能可靠評分、且具有品味的評估器,首先必須開發一套評分標準,能將「這個設計好嗎?」這類主觀判斷轉化為具體可評分的條件。
接著,我將這些技術應用於長時間自主編碼,沿用了早期 harness 工作的兩個經驗:將建構過程分解為可處理的小塊,以及使用結構化的 artifact 在 session 之間傳遞 context。最終成果是一個三代理架構——規劃器(planner)、生成器、評估器——可以在多小時的自主編碼 session 中產出豐富的全端應用程式。
我們先前已經證明,harness 設計對長時間運行的代理編碼效果有重大影響。在早期的實驗中,我們使用初始化代理將產品規格分解為任務清單,再由編碼代理逐功能實作,並在 session 之間傳遞 artifact 以攜帶 context。更廣泛的開發者社群也已收斂到類似的洞見,例如「Ralph Wiggum」方法使用 hooks 或腳本讓代理持續迭代。
但一些問題仍然頑強存在。對於更複雜的任務,代理仍然容易隨著時間失去一致性。在分析這個問題時,我們觀察到代理執行此類任務時有兩種常見的失敗模式。
第一個是 context 焦慮。 模型在較長任務中,隨著 context window 填滿,往往會失去連貫性(詳見我們關於 context 工程的文章)。部分模型還會出現「context 焦慮」——當它們接近自認為的 context 極限時,開始過早收尾。Context 重置——完全清空 context window 並啟動新的代理,搭配攜帶前一個代理狀態與後續步驟的結構化交接——能解決這兩個問題。
這與 compaction 不同。Compaction 是對先前的對話進行就地摘要,讓同一個代理能在縮短的歷史上繼續運作。雖然 compaction 保留了連續性,但它不能給代理一個乾淨的狀態,因此 context 焦慮仍可能持續。重置提供了乾淨的狀態,代價是交接 artifact 必須包含足夠的狀態讓下一個代理接續工作。在我們的早期測試中,Claude Sonnet 4.5 的 context 焦慮嚴重到單靠 compaction 無法維持強勁的長任務表現,因此 context 重置成為 harness 設計的關鍵。這解決了核心問題,但為每次 harness 運行增加了協調複雜度、token 負擔和延遲。
第二個問題是自我評估, 我們之前從未正面處理過。當代理被要求評估自己產出的工作時,往往會自信地稱讚——即使對人類觀察者而言,品質明顯平庸。這個問題在設計等主觀任務中尤為突出,因為沒有像可驗證的軟體測試那樣的二元檢查。一個版面是否精緻或平庸是一種判斷,而代理在評估自己工作時往往偏向正面。
然而,即使在有可驗證結果的任務上,代理有時仍會表現出妨礙任務完成的判斷失誤。將執行工作的代理與評判工作的代理分開,被證明是解決這個問題的有力槓桿。這種分離本身並不能立即消除寬鬆傾向——評估器仍然是一個傾向對 LLM 產出寬容的 LLM。但事實證明,將獨立的評估器調教成持懷疑態度,遠比讓生成器對自己的工作自我批判更可行。一旦外部回饋存在,生成器就有了可以迭代的具體依據。
我從前端設計開始實驗,這是自我評估問題最為明顯的地方。在沒有任何干預的情況下,Claude 通常傾向於安全、可預測的版面——技術上可用,但視覺上乏善可陳。
兩個洞見塑造了我為前端設計建立的 harness。首先,雖然美學不能完全化約為分數——個人品味也會有所不同——但可以透過編碼設計原則與偏好的評分標準來提升。「這個設計美嗎?」難以一致地回答,但「這是否符合我們的優秀設計原則?」給了 Claude 可以具體評分的依據。其次,透過將前端生成與前端評分分開,我們可以建立一個驅動生成器走向更強輸出的回饋循環。
基於此,我寫了四個評分標準,同時給予生成器和評估器代理:
我強調設計品質和原創性勝過工藝和功能性,因為 Claude 在工藝和功能性上本來就得分不錯。但在設計和原創性上,Claude 往往產出最好也就是乏味的輸出。評分標準明確懲罰高度通用的「AI 爛貨」模式,透過對設計和原創性加重權重,推動模型進行更多美學冒險。
我使用帶有詳細評分細目的少樣本示例來校準評估器,確保評估器的判斷與我的偏好一致,並減少迭代過程中的評分漂移。
我在 Claude Agent SDK 上建立了這個循環,保持協調的簡潔。生成器代理首先根據使用者提示創建 HTML/CSS/JS 前端。我給了評估器 Playwright MCP,讓它在評分每個標準並撰寫詳細評論之前,能直接與即時頁面互動。實際上,評估器會自行導覽頁面,截圖並仔細研究實作,再產出評估結果。這個回饋流回生成器作為下一次迭代的輸入。每次生成我跑 5 到 15 次迭代,每次迭代通常都會回應評估器的批評,推動生成器走向更具特色的方向。由於評估器在主動導覽頁面而非對靜態截圖評分,每個循環都需要實際的時鐘時間,完整運行長達四小時。我還指示生成器在每次評估後做出策略決定:如果分數趨勢良好就精進當前方向,如果方法行不通就轉向完全不同的美學。
在各次運行中,評估器的評估在迭代中逐漸改善,最終趨於穩定但仍有提升空間。有些生成逐步精進,有些則在迭代之間出現了急劇的美學轉變。
評分標準的措辭以我未完全預料到的方式引導了生成器。包含「最好的設計是博物館等級」這類短語,將設計推向了特定的視覺收斂,顯示與評分標準相關的提示直接塑造了輸出的特性。
在一個值得注意的例子中,我提示模型為一間荷蘭藝術博物館創建網站。到第九次迭代,它為一間虛構的博物館創建了一個乾淨的深色主題首頁,視覺上精緻但大致符合預期。然後,在第十次循環,它完全放棄這個方向,重新將網站設想為一個空間體驗:一個用 CSS 透視法渲染的棋盤格地板 3D 房間,藝術作品自由懸掛在牆上,以門道為基礎的導覽取代滾動或點擊在展覽室間移動。這是在單次生成中我從未見過的創意飛躍。
有了這些發現,我將這個 GAN 啟發的模式應用於全端開發。生成器—評估器循環自然地對應到軟體開發生命週期,其中代碼審查和 QA 扮演與設計評估器相同的結構性角色。
在我們早期的長時間運行 harness 中,我們已透過初始化代理、逐功能運作的編碼代理,以及 session 之間的 context 重置,解決了連貫的多 session 編碼問題。Context 重置是關鍵突破:該 harness 使用的 Sonnet 4.5 表現出前述的「context 焦慮」傾向,而 Opus 4.5 基本上自己消除了這個行為,因此我能夠完全取消 context 重置。代理在整個建構過程中以一個連續 session 運行,由 Claude Agent SDK 的自動 compaction 處理 context 增長。
在此基礎上,我建立了一個三代理系統,每個代理解決我在先前運行中觀察到的特定缺口:
規劃器(Planner): 我們之前的長時間運行 harness 需要使用者預先提供詳細規格。我想自動化這個步驟,因此創建了一個規劃器代理,接受簡單的 1-4 句提示並將其擴展為完整的產品規格。我提示它對範圍保持雄心,並專注於產品 context 和高層次技術設計,而非詳細的技術實作。這種強調是出於擔憂:如果規劃器試圖預先指定細粒度的技術細節並出錯,規格中的錯誤將層層傳遞到下游實作。更明智的做法是約束代理要產出什麼,讓它們在工作過程中自己找到路徑。我還要求規劃器在產品規格中尋找機會融入 AI 功能。
生成器(Generator): 早期 harness 中逐功能的做法在範圍管理上效果很好。我在這裡應用了類似的模式,指示生成器以 sprint 方式工作,從規格中逐功能實作。每個 sprint 使用 React、Vite、FastAPI 和 SQLite(後來換成 PostgreSQL)堆疊實作應用程式,生成器被指示在每個 sprint 結束時自我評估工作,然後再移交給 QA。它還有 git 版本控制。
評估器(Evaluator): 早期 harness 的應用程式看起來令人印象深刻,但實際使用時仍然有真實的 bug。為了捕捉這些問題,評估器使用 Playwright MCP 像使用者一樣點擊運行中的應用程式,測試 UI 功能、API 端點和資料庫狀態。它根據發現的 bug 和一套仿造前端實驗的標準對每個 sprint 評分——在這裡調整為涵蓋產品深度、功能性、視覺設計和代碼品質。每個標準都有硬性門檻,任何一個低於門檻,sprint 就失敗,生成器會收到關於哪裡出錯的詳細回饋。
Sprint 合約: 每個 sprint 開始前,生成器和評估器商定一份「sprint 合約」:在任何代碼編寫之前,先就「完成」對於那個工作塊意味著什麼達成一致。這是因為產品規格是刻意高層次的,我想要一個步驟來彌合使用者故事和可測試實作之間的差距。生成器提出它將建構什麼以及如何驗證成功,評估器審查該提案以確保生成器在建構正確的東西,兩者迭代直到達成一致。
通訊透過檔案處理:一個代理寫入檔案,另一個代理讀取並在該檔案中回應,或者用前一個代理依序讀取的新檔案回覆。生成器根據商定的合約進行建構,然後將工作移交給 QA。這讓工作忠實於規格,同時避免過早過度指定實作細節。
對於這個 harness 的第一個版本,我使用 Claude Opus 4.5,針對完整 harness 和單一代理系統運行相同的使用者提示進行比較。
我寫了以下提示來生成一個復古電子遊戲製作器:
創建一個 2D 復古遊戲製作器,功能包括關卡編輯器、精靈編輯器、實體行為和可玩的測試模式。
| Harness | 時長 | 費用 |
|---|---|---|
| 單一代理 | 20 分鐘 | $9 |
| 完整 harness | 6 小時 | $200 |
Harness 貴了超過 20 倍,但輸出品質的差異立即顯現。
打開單一代理的輸出,初始應用程式看起來符合預期。但點擊過程中,問題開始浮現。版面浪費空間,固定高度的面板讓大部分視窗空白。工作流程僵硬。嘗試填充關卡時,需要先創建精靈和實體,但 UI 沒有引導使用者朝向這個順序。更重要的是,遊戲本身是壞的。我的實體出現在螢幕上,但沒有任何東西響應輸入。深入代碼發現,實體定義和遊戲執行時期之間的連接是壞的,但介面上沒有任何提示。
轉而查看 harness 的運行結果。這個運行從同一個一句話提示開始,但規劃器步驟將提示擴展成了橫跨十個 sprint 的 16 功能規格,遠超過單一代理所嘗試的範圍。除了核心編輯器和遊戲模式外,規格還要求精靈動畫系統、行為模板、音效和音樂、AI 輔助精靈生成器和關卡設計師,以及帶有分享連結的遊戲匯出功能。
應用程式立即顯示出比單一代理更多的精緻感。畫布佔用了整個視窗,面板大小合理,介面有一致的視覺識別感,符合規格中的設計方向。最大的差異在於遊戲模式——我實際上可以移動實體並玩遊戲,這是單一代理做不到的。
查看日誌,評估器將實作保持在與規格一致。每個 sprint,它都通過 sprint 合約的測試標準,並通過 Playwright 操作運行中的應用程式,對任何偏離預期行為的地方提出 bug。合約非常細緻——僅 Sprint 3 就有 27 個涵蓋關卡編輯器的標準——評估器的發現具體到無需額外調查就能採取行動。
讓評估器達到這個水準需要大量工作。開箱即用的 Claude 是個糟糕的 QA 代理。在早期運行中,我看它識別出合法的問題,然後說服自己認為這不是大問題並批准了工作。它也傾向於表面測試而非探索邊緣情況,所以更微妙的 bug 往往漏過。調教的循環是閱讀評估器的日誌,找到它的判斷與我的判斷有出入的例子,然後更新 QA 提示以解決那些問題。經過幾輪這樣的開發循環,評估器的評分方式才達到我認為合理的程度。
第一批 harness 結果令人鼓舞,但也臃腫、緩慢且昂貴。符合邏輯的下一步是找到在不降低性能的情況下簡化 harness 的方法。這部分是常識,部分是一個更普遍原則的體現:harness 中的每個組件都在編碼一個關於模型無法單獨完成的事情的假設,而這些假設值得壓力測試——不僅因為它們可能是錯的,更因為隨著模型進步,它們可能很快就會過時。我們的博文《Building Effective Agents》將這個底層理念框架為「找到最簡單的解決方案,只在需要時增加複雜度」。
與此同時,我們還發佈了 Opus 4.6,這提供了進一步減少 harness 複雜度的動力。從我們的發佈部落格:「[Opus 4.6] 規劃更仔細,能持續更長時間的代理任務,能在更大的程式碼庫中更可靠地運作,並有更好的代碼審查和偵錯技能來捕捉自己的錯誤。」
我首先完全移除了 sprint 結構。Sprint 結構幫助將工作分解成塊,讓模型能夠連貫地工作。考慮到 Opus 4.6 的改進,有充分理由相信模型可以在沒有這種分解的情況下原生處理這項工作。
我保留了規劃器和評估器,因為兩者都繼續帶來明顯的價值。沒有規劃器,生成器會低估範圍:給定原始提示,它會在沒有先確定規格的情況下開始建構,最終創建的應用程式功能比規劃器做的要少。
移除 sprint 結構後,我將評估器移至在運行結束時進行一次評估,而非每個 sprint 評分一次。由於模型能力大幅提升,評估器對某些運行的重要性改變了——其有用性取決於任務相對於模型能夠可靠獨立完成的邊界在哪裡。
評估器不是一個固定的是非決定。當任務超出當前模型能可靠單獨完成的範圍時,它才值得這個成本。
為了測試更新後的 harness,我使用以下提示生成一個數位音頻工作站(DAW):
使用 Web Audio API 在瀏覽器中建構一個全功能的 DAW。
運行仍然耗時且昂貴,約 4 小時和 $124 的 token 費用。
| 代理與階段 | 時長 | 費用 |
|---|---|---|
| 規劃器 | 4.7 分鐘 | $0.46 |
| 建構(第 1 輪) | 2 小時 7 分鐘 | $71.08 |
| QA(第 1 輪) | 8.8 分鐘 | $3.24 |
| 建構(第 2 輪) | 1 小時 2 分鐘 | $36.89 |
| QA(第 2 輪) | 6.8 分鐘 | $3.09 |
| 建構(第 3 輪) | 10.9 分鐘 | $5.88 |
| QA(第 3 輪) | 9.6 分鐘 | $4.06 |
| V2 Harness 總計 | 3 小時 50 分鐘 | $124.70 |
QA 代理仍然捕捉到了真實的差距。在第一輪回饋中,它指出:
這是一個出色的應用程式,設計保真度高、AI 代理穩固、後端良好。主要失敗點是功能完整性——雖然應用程式看起來令人印象深刻,AI 整合也運作良好,但幾個核心 DAW 功能是純顯示而沒有互動深度:clips 無法在時間軸上拖動/移動,沒有樂器 UI 面板(合成器旋鈕、鼓墊),也沒有視覺效果編輯器(EQ 曲線、壓縮器儀表)。這些不是邊緣情況——它們是讓 DAW 可用的核心互動,而規格明確要求它們。
最終應用程式擁有功能性音樂製作程式的所有核心組件:在瀏覽器中運行的工作排列視圖、混音器和傳輸控制。代理能夠設置節拍和調性、記下旋律、建構鼓點、調整混音器電平並添加混響——核心作曲原語都在那裡,代理可以自主驅動它們。
隨著模型持續進步,我們大致可以預期它們能夠工作更長時間、完成更複雜的任務。在某些情況下,這意味著圍繞模型的支架隨著時間的推移重要性降低,開發者可以等待下一個模型,看著某些問題自行解決。另一方面,模型越好,開發能超越模型基準能力的複雜任務 harness 的空間就越大。
從這項工作中,幾個值得帶走的教訓:對正在建構的模型進行實驗、閱讀其在實際問題上的軌跡,並調整其性能以達到目標。在更複雜的任務上,有時透過分解任務並將專業化代理應用於問題的每個方面,可以獲得更多提升。當新模型發佈時,重新審視 harness 通常是好做法——拆掉不再對性能起作用的部分,添加新的部分以實現之前無法達成的更大能力。
我的信念是:隨著模型進步,有趣的 harness 組合空間不會縮小,而是移動。AI 工程師有趣的工作,正是不斷找到下一個新穎的組合。
這篇文章最值得細品的,不是三代理架構本身,而是作者在文末揭示的那條原則:每個 harness 組件都在「編碼」模型的限制假設。
當 Opus 4.5 有 context 焦慮,sprint 結構就是必要的;當 Opus 4.6 解決了這個問題,sprint 結構就成了多餘的負擔。這意味著維護一個 agentic 系統不是「建好就放著」,而是需要隨著模型能力的進步,持續審視哪些設計是在「補貼」模型的不足。
對於真正在打造 AI 產品的團隊,這個洞察有幾個實際意涵:
調教評估器比讓模型自我批判容易得多。 原因不是技術上的,而是心理上的——評估器只有一個任務(找問題),生成器卻有衝突的動機(想要完成)。分工讓每一方都能更徹底地扮演好自己的角色。
「Sprint 合約」解決的是 AI 版的需求對齊問題。 人類工程師和 PM 之間常有的「我以為要做的是 X,結果你要的是 Y」,在 AI 代理之間同樣存在。在動手前先協商「完成」的定義,是讓輸出品質大幅提升的關鍵步驟之一。
20 倍成本換來「能用」vs「不能用」,本質上是在討論 P(success) 的跳躍。 不是優化效率,而是越過一個從「形式上完成但沒法用」到「真正能交付的產品」的門檻。對於需要交付可用產品的場景,這個成本差距可能是值得的。