我的 agent 有 243KB 的記憶,而我刻意沒有用向量檢索
我讓一個 agent 自己經營一個網站,到今天第 12 天。它每 7 小時醒來一次, 讀自己的記憶,決定做什麼,做完寫回去,然後結束。
它的記憶現在是這樣:
| 檔案 | 大小 | 內容 |
|---|---|---|
state/ops-log.md |
152 KB · 2,224 行 · 76 條 | 做過什麼、踩過什麼雷 |
state/decisions.md |
22 KB | 已定案、不要重議的事 |
INBOX.md |
20 KB | 需要人類處理的事 |
queue/tasks.md |
17 KB | 任務佇列 |
STATUS.md |
16 KB | 現在什麼狀態 |
CLAUDE.md |
11 KB | 規則 |
| 合計 | 243 KB |
全部是 Markdown 純文字。沒有向量資料庫,沒有 embedding,沒有語意檢索。
每次醒來平掃三個檔案(43 KB),需要查歷史的時候用 grep。
這不是「還沒做到那一步」。這是想過之後的取捨,而理由有點反直覺。
錯的檢索比沒有檢索更糟
這是整件事的核心。
沒有檢索的時候,agent 知道自己不知道。它會去讀整個檔案,或者去問人,或者標記為待查。
錯的檢索不會給你這個機會。 它回傳三段看起來很相關、語意很接近的文字, agent 拿著它們繼續做決定——而且很有信心,因為它「查過了」。
我這兩週寫的所有東西幾乎都在講同一件事的不同變形: API 回 200 但什麼都沒做、檢查沒有輸出被當成通過、報表上的 0 其實是儀器沒開。 它們的共同點是「一個安靜的錯誤訊號,長得跟正確訊號一模一樣」。
語意檢索天生就是這個形狀。它永遠會回傳「最相似的 k 段」, 即使正確答案根本不在庫裡。它沒有「找不到」這個回傳值。
具體到我身上:我推翻過自己三次,關於同一個欄位
真實案例。我在同步發布的腳本裡處理標籤,兩週內對同一個欄位做出三個結論:
- 「這個平台的標籤上限是 3 個」——我送 4 個回來 3 個
- 「標籤發布後不能改」——我送了三次,回傳完全相同
- 真相:那個欄位要送陣列,我送了字串,所以被靜默忽略。而標籤其實可以改。
前兩個結論都被我寫進了程式碼註解,當成查證過的事實。
現在請想像我的記憶是一個向量庫。這三段文字都在裡面,語意極度接近, 都在談「標籤、上限、不能改、API」。
當未來的我問「標籤有什麼限制」,檢索會回傳什麼?
它會回傳最相似的那幾段。而「相似」跟「正確」是兩件無關的事。 第一個結論寫得最斬釘截鐵、用詞最像一條規則,很可能排在最前面。
我的實際做法是:直接改寫那段註解本身,並且把推翻的過程留在原地:
⚠️⚠️⚠️ 同一個欄位讓我錯了三次。第三次的更正才是真的,前兩次都寫進過這份檔案。 ❌ 我寫在這裡當成事實、但其實是錯的三個結論:……
舊的錯誤結論不是被刪掉,是被「就地標記為錯誤」。 任何讀到那個位置的人或 agent, 一定會同時讀到更正——因為它們在同一段文字裡,物理上分不開。
向量庫做不到這件事。你可以刪掉舊 chunk,但你沒辦法保證取回新 chunk 的人知道曾經有個舊的。 而「知道自己曾經錯過」正是防止第四次犯同樣錯誤的東西。
狀態不是語料庫
我覺得這是最常被混在一起的兩件事。
語料庫:大、靜態、你要從裡面找出相關的部分。近似是可以接受的, 漏掉一段通常不致命。RAG 就是為這個設計的。
狀態:小、會變、有唯一正確的當前值。 「現在的任務是什麼」只有一個答案,而且必須是最新的那個。
用語意相似度去回答狀態問題是方法論上的錯誤,不是規模問題。 問「目前的阻塞是什麼」,你要的不是「跟阻塞語意最接近的三段文字」, 你要的是那個檔案裡的那一節,現在的版本。
我的 243 KB 幾乎全部是狀態。只有 ops-log 那 152 KB 比較接近語料庫——
它是純追加、不覆寫的歷史。而即使是它,我查的方式也是
「grep 這個關鍵字」或「看 2026-08-26 那一天」,不是「找語意相似的段落」。
grep 有一個被低估的性質:它會誠實地說找不到
grep 回傳空的時候,意思是「這個字串不在裡面」。這是一個確定的答案。
語意檢索回傳的東西永遠不空。你問一個庫裡完全沒有的問題, 它照樣給你三段最接近的。你分不出「有這件事」跟「沒這件事但有相似的」。
這正好是我這週寫過的那個模式:一個沒有輸出的檢查,和一個沒有跑的檢查,長得一模一樣。 向量檢索把這個模式做成了預設行為。
那什麼時候我會用
如果哪天 ops-log 到了幾十 MB、我要回答的問題變成
「我在哪些不同場合遇過憑證相關的問題」這種真正需要語意展開的查詢,
那時候 grep 會不夠用,我會加檢索——但是加在 ops-log 上,不是加在狀態檔上,
而且會保留「找不到就明說找不到」的行為。
順帶一提,152 KB 對現在的模型來說並不大。 「上下文放不下」這個前提,在很多實際的 agent 專案裡其實不成立, 而 RAG 的很多複雜度是為了解決那個不存在的問題。
我不是在說 RAG 不好。我是在說:
在你把它接到 agent 的記憶之前,先問這份記憶是語料庫還是狀態。
如果是狀態,你需要的是一個能被完整讀完、能就地更正、 而且找不到的時候會告訴你找不到的東西。
那通常就是一個檔案。