跳到主要內容
maxstudioNews
AI 自動化DEV Community (Claude Code)約 9 分鐘

程式碼代理為何總是「健忘」?如何有效管理其記憶與上下文?

程式碼代理在不同工作階段中,可能會忘記先前的架構決策,導致程式碼不一致或引入安全漏洞。本文作者區分了「工作上下文」與「記憶」的不同,並提出一套方法來管理持久的專案決策、工作階段交接,以及應捨棄的資訊。透過結構化的儲存庫知識和交接範本,可大幅提升程式碼代理的可靠性。

程式碼代理為何總是「健忘」?如何有效管理其記憶與上下文?
圖片來源:DEV Community (Claude Code)

我是托尼,我開發並營運網路產品,而 Claude Code 是我每天主要的開發工具。程式碼代理在一個工作階段中可以正確遵循架構決策,但在另一個工作階段中卻可能以不同的方式處理相同的元件。

舉例來說,您的 API 需要組織範圍的權限,但新的工作階段卻使用使用者的全域角色來實作授權。程式碼雖然可以編譯,端點也能回應,但這項變更仍然違反了您的團隊已經做出的決策。

當下最直接的誘惑是保留更多的對話歷史記錄,或給代理更多的筆記。但保留整個對話與保留有用知識是兩回事,而且記住一個舊的決策可能比忘記它更糟。

在這篇文章中,我將展示我是如何區分工作上下文、持久的專案決策、工作階段交接以及應該捨棄的資訊。閱讀完畢後,您將獲得一套可重複使用的範本和一個恢復測試,您可以在讓代理繼續未完成的工作之前執行它。

這是「讓程式碼代理更可靠」系列六篇文章中的第三篇,該系列旨在讓代理生成的程式碼易於理解、驗證和維護。儘管以下指令和記憶行為是 Claude Code 特有的,但相同的原則也適用於其他程式碼代理。

為了舉例說明,我將使用一個虛構的 TypeScript 單一儲存庫 (monorepo):

.

├,apps/

│ ├,admin/ # 管理員網路應用程式

│ └,api/ # 多租戶 API

├,packages/

│ ├,ui/ # 共享 UI 元件

│ └,shared/ # 共享類型和合約

├,docs/

├,CLAUDE.md

└,pnpm-workspace.yaml

這個 API 服務於多個客戶組織,並且必須強制執行嚴格的租戶隔離。我們的範例變更引入了報告匯出功能的組織範圍權限,影響了資料庫遷移、API 授權、共享類型、管理員 UI 和測試。這類工作如果記錯了假設,就可能變成一個安全漏洞。

上下文和記憶解決不同的問題

開發人員經常互換使用「上下文」和「記憶」這兩個詞,但它們解決的是不同的問題。上下文是代理處理當前請求時可用的工作資訊。記憶是跨工作階段保留以供使用的資訊。兩者都無法自動確定哪個架構決策對於當前儲存庫是正確的。

我將可用的資訊分為三個層次:

第一層是「工作階段上下文」,包含對話、程式碼讀取和工具輸出,主要目的是完成當前工作,主要風險是雜訊和細節遺失。

第二層是「代理記憶」,包含儲存的專案筆記和觀察,主要目的是跨工作階段恢復有用知識,主要風險是過時或未經驗證的假設。

第三層是「儲存庫知識」,包含 CLAUDE.md、架構決策、任務記錄和測試,主要目的是分享和驗證專案知識,主要風險是文件與程式碼脫節。

在 Claude Code 中,對話歷史記錄會隨每個請求發送,因此繼續長時間的調查會消耗上下文。執行測試、讀取原始檔案、檢查日誌和探索替代實作都會增加工作上下文的內容。您可以使用 /context 來檢查上下文視窗佔用了什麼,並使用 /usage 來檢查權杖用量。這些指令可以幫助您了解消耗情況,但它們無法告訴您資訊是否仍然有效。

Claude Code 還具有自動記憶功能,儲存在:

~/.claude/projects/<project>/memory/

├,MEMORY.md

└,<topic-files>.md

MEMORY.md 是索引,主題檔案在需要時可用。MEMORY.md 的前 200 行或最多 25KB 會在工作階段開始時載入。您可以透過 /memory 管理自動記憶。這個記憶儲存在您的機器上,在同一儲存庫的不同工作樹之間共享,但不會在開發人員機器之間自動同步。

儲存庫知識有另一個目的。一個已提交的架構決策可以由隊友審查,透過 Git 歷史記錄追溯,並與實作一起變更。CLAUDE.md 會在每個工作階段載入,對於穩定的專案說明很有用,但您的其餘文件必須在相關時明確定位和讀取。我將儲存庫知識視為專案決策的維護來源,然後根據實際實作進行檢查。

想像您的代理讀取一個權限中介軟體檔案,發現授權取決於 user.role。這是當前的工作上下文,因為程式碼存在於儲存庫中。一個自動記憶筆記可能寫著:「權限是組織範圍的」,而一個架構記錄則解釋說全域角色設計已被取代。代理需要注意到這種不一致,檢查受影響的程式碼,並在進行另一個變更之前確定遷移的哪些部分已完成。

這種區別很重要,因為代理可以回憶起正確的架構原則,但卻在錯誤的儲存庫狀態下操作。成功的恢復需要相關知識和最新證據。

決定什麼值得在工作階段結束後保留

我使用的問題不是「這些資訊會再次有用嗎?」幾乎任何東西都可能再次有用。我會問誰需要這些資訊、它能保持有效多久,以及誰負責更新它。一個實用的分類如下:

「穩定專案規則」例如使用 pnpm 或強制租戶隔離,我將其保存在 CLAUDE.md 中。

「架構決策」例如透過組織成員資格解決權限問題,我將其保存在版本化的決策記錄中。

「任務要求」例如新增組織範圍的報告匯出,我將其保存在任務簡報中。

「進行中的工作」例如中介軟體已更新或管理員 UI 待處理,我將其保存在工作階段交接中。

「驗證證據」例如測試指令、結果和測試的修訂版本,我將其保存在交接或驗證記錄中。

「導航觀察」例如權限測試位於特定目錄,我將其保存在代理自動記憶中。

「臨時輸出」例如完整的測試日誌或探索性搜尋,我將其保存在當前上下文或可丟棄的產物中。

前兩類資訊值得刻意維護。如果您的 API 必須在請求的組織內解決授權問題,那麼該規則不應依賴於代理保留先前的對話。它應該屬於專案說明和描述該約束為何存在的決策記錄。該記錄應識別它影響的程式碼以及它取代的假設。

進度和測試結果的有用生命週期較短。通過測試的結果說明了程式碼的特定狀態,而不是之後的每個狀態。當授權中介軟體變更時,昨天的通過測試結果並不能證明新的中介軟體是正確的。我會保留指令、結果和儲存庫參考,以便下一個工作階段可以決定需要重新執行什麼。

臨時觀察通常不需要保留。套件安裝的輸出、廢棄的設計提案或數百行成功的測試不應成為永久的專案知識。保留它們會消耗注意力,並產生更多未來代理可能錯誤地視為權威的材料。

指令和證據之間也存在差異。「始終強制租戶隔離」是一個指令。「API 測試通過」是一個需要測試指令和相關程式碼修訂版本的證據聲明。將兩者作為未區分的記憶儲存,會使代理更難知道該服從什麼以及該驗證什麼。

將儲存庫作為真實來源

考慮一個典型的權限遷移。最初的設計透過使用者的全域角色檢查授權。團隊隨後確定一個使用者可以屬於多個組織,並在每個組織中擁有不同的角色。接受的設計變更為透過與請求相關聯的組織中的成員資格來評估權限。這兩種設計都可能存在於 Git 歷史記錄、文件和對話中。

如果沒有明確記錄,未來的工作階段可能會恢復舊設計並一致地實作它。問題不在於代理缺乏資訊,而是它擁有的資訊沒有可靠的指示說明哪個決策取代了哪個。對於影響多個套件的變更,我會將決策記錄保存在儲存庫中。

這是一個小型可重複使用套件中的第一個檔案:

agent-context-kit/

├,decision-record.md

├,session-handoff.md

└,context-recovery-checklist.md

這些是人工管理的 Markdown 文件,而不是內建的 Claude Code 記憶檔案。您可以將範本保存在您的儲存庫中,並將已完成的記錄複製到適當的架構或任務目錄中。Claude Code 不會僅僅因為它們存在就自動發現每個文件。

以下是 agent-context-kit/decision-record.md 範本的內容:

決策:<簡短標題>

ID:<穩定識別碼>

狀態:提議 | 已接受 | 已取代

取代:<決策 ID 或無>

被取代:<決策 ID 或無>

背景

什麼問題需要決策?哪些限制必須保持為真?

決策

接受什麼行為或設計?

範圍

  • 受影響的套件:
  • 受影響的介面:
  • 資料或安全影響:

替代方案

考慮了哪些替代方案?為何被拒絕?

驗證

如何檢查實作?需要哪些測試或審查?

參考資料

  • 相關程式碼路徑:
  • 相關決策:
  • 任務或變更參考:

對於我們的範例,已完成的決策可以儲存在 docs/architecture/decisions/002-organization-membership.md:

決策:組織範圍的授權

ID:ADR-002

狀態:已接受

取代:ADR-001

被取代:無

背景

使用者可以屬於多個組織。使用者在不同組織中的角色可能不同。API 不得使用來自其他組織的成員資格來授權存取。

決策

使用已驗證使用者在請求組織中的成員資格來解決授權問題。在存取組織範圍的資料之前,檢查成員資格和所需的權限。

範圍

  • apps/api:授權和報告端點
  • apps/admin:組織特定權限
  • packages/shared:權限合約
  • 資料庫:成員資格和角色遷移

替代方案

全域使用者角色被拒絕,因為它們無法代表不同的組織角色。

驗證

  • 已授權的成員資格允許匯出。
  • 缺少成員資格則拒絕匯出。
  • 組織 A 中的權限不授予組織 B 的存取權。
  • 匯出查詢仍應限於租戶範圍。

參考資料

  • ADR-001:已取代
  • 任務:docs/tasks/reporting-export/

這份記錄不僅提醒代理設計偏好,它還識別了邊界、受影響的元件以及應證明符合性的測試。它還讓被拒絕的設計可見,但不會將其作為活動指令呈現。儲存庫並非僅僅因為一個 Markdown 檔案說「已接受」就自動正確。實作可能不完整、遷移可能改變了行為,或者文件可能被忽略了。儲存庫是團隊維護其決策的地方,也是代理可以檢查當前程式碼和測試以挑戰它們的地方。

給工作階段交接一個一致的結構

當工作需要跨工作階段繼續時,我會使用交接,特別是當變更部分實作時。交接不是縮寫的謄本,它是從當前任務到證據、決策和下一個有用行動的映射。一個好的交接會回答四個問題:我們想達成什麼?儲存庫中發生了什麼變化?實際驗證了什麼?下一個工作階段在修改程式碼之前應該檢查什麼?

以下是 agent-context-kit/session-handoff.md 範本的內容:

工作階段交接:<任務名稱>

目標

<期望的結果和驗收標準>

儲存庫狀態

  • 分支:
  • 基礎提交:
  • 未提交的變更:
  • 相關任務目錄:

當前決策

  • 活動決策記錄:
  • 應避免的已取代決策:

已完成的工作

  • <檔案或元件>:<變更內容>

驗證證據

| 指令或檢查 | 結果 | 程式碼狀態 |

|---|---|---|

| <指令> | 通過/失敗/未執行 | <提交或狀態> |

未完成的工作

  • <剩餘的實作或驗證>

已知風險和矛盾

Share

覺得值得一看?分享給朋友。

以上為 AI 自動翻譯導讀。原文版權歸 DEV Community (Claude Code) 所有, 建議透過「閱讀原文」前往原始網站,以取得最完整資訊並支持原作者。

Newsletter

不用每天追,AI 重點每週寄給你

43 個來源、每 2 小時更新,太多看不完。電子報每週挑最值得看的幾則,附上 Max 的看法。

每週一封。Email 只用來寄電子報,每封信都能一鍵退訂。