跳到主要內容
OpenAI

2026年2月11日

工程

Harness 工程:在以代理為核心的世界利用 Codex 推動工程效率

作者:Ryan Lopopolo,技術團隊成員

正在載入...

在過去五個月中,我們的團隊一直在進行一項實驗:構建並交付一款內部 Beta 版軟件產品,且完全沒有手寫程式碼

該產品目前同時服務內部日常用戶及外部 Alpha 測試人員。它會被發佈、部署、出現問題,然後再修復。不同之處在於,每一行程式碼—應用程式邏輯、測試、CI 配置、文件、可觀測性,以及內部工具—都是由 Codex 撰寫的。我們估計,用 Codex 生成程式碼來完成這個產品,所需時間約為手寫程式碼的十分之一。

人類掌控方向。智能代理負責執行。

我們刻意選擇這項限制,專注於必要的功能,將開發效率提升好幾倍。我們用了數週時間,就交付了最終達到一百萬行程式碼的產品。為做到這一點,我們需要了解:當一個軟件工程團隊的工作重心不再是寫代碼,而是設計系統環境、明確意圖,並建立能讓 Codex 智能代理可靠運行的反饋循環時,會有哪些變化。

這篇文章討論了我們在用代理團隊打造新產品時所學到的經驗—出現了哪些問題、問題如何相互影響,以及如何最大化我們唯一真正稀缺的資源:人類的時間與專注力。

一切從空的 Git 程式碼庫開始

我們在 2025 年 8 月下旬對空程式碼庫進行了第一次提交。

最初的搭建框架—包括程式碼庫結構、CI 配置、格式化規則、套件管理器設定以及應用程式框架—是透過 Codex CLI 調用 GPT‑5,在一小組既有範本引導下自動生成的。甚至連最初用來指引代理如何在這個程式碼庫執行任務的 AGENTS.md 文件,本身也是由 Codex 生成的。

系統中沒有任何既有的由人類撰寫的程式碼作為基礎。從一開始,程式碼庫的構建就是由代理主導的。

五個月後,這個程式碼庫已包含約一百萬行程式碼,涵蓋應用程式邏輯、基礎設施、工具、文件,以及內部開發人員工具。在這段時間裡,約有 1,500 個 pull request 被開啟與合併,而這一切都是由只有三名工程師、專注於驅動 Codex 的小團隊完成的。這相當於每位工程師每天平均完成 3.5 個 pull request,而令人驚訝的是,隨著團隊擴展到七名工程師,工作產出率反而提升。值得注意的是,這些產出並非為了「有產出而產出」:該產品已被數百名內部用戶使用,其中包括每日活躍的核心用戶。

在整個開發過程中,人類從未直接撰寫任何程式碼。這成為團隊的核心理念:完全不用手寫程式碼

重新定義工程師的角色

人類不再直接撰寫程式碼,工程師的工作重心轉向系統設計、搭建框架,以及提升工作效率的杠桿作用

在早期階段,進展比我們預期的要慢,並非因為 Codex 能力不足,而是整個開發環境沒有被明確定義。代理缺乏實現高層次目標所需的工具、抽象化和內部結構。我們工程團隊的主要工作,變成讓代理能夠執行有用的工作。

實際上,這意味著以深度優先的方式工作:將較大的目標拆解成較小的構建模組(設計、程式碼、審查、測試等),提示代理去生成這些模組,並利用它們來完成更複雜的任務。當出現問題時,解決方法幾乎從來不是「更努力嘗試」。因為取得進展的唯一方法是讓 Codex 來完成工作,人類工程師總是會介入並詢問:「缺少甚麼能力?我們該如何把它以清晰且可執行的方式交給代理?」

人類幾乎完全透過提示詞與系統互動:工程師描述一項任務,讓代理執行,並允許它開啟 pull request。為完成 PR,我們指示 Codex 先在本地審查自身的變更,並請求其他指定代理在本地與雲端進行額外審查,對任何人類或代理提供的反饋作出回應,並在迴圈中持續迭代,直到所有代理審查者滿意為止(這實際上是一個 Ralph Wiggum Loop 方法(在新視窗中開啟))。Codex 直接使用我們的標準開發工具(如 gh、在地腳本和嵌入程式碼庫的技能)來收集上下文,而無需人類將內容逐條複製貼到 CLI。

人類可能會審查 Pull Request,但並非必須。隨著時間推移,我們幾乎將所有的審查工作都交給代理之間自動執行。

提升應用程式的可讀性

隨著程式碼產出效率提升,我們的瓶頸變成人類 QA 的處理能力。由於人類的時間與注意力是真正的稀缺資源,我們透過讓應用 UI、日誌與應用程式指標等直接對 Codex 可讀來提升代理的能力,使其能更自主地完成工作。

例如,我們讓應用程式能夠根據每個 git worktree 啟動,這樣 Codex 就可以為每次變更啟動並驅動應用實例來執行任務。我們還將 Chrome DevTools Protocol 接入代理運行環境,並建立用於 DOM 快照、截圖與頁面導覽的技能模組。這使得 Codex 能夠重現錯誤、驗證修復結果,並直接推理 UI 行為。

標題為「Codex 使用 Chrome DevTools MCP 驅動應用程式以驗證其工作。」的圖表。Codex 會選擇一個目標,在觸發用戶介面路徑之前及之後擷取狀態快照,透過 Chrome DevTools 觀察運行時事件,應用修復程式、重新啟動,並循環重複運行驗證,直到應用程式清理乾淨。

我們對可觀測性工具也採取了相同措施。Codex 能透過一個本地的可觀測性堆疊直接存取日誌、指標與追蹤資料,而這個堆疊是針對每個 worktree 獨立啟動並且短暫存在的。Codex 能在該應用程式的完全隔離版本上運作—包括應用本身的日誌和指標,而這些資料會在該任務完成後被清除。代理可使用 LogQL 查詢日誌,並使用 PromQL 查詢指標。當代理掌握了上下文後,「確保服務啟動時間低於 800ms」或「四個核心用戶流程中的任何 span 不超過兩秒」這類提示詞就能實際執行。

標題為「為 Codex 在本地開發中提供完整的可觀測性堆疊」的圖表。應用程式將日誌、指標和追蹤傳送到 Vector,然後 Vector 將資料分發到包含 Victoria 日誌、指標和追蹤的可觀測性堆疊,每個堆疊均透過 LogQL、PromQL 或 TraceQL API 進行查詢。Codex 會使用這些信號進行查詢、關聯和推理,然後在儲存庫中實施修復程式、重新啟動應用程式、重新執行工作負載、測試 UI 流程,並在反饋循環中重複進行此過程。

我們經常看到單次 Codex 智能代理運行同一項任務超過六個小時(通常是在工程師睡覺時運行)。

我們將程式碼庫知識作為系統的唯一可信來源。

在處理龐大且複雜的任務時,上下文管理是提升代理效率的關鍵挑戰。我們最早學到的一個教訓很簡單:對 Codex 來說,給一張清晰的地圖比給一千頁的操作手冊更為有效。

我們曾嘗試「一個大型 AGENTS.md(在新視窗中開啟)」策略。它以可預期的方式失敗:

  • 上下文是一種稀缺資源。一個龐大的指令檔案擠掉了任務、程式碼和相關文件—導致代理要麼忽視關鍵限制,要麼開始針對錯誤目標進行最佳化。
  • 過多指導反而變成非指導 當所有事情都「重要」時,實際上就沒有真正重要的東西。代理最終會在本地進行模式配對,而非有意識地導覽。
  • 它會立即失效。一本龐大的手冊最終會變成過時規則的墳場。代理無法判斷哪些規則仍然有效,人類也停止維護,這個文件最終悄悄成為一個「誘人的麻煩」。
  • 很難驗證。單一的大文件不利於進行機械化檢查(覆蓋率、更新狀態、所有權、交叉連結),因此偏離現實的情況無法避免。

因此,我們不再將 AGENTS.md 視為百科全書,而是將其視為目錄

程式碼庫知識位於結構化的 docs/ 目錄中,並被視為系統的唯一可信來源。一份簡短的 AGENTS.md(約 100 行)被注入上下文,主要作為導覽地圖,並指向其他更詳細的真實資料來源。

純文字

1
AGENTS.md
2
ARCHITECTURE.md
3
docs/
4
├── design-docs/
5
│ ├── index.md
6
│ ├── core-beliefs.md
7
│ └── ...
8
├── exec-plans/
9
│ ├── active/
10
│ ├── completed/
11
│ └── tech-debt-tracker.md
12
├── generated/
13
│ └── db-schema.md
14
├── product-specs/
15
│ ├── index.md
16
│ ├── new-user-onboarding.md
17
│ └── ...
18
├── references/
19
│ ├── design-system-reference-llms.txt
20
│ ├── nixpacks-llms.txt
21
│ ├── uv-llms.txt
22
│ └── ...
23
├── DESIGN.md
24
├── FRONTEND.md
25
├── PLANS.md
26
├── PRODUCT_SENSE.md
27
├── QUALITY_SCORE.md
28
├── RELIABILITY.md
29
└── SECURITY.md

儲存庫內知識儲存版面配置。

設計文件已編目並建立索引,包括驗證狀態,以及一套確立 agent-first 運作原則的核心信念。架構文檔(在新視窗中開啟)提供了各個領域和套件分層的最高層級地圖。品質文檔會對每個產品領域和架構層進行評分,並隨時間追蹤差距變化。

計劃被視為最重要的工作。臨時且輕量的計劃用於小幅修改,而複雜工作則記錄在執行計劃(在新視窗中開啟),並附帶進度與決策日誌,這些都會存入程式碼庫。所有現行計劃、已完成計劃以及已知的技術債務都會進行版本控制並集中管理,使代理能在無需外部上下文的情況下運作。

這實現了逐步揭露:代理從小而穩定的切入點開始,逐步學習下一步應查看的位置,而非一開始就被大量資訊淹沒。

我們透過機械化的方式強制執行這個流程。專用 Linter 和 CI 任務會驗證知識庫是否為最新、連結完整且結構正確。一個持續運行的「doc-gardening」代理會掃描過時或不準確的文檔,這些文檔與實際程式碼行為不符,並會自動發起修正的 pull request。

代理的可讀性是我們的目標

隨著程式碼庫的演進,Codex 在做設計決策時所依賴的框架也需要隨之演進。

由於程式碼庫完全由代理生成,因此首先針對 Codex可讀性進行最佳化。就如團隊致力提升程式碼對新入職工程師的可導覽性一樣,我們人類工程師的目標,是讓代理能夠直接從程式碼庫本身理解整個業務領域。

從代理的角度來看,任何在運行時無法在上下文中存取的內容,實際上都不存在。儲存在 Google 文件、對話串或人們腦海中的知識無法被系統存取。程式碼庫本地、具版本控制的工件(例如,程式碼、Markdown、結構定義、可執行計劃)是它所能看到的全部內容。

標題為「代理知識的限制:Codex 看不到的就不存在。」的圖表。Codex 的知識顯示為一個有邊界的氣泡。在其下方是一些未見過的知識例子—Google Doc、Slack 訊息,以及隱性人類知識。箭頭表示,若要讓 Codex 能夠看見此資訊,必須將其編碼為 Markdown 格式,並納入程式碼庫中。

我們發現,隨著時間推移,必須將越來越多的上下文納入程式碼庫中。那次讓團隊在架構模式上達成共識的 Slack 討論呢?如果代理無法發現這些資訊,那麼它就是不可讀的,就像三個月後加入的新工程師對此一無所知並無差別。

為 Codex 提供更多上下文,意味著整理並呈現正確資訊,讓代理可以進行推理,而不是用臨時指令使其不堪重負。就像你會為新同事進行入職培訓,介紹產品原則、工程規範與團隊文化(甚至包括表情符號的偏好),當你把這些資訊提供給代理時,也能產出更符合期望的結果。

這種框架釐清了許多取捨。我們偏向選擇可以在程式碼庫內完全內化並進行推理的依賴項和抽象化。經常被形容為「無聊」的技術,往往因為良好的可組合性、API 穩定性,以及在訓練資料中的廣泛代表性,而更容易讓代理建立模型。在某些情況下,讓代理重新實作部分功能,比試圖繞過公共函式庫中不透明的上游行為更划算。例如,我們沒有引入通用的 p-limit 類套件,而是自行實作了 map-with-concurrency 輔助函數:它與我們的 OpenTelemetry 監測系統緊密整合,測試覆蓋率達 100%,且行為完全符合我們運行時的預期。

將更多系統轉化為代理可檢查、驗證並直接修改的形式,會提升槓桿效應——不僅對 Codex 如此,對其他代理亦然(例如Aardvark) 也在程式碼庫上工作。

維護架構一致性與程式碼風格。

僅靠文件無法保持完全由代理生成的程式碼庫的一致性。透過強制執行不變式,而非事無巨細地管理實作,我們讓代理能快速交付,同時不破壞基礎架構。例如,我們要求 Codex 在邊界處解析資料結構(在新視窗中開啟),但並不指定要用哪一個特定函式庫(雖然模型似乎偏好使用 Zod),這種架構約束讓代理更容易推理。

代理在具備嚴格界限及可預測結構(在新視窗中開啟)的環境中最為有效,因此我們圍繞嚴謹的架構模型建立了此應用程式。每個業務領域都被劃分為一組固定的層級,依賴方向經過嚴格驗證,且允許的依賴連線數量有限。這些限制會透過自訂 Linter(當然是由 Codex 生成的!)和結構測試以機械方式強制執行。

下方的圖表顯示以下規則:在每個業務領域內(例如,App Settings),程式碼只能「向前」依賴於一組固定的層級(Types → Config → Repo → Service → Runtime → UI)。橫切關注點(驗證、連接器、遙測、功能旗標)透過單一明確的介面進入:Providers。其他任何內容均不允許,並會以機械方式強制執行。

標題為「具明確橫切關注點邊界的分層式領域架構」的圖表。在業務邏輯領域中包含以下模組:Types → Config → Repo,以及 Providers → Service → Runtime → UI,底部為 App Wiring + UI。 一個 Utils 模組位於邊界之外,並為 Providers 提供支援。

這種架構通常會等到擁有數百名工程師時才會考慮。對於編程代理來說,這是一個早期的先決條件:正是這些約束,讓開發速度得以提升,同時避免程式碼腐化或架構漂移。

在實際操作中,我們使用自訂 linters 和結構測試來執行這些規則,此外還有一小組「風格不變量」。例如,我們透過自訂 linter 靜態強制執行結構化日誌、結構定義與類型命名規範、文件大小限制,以及平台特定的可靠性要求。由於這些 Lint 是自訂的,我們撰寫錯誤訊息,將修正指示注入代理的上下文中。

在以人為本的工作流程中,這些規則可能會令人覺得過於拘泥或有所限制。有了代理,它們就會成為倍增器:一旦編碼完成,便可立即在整個系統中生效。

同時,我們明確指出哪些限制條件重要,哪些不重要。這類似於領導大型工程平台組織:集中強制規範邊界,並允許各地團隊自行運作。你非常重視邊界、正確性和可重現性。在這些邊界內,你允許團隊—或代理—在表達解決方案的方式上享有高度自主。

生成的程式碼不一定總是符合人類的風格偏好,但這樣也無妨。只要輸出結果正確、可維護,並且後續代理執行易於閱讀,就符合標準。

人類的風格會不斷地回饋到系統中。審查意見、重構的 Pull Request,以及面向用戶的 Bug 都會被納入文檔更新,或直接編碼到工具中。當文件不足時,我們會將規則轉化為程式碼

產出效率改變合併策略

隨著 Codex 的產出效率提升,許多傳統的工程規範變得不再有效。

程式碼庫的運作幾乎不設阻塞式合併門檻。pull requests 係短暫嘅。測試不穩定通常會透過後續重跑來解決,而不是無限期地阻礙進度。在一個代理產出效率遠超人類注意力的系統中,修正成本低,而等待成本高。

在產出效率低的環境中,這樣做是不負責任的。在這種情況下,這通常是正確的取捨。

「智能代理生成」的真正含義

當我們說程式碼庫是由 Codex 智能代理生成時,我們指的是程式碼庫中的所有內容。

代理產生:

  • 產品程式碼與測試
  • CI 配置和發佈工具
  • 內部開發工具
  • 文檔與設計歷史
  • 評估框架
  • 查看評論與回應
  • 管理程式碼庫的腳本
  • 以及生產儀表板的定義文件

人類始終在流程中,但工作的抽象層次已與過去不同。我們優先處理工作,將用戶反饋轉化為驗收標準,並驗證結果。當代理遇到困難時,我們會將其視為一個訊號:找出缺少的工具、防護措施或文檔,並將其反饋到程式碼庫中,始終由 Codex 自行撰寫修復程式。

智能代理會直接使用我們的標準開發工具。它們會拉取審查意見、內嵌回覆、推送更新,並且經常將自己的 Pull Request 壓縮並合併。

自主性水平不斷提高

隨著更多的開發循環被直接編碼到系統中—包括測試、驗證、審查、反饋處理及復原—程式碼庫最近跨越了一個重要的門檻,使 Codex 能夠端到端地推動新功能。

只需提供單一提示詞,代理現在可以:

  • 驗證目前程式碼庫的狀態
  • 重現已報告的漏洞
  • 錄製影片以展示故障情況
  • 實施修復
  • 透過運行應用程式來驗證修復情況
  • 錄製第二段影片,演示解決方案
  • 開啟 pull request
  • 回應代理和人類反饋
  • 偵測並修正構建故障
  • 僅在需要作出判斷時才升級至人工處理
  • 合併更改

此行為在很大程度上依賴於此程式碼庫的特定結構和工具,且不應假設在沒有類似投入的情況下可以概括化—至少目前還無法做到。

熵與垃圾回收

完全的代理自主也會帶來新的問題。 Codex 會複製程式碼庫中已存在的模式,即使是不一致或不理想的模式。隨著時間推移,這不可避免地會導致偏移。

最初,人類是手動處理這個問題的。我們的團隊以前每個週五(佔一週 20%)都要花時間清理「AI 垃圾」。毫不意外,這種方式無法擴展。

相反地,我們開始將所謂的「黃金原則」直接編碼到程式庫中,並建立一套定期清理機制。這些原則屬於具明確取向、可機械化執行的規則,確保程式碼庫在未來由智能代理執行時,仍然清晰易讀且保持一致。例如:(1) 我們傾向使用共用的工具套件,而非自行撰寫零散的輔助函式,以集中管理不變條件;(2) 我們不採取「YOLO 式」的資料探測方式,而是驗證邊界條件,或依賴具型別的 SDK,避免智能代理基於猜測的資料結構進行開發。我們亦會按固定節奏執行一系列背景 Codex 任務,掃描偏離原則的情況、更新品質評級,並自動建立針對性的重構 pull request。大部分變更都可在一分鐘內完成審閱,並自動合併。

這個功能類似於垃圾回收。技術債如同高息貸款:持續以小額方式償還,比起任由其複利滾存再一次處理要有效且省力。人類的偏好風格只需捕捉一次,然後在每一行程式碼中持續應用。這也讓我們能夠每天發現並解決不良模式,而不是讓它們在程式碼庫中擴散數天或數週。

我們仍在學習的內容

到目前為止,這個策略在 OpenAI 的內部推廣和採用過程中運作良好。為真實用戶打造真實的產品,有助將我們的投資建基於現實,並引導我們實現長期的可維護性。

我們尚未知道的是,在一個完全由代理生成的系統中,架構連貫性會如何隨著時間演變。我們仍在探索人類判斷在哪些方面能發揮最大作用,以及如何對這種判斷進行編碼,使其能夠持續增長。我們也不知道,隨著模型性能的持續提升,這個系統將會如何演變。

明顯可見的是:構建軟件仍然需要紀律,但這份紀律更多體現在框架上,而非程式碼本身。保持程式碼庫連貫一致的工具、抽象化和反饋循環變得愈來愈重要。

我們目前最棘手的挑戰集中在設計環境、反饋循環和控制系統,以幫助代理達成我們的目標:大規模構建並維護複雜且可靠的軟件。

隨著像 Codex 這樣的代理承擔軟件生命週期中多數工作,這些問題將變得更加重要。我們想要分享一些早期經驗教訓,幫助你思考應該將精力投放在哪裡,這樣你就可以直接開始構建

作者

Ryan Lopopolo

鳴謝

特別感謝 Victor Zhu 和 Zach Brock 對本帖的貢獻,以及開發這款新產品的整個團隊。