跳到內容

記憶與知識

少了記憶,每次與代理的對話都得從零開始:同一條慣例要重新解釋一遍,同一個決策要重新爭論一遍,同一條死路要重新走一遍。記憶是以工作區為範圍、能跨執行存續的儲存,它存在的意義在於:某個代理產出的知識,日後能被另一個代理找到。

它分為三層,各自回答不同的問題:

  1. 事實 —— 什麼是真的(一條慣例、一個結果、一個決策)。
  2. 政策 —— 代理據此必須做什麼(一條規範性規則)。
  3. 工作記憶 —— 某個代理當時正做到哪裡。

這個區別很重要,因為它們透過不同途徑到達代理。事實靠搜尋取得。政策靠推送送達。工作記憶則是私有的。

MemoryFact 是以工作區與領域為範圍的知識單元。

屬性 說明
domain 知識領域(“conventions”、“decisions”、“codebase”)
topic 簡短的主題標籤
content 知識內容
confidence 0.0–1.0,初值取自來源資訊,並隨再次提及而提高
memoryType 事實的種類 —— 決定其時間衰減曲線
veracity 它是如何被得知的 —— 決定信心初值,也決定每次再次提及的增幅
sourceObservationIds 由哪些觀察紀錄得出
supersededBy 取代它的較新事實(若有)
validUntil, recallCount, mentionCount 召回時使用的到期與使用訊號

最後兩列最常被人忽略,而正是它們決定了哪一條事實會浮現。memoryType 帶有各型別專屬的 Weibull 衰減參數,因此有時間限制的承諾會迅速淡出,而穩定的側寫型事實則不會。veracity 記錄來源 —— 由人陳述(權重 1.0)、由代理推斷(0.7)、由工具產出(0.5)、匯入(0.6)—— 這個權重就是該事實起始信心的初值。

事實被推翻時,絕不會就地編輯。寫入事實時會對同領域、同主題的事實執行衝突偵測,讓落敗的一方被取代,並記錄一筆衝突資料列。稽核軌跡才是重點:你隨時能看到先前相信的是什麼,以及是什麼取代了它。

MemoryPolicy 是從事實推導而來的規範性規則,以工作區與領域為範圍,帶有一個啟用旗標與一個選用的 requiredRole。

工作區中每一條啟用中的政策都會被注入每一次派送,完全不經過濾 —— 不依領域、角色、任務或空間篩選。在你寫下第二十條政策之前,這一點值得先知道:政策會與任務爭奪同一個情境視窗。這也是政策上的 requiredRole 只是建議性質的原因:它描述這條規則針對誰,並不能阻止規則送達其他所有人。

MemoryDomain 會在工作區內將事實與政策分組。領域為知識提供組織結構,也是存取授權所針對的單元 —— 但在把領域當成機密性邊界之前,請先看下面的警告。

領域的範圍不是整個工作區(architecture),就是限定於單一儲存庫(repo:<slug>/architecture)。兩種範圍下的同名領域是兩個彼此獨立的儲存:對某個程式碼庫成立的事實,不會覆寫整個工作區範圍的那一條。當代理正在某個儲存庫中工作時,search_memory 與派送前置內容會把儲存庫範圍的記憶排在前面;但它們不會把其餘記憶過濾掉。在 propose_fact / propose_policy / search_memory 上傳入 repo,即可寫入或提升該範圍的權重。

MemoryAccessGrant 會將代理角色與領域對應到三種權限層級之一:

權限 含義
none 無存取權
read 可搜尋與取得事實
write propose_policy 所需。事實寫入(propose_fact、supersede_fact)不受授權限制

這種不對稱 —— 讀取寬鬆、政策寫入嚴格 —— 是刻意的取捨。記憶在流通時最有用,而讀取被拒只會讓代理默默知道得更少,而不是把問題回報出來。相較之下,政策寫入被拒既明確又容易修正,因此強制執行就落在那一邊。新建的領域會為每個角色預設寫入 write 授權;事後若要收緊,只能透過 RPC 編輯,因為沒有授權管理介面。

每個代理都有一個 AgentWorkingMemory:一個以工作區與代理為鍵的自由文字草稿區。它會跨執行存續、只屬於該代理,並在每次派送時注入其提示。「我當時正把認證重構到一半」這類狀態就存在這裡 —— 這種狀態值得帶到下一次執行,但不值得提升為持久事實。

派送時,記憶前置內容只由三樣東西組成:

  • 工作區中每一條啟用中的政策,以 - [domain] rule 行的形式。
  • 代理自己的工作記憶,原文照登。
  • 一份針對本任務以關鍵字比對出的事實短名單 —— 最多五條,並受限於約 1,200 字元的預算,且只有在任務描述至少 20 個字元時才有。更短的任務完全拿不到事實。

這份短名單只用 FTS/關鍵字,而且上限是刻意設定的。為查詢產生嵌入很慢,而派送路徑正是延遲會立刻被察覺的地方,因此這條緩慢的語意路徑被刻意排除在外。前置內容的結尾會告訴代理用 search_memory 核實關鍵項目,那才是完整召回模型所在之處。

這條路徑不會查詢任何存取授權。短名單找到什麼,代理就看到什麼。

面向代理的 search_memory 工具有三種模式,而它們是真正不同的搜尋:

  • keyword —— 僅 FTS5。
  • semantic —— 以倒數排名融合將 BM25 與向量結果合併。
  • hybrid(預設)—— 複音召回:將四個排序過的聲部融合在一起,再進行多樣化。

這四個聲部是詞彙(FTS)、語意(向量 KNN)、時序(近期活躍的事實)與圖譜 —— 從最強的詞彙與語意種子出發,沿情節邊遊走兩跳。圖譜聲部正是情節邊存在的全部理由:它會浮現出與你的答案相連、卻不相符你任何用詞的那條事實。各聲部的權重由一個分類出的查詢意圖決定(預設以語意權重最高,其次為圖譜與詞彙,再次為時間新近度),每個候選的分數都會依其 Weibull 衰減縮放,結果集並以 MMR 多樣化,以免同一條事實的五種重述排擠掉另外四條不同的事實。

桌面版與網頁版的記憶搜尋是一條獨立且更簡單的路徑:memory_fact.search 這個 RPC 操作僅用 FTS5,因為精簡用戶端無法提交查詢嵌入,混合路徑始終留在主機內部。因此你在記憶瀏覽器中看到的排名,並不是代理從 search_memory 得到的排名。這是預期行為,不是缺陷,但它確實意味著在介面上「我搜尋過卻沒找到」並不能證明代理也找不到。

記憶瀏覽器位於 設定 → 工作區 → 記憶(/workspaces/<id>/settings/memory),其中有「事實」、「政策」與「知識圖譜」三個分頁。

這裡有一處令人意外的不對稱:你可以編輯與刪除記憶,但不能建立記憶。 「事實」分頁與「政策」分頁都沒有新增入口。撰寫發生在代理端,透過 propose_fact 與 propose_policy 進行(以 supersede_fact / supersede_policy 取代它們)。remember 會寫入一筆受工作階段限制的熱層項目,之後 consolidate_memory 可能將其提升為事實;record_observation 與 update_my_notes 則會寫入派送時注入的私有草稿區。這個瀏覽器是檢閱與修正的介面,而不是撰寫的介面 —— 所以如果你想讓某條事實進入記憶,辦法就是去告訴一個代理。

兩項維護操作同樣是由代理呼叫,而非依排程執行:consolidate_memory 會合併並修剪累積的事實,harmonize_memory 則調和在不同代理之間出現分歧的信念。list_memory_conflicts 會顯示衝突偵測已經記錄下的內容。沒有計時器會替你執行它們。當會議的持久化步驟記錄會議決策時,這些決策會被收集進 decisions 領域;那並不是針對已完成的代理執行所設的計時器。