深度解析 Claude Code 源码(二):上下文管理与消息压缩机制
1. 长对话为什么会突然“失忆”从一次 413 报错说起如果你用 Claude Code 跑过稍微复杂点的重构任务大概率见过这样的场景前 20 轮对话它还记得你项目里那个UserService的字段命名到第 40 轮你让它接着改它却像换了个人问你“请问 UserService 在哪个文件”。这不是模型变笨了而是上下文窗口Context Window被撑爆后系统触发了消息压缩机制把早期对话“折叠”掉了。Claude Code 的上下文管理是一套分层防御体系核心目标只有一个在 200K tokens 的窗口里尽可能让模型“记得住关键信息”同时不因为超限直接报错退出。它把压缩分成两大层——预防层在调用 API 之前就动手反应层在 API 返回prompt_too_longHTTP 413之后紧急补救。设计哲学是从轻到重、从快到慢、从局部到全局能不调 API 就不调能局部处理就不整体处理。这篇文章聚焦源码实现拆解 token 预算怎么分配、历史消息怎么裁剪、摘要压缩在什么条件下触发。我会给出可复制的配置片段和验证动作让你在本地跑 Claude Code 时能亲眼看到压缩日志对照源码定位关键函数验证压缩前后上下文长度的变化。适合已经用过 Claude Code、想搞清楚它内部机制的开发者也适合正在自研 Agent 框架、需要借鉴上下文管理思路的人。先明确一个概念这里的“压缩”不是把文本用 gzip 压小而是减少发给模型的 token 数量。手段包括把大工具结果存磁盘只留预览、直接砍掉老消息、清空旧工具调用内容、把旧消息段折叠成摘要、以及调用模型生成全量摘要。每一层的“重量”不同触发条件也不同。2. TaoToken 前置准备让 Claude Code 稳定跑起来观察压缩行为要观察压缩日志前提是 Claude Code 能正常发请求。Claude Code 默认走 Anthropic 官方端点但在国内网络环境下直连经常超时而且官方按量计费对频繁调试不太友好。我的做法是把它接到兼容 Anthropic 协议的网关服务上TaoToken 就是这类服务它提供 Anthropic 兼容的/v1/messages接口Claude Code 不用改代码只改环境变量就能指向它。这一步不是必须的如果你已经有可用的 Anthropic Key可以跳过直接看第 3 节。但如果你想像我一样反复触发压缩、观察日志用按量计费的官方 Key 调试成本会很高接一个兼容网关更划算。先说清楚 TaoToken 是什么它是一个大模型 API 聚合网关对外暴露 Anthropic 兼容接口和 OpenAI 兼容接口Claude Code、Cline、Codex 这类工具都能接。它本身不是模型也不改变 Claude Code 的压缩逻辑——压缩逻辑在 Claude Code 客户端源码里网关只负责转发请求。这点要分清楚否则你会误以为换个网关就能改压缩行为。接入前你需要准备三样东西我称之为“三件套”Base URLhttps://taotoken.net/api这是 Anthropic 兼容端点的根路径API Key在控制台创建形如sk-开头的一串字符Model ID比如claude-sonnet-4-5-20250929或claude-opus-4-1-20250805要和你实际想调的模型对应获取 Key 的入口在控制台的 API Keys 页面创建后复制保存页面关闭后不再完整显示。模型对话页面可以用来单独测试某个 Model ID 是否可用避免在 Claude Code 里反复试错。如果你打算长期用 Claude Code 做编码和 Agent 任务Coding Plan 套餐比按量计费更适合高频调试场景。这里要提醒一点Claude Code 的压缩机制和网关无关但网关的上下文长度上限会影响你能不能观察到压缩。如果网关侧对单次请求的 token 数限制比 Claude Code 估算的更严你可能会先撞上网关的 413而不是 Claude Code 自己的压缩触发。所以调试压缩时尽量选上下文上限足够大的模型。3. 可复制配置把 Claude Code 指向兼容端点并打开压缩日志Claude Code 读取配置的方式有好几种最直接的是环境变量。下面这套配置我实测可用你可以直接复制到~/.zshrc或~/.bashrc里。注意 Base URL 用https://taotoken.net/api不要带末尾斜杠也不要加 UTM 参数否则某些版本的 SDK 会拼接出双斜杠路径导致 404。# ~/.zshrc 或 ~/.bashrc export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的Key export ANTHROPIC_MODELclaude-sonnet-4-5-20250929 # 打开调试日志观察压缩触发 export ANTHROPIC_LOGdebug export DEBUGclaude-code:*如果你用的是 Claude Code 的 settings 文件方式可以在项目根目录或用户目录建.claude/settings.json内容如下。这种方式的优先级高于环境变量适合团队统一配置{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的Key, ANTHROPIC_MODEL: claude-sonnet-4-5-20250929, ANTHROPIC_LOG: debug }, permissions: { allow: [Read, Edit, Bash(git:*)] } }配置写完后先别急着跑长对话用一条最简单的请求验证连通性。Claude Code 提供了非交互模式可以直接发一句 promptclaude -p 回复 OK 两个字母即可 --model claude-sonnet-4-5-20250929如果返回OK说明 Base URL、Key、Model ID 三件套都对。如果报 401检查 Key 是否复制完整如果报local proxy failed或连接超时检查 Base URL 是否写成了https://taotoken.net/api/多了斜杠或者误加了其他路径。接下来是关键一步制造一个会触发压缩的长对话。最省事的办法是让 Claude Code 反复读一个大文件。你可以准备一个几千行的日志文件然后连续让它读# 生成一个约 8000 行的测试文件 seq 1 8000 | awk {print line $1 : some log content here} /tmp/big.log # 启动 Claude Code 交互模式 claude进入交互后连续输入类似“读取 /tmp/big.log 的前 2000 行并总结”这样的指令重复十几次。每次工具调用都会往消息历史里塞入一大段tool_result上下文会快速膨胀。这时候你就能在终端里看到压缩相关的日志了。关于日志Claude Code 的压缩触发点会打印类似applyToolResultBudget、microcompact、autocompact的关键字。如果你用的是DEBUGclaude-code:*日志会比较杂建议配合grep过滤claude 21 | tee /tmp/cc.log # 另开一个终端 tail -f /tmp/cc.log | grep -E compact|budget|collapse|prompt_too_long这样你能实时看到哪一层被触发了。我试过连续读 15 次大文件大概在第 8 次左右看到applyToolResultBudget先触发把单条超大结果存到了/tmp下的临时文件消息里只留了前 2000 字节的预览。4. 验证请求与成功结果对照源码看压缩前后上下文长度变化配置跑通后重点来了怎么确认压缩真的发生了以及压缩前后上下文长度变了多少。Claude Code 的源码里上下文管理的核心逻辑嵌在query循环中每一轮 API 调用前会依次执行预防层的五个步骤。你可以对照仓库ChinaSiro/claude-code-sourcemap里的query.ts来定位。先看预防层的执行顺序这是理解压缩的关键// 伪代码对应 query 循环中的预防层 while (true) { // ① 单条工具结果太大 → 存磁盘 messages applyToolResultBudget(messages) // ② 老消息太多 → 直接砍 messages snipCompact(messages) // ③ 旧工具结果 → 清空内容 messages microcompact(messages) // ④ 旧消息组 → 折叠为摘要 messages contextCollapse.projectView(messages) // ⑤ 整体太大 → 调 API 生成全量摘要 messages await autocompact(messages) // 调用模型 for await (const msg of callModel(messages)) { if (isPromptTooLong(msg)) { withheld true // 拦截 413先不吐给 UI } if (!withheld) yield msg } // 反应层API 失败后补救 if (apiReturned413) { await contextCollapse.drain() await reactiveCompact.tryReactiveCompact() continue // 重试 } }每一层都尝试把上下文压到安全范围如果够了后面的层就不触发。这就是“从轻到重”的含义。现在验证压缩前后的长度变化。最直接的办法是在日志里找 token 计数。Claude Code 内部用tokenCountWithEstimation做客户端估算这个估算值会出现在 debug 日志里。你可以在长对话过程中观察这个数字的走势# 过滤出 token 估算相关的日志行 grep -E tokenCount|estimated|context.*window /tmp/cc.log | tail -50正常情况下你会看到 token 数随着对话轮次上升然后在某一轮突然下降——那个下降点就是压缩触发点。下降的幅度取决于触发了哪一层microcompact只清空旧工具内容下降幅度中等autocompact做全量摘要下降幅度最大可能从 180K 直接掉到 30K。再验证一个细节applyToolResultBudget的触发阈值。源码里这个阈值大约是单组tool_result总大小超过 200K 字符。触发后从大到小逐个替换直到总大小降到 200K 以下。替换后的内容长这样persisted-output Output too large (10.5MB). Saved to: /tmp/claude/tool-use-abc123.txt Preview (first 2000 bytes): ...前2000字节... /persisted-output你可以在/tmp下找到这些持久化文件验证它们确实存在。这一步很关键因为它证明了压缩不是“丢弃”而是“外置存储”——模型看不到完整内容了但内容还在磁盘上必要时可以重新读取。contextCollapse的验证稍微复杂一点因为它涉及后台侧链 agent。它的生命周期分四步spawn后台调模型生成摘要、staged摘要进队列缓冲、committed确认安全后提交、projectView读时投影把原消息替换成collapsed占位符。你在 REPL 里看到的还是完整消息但发给 API 的版本已经被替换了。要验证这一点可以在 debug 日志里搜索collapsed关键字对比 REPL 显示和实际请求体。autocompact的触发条件是消息总 token 数 contextWindow - 33000。以 200K 窗口为例大约在 167K tokens 时触发。它是最重的一层会再调一次模型把整个历史压成一条摘要消息。源码里有个标记hasAttemptedReactiveCompact防止反应层无限循环重试。5. 本篇常见错排查401、local proxy failed、reading choices 与 OAuth调试压缩机制时你大概率会先撞上接入层的报错而不是压缩逻辑本身的问题。我把几个高频错误和对应排查方法列出来都是实际踩过的。401 Unauthorized最常见。原因通常是 Key 没复制完整、Key 已过期、或者 Base URL 和 Key 不匹配比如把 OpenAI 格式的 Key 用在了 Anthropic 端点上。排查方法先用模型对话页面单独测这个 Key 和 Model ID 的组合确认 Key 本身可用再回到 Claude Code 检查环境变量。注意ANTHROPIC_API_KEY和ANTHROPIC_AUTH_TOKEN是两个不同的变量Claude Code 认前者。local proxy failed / connection refused这个报错通常出现在 Base URL 写错的情况下。检查三点一是 URL 是不是https://taotoken.net/api不要带末尾斜杠二是有没有误加 UTM 参数SDK 拼接路径时会把查询参数带进去导致 404三是本地有没有残留的代理配置比如HTTP_PROXY环境变量干扰请求。如果你之前配过其他工具的代理先unset HTTP_PROXY HTTPS_PROXY再试。reading choices 报错这个错误信息通常来自 OpenAI 兼容格式的响应解析说明请求打到了 OpenAI 端点而不是 Anthropic 端点。Claude Code 走的是/v1/messages如果你把 Base URL 配成了 OpenAI 兼容的路径就会解析失败。确认 Base URL 是 Anthropic 兼容端点Model ID 也是 Anthropic 的模型名。OAuth 相关报错Claude Code 某些版本会尝试 OAuth 登录流程如果你用的是 API Key 方式需要在配置里明确禁用 OAuth。检查 settings 里有没有forceLoginMethod之类的字段或者环境变量里有没有残留的 OAuth token。最干净的做法是清空~/.claude下的缓存再重新配置。压缩不触发如果你跑了很久长对话却没看到压缩日志可能是 token 估算没到阈值。检查ANTHROPIC_LOG是否真的生效有些版本需要DEBUG和ANTHROPIC_LOG同时设置。另外如果你用的是小窗口模型比如 32K压缩会更早触发反而更容易观察。压缩后模型“失忆”太严重这是snipCompact或autocompact触发后的正常现象。snipCompact是直接砍掉老消息信息直接丢失autocompact是生成摘要摘要质量取决于模型。如果你发现关键信息丢了可以在对话里主动重申或者把重要上下文写进CLAUDE.md项目文件这样每轮都会带上。排查时有个通用技巧把ANTHROPIC_LOGdebug和DEBUGclaude-code:*都打开日志会记录每一层压缩的触发和 token 变化。对照源码里的函数名搜索日志能快速定位是哪一层在起作用。6. 继续深入把压缩机制用在你自己的 Agent 里Claude Code 的这套分层防御体系本质上是把“上下文管理”从一个大函数拆成了五个职责单一的步骤每个步骤有独立的触发条件和压缩力度。这个设计思路可以直接搬到自研 Agent 里先做最轻的局部清理清空旧工具结果再做中等的裁剪砍老消息最后才动用最重的模型摘要。关键是每一层都要有明确的触发阈值和降级路径避免一上来就调模型做摘要那样成本和延迟都不可控。如果你想继续验证可以试着改一下源码里的阈值参数比如把applyToolResultBudget的 200K 字符限制调小到 50K观察压缩触发频率的变化。源码仓库在ChinaSiro/claude-code-sourcemapquery.ts是入口。改完后重新跑长对话对比日志里的 token 曲线你会对“预算分配”有更直观的感受。接入层如果还没跑通先去 API Keys 页面把三件套配好再用模型对话页面单独验证 Model ID 可用最后回到 Claude Code 跑长对话观察压缩日志。接入文档里有各工具的完整配置示例Cline、Codex 的接法也在里面。长期做编码和 Agent 任务的话Coding Plan 比按量计费更适合反复调试压缩行为的场景。

相关新闻

华为OD机试真题 新系统 2026-09-20 JavaGoC【字符串分组求和】

华为OD机试真题 新系统 2026-09-20 JavaGoC【字符串分组求和】

目录 题目 思路 Code 题目 题目内容: 给定一个字符串数组,每个字符串表示一个数字(可能包含正负号)。将数组中前 n 个成员按照绝对值大小分为以下几组,并计算每组数字总和: 第1组:绝对值在 [0,100) 范围内的数字;第2组:绝对值在 [100,1000) 范围内的数字;第3组…

2026/10/9 13:35:24 阅读更多 →
A.每日一题:678. 有效的括号字符串

A.每日一题:678. 有效的括号字符串

题目链接:678. 有效的括号字符串(中等) 算法原理: 解法:贪心 时间复杂度O(N) 0ms击败100.00% * 有三种选择:左括号(、右括号)、空 1️⃣核心思路: 我们没法枚举全部情况,所以维护一个…

2026/10/9 13:35:24 阅读更多 →
盟接之桥说线束:数字化转型的价值,不止是省了几个人工

盟接之桥说线束:数字化转型的价值,不止是省了几个人工

一个常见的认知误区:数字化减人?在与线束企业管理者交流数字化转型时,我们经常听到这样的说法:"上系统嘛,就是能省几个人工,算算省的人工工资多久能收回系统投入。"这种认知看似务实,…

2026/10/9 13:35:24 阅读更多 →

最新新闻

降AI工具隐私保护真相:论文上传后数据到底去了哪里?

降AI工具隐私保护真相:论文上传后数据到底去了哪里?

2026年还没到正式年关,朋友圈里就已经开始被论文季焦虑刷屏了。凌晨一点,一个学弟给我发来消息,说他查重已经过了,结果学校要求提交的AI检测报告显示“疑似AI生成比例偏高”,问我有没有什么靠谱的降AI工具能救急。我反…

2026/10/9 14:36:04 阅读更多 →
Redis集群Lua脚本CROSSSLOT报错解析与哈希标签实战指南

Redis集群Lua脚本CROSSSLOT报错解析与哈希标签实战指南

1. 报错现场:一张截图背后的真相 前阵子有个同事发来一张截图,问我说:"群里有人说Redis集群不支持Lua脚本,是不是真的?"我点开一看,线上日志里赫然一行: CROSSSLOT Keys in request…

2026/10/9 14:36:04 阅读更多 →
多语言帮助中心数据采集:从URL规律到爬虫架构的完整实践

多语言帮助中心数据采集:从URL规律到爬虫架构的完整实践

1. 先摸清多语言帮助中心的三种结构规律说实话,我第一次接到“把某产品所有语言的帮助中心内容都抓下来”这个需求时,第一反应不是打开代码编辑器,而是打开浏览器,把要采集的站点翻了整整一晚上。原因很简单:写爬虫之前…

2026/10/9 14:36:04 阅读更多 →
DMODBD 32/64位安装避坑:ODBC驱动位数匹配与DSN配置详解

DMODBD 32/64位安装避坑:ODBC驱动位数匹配与DSN配置详解

简介:达梦数据库(DMDB)ODBC驱动部署资源,面向需要在32位或64位操作系统下连接达梦数据库的开发、运维及数据库管理人员,帮助解决驱动安装、依赖配置和数据源连接等基础却关键的问题。压缩包共610个文件、58.52MB&#…

2026/10/9 14:36:04 阅读更多 →
OpenClaw 架构解析:从 Channel 到 Gateway 的 Session 路由设计

OpenClaw 架构解析:从 Channel 到 Gateway 的 Session 路由设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 14:36:03 阅读更多 →
微博前端内容过滤:基于MutationObserver的本地化可见性控制

微博前端内容过滤:基于MutationObserver的本地化可见性控制

简介:这是一份面向前端开发者与微博重度用户的轻量级浏览器端 JavaScript 工具脚本,用于在登录状态下隐藏微博首页全部动态内容,实现‘仅自己可见’的浏览体验,适用于信息流干扰严重、需专注阅读或隐私保护场景。资源包为6KB的ZIP…

2026/10/9 14:35:02 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →