記憶層的失效模式與一般後端系統很不一樣:它不會拋錯,會靜默地讓行為變差;它的錯誤會自我強化(錯的記憶被召回、影響回答、回答又被寫回記憶);而且它的攻擊面是持久的——一次成功的注入可以影響之後的所有對話。這一篇按症狀組織,每一條給成因與具體解法。


一、記憶污染與記憶投毒

症狀:agent 記住了錯的事,而且改不掉;或者 agent 開始表現出沒有被指示過的行為。

成因分兩類,處方完全不同。

自我強化的錯誤(無惡意)——一次錯誤的抽取(把使用者的假設當成事實、把工具的錯誤輸出當成結論)被寫入記憶,之後被召回、影響回答,回答又被抽取寫回,於是錯誤被加固。這在把 agent 自己的輸出也送進寫入管線的系統裡幾乎必然發生。

解法:區分來源的信任等級並記錄它。使用者的明確陳述、工具的成功輸出、agent 自己的推論,三者的 confidence 應該不同,而 agent 自己的推論預設不應該進入長期記憶——這是 SourceRef.channel 這個欄位在 schema 裡存在的主要理由。若要讓反思產物進入記憶(舊專欄:反思與技能沉澱 討論的機制),它應該進入一個獨立的、可以被單獨清空的分區。

惡意注入(memory injection / MINJA)——攻擊者透過正常的對話輸入,把惡意內容植入 agent 的長期記憶。payload 潛伏在儲存中,直到未來某個查詢在語意上匹配到它,agent 便把它當成合法 context 取回並照著執行。MINJA 於 NeurIPS 2025 發表,論文報告對生產級 agent 架構有超過 95% 的注入成功率。OWASP 在 2026 年把「Memory and Context Poisoning」列為 Agentic AI Top 10 的 ASI06

解法是分層的,而且必須承認沒有一層是完整的

結構性防禦(最有效)——把「行為規則」放進唯讀分區,讓它在結構上不可能被對話內容寫入(Letta 的 read-only block 模式)。這比任何內容過濾都可靠,因為它不依賴偵測,而是移除了通道。規則的變更走人工審核,不走自動寫入管線。

寫入端過濾——在寫入路徑上偵測指令式語句、越權要求與可疑模式。2026 年中發布的 OWASP Agent Memory Guard 提供了標準對齊的基線做法:作為 agent 與記憶儲存之間的中介層,用 YAML 驅動的偵測器管線篩查每一次讀與寫,處置分成 allow/redact/quarantine/block。

讀取端過濾——召回時再篩一次。必要,因為寫入端的規則會過期而歷史記憶已經在庫裡。

可稽核性——記錄每一次寫入的來源與理由(memory_decisions 表),讓事後追查可能。檔案原生路線在這一點上有結構性優勢git diff 直接顯示記憶的變更歷史。

明確的限制:所有已知防禦處理的都是「可偵測的模式」。「合法來源寫入了語意上有害但形式上正常的內容」目前沒有好的自動解法,這是本領域的開放問題。


二、召回不準

症狀:庫裡明明有相關記憶,但沒被召回;或召回了一堆無關的東西。

四個常見成因,逐一有明確的處方

把必須遵守的規則放進向量庫。 這是最貴的單一錯誤。經過相似度篩選的東西不能被稱為「必須遵守」——它只是「有機會被召回的建議」。解法:規則走常駐層,全量載入、精確定址,不經過檢索(見 藍圖的常駐層)。

純向量檢索。 向量在專有名詞、代號、版本號、人名上表現很差,這是被反覆驗證的已知弱點。解法:補上關鍵字檢索(BM25 / FTS5),成本很低、收益很高GraphitiCognee 都獨立收斂到混合檢索,應該當成預設。

沒有時效過濾。 舊事實與新事實同時被召回,模型自行猜測。解法:雙時間軸 + 召回時的時效條件。

庫膨脹造成的稀釋。 同一件事的二十個措辭變體塞滿 top-k。解法見下一節。


三、無限膨脹

症狀:記憶條目數超線性成長;召回品質隨時間下降;召回 token 數持續上升。

核心成因幾乎總是同一個:寫入的預設是 append。

解法一:實作完整的四操作(含 NOOP)。 沒有 NOOP 的系統會把每次重複提及存成新條目。NOOP 比例低於三成幾乎確定表示膨脹正在發生(見 操作分佈曲線)。

解法二:內容雜湊去重放在最前面。 零成本,處理掉完全相同的內容,同時省下 LLM 對帳呼叫。

解法三:對常駐層用嚴格的寫入門檻。 常駐記憶的成本是每一輪都要付的 token 稅,因此它的寫入門檻應該與召回層完全不同。Hermes 的 periodic nudge 是這個原則的極端實作:預設不寫,除非通過「未來 session 會用到」的判斷。

解法四:歸檔而非只失效。 失效的記憶留在索引裡會繼續稀釋檢索結果。Graphiti 明確不提供自動清理,因此採用它時必須自己設計歸檔策略。一組可用的預設:失效超過 90 天、或建立後 180 天未被召回一次,移出主索引。

解法五:容量上限與監控。 每個 scope 設條目數上限,超過時觸發歸檔而非拒絕寫入。同時監控成長曲線——這是唯一能在使用者抱怨之前發現問題的方式。


四、PII 與可刪除性

症狀:使用者要求刪除資料,但你不確定它存在哪裡;或者敏感資料被寫進了不該有它的地方。

這一類問題的處方全部是結構性的,事後補救幾乎不可行。

Scope 必須是一等公民。 每一條記憶都帶 subject_typesubject_id,因此「刪除某使用者的全部資料」是一個 WHERE 條件,而不是一段需要小心維護的邏輯。這是 schema 設計的第一優先,不是後來能補上的欄位。

衍生物必須可追溯。 刪除真源時,向量索引、圖的節點與邊、摘要、快取都必須一起清除。圖架構在這裡特別麻煩——一個實體節點可能被多個使用者的 episode 引用,級聯刪除的邊界不明確。這是採用圖之前必須設計好的事。

寫入路徑上做 redaction。 敏感資料(憑證、身分證號、金融資訊)不該進入儲存。在寫入時擋比在查詢時過濾可靠,因為查詢過濾一旦有遺漏就是洩漏。同時要誠實理解它的邊界:redaction 阻止的是憑證與 PII 外洩這個子集,它不阻止語意層面的記憶投毒(惡意 payload 裡沒有正則能抓的模式)。

權限檢查放在寫入路徑。 Cognee 把它做進 cognify 管線內,這個設計是對的:不該被某個主體看到的資料,不應該進入該主體的記憶。

共享記憶絕對不能混入使用者記憶。 一旦混入,刪除使用者資料會破壞系統能力,而不刪除則是違規。這是 分類學 裡主體歸屬維度必須在 schema 層落實的理由。


五、多 agent 共享

症狀:多個 agent 各記一套,彼此矛盾;或者一個 agent 的錯誤擴散到全系統。

污染擴散是最嚴重的問題。 公開分析描述的傳播路徑很直接:agent A 存入一條惡意記憶;agent B 在日常任務中取回它;agent B 受影響的輸出又被存成新的記憶條目。污染透過正常的協作流程擴散,而沒有任何 agent 偵測到異常。

解法:

共享記憶應該是唯讀的,或者寫入需要更高門檻。 一個 agent 可以讀共享知識,但寫入共享層應該經過額外驗證(多 agent 確認、或人工審核)。單一 agent 能直接寫入所有 agent 都會讀的層,是一個設計缺陷而非功能。

記錄 provenance 到 agent 層級。 每條共享記憶要知道是哪個 agent、基於哪個 episode 寫入的,才能在發現污染時精確回溯與撤銷。

分離「共享事實」與「共享規則」。 事實可以較寬鬆地共享,行為規則不應該被任何 agent 動態寫入。

併發寫入的語意目前是空白的。 Letta 的 block 共享 是最接近的實作(多個 agent 掛同一個 block_id),但它沒有定義併發寫入的行為。實務上的建議是把共享 block 的寫入序列化(單一 writer,或加樂觀鎖),並接受這是一個目前只能自己處理的問題。


六、一致性

症狀:同一件事在不同地方有不同的值;或者記憶與真實系統狀態(資料庫、API)不同步。

最重要的一條原則:不要把可以查的東西記下來。

使用者的訂單狀態、帳戶餘額、專案的當前分支——這些有權威來源的資料不該進入記憶,應該在需要時查詢。記憶下來的那一刻,它就開始腐化,而且記憶沒有 cache invalidation 機制

該記的是無法從系統查到的東西:偏好、意圖、過去的決策與理由、溝通風格。這條界線比它聽起來難守,因為抽取管線會很樂意把「使用者的訂單編號是 12345」存成一條記憶。解法是在抽取的 schema 約束裡明確排除可查詢的實體型別。

其餘的一致性問題:

真源與索引的不一致。 寫入真源成功但索引更新失敗。解法:索引必須可從真源完整重建(rebuild()),並定期執行對帳。順序上先寫真源、後更新索引——反過來會產生指向不存在資料的索引項。

跨 scope 的矛盾。 使用者記憶說偏好 A,共享記憶說這類使用者偏好 B。解法:明確的優先序(具體 scope 覆蓋一般 scope),並在組裝時只注入勝出的那一條而非兩條都給模型。

抽取版本的不一致。 改進抽取邏輯後,新舊記憶的品質與格式不同。解法:extractor_version 欄位 + 保留不可變的 episode,讓管線可以重跑GraphitiCognee 都靠這個性質)。這是「episode 不可變」這個約束最實際的回報。


一張快速對照

症狀最可能的成因第一個該做的事
agent 記住錯的事且改不掉自我強化 / 注入檢查 agent 自己的輸出有沒有進寫入管線
agent 做了沒被指示的事記憶投毒把行為規則移進唯讀分區
規則有時被遵守有時不規則放進了向量庫移進常駐層,全量載入
專有名詞查不到純向量檢索加上關鍵字檢索
用了舊的事實沒有時效過濾加雙時間軸 + 召回時過濾
召回品質隨時間下降庫膨脹稀釋檢查 NOOP 比例與歸檔策略
token 成本持續上升常駐層無配額為每個分區設 token 配額
不確定資料存在哪scope 不是一等公民補 schema,不要靠應用層邏輯
多 agent 彼此矛盾共享層可被任意寫入共享層改唯讀或提高寫入門檻
記憶與系統狀態不同步記了可以查的東西從抽取 schema 裡排除可查實體

相關