長運行 Agent
Session 不等於 Context Window
兩個最容易混淆的概念:Claude 當前能看到的,和所有發生過的事。它們必須分離。
兩個容易混淆的概念
臨時 / 有限
Context Window
Claude 當前能看到的 Token。就像人的工作記憶:容量有限,過了就忘。每次對話開始時構建,用完就丟。
當前推理所需的精選內容
永久 / 可回溯
Session
所有發生過的事件的持久日誌。就像完整的錄像:從頭到尾什麼都記着,永遠可以倒回去看。Append-only,只增不減。
所有原始事件的完整記錄
為什麼必須分離
上下文管理的不可逆性
- 1 Compaction(壓縮)和 Trimming(裁剪)都是不可逆操作,一旦壓縮,原始細節就丟了
- 2 壓縮時很難知道未來哪些 Token 重要,今天看似無關的信息,可能是明天關鍵決策的依據
- 3 如果壓縮後原始信息丟了,就永遠回不來了,這是信息論的基本約束
所以正確的做法是:原始事件永久保存在 Session 裏,Context Window 只是從 Session 中臨時取景的一個視角。丟了 Context 沒關係,因為 Session 還在,隨時可以重建。
Session 作為持久上下文對象
getEvents() 接口
Session 提供一個類似數據庫的查詢接口:Brain 可以按需讀取任意範圍的事件,擺脱固定上下文窗口的限制。
// Brain 可以靈活查詢 Session
const recentEvents = session.getEvents({
from: position - 100, // 從某個位置開始讀
to: position // 讀到當前位置
});
// 可以倒回到某個時間點
const beforeDecision = session.getEvents({
from: decisionPoint - 20,
to: decisionPoint + 5
});
// 可以過濾特定類型的事件
const toolCalls = session.getEvents({
filter: "tool_use"
});
這就像 REPL 中的對象一樣,LLM 可以寫程式碼來查詢和過濾 Session 中的事件。Brain 從任意位置開始讀、倒回到某個時間點、重讀某個決策前後的上下文。
Harness 的靈活性
從 Session 取出的事件可以做任意變換
- 優化 Prompt Cache 命中率:保持前綴穩定,減少重複計算的 Token 開銷
- 做上下文工程:根據當前任務類型,選擇性地放入最相關的歷史事件
- Harness 是可換的:不同模型可能需要不同的上下文策略,換 Harness 不影響 Session
核心對比
| 維度 | Context Window | Session |
|---|---|---|
| 持久性 | 臨時,用完即丟 | 永久,持久化存儲 |
| 內容 | 精選後的 Token | 所有原始事件 |
| 操作 | 只讀(對 Claude 來説) | 可追加(append-only) |
| 大小 | 有限(模型上限) | 無限制 |
| 用途 | 當前推理 | 歷史回溯、狀態恢復 |
硬件類比
記憶體 (RAM)
Context Window
速度快、容量小、斷電即失。CPU 正在用的數據必須在記憶體裏,但記憶體不是用來長期存儲的。
硬盤 (Disk)
Session
速度慢、容量大、斷電不失。所有數據最終都存在硬盤上,需要時再載入到記憶體。
你不會把所有檔案同時載入到記憶體裏,那樣記憶體會爆。同樣的道理,你不應該把所有歷史事件都塞進 Context Window,那樣 Token 會爆。正確的做法是按需載入:Session 存全量,Context 取子集。
Session 是 Agent 的硬盤,Context Window 是記憶體,不要把記憶體當硬盤用。把所有原始事件存進 Session,讓 Harness 按需組裝 Context。這樣即使上下文壓縮了、模型換了,歷史永遠不會丟。