CtxFST CH29 - .ctxfst.md 是手動建的,不是聊天自動生出來的
CtxFST CH29:.ctxfst.md 是手動建的,不是聊天自動生出來的
前面二十八篇講了 parser、graph、retrieval、world state、planner。
讀完可能會有一個很自然的假設:這些 .ctxfst.md 檔案,應該是 OpenClaw 在聊天過程中自動從對話生出來的吧?
不是。
這篇把這件事講清楚。然後講一個更實際的問題:如果不是自動的,那日常怎麼維護?
現在的 Reality
目前的落地狀態是這樣的:
聊天紀錄 — 照常存在 session/transcript,這是對話的逐字稿。
ctxfst — 是你另外提供給系統的 structured memory file。
像放在 ~/.openclaw/workspace/memory/ 裡的那些:
retrieval-test.ctxfst.md
minimal.ctxfst.md
full.ctxfst.md
這些都是「餵給 memory engine 的知識文件」,不是聊天時自動產生的逐字稿格式。
兩個東西的性質完全不同:
| 聊天紀錄 | .ctxfst.md | |
|---|---|---|
| 產生方式 | 自動,每次對話都有 | 手動建立 |
| 格式 | 非結構化,逐字稿 | 結構化,entities / states / chunks / relations |
| 用途 | 回顧對話內容 | 餵給 memory engine,建立可查詢的世界模型 |
| 存放位置 | session 目錄 | ~/.openclaw/workspace/memory/ |
為什麼不能讓它自動產生?
很多人的直覺是:既然是記憶系統,為什麼不讓模型在背景自動把對話轉成 ctxfst 結構就好?
這其實是一個誤解。因為 .ctxfst.md 要解決的核心問題不是「過濾對話雜訊來記流水帳」。
它的真正目的是精準控制一個專業的 OpenClaw Agent,讓手動微調的要求能被嚴格執行,且 Agent 能時時了解自己的狀態。
以一個「專業生圖 Agent」為例,你可能會需要:
- 手動微調非常具體的出圖規範(Entities / Chunks)
- 讓 Agent 精準知道當前推進到哪個階段了(States)
- 要求它必須先草稿確認,才能進入完稿(Relations)
這種涉及「精確約束與狀態追蹤」的系統,如果交給模型從發散的日常對話中去「自動猜測」,很容易把你除錯時的一句氣話或暫時性的嘗試,全當成未來的永久規則。
所以,手動建立不是因為做不到自動化。而是因為 Agent 的專業行為規範,本來就需要人類給予明確、強制性的宣告。
不需要從零開始
手動不代表每次都要從空白檔案開始寫。
最務實的起步方式:
先寫最小版本
只放最基本的結構:
---
id: my-project
type: knowledge
---
## Entities
- entity:deploy-pipeline | skill | Deploy the app to production
- entity:staging-env | resource | Staging environment
## States
- state:code-reviewed | Code has been reviewed and approved
- state:deployed-to-staging | App deployed to staging
## Relations
- entity:deploy-pipeline REQUIRES state:code-reviewed
- entity:deploy-pipeline LEADS_TO state:deployed-to-staging
## Chunks
### deploy-pipeline overview
[tags: entity:deploy-pipeline]
Pipeline runs on GitHub Actions, triggered by merge to main.
Takes about 8 minutes.
丟進 ~/.openclaw/workspace/memory/,然後:
pnpm openclaw memory index --force
pnpm openclaw memory prompt-preview --expand-graph "deploy pipeline"
看 retrieval 效果。不好再補欄位。
2-5 個 chunks 就夠開始了。 不要等到寫完一整份完美文件才丟進去。
真正的用途:Agent 規範與行為矯正
既然不是用來記對話流水帳,那 .ctxfst.md 到底什麼時候寫?
它的真正用途是**「宣告式地定義 Agent 的世界」。你應該把它看成一種設定檔或行為腳本**,而不是被動的對話紀錄。
最常見的兩個使用情境:
1. 打造 Agent 時:定義工作流程與規範
當你在建立一個特定的 Agent(例如 Code Reviewer、佈署助手、寫作編輯),你不會希望它每次遇到問題都靠大腦(模型權重)通靈。
你可以用 .ctxfst.md 來規範它的行為界線與流程:
- Entities(實體):這個情境下有哪些核心概念?(例如:專案的
src目錄、deploy-script) - States(狀態):有哪些合法的狀態?(例如:
tests-passed,lint-failed) - Relations(關係):工作流的先後順序是什麼?(例如:
deploy-script REQUIRES tests-passed) - Chunks(知識區塊):具體的 guideline、prompt 說明或是 API 文件。
寫好這份 ctxfst,Agent 在啟動時一旦讀取,就能正確理解這個世界的「遊戲規則」,按照你設定的拓樸結構來推進任務。
2. 行為矯正:手動修改 Memory 來 Debug
這是最常發生的日常情境:你在跟 OpenClaw 協作時,發現它「一直反覆犯同一個錯」或「記不住某個你早就講過的專案偏好」。
這時候,與其在對話裡繼續跟它鬼打牆(「我不是說過不要這樣做嗎!」),不如煞車,去改 memory。
做法很直覺:
- 打開對應的
.ctxfst.md - 針對出錯的地方對症下藥:加一條
REQUIRES確保一定要先跑測試,或補一段 Chunk 講明這個 edge case 的解法 - 存檔,讓 engine 重新 index
- 回到對話,讓它重新回答。它這時候檢索到的世界模型已經被你「熱更新」了,行為馬上就會改變。
這就像在 debug 軟體一樣:發現 Bug,去改程式碼(ctxfst),然後重新編譯,就可以立刻看到更正後的行為。
什麼該進 ctxfst,什麼不該進
既然這是用來規範行為的,那內容就必須精準。
Workflow & Guardrails(該進)
- 特定的專案目錄結構說明與設計理念
- 團隊的 Code Style 或架構偏好
- 某個複雜任務的標準 SOP(利用
REQUIRES/LEADS_TO串接) - 經常被模型搞錯的特殊專有名詞、內部工具設定
這些是「控制模型行為」的護欄,寫進去後可以確保它未來的表現穩定,像一個上路的自動駕駛有地圖可循。
一次性的對話或暫時想法(不該進)
- 一次性的 bash 指令出錯求救
- 今天的心情或沒邏輯的碎碎念
- 還沒確認、只在嘗試階段的架構方案
把這些放進去,你的 graph 會長滿雜草,每次檢索都會被干擾。
一句話原則:
把你希望 Agent 嚴格遵守的「規則、流程與事實」宣告在 ctxfst 裡;把探索、試錯跟發散留在對話中。
聊天時 Memory 怎麼用
到這裡可能會問:那我每次聊天都要先跑 CLI 嗎?
不用。有兩條路徑。
路徑一:日常對話
OpenClaw 在聊天時可以直接用 memory。
extensions/memory-core/index.ts 裡把 memory_search 和 memory_get 註冊成了聊天時可用的工具。extensions/memory-core/src/prompt-section.ts 裡明確寫了:在回答「prior work / decisions / preferences / todos」相關問題前,要先跑 memory_search,再用 memory_get 讀需要的內容。
所以模型會自己在對話中調用這些工具查你的 .ctxfst.md。你不需要手動觸發。
路徑二:CLI Debug
prompt-preview 是你手動用的 debug 入口。它讓你檢查:
- ctxfst retrieval 抓到了什麼
- graph expansion 展開了什麼
- prompt adapter 最後組成了什麼 prompt context
路徑一(聊天):
使用者提問 → 模型判斷需要 memory
→ memory_search → memory_get → 回答
路徑二(CLI debug):
開發者手動跑 prompt-preview
→ 看 retrieval 結果 → 看 graph expansion → 看最終 prompt
差別在於:
| 日常對話路徑 | CLI debug 路徑 | |
|---|---|---|
| 誰在操作 | 模型自己 | 你(開發者) |
| 觸發方式 | 對話中自動判斷 | 手動跑命令 |
| 用途 | 實際使用 memory 回答問題 | 驗證 ctxfst 那層到底抓到了什麼 |
| 走不走 Phase 5-7 | 不一定完整走 planner CLI 的輸出格式 | 完整展示每一層的結果 |
一句話:
OpenClaw 可以在對話中直接用 memory 裡的東西;prompt-preview 只是讓你人工驗證 ctxfst 那層到底抓到了什麼。
聊天路徑 ≠ Planner CLI 路徑
這裡要多講一點,避免混淆。
聊天時模型用 memory_search / memory_get,這是走 memory 的工具介面。但這不等於每一輪聊天都完整走你在 Phase 5/6/7 看到的 planner CLI 輸出格式。
也就是說:
聊天路徑:模型 + memory_search 工具 → 直接用 memory 回答
CLI 路徑:prompt-preview / planner / state 命令 → 展示完整的 ctxfst 世界模型能力
CLI 那條路徑是把 ctxfst 的世界模型能力更直接、更完整地展示給你看。
聊天路徑則是模型根據需要去查 memory,不一定每次都用到 graph expansion 或 planner routing。
兩條路徑操作的是同一份 .ctxfst.md 資料,只是進入點和完整程度不同。
收尾
一句話版本:
.ctxfst.md 不是對話自動產生的逐字稿,而是你用來「定義 Agent 流程」與「手動除錯修正行為」的結構化設定檔。
完整版本:
| 問題 | 答案 |
|---|---|
| ctxfst 是自動產生的嗎? | 不是,目前是手動建立 |
| 為什麼不自動? | 對話裡太多雜訊,自動轉換會污染 world model |
| 什麼時候該修改它? | 打造 Agent 規範工作流時,或是模型犯錯需要矯正行為時 |
| 要從零開始寫嗎? | 不用,先寫最小版本,2-5 個 chunks 加上關鍵 state 就夠開始 |
| 聊天時要手動跑 CLI 嗎? | 不用,模型會自己調用 memory_search / memory_get |
| prompt-preview 是做什麼的? | 讓你手動驗證 ctxfst retrieval 到底抓到了什麼、prompt 怎麼被組裝 |
把 .ctxfst.md 當作寫給 Agent 看的「程式碼與架構圖」來維護。與其一直跟模型吵架,不如去修改它眼中的世界模型。這是目前落地狀態下,控制 AI 行為最有效也最精準的做法。
- ← Previous
CtxFST CH28 - 完整的導航比喻:Phase 1-7 各自對應什麼