简

理解 Initializer、Feature List、Progress File 與 Git 的分工,建立新會話恢復、增量實現、端到端驗證和狀態交接的完整流程。

Long-running Agent:怎樣跨多個 Context 持續完成任務?
18 分鐘
3518 字

Agent Loop解釋了模型怎樣根據工具結果繼續行動。但一個軟件項目可能需要很多輪開發,甚至跨越多個 Context Window。模型繼續運行,不等於任務能夠連續推進:上一輪的推理結束以後,下一輪要根據什麼判斷現狀?

長期開發需要保存的不是每一句歷史,而是可核對的任務狀態:完整需求是什麼、哪些功能已經驗證、代碼處於哪個版本,以及下一步從哪裏開始。

Anthropic 的《Effective harnesses for long-running agents》給出了一種跨會話開發方案。本文圍繞三個問題展開:

  • 狀態保存: 功能清單、進度記錄和 Git 各自承擔什麼職責。
  • 增量開發: 一輪工作怎樣形成可驗證、可交接的結果。
  • 會話恢復: 新 Context 怎樣檢查現狀,而不是重新猜測項目進度。

一、長期任務怎樣跨 Context 接續h2

先看連續開發在哪裏中斷,再明確首次會話需要為後續留下什麼起點。

1. Long-running:跨會話開發的失敗模式h3

長期任務經常在兩個位置失去連續性。

中斷在實現過程裏。 一輪同時修改頁面、接口和存儲,Context 耗盡時只完成了一部分。下一輪看到文件已經存在,卻不知道哪些能運行、哪些只是佔位,也不知道失敗是新引入的還是早就存在。

把已有進展當成全部完成。 頁面能夠打開、主要按鈕已經出現,不代表原始需求全部滿足。如果完整需求沒有留下可檢查的記錄,下一輪容易根據眼前的成果判斷項目已經結束。

Compaction 可以壓縮歷史,讓模型保留重要信息,但它與項目狀態管理承擔不同職責。摘要主要描述此前發生過什麼;需求清單則必須保留尚未完成的目標,驗證記錄必須對應某份真實代碼。

例如,摘要寫着“已加入文章搜索”,仍然留下幾種可能:只寫好了搜索框,查詢能返回結果,或者篩選、空結果與移動端交互都驗證過了。同一句歷史描述,不能代替明確的完成條件。

因此,壓縮和外部狀態並不互斥:摘要幫助恢復背景,項目材料提供可逐項核對的事實。長期開發需要把“發生過什麼”和“現在可以確認什麼”分開。

2. Initializer:準備環境與完整任務清單h3

Initializer 是首次運行的初始化角色。它的產出不應只是一批源碼,還包括後續會話使用的工作約定:怎樣啓動項目、怎樣判斷功能完成、怎樣記錄進度。

原文實驗裏的 Initializer 與後續 Coding Agent 使用相同的 Harness 和工具,主要區別在於首次提示詞。初始化是一種工作階段,不必為了它另造一套 Runtime。

一個最小起點可以包含:

材料解決的問題
環境啓動腳本,如 init.sh怎樣啓動應用並進入可測試狀態
功能清單,如 feature_list.json完整需求包含什麼,哪些尚未完成
進度文件,如 claude-progress.txt當前工作位置和交接説明
Git 初始提交初始化實際增加了哪些文件

啓動腳本的價值在於讓操作可重複,而不是保證環境永遠不出錯。依賴、端口或服務狀態變化以後,仍需檢查啓動結果。

下面以一個假設的課程筆記應用為例:用户要求筆記編輯、標籤篩選和關鍵詞搜索。Initializer 需要把這些目標轉成可觀察的行為,而不是隻建好三個組件就算完成準備。

二、任務狀態怎樣記錄與更新h2

完整需求、進度解釋和實際代碼需要分別保存,再通過一輪可驗收的工作保持對應。

3. Feature List、Progress File 與 Git:記錄需求、進度與代碼h3

這三類材料分別回答三個問題:還要做什麼、之前做了什麼、代碼實際變成了什麼。

Feature List:保存需求和驗收狀態

一項功能應當寫到能夠測試的粒度。例如,搜索不是“有搜索模塊”,而是用户輸入關鍵詞後能看到匹配筆記,並能識別無結果狀態。

下面是自擬的簡化記錄:

{
"id": "search-notes",
"description": "用户可以按关键词搜索笔记",
"checks": [
"输入正文中存在的关键词,显示对应笔记",
"输入不存在的关键词,显示空结果提示",
"清空关键词,恢复完整列表"
],
"passes": false
}

這裏最重要的不是 JSON 語法,而是需求不會因實現困難而被悄悄縮小。狀態應依據測試更新;需求本身發生變化,則應明確記錄變更,而不是把失敗的檢查直接刪掉。

Progress File:保存交接所需的解釋

進度記錄補充代碼沒有直接表達的信息,例如:

本輪完成搜索接口與列表聯動,正常查詢和空結果已驗證。清空關鍵詞後列表沒有恢復,仍未通過。問題位於篩選狀態重置;本輪未修改標籤功能。

下一輪據此可以定位缺口,也知道哪些範圍沒有處理。它不需要複述所有搜索和嘗試,而應保留結果、依據、未完成項與必要提醒。

Git:保存實際修改和可恢復版本

Git 能説明本輪改了哪些文件、不同修改如何演進,並提供可恢復的代碼版本。但提交存在,不代表功能正確;一個名叫“完成搜索”的 commit,也不能自動成為驗收證據。

三者需要相互對應:清單裏的通過狀態應能找到驗證依據,進度應説明對應的代碼位置,提交則保存那份實際產物。出現矛盾時,應回到代碼和測試核查,而不是隻相信某一份説明。

4. Incremental Progress:完成可以驗證和交接的功能h3

增量不是機械地限制修改行數,而是控制一輪工作的範圍,使它能夠完整實現、驗證並交接。

例如,“加入筆記搜索”可以成為一個閉環:從輸入關鍵詞,到查詢和顯示結果,再到空結果與清空行為。只實現輸入框、把後端和驗證留給下一輪,仍然是沒有閉合的功能。

圖 1 · 項目材料把首次初始化、當前會話和新 Context 連接起來
圖 1 · 項目材料把首次初始化、當前會話和新 Context 連接起來 Initializer首次建立環境與任務邊界 項目交接材料功能清單 · 進度 · Git 恢復與基線檢查讀取材料,驗證項目現狀 實現一項功能完成端到端驗證 保存可接續狀態更新清單、進度與提交 新會話接手重新讀取並核對項目狀態 推進下一項功能繼續遵守恢復與交接約定 跨 Context

每輪可以按同一套步驟組織:

  1. 從完整清單選擇一項優先工作,確認依賴已經具備。
  2. 實現功能及必要的測試,不同時鋪開無關改動。
  3. 按用户路徑驗證結果,檢查已有能力是否被破壞。
  4. 根據實際結果更新功能狀態與進度。
  5. 保存清楚的代碼變更,為下一輪留下可使用的起點。

原文采用每輪一項功能的約束。它的作用是防止範圍不斷擴張,而不是證明所有項目都只能按同一種大小切分。

如果本輪無法完成,交接時應準確標記未完成狀態、失敗證據和已修改範圍。乾淨交接不是把所有狀態寫成成功,也不是為了得到一個整潔提交而隱藏問題;它要求下一輪能辨認並接續當前工作。

三、新會話怎樣恢復和驗證項目h2

交接材料提供入口,當前代碼與運行結果則用來核對這個入口是否仍然可信。

5. Session Handoff:恢復環境與核對已有進度h3

這裏的 Handoff 指跨會話交接項目狀態,不是上一篇編排文章中切換執行 Agent 的協議操作。

新會話的第一項工作,不應是立即實現下一功能,而是建立對當前項目的可信認識。

讀取任務與代碼狀態

先確認工作目錄,檢查當前修改、最近提交和進度,再看完整功能清單。這一步把目標、解釋和實際代碼對應起來,也能發現進度記錄落後於源碼的情況。

啓動環境,驗證基本路徑

對於課程筆記應用,可以先打開列表、進入一篇已有筆記,再執行一條已完成的查詢。基線檢查不需要重複全部驗收,但要覆蓋足以判斷項目能否繼續開發的關鍵路徑。

如果基本路徑已經損壞,應先定位原因。否則繼續增加功能,會把原有故障和新修改混在一起,下一次更難判斷是哪一步出了問題。

根據當前證據選擇任務

恢復完成後,再從未通過的清單裏選擇工作。最近進度寫着“接下來做標籤”,並不意味着無需查看實際依賴;如果搜索仍有未解決的迴歸,應調整順序並説明原因。

這個流程的目的,是讓新 Context 快速恢復必要信息,而不是把整個舊會話重新加載一遍。

6. End-to-end Testing:驗證功能的實際完成狀態h3

代碼檢查、單元測試和端到端測試觀察的是不同層次。

搜索函數能返回數據,不代表界面正確顯示;接口請求成功,也不代表用户清空關鍵詞後能恢復列表。功能完成需要驗證聲明中的那條用户路徑。

對 Web 應用,可以通過瀏覽器實際輸入、點擊、切換頁面,觀察顯示與狀態變化;必要時再結合請求、日誌和數據檢查解釋失敗原因。

測試範圍要與功能聲明一致。“桌面端正常查詢通過”不能被寫成“所有搜索交互完成”。驗證工具也有觀察邊界:沒有覆蓋到的交互,不應被默認為已經檢查。

因此,完成判定應形成一條對應關係:

功能要求 → 可執行的檢查 → 觀察到的結果 → 更新完成狀態

我認為這套交接設計最有價值的地方,是讓長期開發不依賴某一輪模型對歷史的模糊記憶。每輪都能留下可讀的説明、可檢查的結果和可恢復的代碼,下一輪才有可靠的起點。

幾個關鍵問題,串起狀態記錄、增量開發與恢復h2

有 Compaction,為什麼還需要項目狀態文件?

壓縮幫助延續背景,狀態文件則明確保存需求、完成條件和交接位置。兩者用途不同,摘要不能自動證明某項功能已經通過。

Initializer 是一套獨立的 Agent Runtime 嗎?

不一定。原文實驗主要通過首次提示詞區分初始化與後續開發,工具和 Harness 相同。角色差異不等於底層實現必須不同。

為什麼不能只保留 Git?

Git 保存修改與版本,但不直接表達完整需求、尚未完成的任務和交接解釋。它需要與功能清單、進度記錄配合。

Incremental Progress 等於每輪少改幾行嗎?

不是。重點是工作範圍能形成實現、驗證、記錄的閉環。小補丁也可能只留下半成品,較大改動也可能具有清晰邊界。

新會話為什麼要檢查已完成功能?

因為當前代碼可能已經發生變化,進度記錄也可能過時。基線檢查確認當前起點可用,避免在損壞狀態上疊加新功能。

什麼時候可以把功能標為完成?

相關驗收路徑得到實際驗證,結果與聲明範圍一致時。生成了代碼、提交了修改,或者 Agent 口頭宣佈完成,都不足以單獨支持這個狀態。

參考資料h2