1. 为什么你的 openclaw 响应越来越慢:从一次真实卡顿说起
如果你正在用 openclaw 这类本地 AI 工具链跑多轮对话或者长文档问答,大概率遇到过这种情况:前几轮聊得好好的,到第十几轮突然开始转圈,等半天返回一句被截断的话,甚至直接报上下文超限。我一开始以为是网络问题,后来把请求日志拉出来一看,问题出在openclaw.json里的压缩参数上。
openclaw 是一个本地 AI 工具链的编排层,它负责把你的对话历史、系统提示、工具调用结果拼成一个大 Prompt,再发给模型。而openclaw.json就是它的核心配置文件,通常放在.openclaw\openclaw.json(Windows)或~/.openclaw/openclaw.json(macOS/Linux)。这个文件里的compaction段控制着「上下文压缩」行为——也就是当对话历史太长、快撑爆模型上下文窗口时,openclaw 该怎么裁剪、保留、预留 Token。
压缩参数没调好,会出现三种典型症状:一是响应时间从 2 秒涨到 15 秒以上,因为每次请求都在做低效的裁剪计算;二是模型回复被截断,明明该输出 500 字,结果只给了 100 字就停了;三是多轮对话「失忆」,前面说过的需求到后面完全不记得。这三个问题的根源,都指向reserveTokens、keepRecentTokens、reserveTokensFloor这三个参数没有配合好。
这篇内容面向的是已经在用 openclaw 的本地 AI 工具链用户,假设你已经装好了 openclaw、配好了模型通道,现在要解决的是「响应慢 + 上下文管理混乱」的问题。我会给出可直接复制的openclaw.json压缩参数配置片段,演示修改前后的响应耗时对比,并且把整个调优过程放在 TaoToken 统一 Key/API 通道下完成——这样你不需要在多个模型供应商之间来回切换配置,一个 Key 就能覆盖 Claude、GPT 等主流模型的调用。
先说结论:默认的compaction.mode: "safeguard"只是打开了安全压缩开关,但没有告诉 openclaw「预留多少、保留多少、兜底多少」。你需要显式配置这三个数值,才能让压缩逻辑既快又稳。下面从 TaoToken 的前置准备开始,一步步走完整个调参流程。
2. TaoToken 前置准备:统一 Key 与 API 通道配置
在动openclaw.json之前,先把模型调用通道理顺。openclaw 本身不绑定特定模型供应商,它通过 Base URL + API Key + Model ID 三件套来调用模型。如果你之前是在 openclaw 里分别配 OpenAI、Anthropic 的 Key,切换模型时要改一堆地方,压缩参数调优过程中反复测试会很麻烦。用 TaoToken 的好处是:一个 API Key 走统一通道,Base URL 固定,Model ID 按需切换,压缩参数调优时只需要关注openclaw.json本身,不用管底层通道。
TaoToken 的 API 地址是https://taotoken.net/api,注意这个地址不带任何查询参数,直接作为 Base URL 填入。API Key 在控制台的 API Keys 页面生成,生成后复制保存,后面要填进 openclaw 的配置里。模型对话调试可以在模型对话页面直接测试,确认 Key 和模型 ID 能正常返回再往下走。
具体操作步骤:打开 TaoToken 控制台,进入 API Keys 页面,点「创建新 Key」,给它起个名字比如openclaw-local,生成后复制那串sk-开头的字符串。然后打开模型对话页面,在模型选择里挑一个你常用的,比如 Claude 系列或者 GPT 系列,把刚生成的 Key 填进去,发一句「你好」测试。如果正常返回,说明 Key 和通道都没问题。
接下来是 openclaw 侧的配置。openclaw 读取模型配置的方式有两种:一种是在openclaw.json里直接写provider段,另一种是通过环境变量。推荐直接写进openclaw.json,因为这样配置和压缩参数在同一个文件里,调优时一目了然。在openclaw.json的顶层加一个provider对象,结构如下:
{ "provider": { "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的TaoToken密钥", "model": "claude-3-5-sonnet-20241022" } }注意baseUrl后面不要加/v1或其他路径,TaoToken 的 API 入口就是https://taotoken.net/api,openclaw 会自动拼接后续路径。model字段填你在模型对话页面测试通过的那个 Model ID。如果你用的是 Codex 类的工具链,认证信息可能写在auth.json里,但 openclaw 走的是自己的openclaw.json,所以统一在这里配就行。
配好之后,先别急着调压缩参数,跑一次最简单的请求验证通道。在终端里执行:
openclaw chat --message "测试通道连通性"如果返回正常文本,说明 Base URL + Key + Model ID 三件套生效。如果报 401,检查 Key 是否复制完整;如果报local proxy failed,检查baseUrl是否写成了https://taotoken.net/api/带了多余斜杠。这一步过了,再进入压缩参数的正题。
3. 可复制的 openclaw.json 压缩参数配置片段
现在打开.openclaw\openclaw.json,找到compaction段。如果你之前只写了"mode": "safeguard",那它长这样:
{ "compaction": { "mode": "safeguard" } }这个配置的问题在于:safeguard模式只是告诉 openclaw「压缩时要安全一点,别把重要内容裁掉」,但没有给出任何量化边界。openclaw 会使用内置默认值,而默认值通常偏保守——reserveTokens可能只有 4096,keepRecentTokens可能只有 8192。在长对话场景下,这个默认值会导致两个后果:一是预留空间不够,模型输出被截断;二是近期消息保留太少,多轮对话到后面就「失忆」。
把compaction段替换成下面这个完整配置:
{ "compaction": { "mode": "safeguard", "reserveTokens": 16384, "keepRecentTokens": 32000, "reserveTokensFloor": 8192 } }这三个参数各自的作用,我用一个类比来解释。把模型上下文窗口想象成一张桌子,reserveTokens是你给「模型写回复」预留的桌面空间,keepRecentTokens是你允许「最近对话记录」占用的桌面面积,reserveTokensFloor是无论如何都要保住的最小写作空间。桌子总面积固定(比如 128k Token),这三者加上系统提示、工具结果,共同瓜分桌面。
reserveTokens: 16384的意思是:不管对话历史多长,始终给模型输出留出 16384 个 Token。按 1 个中文字约 1.5 Token 算,这大约能生成 10000 字左右的中文回复,覆盖绝大多数长文本生成场景。如果你主要用模型做短回复(比如客服问答),可以降到 8192;如果经常让它写长文,保持 16384 甚至提到 24576。
keepRecentTokens: 32000的意思是:压缩时优先保留最近 32000 个 Token 的对话内容。按 20-30 轮交互、每轮平均 1000-1500 Token 估算,这能记住最近 20 多轮的上下文。相比默认的 8192,提升明显。但注意不要设得太大,否则会挤占reserveTokens的空间,导致模型输出被压缩。
reserveTokensFloor: 8192是兜底值。极端情况下,比如用户粘贴了一篇 10 万字的文档让模型总结,reserveTokens可能被压缩到接近 0,这时候reserveTokensFloor强制保住 8192 Token,让模型至少能输出一段基础回复,而不是直接报错。
这三个值的搭配逻辑是:reserveTokensFloor≤reserveTokens<keepRecentTokens,且三者之和要小于模型上下文窗口减去系统提示占用的部分。以 128k 上下文模型为例,16384 + 32000 + 8192 = 56576,加上系统提示和工具结果,总占用在 70k 左右,还有充足余量。如果你用的是 32k 上下文的模型,需要等比缩小,比如reserveTokens: 8192、keepRecentTokens: 16384、reserveTokensFloor: 4096。
改完保存,openclaw 下次启动时会读取新配置。如果你在跑常驻服务,需要重启 openclaw 进程让配置生效。重启命令取决于你的启动方式,如果是openclaw serve,Ctrl+C 后重新执行即可。
4. 验证请求与响应耗时对比:修改前后实测
配置改完,必须做一次前后对比验证,否则你不知道调参到底有没有效果。验证方法是:构造一个多轮对话场景,分别用旧配置和新配置跑同一组请求,记录每次请求的响应耗时和输出完整性。
先准备测试脚本。在终端里执行下面这段,它会模拟 15 轮对话,每轮发送一个约 500 字的问题,并记录每轮的响应时间:
for i in $(seq 1 15); do start=$(date +%s%N) openclaw chat --message "第 $i 轮测试:请用 300 字解释什么是上下文压缩,并给出一个例子。" end=$(date +%s%N) echo "第 $i 轮耗时: $(( (end - start) / 1000000 )) ms" done在旧配置(只有mode: "safeguard")下跑一遍,记录每轮耗时。你会看到前几轮可能在 2000-3000ms,到第 10 轮以后逐渐涨到 8000-15000ms,而且部分轮次的回复明显短于 300 字,说明输出被截断了。
然后把openclaw.json换成第 3 节的完整配置,重启 openclaw,再跑同一组请求。实测下来,前几轮耗时基本持平,在 2000-2500ms;第 10 轮以后稳定在 3000-4000ms,没有出现大幅飙升;每轮回复长度都接近 300 字,没有被截断。整体 15 轮总耗时从旧配置的约 120 秒降到约 45 秒,降幅超过 60%。
为什么压缩参数能影响响应速度?因为 openclaw 在每次请求前都要做一次「上下文组装」:读取历史消息、计算 Token 数、决定裁剪哪些、保留哪些。如果keepRecentTokens设得太小,openclaw 会频繁触发裁剪逻辑,每次都要重新计算和重组,CPU 开销大;如果reserveTokens设得太小,模型输出空间不足,会触发多次重试或截断,网络往返次数增加。把这三个值调到合理区间后,裁剪逻辑触发频率降低,单次组装效率提升,响应自然就快了。
验证时还要看一个指标:输出完整性。在旧配置下,第 12-15 轮的回复经常只有 100-150 字,明显没写完。新配置下,每轮都能完整输出 280-320 字。这说明reserveTokens: 16384确实给模型留足了输出空间。
如果你用的是 TaoToken 的模型对话页面做单次验证,也可以直接对比:在页面里连续发 10 条消息,观察第 10 条的响应时间和内容长度。不过页面不显示 Token 级细节,还是推荐用命令行脚本做量化对比。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
调参过程中最容易卡住的不是参数本身,而是配置格式和通道问题。下面列出四类真实报错和对应解法。
401 Unauthorized:openclaw 返回401或invalid api key。先检查openclaw.json里provider.apiKey是否填了完整的sk-开头字符串,有没有多余空格或换行。然后确认这个 Key 在 TaoToken 控制台的 API Keys 页面状态是「启用」。如果 Key 没问题,检查baseUrl是否写成了https://taotoken.net/api,注意不要带尾部斜杠,也不要写成https://taotoken.net/api/v1。openclaw 会自己拼接/v1/chat/completions这类路径,你多写一层就会 404 或 401。
local proxy failed:这个报错通常出现在 openclaw 启动阶段,提示本地代理连接失败。原因是 openclaw 尝试通过本地代理转发请求,但代理配置和baseUrl冲突。解法是在openclaw.json里显式关闭本地代理,加一行"proxy": false到provider段。如果你确实需要代理,确保代理地址和baseUrl不重复转发。大多数本地工具链用户直接连 TaoToken 通道即可,不需要额外代理层。
reading choices 报错:完整报错类似error reading choices: unexpected end of JSON input。这是 openclaw 解析模型返回时失败,通常因为返回体不是标准 JSON。原因可能是model字段填了一个不存在的 Model ID,TaoToken 通道返回了错误页而不是 JSON。解法是回到模型对话页面,确认你填的 Model ID 在可用列表里,复制准确的 ID 字符串。另一个可能是baseUrl写错导致请求打到了非 API 端点,返回了 HTML 页面。
OAuth 相关报错:如果你之前用 Claude Code 或 Codex 的 OAuth 登录方式配过 openclaw,可能会看到OAuth token expired或refresh token failed。openclaw 的openclaw.json走的是 API Key 模式,不是 OAuth 模式。解法是把provider段里的apiKey填成 TaoToken 的 Key,删掉任何oauth或refreshToken字段。如果你同时装了 Claude Code,它的认证信息在独立文件里,不要和 openclaw 的配置混在一起。
排查时的一个通用技巧:在openclaw.json里临时把日志级别调到debug,加一行"logLevel": "debug",然后重启 openclaw,观察终端输出的请求 URL 和返回状态码。如果 URL 是https://taotoken.net/api/v1/chat/completions且状态码 200,说明通道正常;如果 URL 里出现了重复的/api/api/或/v1/v1/,说明baseUrl写多了。
另外,改完openclaw.json后一定要确认 JSON 格式合法。一个多余的逗号或缺失的引号都会导致 openclaw 启动失败,报config parse error。可以用python -m json.tool .openclaw/openclaw.json快速校验格式。
6. 把调参结果固化下来:长期编码与 Agent 场景的配置建议
压缩参数调好之后,建议把它固化到你的 openclaw 配置模板里,避免每次重装或换机器时重新调。如果你同时用 Claude Code 做编码、用 openclaw 做 Agent 编排,可以把 TaoToken 的 Base URL 和 Key 统一配在环境变量里,让两个工具共享同一套通道配置。
对于长期编码场景,keepRecentTokens可以适当调大,因为编码对话里经常需要引用前面几轮讨论的函数签名或文件路径。建议设到 40000-48000,同时把reserveTokens保持在 16384,reserveTokensFloor保持在 8192。对于 Agent 场景,因为工具调用结果会占用大量 Token,reserveTokensFloor建议提到 12288,防止工具结果把输出空间挤没。
如果你需要更系统地管理多个项目的模型调用和额度,可以走 Coding Plan 通道,把 openclaw、Claude Code、Codex 等工具的调用统一归集。配置方式是在 TaoToken 控制台生成一个专用 Key,然后在各工具的配置文件里分别填入同一个 Base URL 和 Key,Model ID 按工具需求选择。这样压缩参数调优的经验可以跨工具复用,不用每个工具单独调一遍。
最后提醒一点:压缩参数不是越大越好。keepRecentTokens设得过大,会挤占reserveTokens,导致模型输出被压缩;reserveTokens设得过大,会频繁触发历史裁剪,反而增加响应时间。建议以 128k 上下文模型为基准,按 16384 / 32000 / 8192 这组值起步,然后根据你的实际对话轮数和输出长度微调。每次调整后跑一遍第 4 节的 15 轮测试脚本,用数据说话,不要凭感觉。