跳到主要內容
Lab Grimoire
TW EN
請喝咖啡
AI Agent 記憶系統設計:三層架構實作
動手實作

AI Agent 記憶系統設計:三層架構實作

Agent 工作流實戰 · 第 4/19 篇
本頁目錄

為什麼不能只用一個檔案

有沒有想過,你的 AI 助手其實是個金魚腦?上週我請 Claude Code 幫我改一個統計分析腳本。它問:「要用 Python 還是 R?」三個月前我就在設定檔裡寫了「統計用 R」。但那次對話的上下文早就消失了。同一件事,我至少重複講了 7 次。真的。

偶爾聊幾句,失憶無所謂。但你每天都靠它處理文獻、寫程式碼、管專案。「記不住事情」就像跟一個每天都失憶的同事合作。煩不煩?煩。時間就這樣被吃掉了。

三層記憶架構是一種 AI Agent 記憶系統設計模式,將資訊分為事實層(fact)、情節層(episodic)和暫存層(scratchpad)三個層級,各自負責不同時間尺度和用途的記憶存取,讓 AI 在跨對話、跨任務的場景中保持上下文連續性。

我的工作橫跨學術研究跟產品開發。過去半年一直在用 Claude Code 跑這套架構。以下拆解為什麼要分三層。每一層怎麼做。以及我一開始做錯了什麼。

三層記憶架構總覽圖

最直覺的做法是開一個 memory.md。把所有該記的東西都寫進去。我一開始就是這樣幹的。

兩週後這個檔案膨脹到 500 多行。個人偏好、上週的技術決策、當前任務筆記、三個月前的踩坑紀錄全攪在一起。雜訊不斷堆積。AI 每次啟動都得讀完整份。token 用掉在一堆不相關的內容上,而且該留的跟該丟的混在一塊。根本不知道哪些能安全刪掉。想清理?不敢。怕刪錯。混成一份檔案後,啟動載入時間膨脹了約 3 倍

根本問題就一句話:不同類型的記憶有不同的生命週期跟存取模式。就像你不會把身分證、日記跟便利貼塞進同一個信封。你的名字和語言偏好不太會變。但昨天的任務暫存筆記明天就沒用了。半年前的架構決策偶爾要回頭看。但不需要每次對話都載入。

所以要分層。

三層架構的設計哲學

這不是我發明的概念。三層架構其實借鏡人類記憶的運作方式。大腦本來就不是把所有東西存在同一個地方:

記憶層 對應人類記憶 AI 實作 生命週期 存取頻率
事實層 語義記憶(知識、事實) fact.yml(AI 的身分證) 長期穩定 每次啟動
情節層 情節記憶(經歷、事件) episodic.jsonl(AI 的日記本) 長期累積 按需查詢
暫存層 工作記憶(當前任務) scratchpad.md(AI 的便利貼) 短期 任務進行中

核心原則就一句話:按需載入。不用每次啟動都把所有記憶灌進 context window。當前任務需要什麼,載入對應的那一層就好。省 token。也省 AI 的注意力。

事實層:AI 的身分證

事實層就像你幫 AI 辦的一張身分證。上面寫著姓名、語言、慣用工具。用 YAML 格式,檔名 fact.yml。專門放穩定、很少變的個人檔案:

user:
  name: CYHsieh
  language: "台灣繁體中文 (嚴格)"
  timezone: "Asia/Taipei (GMT+8)"
  roles:
    - org: 元培醫事科技大學
      title: 助理教授
    - org: 宇君生技
      title: 研發總監

  preferences:
    statistics_workflow:
      primary_language: "R"
      rule: "假設檢定、效應量、發表級圖表 用 R;其餘用 Python"
    tech_stack: ["Tailwind CSS", "React", "Zod"]

  language_rules:
    forbidden_words:
      - "軟件 → 軟體"
      - "信息 → 資訊"
      - "視頻 → 影片"

為什麼不用 Markdown?因為事實層需要結構化查詢。AI 想知道「統計偏好語言是什麼」。直接從 preferences.statistics_workflow.primary_language 取值就好。你用 Markdown 寫「我偏好用 R 做統計」?AI 得從一段自然語言裡去猜、去解析。穩定度差很多。

更新策略是 append-only。不刪東西。改加 archived: true 標記。歷史設定永遠有跡可循。我曾經手賤直接刪了一條舊偏好。結果呢?兩週後 AI 又開始用舊的行為模式。從此學乖了。

Claude Code 每次啟動時,事實層透過 CLAUDE.md 的記憶路由載入。這就是 AI「認識你」的基礎。

情節層:AI 的日記本

如果事實層是身分證,情節層就是日記本。每一頁記一件事:今天做了什麼決策、踩了什麼坑、學到什麼教訓。用 JSONL 格式(每行一筆 JSON)。檔名 episodic.jsonl

{"ts":"2026-03-15T14:30:00+08:00","type":"decision","summary":"統計語言選定 R","detail":"假設檢定/效應量/圖表用 R,其餘工程任務用 Python","tags":["statistics","R","tooling"]}
{"ts":"2026-04-02T09:15:00+08:00","type":"failure","summary":"AI 誤刪設定檔","detail":"Claude Code 執行清理腳本時刪除了 .env.local,導致開發環境掛掉","lesson":"建立 Hook 守門系統,禁止 rm 指令","tags":["safety","hook","incident"]}
{"ts":"2026-05-10T16:00:00+08:00","type":"milestone","summary":"記憶系統 v4.0 上線","detail":"strength 衰減公式: base(imp/10) + retrieval(count*0.08) + assoc(edges*0.05) - decay(weeks*0.03)","tags":["memory","architecture"]}

為什麼選 JSONL?因為每筆記錄獨立一行。新增不影響既有內容。格式不會壞。想查「所有 failure 類型的紀錄」或「最近兩週的決策」?一行 jq 就搞定。也不用每次全部載入。AI 根據 tags 篩選相關的情節就好。其餘的不碰、不浪費 token。

情節層不是啟動就載入的。是按需查詢。AI 遇到類似問題(比如又要選統計語言),會回去翻情節層:「之前有沒有做過類似決策?」踩過的坑不會再踩第二次。分層之後,啟動讀取的 token 量減少了約 60%

暫存層:AI 的便利貼

暫存層就是貼在螢幕邊框上的便利貼。隨手記、用完就撕掉。用 Markdown,檔名 scratchpad.md。三層裡最短命的一層。記的是當前任務的進度、待辦跟臨時筆記:

# Scratchpad - 當前任務暫存

## 進行中:統計分析腳本重構
- [x] 讀取原始 Python 腳本
- [x] 確認改用 R 的 rstatix 套件
- [ ] 重寫假設檢定段落
- [ ] 產出效應量圖表

## 暫存筆記
- 資料集在 data/experiment_2026Q1.csv
- 客戶要求用 Cohen's d 而非 Hedge's g

暫存層解決一個痛點:跨 session 接力。想想看。任務做到一半、電腦要關機、或者你被會議打斷了。下次開新 session,AI 讀到 scratchpad.md 就能接上進度。不用你重新解釋「上次做到哪了」。

清理策略很直接:任務結束後,重要決策「升遷」到情節層,暫存層清空。

三層記憶的生命週期與流向

三層之間的協作流程

三層不是各自獨立的孤島。它們之間有明確的流動關係:

  1. 啟動階段:CLAUDE.md 觸發,載入事實層(fact.yml)。AI 知道你是誰、你的偏好
  2. 任務進行中:暫存層(scratchpad.md)即時更新進度。遇到需要歷史參照的決策時,查詢情節層(episodic.jsonl)
  3. 任務完成後:暫存層中的關鍵決策「升遷」到情節層。暫存層清空
  4. 偏好變更:如果任務過程中發現需要更新長期偏好(例如「以後統計都用 R」),寫入事實層
啟動 → 載入 fact.yml(你是誰)
         ↓
任務中 → 讀寫 scratchpad.md(現在做什麼)
         ↓ 需要歷史參照時
         查詢 episodic.jsonl(之前發生過什麼)
         ↓
完成 → 決策升遷到 episodic.jsonl
       暫存清空
       偏好更新到 fact.yml(如果有的話)

關鍵在這裡:CLAUDE.md 只是路由入口。就像辦公室門口的樓層導覽牌。它本身不存記憶內容。只告訴 AI「去哪裡找什麼資訊」。身分證放一樓。日記本放二樓。便利貼在桌上。這樣每一層可以獨立長大。整個系統保持模組化。不會又變回那個 500 行的垃圾場。

CLAUDE.md 路由入口的完整設計,CLAUDE.md 設計哲學:讓 AI 記住你是誰 有詳細說明。

從零開始建:三步驟

想在自己的 Claude Code 專案裡建三層記憶?十分鐘就能搞定最小可行版本:

步驟一:建立 memory 目錄和事實層

mkdir -p memory
cat > memory/fact.yml << 'EOF'
user:
  name: "你的名字"
  language: "台灣繁體中文"
  timezone: "Asia/Taipei"
  preferences:
    tech_stack: ["你常用的框架"]
EOF

步驟二:建立暫存層

cat > memory/scratchpad.md << 'EOF'
# Scratchpad - 當前任務暫存

(任務開始時在這裡記錄進度)
EOF

步驟三:在 CLAUDE.md 中加入記憶路由

## 記憶路由
- 偏好/設定: memory/fact.yml
- 任務暫存: memory/scratchpad.md

情節層(episodic.jsonl)可以等你真的需要記錄決策時再建。不用一開始就把三層都填滿。先用起來。系統會隨著你的使用自然長出來。我的情節層從零到 100 篇,花了大約六週。等 fact.yml 長到某個臨界點,你自然會想把它拆成 fact_tools.ymlfact_sop.yml 之類的領域檔案。到時候再拆就好。

進階:記憶強度與衰減

情節層累積到幾百筆之後,新的問題浮出來了:哪些記憶重要、哪些可以淡出?記憶像冰塊。放著不管就會慢慢融化。全部留著太亂。全部刪又太狠。我需要一套「記憶的保鮮期」機制。所以設計了一個記憶強度公式:

strength = base(importance/10)
         + retrieval(count * 0.08)
         + association(edges * 0.05)
         - decay(weeks * 0.03)

四個因素:初始重要性、被回顧的次數、跟其他記憶的關聯數量、隨時間的自然衰減。常拿出來用的保鮮期自動延長,放到深處忘記的慢慢過期。強度低於閾值就標記為可歸檔,但不刪除。

效果?真正重要的經驗(像「那次 AI 誤刪我的 .env.local」)因為反覆被引用,強度一直很高。瑣碎的暫存紀錄自然淡出。這個公式不需要多精密,能讓重要記憶浮上來、雜訊沉下去就夠了。

不過,這套衰減機制有侷限。它只管「要不要淡出」,不管「記憶之間的語義衝突」。如果事實層跟情節層對同一件事有矛盾記錄,公式本身不會幫你抓出來。這部分還是得靠人工巡檢。

三層之上:系統怎麼長大的

用了幾個月之後,三層架構自然往外長出新東西:

  • 關聯圖譜:情節之間不是孤立的。「那次 AI 誤刪 .env.local」跟「建立 Hook 守門系統」有因果關係。我加了一層 associations.jsonl 搭配 SQLite 快取,記錄記憶之間的加權連結。強度公式裡的 association(edges) 就是從這裡算的。
  • 腦區路由:記憶一多,全部擠在同一個 fact.yml 裡又變成新的垃圾場。所以我把事實層拆成多個領域檔案(fact_sop_dispatch.ymlfact_governance.ymlfact_tools_detail.yml),再用一個 brain region manifest 管路由。有點像大腦皮質分區。
  • 聖域分層:有些記憶不該被隨便改。API 金鑰、安全規則、核心身份設定。我做了一個三級存取控制(public / private / sacred),AI 要修改 sacred 層的記憶必須明確取得許可。

這些擴展不是一開始就設計好的。是用到某個臨界點,痛點冒出來才加的。三層架構是地基。地基穩了,上面要蓋什麼都蓋得起來。

我把這套系統的完整邏輯寫成了一個 Python 套件:Ghost in Shell,包含衰減引擎、關聯圖譜、腦區路由、去重機制、多平台適配器(Claude / Codex / Copilot / Gemini)。想直接跑起來的可以從這裡開始。

整套系統的全貌,我用 Claude Code 自動化了 80% 的日常開發工作 有展示記憶系統怎麼跟 Skill 路由、Hook 守門等模組協作。

常見的設計陷阱

事實層塞太多東西。 我犯過。事實層只放「跨任務通用、長期穩定」的資訊。某個專案的 API endpoint 不該放在全域 fact.yml 裡。那屬於該專案自己的 CLAUDE.md。

從不清理暫存層。 便利貼只貼不撕。兩週螢幕就被糊滿了。系統變懶了嗎?不是。是你變懶了。每次任務結束花一分鐘。重要的升遷到日記本。其餘撕掉。一分鐘而已。

情節層沒有 tags。 沒 tags 的情節紀錄跟沒索引的資料庫一樣。查什麼都是全表掃描。每筆紀錄至少打 2 個 tag。未來的自己會感謝現在的自己。


常見問題

三層記憶架構只能用在 Claude Code 嗎?

不是。任何支援檔案存取的 AI 工具都能套。Gemini CLI、Codex CLI 都有類似的設定檔載入機制。差異只在格式跟載入方式。三層的設計邏輯是通用的。跟你用哪家的 AI 無關。

記憶檔案需要進 Git 版控嗎?

fact.yml 建議進版控(它是系統設定的一部分)。episodic.jsonl 看情況。如果裡面有敏感決策可以加進 .gitignore。scratchpad.md 通常不需要版控。它是短命的暫存。

記憶系統會不會讓 AI 變慢?

不會。事實層通常幾十到幾百行。token 消耗很小。情節層是按需查詢不是全量載入。啟動速度不受影響。唯一要注意的是暫存層別累積太多內容。塞到兩三百行以上 AI 的注意力就會被稀釋。

跟 ChatGPT 的 Memory 功能有什麼不同?

ChatGPT 的 Memory 是黑箱。你不知道它記了什麼、怎麼存的、什麼時候會忘。三層記憶架構是完全透明的純文字檔案。每一筆記憶你都看得到、改得動、砍得掉。控制權在你手上。不在 AI 公司手上。

三層架構有什麼風險或限制?

有。最大的限制是維護成本。三層分開管理。代表你要記得三個地方的內容各是什麼。偶爾事實層跟情節層會出現矛盾記錄。你得手動核對。暫存層如果忘了清理,會慢慢變成第二個垃圾場。這套架構不是「設好就不用管」的東西。它需要你養成定期巡檢的習慣。

要多久才能累積出有效的記憶系統?

每天用 Claude Code 的話,大約 2 到 3 週就能感受到差異。事實層第一天就能建好。情節層做了幾個決策、踩了幾個坑之後自然會有內容。關鍵不是技術,是習慣。每次任務結束花一分鐘記錄。就一分鐘。養成了,整個系統就活了。


想更深入?

我整理了一份《AI Agent 記憶系統設計藍圖》,包含三層架構的完整檔案結構、YAML/JSONL 格式規範、記憶強度公式、以及一份可以直接複製使用的起始模板包。

免費下載記憶系統藍圖

下一篇:Skill 路由引擎:讓 AI 自動選擇正確工作流

常見問題

三層記憶架構只能用在 Claude Code 嗎?

不是。這個設計模式可以套用到任何支援檔案存取的 AI 工具。Codex CLI 等 CLI 型 AI 工具都有類似的設定檔載入機制。差異只在設定檔格式和載入方式,三層的設計哲學是通用的。

記憶檔案需要進 Git 版控嗎?

fact.yml 建議進版控(它是系統設定的一部分)。episodic.jsonl 看情況,如果裡面有敏感決策可以加進 .gitignore。scratchpad.md 通常不需要版控,它是短命的暫存。

記憶系統會不會讓 AI 變慢?

事實層通常只有幾十到幾百行,對 token 消耗的影響很小。情節層因為是按需查詢而非全量載入,所以也不會拖慢啟動速度。真正要注意的是暫存層不要累積太多內容。

跟 ChatGPT 的 Memory 功能有什麼不同?

ChatGPT 的 Memory 是黑箱,你無法控制它記住什麼、怎麼儲存、何時遺忘。三層記憶架構是完全透明的純文字檔案,你能看到每一筆記憶的內容,能手動編輯、刪除、遷移。控制權完全在你手上。

要多久才能累積出有效的記憶系統?

如果你每天使用 Claude Code,大約兩到三週就會感受到差異。事實層第一天就能建好。情節層在你做了幾個決策、踩了幾個坑之後就會有內容。關鍵是養成「完成任務後花一分鐘記錄」的習慣。

覺得這篇有幫助?

追蹤以收到新的 AI × 生醫研究筆記:

或請我喝杯咖啡,讓新內容持續產出。

☕ 請我喝杯咖啡