全球「AI学术顶会」精华汇聚地
您正在使用IE低版浏览器,为了您的雷峰网账号安全和更好的产品体验,强烈建议使用更快更安全的浏览器
此为临时链接,仅用于文章预览,将在时失效
人工智能 正文
发私信给郑佳美
发送

0

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

本文作者: 郑佳美   2026-08-28 15:23
导语:代码确实是 Agent 写的,只是后来的 Agent 已经不知道前面的 Agent 为什么这么写了。
Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?
代码确实是 Agent 写的,只是后来的 Agent 已经不知道前面的 Agent 为什么这么写了。

    作者丨郑佳美

    编辑丨岑   峰

                                                                                                       

Claude Code 原定于 8 月 19 日结束的 +50% 周额度加成,又被 Anthropic 延长到了 8 月 31 日。也就在原定截止日前后,Hacker News 上出现了一轮关于 Claude Code 使用成本的讨论:不少人发现,一个并不复杂的任务,Agent 跑上几轮,额度就会掉得很快。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

问题在于,Claude Code 消耗的并不只是最后生成的那几行代码。读文件、搜调用链、跑测试、处理日志,每一步都会继续进入后面的上下文。任务越长,Agent 背着的历史越重,系统也越依赖清理和压缩。

代码可以完整留在仓库里,早期的设计理由却可能在压缩中逐渐变薄。于是 Token 消耗和代码屎山开始在同一个地方汇合。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?
Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

01


修个小 Bug,为何需要几十次推理?

普通 Chat coding 的计算边界很清楚。输入一段代码,模型读完以后给出解释或者修改方案,这一轮基本结束。雷峰网(公众号:雷峰网)

而 Claude Code 的基本单元换成了 agent loop。模型先观察当前状态,决定下一步要读哪个文件或者执行什么命令;工具返回结果以后,模型再进行下一轮判断。

读源码、搜索引用、运行测试、查看 Git diff、修改文件,看上去像一个连续动作,在模型侧其实是一串独立的推理请求。Claude Code 官方文档也把这种“模型判断—调用工具—根据结果继续判断”的循环作为 Agent 工作方式的核心。

比如一个登录状态偶发失效的问题。Agent 先找到入口,发现状态来自 service,于是继续读取 service;看到缓存后搜索谁在写它;接着跑测试,测试出现另一个异常,于是去看 fixture;修完以后再次验证,旧测试又暴露出兼容问题。

可能直到这时,它才真正开始写那几行代码。因此,diff 大小和计算量之间几乎不存在稳定比例。5 行补丁背后可能只有 3 次推理,也可能已经经过 30 次工具交互。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

如果把一次 Agent 任务拆开,可以先得到两个变量:一个是 step count,Agent 为了完成任务走了多少步;另一个是 working set,走到当前这一步时,模型还需要掌握多少项目状态。

只增加 step count 已经会提高消耗。如果 working set 还在同步变大,情况就完全不同了。第 3 步也许只需要处理几千 Token,第 30 步却可能已经背着项目规则、相关源码、测试结果、修改历史和工具返回继续推理。雷峰网

这也是 Coding Agent 成本结构发生变化的起点:计算量开始取决于“走多少步 × 每一步背多重”,而不再取决于写了多少行代码。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

02


Token 到底烧在哪里?

把 Agent 的一次模型请求拆开,可以粗略看成三块。相对稳定的部分包括 system prompt、CLAUDE.md、工具定义和项目规则;不断变化的部分包括代码文件、搜索结果、测试日志、Git diff 和此前的任务轨迹;最后还有这一轮模型生成的 reasoning、文字与代码。

这里容易产生一个误区:只要前面的内容已经读过,就不应该重复产生太多成本。问题在于,LLM 两次请求之间不存在一个传统程序那样可以随时访问的内部内存。上一轮知道的信息,如果下一轮判断仍然依赖它,相关状态还得继续出现在可用 context 中。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

Prompt cache 能缓解这个问题。Claude Code 官方文档明确说明,如果没有 prompt caching,每轮请求需要重新处理整段历史;缓存命中后,已经处理过的稳定前缀可以复用,从而降低重复计算和成本。

但 cache 解决的是“同样的历史能不能便宜一点重新使用”,没有解决“这段历史还要不要继续存在”。100K Token 的旧状态命中缓存后便宜了,它依然占据 context,也依然是当前推理建立在上面的状态。

于是可以把一个长任务粗略写成:第 t 步的输入规模,大约等于稳定前缀 S,加上当前有效工作集 W_t,再加这一轮刚产生的新信息 Δ_t

真正麻烦的是 W_t。如果每走一步,Agent 又多读一点源码、多得到一点日志、多留下一个决策,而旧信息没有及时退出,那么 W_t 会随着任务推进不断增加。

在一个极端简化、完全没有缓存和清理的模型里,如果每轮新增的有效状态大致相同,总处理量会出现接近 1 + 2 + 3 + … + n 的累积结构。也就是说,step count 只增加了一倍,整个任务处理过的历史状态可能增加得更快。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

实际系统有 cache、context editing 和 compaction,不会机械遵循这个增长曲线,但问题的形状没有改变:Agent 运行时间越长,每一个新动作越可能建立在一块更重的历史之上。

所以长任务里那个很短的用户 prompt 很快就会失去存在感。真正开始主导成本的,是模型为了保持任务连续性而不断携带的工作集。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

03


删得太狠会出现语义缺页

working set 为什么膨胀得这么快,工具输出是一个很大的来源。源码至少有结构,日志经常没有。

一次 grep 可以返回几百处引用,一次构建可能吐出大片 warning,一次测试失败可能带着完整 stack trace,Docker、编译器、包管理器也会制造大量对任务没有长期价值的文本。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

假设第 10 步测试产生了 8K Token 日志。它第一次进入 context 时,只是 8K Token。可 Agent 还要继续检查源码、修改、重新测试,只要这段日志仍然处于有效历史中,它就会提高后续很多轮请求的基础重量。

这很像存储系统里的 write amplification:一次逻辑写入,造成了后续更多底层处理。Agent 里的情况是,一次 tool output 被写进执行历史,随后跟着后面的推理一起移动。

于是同样是 8K Token,放在任务结束前一轮和放在任务刚开始时,带来的整体影响完全不同。Claude Code 现在也在主动减少这种污染。官方建议用 sub-agent 隔离高输出任务,并明确提到搜索结果、日志和大量文件内容会消耗主会话 context;工具定义本身也会占用空间,因此工具集过大同样会增加状态负担。

可这里又出现一个反方向的问题:不能因为日志很贵,就把它们全部裁掉。一段 3000 行日志里,可能只有 20 行与根因有关。系统事先并不知道是哪 20 行。如果清理过早,Agent 到后面突然需要其中一个细节,只能重新跑测试或者重新打开文件。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

这可以叫做 semantic page fault,语义缺页传统虚拟内存里,程序访问一个已经不在内存中的页面,系统会从磁盘重新加载;Coding Agent 丢掉某段早期证据以后,也会发生类似现象,只不过表现成重新搜索仓库、重复读取文件、再次运行命令,甚至重新推导一个早就分析过的问题。

于是长任务陷入一个两难:留下过多历史,后续每一步越来越重;清理得过于激进,Agent 又会不断重新获取以前见过的信息。

这也解释了为什么 context 管理不能简化成“少塞一点 Token”。真正需要解决的是 working set selection此刻有哪些信息必须留在工作区,哪些只是已经完成使命的中间产物。

到了这里,compaction、memory 和 sub-agent 才真正有了存在的理由。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?
Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

04


什么信息可以被忘掉?

Claude Code 接近 context 边界时会自动压缩会话,同时还会清理部分较旧的工具结果。官方也提醒,长 session 里的无关对话、文件内容和命令结果可能占满窗口并干扰模型表现。

从系统角度看,compaction 很像一次语义垃圾回收。麻烦在于,普通垃圾回收判断的是“这个对象还有没有引用”,而 Agent 必须判断“这段信息以后还有没有意义”。

后者难得多。例如早期有这样一段设计结论:某个模块不能自己缓存用户状态,因为系统要求状态只有一个 owner,所有修改必须经过 service。

几十步之后,如果这段信息被压成:“之前通过 service 调整解决了状态问题。”事实没有错,但信息已经发生了变化。原始内容包含的是 constraint,后面的摘要保存的只是 event

下一次 Agent 碰到性能问题,看到 service 调用很慢,很可能又在模块里增加缓存。它并没有违反自己当前掌握的信息;当初禁止缓存的因果关系已经不在有效状态中了。

Claude Code 的 context 文档甚至明确指出,部分 path-scoped rules 和嵌套的 CLAUDE.md 会随着会话一起被 compaction 摘要掉,需要再次读取匹配文件才会重新加载。

Memory 试图解决长期知识保存的问题。项目根目录的 CLAUDE.md 和 auto memory 可以把构建命令、项目规范、调试经验等内容从短期对话中抽出来,并在会话开始时重新加载。但 Anthropic 对它的定位也写得很清楚:这些 memory 仍然是 context,不属于强制配置。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

这个区别非常关键。“这里不能直接访问数据库”如果只写在 memory 里,它仍然是一句模型需要理解并遵循的自然语言。如果同一条规则被写成 dependency lint、类型约束或者 CI 检查,它才变成一个无法轻易绕开的软件 invariant。

Sub-agent 解决的是另一块:隔离工作集。让一个独立 Agent 去扫描仓库或者分析长日志,再把压缩后的结果交还主 Agent,可以避免原始噪声进入主线程。Claude Code 官方给 sub-agent 的用途之一就是 context isolation。

它的代价也很有意思:主 Agent 得到了更干净的状态,却失去了部分原始证据;多个 Agent 同时运行,还会建立各自的 context。因此 compaction、memory、sub-agent 放在一起看,其实已经很像一套 Agent 时代的内存层级:

当前 context 是昂贵工作内存,compaction 负责压缩,memory 保存跨 session 状态,sub-agent 用独立地址空间隔离噪声。问题也从“context 够不够大”变成了另一个层级:

哪些状态需要高保真保存,哪些状态只需要留下摘要。这个问题会直接影响后面的代码质量。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

05


无法提前预知要跑多久的程序

理解前面这套执行结构后,再看 Claude Code 的周额度,会发现平台很难继续按“消息条数”计量 Agent。因为一条消息已经失去稳定意义。

把变量改个名字是一条消息,重构整个认证模块也是一条消息。前者可能几步结束,后者可能运行几十轮,读取几十个文件,再启动多个 Agent。同样的一个 request,背后的资源需求可以完全不是一个量级。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

Claude Code 用滚动限制和周额度包装这件事;Codex 现在已经明确按照 input token、cached input token 和 output token 折算 credits;Cursor 的套餐则给 Agent 提供不同 usage pool,第三方模型的消耗会受到模型 API 价格影响。

三个产品的界面语言不同,底层需要解决的问题却很接近:怎样给一个执行路径事先无法确定的智能程序分配推理资源。一个 Coding Agent 到底会跑多久,在任务开始时很难确定。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

模型可能很快找到根因,也可能连续提出几个错误假设;可能一次测试就通过,也可能进入长时间 debug loop;可能只需要一个 Agent,也可能拆出多个 sub-agent。

传统 API 很喜欢按 request 计费,是因为一次 request 的资源波动还能控制在一定范围。Agent 把这种稳定性打散了。所以 Token 在这里开始有一点 CPU time 的味道。

这个类比不能画等号。不同模型处理同样数量 Token 的算力成本不同,input、cached input 和 output 也有不同成本。但站在开发者这一侧,它们承担的功能越来越相似:都是在描述一个任务为了继续运行,到底占用了多少计算资源。

Anthropic 在今年提高 Claude Code 使用上限时,也直接把额度提升和新增 compute capacity 联系在一起。这会带来一个很有意思的指标变化。以前看 Coding Agent,容易比较“同一道题谁一次写得好”。往后可能更有意义的是:完成同样的工程状态变化,谁消耗的有效计算更少。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

如果一个 Agent 花掉大量 Token,只是在重复打开文件、重新跑测试、重新恢复已经丢掉的上下文,那些 Token 并没有换来对应程度的工程推进。

而这类低效状态恢复,恰好会和技术债在下一层碰到一起。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

06


AI 祖传代码怎么形成

这里可以把一个 Coding Agent 维护的软件抽象成两套同时演化的状态。一套是代码状态 R_t。文件、类型、接口、测试、Git commit 全部属于这一层。Agent 第 20 步加进去的一行 retry,只要没有被删,第 100 步打开文件时仍然完整存在。代码对过去修改的保存精度非常高。

另一套是设计状态 M_t。为什么这里需要 retry,为什么那个缓存只能放在 service,为什么这个状态不能有两个 owner,为什么一个看起来多余的判断暂时不能删,这些信息属于设计因果。

M_t 没有像 Git 一样天然的无损存储。它分散在对话、推理、工具返回、memory、规则文件和 compaction summary 里。任务不断推进以后,部分内容被清理,部分内容被摘要,部分内容需要重新检索。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

于是会产生一个很关键的不对称:实现结果能够高保真累积,生成这些结果的因果关系却会不断降采样。这比单纯说“Agent 会忘东西”严重得多。

假设一次并发问题中,Agent 分析后加入了一个 queue。当时它掌握的完整结论是:只有写路径 A 存在竞争,因此 queue 只能包住 A;写路径 B 需要低延迟,不能进入这个队列。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

代码把 queue 完整保存下来了。经过长时间执行以后,设计状态可能只剩下“这里用 queue 解决 race condition”。

后来 B 也出现一个偶发错误。Agent 再次读到代码时,很自然地把 B 也接进现有 queue。

随后延迟上升,于是再加 bypass。bypass 又引出偶发状态不一致,于是外围补 retry。到了这里,没有任何一次修改必然是荒谬的。每个补丁在当时看到的局部状态下甚至可能相当合理。代码却已经从“一个明确的并发模型”,变成了 queue、bypass 和 retry 互相补偿。

AI 代码屎山很可能就是这样长出来的。它不一定表现成模型突然写出一团垃圾,更可能表现成局部正确不断累积,整体模型逐渐消失

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

传统软件里这类问题通常经过人员交接慢慢形成。原作者离开,新开发者看到旧代码,却不知道它为什么存在,于是在外面再包一层兼容逻辑。

Coding Agent 把“人员交接”变成了“上下文交接”。第 20 步和第 100 步看起来还是同一个 Claude Code session,但它们实际拿到的设计状态已经不完全相同。从信息角度看,更像两名工程师通过一份不断缩水的交接文档维护同一个仓库。

测试也只能解决其中一部分。测试擅长保护行为:接口应该返回什么,某种输入不能崩溃,过去的 bug 不能重新出现。很多架构约束却不天然表现成输入输出。

状态只能有一个 owner、领域层不能反向依赖 UI、某个 package 不允许直连数据库、写操作必须经过统一事务边界,这些约束如果只存在于文档或者 Agent 记忆里,就很容易在局部修复中被穿过去。

结果会出现一种很麻烦的工程状态:测试还是绿的,代码已经越来越难解释。更危险的是,这里面存在反馈回路。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

架构开始变乱,Agent 下一次理解功能就需要读取更多文件;依赖关系越绕,working set 越大;工作集越重,系统越需要清理和压缩;设计因果保存得越薄,后面的修改又越容易依赖眼前代码和局部测试。

于是代码复杂度开始提高 Token 成本,Token 压力又反过来鼓励更短的状态保留和更局部的修补。这才是 Agent coding 里“越迭代问题越多”背后比较值得警惕的机制。

它不是一个单独的模型能力问题,而是一种代码状态和设计状态保存精度不一致的系统问题。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

07


Agent 需要「状态保真率」

Coding Agent 已经越来越能长时间行动,但“能跑几个小时”本身未必是一个很好的能力指标。

如果一个 Agent 工作 3 小时以后,需要重新阅读自己 2 小时前改过的文件,重新推理某个抽象为什么存在,再重新跑一次此前已经跑过的测试,那么这 3 小时里有相当一部分计算其实花在了状态恢复上。

接下来的问题会变成:一个 Agent 在经历 50 步、100 步之后,还能保留多少对后续决策有价值的因果信息。

可以把它叫作状态保真率

因为它衡量的不是 context 能塞多少 Token,而是经过工具调用、压缩、跨 session 和记忆检索之后,多少关键设计信息仍然以可用的形式存在。这也意味着,Agent 的长期记忆不能只靠更长的 context。

有些知识适合存在 memory 里,比如项目构建方式和开发习惯;有些决策应该进入结构化的 ADR 或代码索引;而那些一旦违反就会破坏系统的架构边界,更适合直接写进类型、测试、 lint、依赖规则和 CI。

一条规则如果已经变成软件可以执行的约束,Agent 就不需要“记住”它。下一轮 Agent 可以忘掉一段对话,却无法轻易越过编译器和测试。

如果保真率低,Agent 跑得越久,其实是在给系统埋越多的地雷。

这可能也是 Coding Agent 从“会写代码”走向“能长期维护软件”需要跨过去的一道线:把设计知识从概率性的语言记忆,逐渐迁移到可检索、可验证、可执行的软件状态里。

否则自主运行时间越长,会出现一个很荒诞的场景。Agent 写代码的速度越来越快,项目也在飞快变化,可每隔一段时间,它又要重新理解上一段时间留下来的世界。

传统祖传代码常见的一句话是:“这段别动,不知道为什么会炸。”

AI 祖传代码可能更离谱:代码确实是 Agent 写的,只是后来的 Agent 已经不知道前面的 Agent 为什么这么写了。

参考链接:https://news.ycombinator.com/item?id=49348751

进群传送门:添加微信Qvv0909777,备注:单位/学校+姓名+方向。

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

上车,带你看遍全球 AI 顶会精华

可独家畅览:

专家演讲PPT

大会报告全文

热门论文解读

学术新星访谈

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

扫描上方二维码

或点击阅读原文关注专区。

雷峰网原创文章,未经授权禁止转载。详情见转载须知

Claude Code 额度回落:Agent 正在制造新的「祖传代码屎山」?

分享:
相关文章
最新文章
请填写申请人资料
姓名
电话
邮箱
微信号
作品链接
个人简介
为了您的账户安全,请验证邮箱
您的邮箱还未验证,完成可获20积分哟!
请验证您的邮箱
立即验证
完善账号信息
您的账号已经绑定,现在您可以设置密码以方便用邮箱登录
立即设置 以后再说