1. 为什么单次会话也需要一套记忆与压缩骨架Claude Code 的会话记忆与三阶段压缩机制解决的是一个很具体的问题单次会话聊到几十轮之后上下文窗口快满了直接截断会丢关键信息不截断又发不出请求。它适合已经在本地跑 Claude Code、想搞清楚 SM-compact 触发链路、并且希望用 settings.json 与 config.toml 把行为固定下来的开发者。读完你能做到三件事知道会话记忆在什么条件下落笔、知道 Microcompact / SM-compact / Full Compact 三阶段各自在什么阈值被拉起、能自己写一份可复制的配置骨架并在本地验证压缩确实发生了。很多人第一次接触这套机制会把它理解成“自动摘要”。实际不是。摘要做的是把说过的话变短会话记忆做的是把说过的话凝结成状态——它维护一份固定区段的笔记文件压缩时用这份笔记替代臃肿的原始消息而不是重新让模型读一遍历史再写一段话。这个区别决定了它的成本结构和触发时机笔记是后台增量更新的压缩时直接复用所以 SM-compact 的成本远低于 Full Compact。我试过在同一个项目里连续跑长会话观察到的现象是前 20 轮几乎不触发任何压缩工具输出堆得很快到 60% 上下开始出现工具输出被截断的痕迹到 80% 附近才会看到消息历史被一条摘要消息替换。这条链路不是靠时间驱动的而是靠 token 增长和工具调用次数两个维度共同判断。下面从配置骨架切入把这条链路拆开。2. 前置准备TaoToken 接入与 Claude Code 环境在动配置文件之前先把模型接入这一层理顺。Claude Code 需要一个兼容 Anthropic 接口的入口TaoToken 提供的就是这个入口。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 注意 API 这一层不带 UTM 参数配置里填的就是这个干净地址。你需要先拿到一个可用的 Key。进入控制台的 API Keys 页面创建地址是 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。创建时给它起一个能认出用途的名字比如 claude-code-local方便后面按项目区分额度。Key 只在创建时完整显示一次复制后先存到本地环境变量里不要直接写进会提交到 Git 的文件。环境变量这样设Linux/macOS 下写进 shell 配置export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的keyWindows PowerShell 下用$env:ANTHROPIC_BASE_URL https://taotoken.net/api $env:ANTHROPIC_API_KEY sk-你的key设完之后验证一下变量确实生效避免后面排查配置时把环境问题误判成压缩问题echo $ANTHROPIC_BASE_URL echo ${ANTHROPIC_API_KEY:0:8}第二行只打印前 8 位确认非空即可不要把完整 Key 打到终端历史里。如果你更习惯用配置文件而不是环境变量Claude Code 也支持在 settings.json 的 env 段里声明但 Key 这种敏感值建议仍然走环境变量配置文件只放非敏感项。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面列了接口路径和请求格式遇到 401 或 404 时对照一下比盲猜快。如果你只是想先确认模型通不通不急着配 Claude Code可以直接用模型对话页面发一条消息试试https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。这一步能快速区分“Key 有问题”和“Claude Code 配置有问题”。3. 可复制配置settings.json 与 config.toml 骨架Claude Code 的配置分两层。settings.json 管的是运行时行为包括压缩阈值、会话记忆开关、钩子注册config.toml 管的是模型与请求层参数。两者职责不要混混了之后排查会很难受。先看 settings.json 的骨架。下面这份是可直接落地的版本字段名按 Claude Code 的约定写数值给的是保守起点你可以按项目规模调{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api }, compact: { autoCompactEnabled: true, microCompactThreshold: 0.6, smCompactThreshold: 0.8, fullCompactThreshold: 0.95 }, sessionMemory: { enabled: true, minimumMessageTokensToInit: 20000, minimumTokensBetweenUpdate: 8000, toolCallsBetweenUpdates: 3, maxSectionTokens: 2000, maxTotalTokens: 12000 }, hooks: { postSampling: true } }几个字段值得单独说。microCompactThreshold 设 0.6意思是上下文用量到 60% 时开始把旧工具输出替换成摘要这一步不调模型纯文本替换成本几乎为零。smCompactThreshold 设 0.8到 80% 时用会话记忆替代历史消息。fullCompactThreshold 设 0.95作为兜底前面两步都没压下来才走模型重写摘要。sessionMemory 段里的 minimumMessageTokensToInit 明显高于 minimumTokensBetweenUpdate这是有意的。第一次提取要把整个会话的背景、任务、进展都写清楚成本最高门槛抬高能避免在对话还没定型时写出一份粗糙笔记。toolCallsBetweenUpdates 设 3配合 token 增长做双条件判断。再看 config.toml管模型和请求层[model] name claude-sonnet-4-6 max_tokens 8192 [request] timeout_seconds 120 retry_attempts 3 stream true [compact] preserve_recent_tokens 10000 preserve_recent_messages 5 max_preserve_tokens 40000preserve_recent_tokens 对应 SM-compact 里的 minTokens默认 10000preserve_recent_messages 对应 minTextBlockMessages默认 5max_preserve_tokens 是硬上限 40000。这三个值决定了压缩后保留多少近期上下文。设太小Agent 会丢失“现在在做什么”的线索设太大压缩效果不明显。10000 / 5 / 40000 是经过验证的平衡点除非你的项目单轮工具输出特别大否则不建议动。注意settings.json 和 config.toml 里不要同时声明同一个阈值。如果两处都写了压缩阈值以 settings.json 为准config.toml 里的会被忽略容易造成“改了没生效”的错觉。4. 验证请求确认三阶段压缩真的被触发配置写完不代表生效必须验证。验证分两步先确认请求能通再确认压缩链路被拉起。第一步发一条最小请求确认接入正常curl -s https://taotoken.net/api/v1/messages \ -H x-api-key: $ANTHROPIC_API_KEY \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: claude-sonnet-4-6, max_tokens: 64, messages: [{role: user, content: reply with ok}] }返回里能看到 content 数组和 usage 字段就说明接入没问题。usage 里的 input_tokens 和 output_tokens 后面会用来估算上下文占用比例。第二步验证压缩触发。Claude Code 在压缩发生时会输出边界标记你可以通过日志观察。启动时打开详细日志claude --debug 21 | tee claude-debug.log然后在会话里连续做几轮带工具调用的操作比如反复读文件、跑命令。观察日志里这几个关键词的出现顺序grep -n microcompact claude-debug.log grep -n sessionMemoryCompaction claude-debug.log grep -n compactBoundary claude-debug.log正常链路是先出现 microcompact 的替换记录上下文继续增长后出现 sessionMemoryCompaction同时伴随 compactBoundary 边界标记。如果只看到 microcompact 反复出现但始终没有 sessionMemoryCompaction说明会话记忆没被提取检查 sessionMemory.enabled 是否为 true以及 minimumMessageTokensToInit 是不是设得过高导致一直没达到初始化门槛。第三步直接检查会话记忆文件是否被写入。Claude Code 会把会话记忆落在项目相关的目录下文件名通常带 session-memory 标识。用 find 定位find . -name *session*memory* -type f 2/dev/null找到后打开看内容应该能看到固定区段的结构比如 Session Title、Current State、Task specification、Files and Functions、Workflow、Errors Corrections 等。如果文件存在但区段是空的说明初始化了但还没触发更新继续聊几轮带工具调用的对话即可。成功的结果长这样日志里三阶段按阈值依次出现会话记忆文件有实际内容压缩后上下文占用比例明显回落。你可以用 usage 里的 input_tokens 前后对比SM-compact 之后通常会从 80% 附近掉到 30% 以下。5. 本篇常见错排查5.1 压缩后请求 400tool_use 与 tool_result 配对断裂这是最高频的报错。现象是压缩刚发生下一次请求直接返回 400错误信息里提到 tool_result 找不到对应的 tool_use。原因是消息数组的物理边界和 API 的逻辑对话边界不重合。streaming 模式下一次 assistant 响应会被拆成多条消息存储thinking 一条、tool_use 一条、tool_result 一条裁剪时如果切点落在多个 tool_use 之间前面的 tool_use 被丢掉后面 user 消息里的 tool_result 就成了孤儿。修复思路是裁剪后必须做一次回溯收集保留范围内所有 tool_result 的 ID到切点之前找匹配的 tool_use把它所在的消息也纳入保留。这一步是向更早方向扩张不会把已保留的消息踢出去。如果你自己写裁剪逻辑这个回溯不能省。5.2 thinking block 丢失导致 normalize 失败和上一条同源但表现不同。同一个 message.id 下的所有 content block 必须一起保留如果切点落在同 id 的 thinking block 和 tool_use block 之间合并时找不到 thinking整块丢失请求同样 400。排查方法是看报错里有没有提到 message id 或 content block 数量不匹配。修复同样是回溯到同 id 消息的起点。5.3 会话记忆一直不更新日志里没有 sessionMemoryCompaction会话记忆文件也不更新。按顺序查三处sessionMemory.enabled 是否为 trueminimumTokensBetweenUpdate 是不是设得过大导致 token 增长一直没到阈值toolCallsBetweenUpdates 是不是设得过高配合 token 条件后双条件始终不满足。注意触发是双条件 ANDtoken 增长和工具调用次数都要达标但自然断点最后一轮没有工具调用时可以只靠 token 阈值触发。如果你一直在连续跑工具反而可能因为缺少自然断点而延迟落笔。5.4 子 Agent 压缩污染主 Agent 状态现象是主会话突然丢失了 microcompact 状态或上下文缓存行为变得异常。原因是 Agent Tool 创建的子 Agent 和主 Agent 共享模块级状态子 Agent 压缩时如果重置了状态会破坏主 Agent。修复是在压缩后清理阶段区分主/子 Agent只有主线程压缩才重置 microcompact 状态、context-collapse 状态和 memory file 缓存子 Agent 的压缩不重置。如果你在自定义钩子里做清理务必加这个判断。5.5 恢复会话后压缩行为异常从历史恢复的会话lastSummarizedMessageId 可能缺失导致压缩时找不到上次压缩位置。回退策略是用 messages.length - 1 作为起点保证恢复的会话也能正常压缩。如果你发现恢复后第一次压缩保留了过多消息检查这个回退是否生效。6. 把配置固定下来然后按需分流配置骨架落地之后建议把 settings.json 和 config.toml 一起纳入版本管理但 Key 走环境变量。这样换机器时只需要重新设两个环境变量压缩行为完全一致。阈值不要频繁调先按 0.6 / 0.8 / 0.95 跑一周观察日志里三阶段的实际触发频率再决定是否微调。如果你主要是在排障和接入阶段重点看 API Keys 和接入文档https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 和 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。如果你只是想先验证模型行为再决定要不要配 Claude Code用模型对话页面最快https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。如果你打算长期跑编码任务或 Agent 工作流压缩会频繁触发建议直接上 Coding Plan额度模型更适合这种持续消耗的场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。最后留一个实操建议在项目根目录放一个 .claude 目录把 settings.json 放进去config.toml 放在用户级配置目录。项目级配置管压缩阈值用户级配置管模型和请求参数。这样不同项目可以用不同的压缩策略而模型接入保持一致。改完配置后重启 Claude Code用第 4 节的 grep 命令确认三阶段链路仍然正常再开始正式的长会话。