制:Context Window、Compaction 與 Pruning 的配置與驗(yàn)證)
1. OpenClaw 長(zhǎng)會(huì)話上下文溢出context_length_exceeded 報(bào)錯(cuò)到底怎么來(lái)的如果你用 OpenClaw 跑過(guò)稍微長(zhǎng)一點(diǎn)的會(huì)話尤其是那種帶一堆工具調(diào)用、還掛了幾個(gè) Skill 的場(chǎng)景大概率見(jiàn)過(guò)下面這幾種報(bào)錯(cuò)Error: context_length_exceeded Error: maximum context length is 32768 tokens, but input is 41230 tokens Error: model crashed / model reload第一次看到的時(shí)候我也懵明明對(duì)話才幾十輪怎么 token 就爆了。后來(lái)把/context detail打開(kāi)一看才明白真正吃 token 的根本不是聊天記錄而是工具 schema、Skill 列表、workspace 文件注入這些東西。它們平時(shí)看不見(jiàn)但每次請(qǐng)求都會(huì)重新拼進(jìn) prompt 里。OpenClaw 的 Context 控制機(jī)制核心就是三條線contextWindow 定硬上限、compaction 壓縮歷史、contextPruning 裁剪緩存。這篇就圍繞這三條線把配置片段和驗(yàn)證動(dòng)作都寫清楚你在本地能直接復(fù)現(xiàn)。先說(shuō)清楚 Context 是什么。OpenClaw 本質(zhì)上是每次請(qǐng)求重新構(gòu)建一個(gè)完整 prompt這個(gè) prompt 包含System prompt系統(tǒng)提示詞Conversation history對(duì)話歷史Tool calls tool results工具調(diào)用和返回Attachments / transcripts附件、轉(zhuǎn)錄Compaction summaries 和 pruning artifacts壓縮摘要、裁剪產(chǎn)物Provider 的隱藏 wrapper不可見(jiàn)但計(jì)入注意最后一條很多 provider 會(huì)在請(qǐng)求里塞一些你看不到的包裝內(nèi)容它們照樣占 token。所以 Context ≠ memorymemory 是磁盤上的東西可以重新加載Context 是這一次請(qǐng)求實(shí)際發(fā)出去的全部?jī)?nèi)容。適合誰(shuí)看這篇本地跑 OpenClaw、接了 LM Studio / Ollama 這類本地推理服務(wù)、或者用云端模型但會(huì)話一長(zhǎng)就崩的人。下面所有配置都基于openclaw.json路徑和字段名跟官方文檔保持一致。2. TaoToken 前置準(zhǔn)備給 OpenClaw 配一個(gè)穩(wěn)定的模型入口在動(dòng) Context 配置之前得先保證模型入口是通的。我本地測(cè)試的時(shí)候模型側(cè)用的是 TaoToken 的 API原因是它的 Base URL 和 OpenAI 兼容格式一致OpenClaw 里api: openai-completions直接就能對(duì)接不用改協(xié)議。你需要準(zhǔn)備三樣?xùn)|西Base URL、API Key、Model ID。這三件套在 OpenClaw 的 provider 配置里缺一不可。Base URL 填https://taotoken.net/api注意這里不加任何 UTM 參數(shù)就是純 API 地址。API Key 去控制臺(tái)生成路徑是 API Keys 管理頁(yè)生成后復(fù)制出來(lái)別截圖存微信直接貼進(jìn)配置文件。Model ID 這塊要注意OpenClaw 的models[].id必須和 provider 側(cè)實(shí)際可用的模型名一致寫錯(cuò)了會(huì)在請(qǐng)求階段直接 404 或者 model not found。你可以先在 模型對(duì)話頁(yè) 里手動(dòng)發(fā)一條消息確認(rèn)模型能正常返回再去配 OpenClaw。如果你打算長(zhǎng)期跑編碼類 Agent 任務(wù)會(huì)話輪次多、工具調(diào)用密集建議直接上 Coding Plan額度模型對(duì)長(zhǎng)會(huì)話更友好不會(huì)跑一半因?yàn)榕漕~問(wèn)題中斷導(dǎo)致 compaction 做到一半失敗。配好之后OpenClaw 的 provider 段落大概長(zhǎng)這樣先別急著加 compaction我們一步步來(lái){ models: { mode: merge, providers: { taotoken: { baseUrl: https://taotoken.net/api, apiKey: YOUR_TAOTOKEN_API_KEY, api: openai-completions, models: [ { id: YOUR_MODEL_ID, name: TaoToken Model, contextWindow: 128000, maxTokens: 4096 } ] } } } }這里contextWindow先填 128000 是假設(shè)你用的模型支持這個(gè)長(zhǎng)度。但如果你本地是 LM Studio 或者 Ollama實(shí)際 KV Cache 只開(kāi)了 8k這里填 128000 就會(huì)直接崩下一節(jié)詳細(xì)說(shuō)這個(gè)坑。3. openclaw.json 可復(fù)制配置contextWindow、compaction、contextPruning 三件套這一節(jié)是核心直接給可復(fù)制的配置片段。先說(shuō)清楚 OpenClaw 能做什么、不能做什么避免你抱錯(cuò)期望。OpenClaw不能精確控制 prompt 拼接不能只保留最近 n 條消息也不能指定只發(fā)送部分歷史。因?yàn)?Context 構(gòu)建是在 Gateway runtime 內(nèi)部完成的不是簡(jiǎn)單 config 能干預(yù)的。OpenClaw能做的是間接控制限制 contextWindow、限制 contextTokens 總預(yù)算、觸發(fā) compaction 壓縮、用 contextPruning 刪緩存。這四件事組合起來(lái)就能把上下文控制在安全范圍內(nèi)。3.1 contextWindow硬上限必須和推理服務(wù)對(duì)齊models.providers.*.models[].contextWindow這個(gè)參數(shù)本質(zhì)是告訴 OpenClaw這個(gè)模型最多能吃多少 token。關(guān)鍵點(diǎn)它必須小于等于模型實(shí)際支持的最大上下文長(zhǎng)度。本地推理最容易踩的坑就在這。比如你在 LM Studio 里加載模型時(shí)n_ctx設(shè)的是 8192但openclaw.json里contextWindow寫了 128000OpenClaw 就會(huì)按 128000 去拼 prompt結(jié)果發(fā)過(guò)去直接超出后端 KV Cache模型崩潰或者 reload。所以第一步永遠(yuǎn)是確認(rèn)后端實(shí)際上下文大小然后把這個(gè)值填進(jìn)contextWindow。contextWindow: 8192如果你用的是云端模型比如通過(guò) TaoToken 接入的模型就填模型官方標(biāo)稱的上下文長(zhǎng)度比如 128000 或 200000。填之前去 接入文檔 確認(rèn)一下當(dāng)前模型的上下文規(guī)格別憑記憶填。3.2 contextTokensAgent 層的軟預(yù)算agents.defaults.contextTokens是 Agent 輸入上下文的總預(yù)算。它和 contextWindow 的區(qū)別是contextWindow 是模型能力上限contextTokens 是你主動(dòng)設(shè)的安全線。建議設(shè)成 contextWindow 的 75% 到 85%。為什么留這么多因?yàn)橄到y(tǒng)提示詞、工具 schema、Skill 列表這些隱形內(nèi)容也要占空間你按 100% 設(shè)實(shí)際請(qǐng)求一拼就超。contextTokens: 6000上面這個(gè) 6000 是配合 8192 的 contextWindow 用的留了約 27% 的緩沖。如果你 contextWindow 是 128000contextTokens 可以設(shè) 100000 左右。超過(guò) contextTokens 會(huì)觸發(fā) compaction 或 pruning所以它本質(zhì)是提前剎車不是減少內(nèi)容。3.3 compaction壓縮歷史防止無(wú)限增長(zhǎng)agents.defaults.compaction是主動(dòng)管理機(jī)制。核心參數(shù)是reserveTokensFloor定義觸發(fā)壓縮的剩余空間閾值。當(dāng)上下文剩余空間小于這個(gè)值時(shí)自動(dòng)把舊對(duì)話總結(jié)成摘要條目釋放空間。compaction: { reserveTokensFloor: 2000, memoryFlush: { enabled: true, softThresholdTokens: 12000, systemPrompt: Session context is filling up. Please archive important information to memory files., prompt: Write key information to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store. } }工作機(jī)制是這樣的上下文增長(zhǎng) → 剩余空間到softThresholdTokens→ 觸發(fā) memoryFlush模型把關(guān)鍵信息寫進(jìn) memory 文件 → 繼續(xù)增長(zhǎng) → 剩余空間到reserveTokensFloor→ 觸發(fā) compaction壓縮舊對(duì)話 → 空間釋放。注意softThresholdTokens必須大于reserveTokensFloor一般高出 10000 左右。上面例子里 soft 是 12000floor 是 2000差 10000符合建議。reserveTokensFloor建議設(shè)成 contextTokens 的 15% 到 20%或者至少保留 2000 到 4000 token。設(shè)太小會(huì)導(dǎo)致壓縮操作本身沒(méi)空間執(zhí)行出現(xiàn)壓縮失敗 → 崩潰的循環(huán)。3.4 contextPruning裁剪工具緩存contextPruning用來(lái)刪除 tool results 或大輸出緩存不影響核心對(duì)話歷史。配置很簡(jiǎn)單contextPruning: { mode: cache-ttl, ttl: 30m }mode: cache-ttl表示按 TTL 過(guò)期清理ttl: 30m是 30 分鐘。工具返回的大塊內(nèi)容比如讀了一個(gè)大文件、跑了一次長(zhǎng)命令30 分鐘后就從上下文里清掉但對(duì)話歷史保留。3.5 bootstrapMaxChars控制文件注入大小agents.defaults.bootstrapMaxChars默認(rèn) 20000 字符控制 workspace 文件注入時(shí)的截?cái)嚅撝?。OpenClaw 默認(rèn)會(huì)注入這些文件如果存在AGENTS.md、SOUL.md、TOOLS.md、IDENTITY.md、USER.md、HEARTBEAT.md、BOOTSTRAP.md僅首次運(yùn)行。這些文件如果寫得很大注入時(shí)就會(huì)吃掉大量 token。用/context命令能看到原始大小 vs 注入大小以及是否發(fā)生截?cái)唷ootstrapMaxChars: 20000如果你發(fā)現(xiàn) workspace 文件注入占比很高要么精簡(jiǎn)文件內(nèi)容要么調(diào)小這個(gè)值。3.6 完整配置示例把上面幾塊拼起來(lái)一個(gè)帶三層防護(hù)的openclaw.json大概是這樣{ models: { mode: merge, providers: { taotoken: { baseUrl: https://taotoken.net/api, apiKey: YOUR_TAOTOKEN_API_KEY, api: openai-completions, models: [ { id: YOUR_MODEL_ID, name: TaoToken Model, contextWindow: 128000, maxTokens: 4096 } ] } } }, agents: { defaults: { model: { primary: taotoken/YOUR_MODEL_ID }, workspace: ~/.openclaw/workspace, contextTokens: 100000, bootstrapMaxChars: 20000, compaction: { reserveTokensFloor: 16000, memoryFlush: { enabled: true, softThresholdTokens: 26000, systemPrompt: Session context is filling up. Please archive important information to memory files., prompt: Write key information to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store. } }, contextPruning: { mode: cache-ttl, ttl: 30m }, subagents: { maxConcurrent: 2, model: taotoken/YOUR_MODEL_ID } } }, session: { maintenance: { mode: warn, pruneAfter: 30d, maxEntries: 500 } } }注意session.maintenance.mode從enforce改成warnpruneAfter從 7d 放寬到 30d。原因是磁盤上的會(huì)話文件清理交給 compaction 處理更合理過(guò)早刪文件反而丟歷史。4. 驗(yàn)證請(qǐng)求與成功結(jié)果用 /context 和 /usage 確認(rèn)機(jī)制生效配置寫完不算完得驗(yàn)證。OpenClaw 提供了幾個(gè)診斷命令我平時(shí)用這幾個(gè)/status # 當(dāng)前上下文占用 /context list # 誰(shuí)在占空間 /context detail # 精細(xì)分析分解最大的工具 schema /usage tokens # 正?;貜?fù)后附加每次回復(fù)的 token 使用量推薦流程是/context list找最大項(xiàng)然后針對(duì)性優(yōu)化。4.1 觀察窗口占用先跑/status看當(dāng)前上下文占了多少。然后跑/context list它會(huì)列出各個(gè)來(lái)源的占用比如 system prompt、conversation、tool schemas、skills、workspace files。我第一次跑的時(shí)候發(fā)現(xiàn) tool schemas 占了將近 40%比我預(yù)想的高很多。因?yàn)槊總€(gè)工具的 JSON schema 都要發(fā)給模型工具越多這塊越大。4.2 觸發(fā)壓縮閾值想驗(yàn)證 compaction 是否生效可以故意把contextTokens設(shè)小一點(diǎn)比如設(shè)成 3000然后連續(xù)對(duì)話幾輪觀察是否觸發(fā)壓縮。觸發(fā)時(shí)你會(huì)看到類似日志[compaction] reserve tokens below floor, starting compaction [compaction] summarized 12 messages into 1 summary entry [memoryFlush] archived key info to memory/2025-01-15.md如果沒(méi)看到檢查reserveTokensFloor是不是設(shè)得比實(shí)際剩余空間還小那樣永遠(yuǎn)不會(huì)觸發(fā)。4.3 裁剪前后行為對(duì)比驗(yàn)證 contextPruning可以跑一個(gè)返回大輸出的工具比如讀一個(gè)大文件然后等 TTL 過(guò)期上面配的是 30m測(cè)試時(shí)可以臨時(shí)改成 1m再跑/context list看 tool results 那塊是不是變小了。對(duì)比前后兩次/context detail的輸出能明顯看到大輸出緩存被清掉但對(duì)話歷史還在。4.4 成功結(jié)果長(zhǎng)什么樣配置正確、機(jī)制生效的情況下長(zhǎng)會(huì)話跑下來(lái)應(yīng)該是這樣/status顯示的占用穩(wěn)定在 contextTokens 以下不會(huì)無(wú)限增長(zhǎng)觸發(fā) compaction 后占用明顯下降對(duì)話能繼續(xù)不再出現(xiàn) context_length_exceeded 報(bào)錯(cuò)模型不會(huì)因?yàn)樯舷挛某薇罎⒒?reload如果這幾點(diǎn)都滿足說(shuō)明三層防護(hù)都起作用了。5. 本篇常見(jiàn)錯(cuò)排查401、local proxy failed、reading choices、OAuth配置過(guò)程中最容易撞的幾個(gè)報(bào)錯(cuò)逐個(gè)說(shuō)。5.1 401 UnauthorizedError: 401 Unauthorized這個(gè)基本就是 API Key 問(wèn)題。檢查apiKey字段是不是填對(duì)了有沒(méi)有多余空格是不是復(fù)制的時(shí)候漏了字符。如果用的是 TaoToken去 API Keys 頁(yè) 重新生成一個(gè)貼進(jìn)去再試。還有一種情況是 Base URL 寫錯(cuò)了比如多加了斜杠或者少了/v1。TaoToken 的 Base URL 是https://taotoken.net/apiOpenClaw 會(huì)自動(dòng)補(bǔ)全路徑別自己加/v1。5.2 local proxy failedError: local proxy failed這個(gè)通常出現(xiàn)在本地推理服務(wù)沒(méi)啟動(dòng)或者端口不對(duì)。檢查baseUrl里的端口比如http://127.0.0.1:1234/v1確認(rèn) LM Studio 或 Ollama 確實(shí)在 1234 端口監(jiān)聽(tīng)。如果本地服務(wù)正常但 OpenClaw 還是報(bào)這個(gè)檢查是不是防火墻攔了本地回環(huán)請(qǐng)求。5.3 reading choices 報(bào)錯(cuò)Error: reading choices這個(gè)一般是 provider 返回的響應(yīng)格式和 OpenClaw 預(yù)期的不一致。常見(jiàn)原因是api字段填錯(cuò)了比如填了openai-completions但實(shí)際服務(wù)返回的是另一種格式。確認(rèn)api字段和 provider 實(shí)際協(xié)議匹配。TaoToken 用openai-completions就行。5.4 OAuth 相關(guān)報(bào)錯(cuò)Error: OAuth token expired Error: OAuth flow failed如果你用的是需要 OAuth 的 providertoken 過(guò)期會(huì)報(bào)這個(gè)。重新走一遍授權(quán)流程或者換成 API Key 方式接入。5.5 上下文還是溢出如果配置都對(duì)了還是溢出按這個(gè)優(yōu)先級(jí)排查先看/context detail找最大的項(xiàng)如果是 tool schemas 占大頭減少工具數(shù)量或者禁用不用的工具如果是 workspace 文件注入占大頭精簡(jiǎn)文件或調(diào)小bootstrapMaxChars確認(rèn) compaction 真的觸發(fā)了看日志有沒(méi)有[compaction]輸出確認(rèn)contextWindow和后端實(shí)際上下文一致這是最常見(jiàn)的坑優(yōu)化優(yōu)先級(jí)建議減少 Tool schemas → 控制 workspace 文件注入 → 開(kāi)啟 compaction → 設(shè)置合適的 contextWindow 和 contextTokens → 最后才是 pruning。6. 把 Context 控制跑通之后幾個(gè)實(shí)用技巧配置跑通之后有幾個(gè)我平時(shí)用的技巧。第一/context detail要養(yǎng)成習(xí)慣定期跑。工具 schema 的占用會(huì)隨著你裝新工具變化隔一段時(shí)間看一眼能提前發(fā)現(xiàn)膨脹。第二compaction 的reserveTokensFloor別設(shè)太小。我試過(guò)設(shè) 500結(jié)果壓縮操作本身沒(méi)空間執(zhí)行直接崩。后來(lái)改成 contextTokens 的 15%穩(wěn)定多了。第三memoryFlush 的softThresholdTokens和reserveTokensFloor的差值保持在 10000 左右。差值太小memory 還沒(méi)寫完就觸發(fā)壓縮差值太大memory 寫入太早浪費(fèi)空間。第四本地推理的contextWindow一定要和后端n_ctx對(duì)齊。這個(gè)坑我踩過(guò)不止一次癥狀是模型跑著跑著突然 reload日志里啥也沒(méi)有就是上下文超了后端 KV Cache。第五如果你要長(zhǎng)期跑 Agent 任務(wù)會(huì)話輪次多建議用 Coding Plan避免跑到一半配額不夠compaction 做到一半中斷反而丟歷史。最后所有配置改完記得重啟 OpenClaw Gatewayopenclaw.json不是熱加載的。重啟后先跑/status確認(rèn)配置生效再開(kāi)始長(zhǎng)會(huì)話測(cè)試。