CLI Agent 高频问题排查
装包失败 / 权限报错 / API 限流 / context 超限 / hook 死循环等终端 Agent 高频问题的快速定位与处置
把 prompt cache 用满、把上下文预算分配清楚的实战策略,结合 Claude Code 实际数据讲清"省钱"和"省时间"两个目标
内容摘要
> 写在前面:这张卡解决的不是"模型怎么变聪明",而是"同一段对话,怎么少花一半的钱、少等一半的时间"。两个目标合在一起,本质上就一句话——**让模型尽量从缓存里读,而不是从头算**。
写在前面:这张卡解决的不是"模型怎么变聪明",而是"同一段对话,怎么少花一半的钱、少等一半的时间"。两个目标合在一起,本质上就一句话——让模型尽量从缓存里读,而不是从头算。
Prompt cache(提示缓存)是模型厂商在推理侧加的一层"前缀复用"机制。它的思路非常朴素:一次对话里,开头那一大段(system prompt、CLAUDE.md、工具定义、历史消息)几乎每轮都不变,与其每次都让模型从头算一遍 KV cache,不如把这段前缀的中间状态存一会儿,下一轮直接挂回来。
Anthropic 的 Claude prompt cache 在 2024 年 8 月公测、2025 年正式 GA,现在是 Claude API 上最大的一个成本杠杆。它的关键参数(截至 2026 年 4 月):
| 维度 | 取值 | 说明 |
|---|---|---|
| 默认 TTL | 5 分钟 | 每次命中自动续期,不另外计费 |
| 扩展 TTL | 1 小时 | 写入费用从 1.25× 提到 2× 基础输入价 |
| 写入价 | 1.25× 基础输入价(5 min)/ 2× 基础输入价(1 hr) | 写入比读多 25%~100% |
| 读取价 | 0.1× 基础输入价 | 缓存命中后只花十分之一 |
| 最小可缓存 token | Sonnet 4.6 = 2048;Opus 4.7 / 4.6 / Haiku 4.5 = 4096;Sonnet 4.5/3.7 = 1024 | 不到这个数静默不缓存,不报错 |
| 单请求最多 cache_control 断点 | 4 个 | 自动缓存额外占 1 个,留给开发者 3 个 |
| 工作区隔离 | 2026-02-05 起 cache 按 workspace 隔离(不再按 organization) | 多 workspace 团队需要重新评估命中率 |
为什么是 5 分钟?这是 Anthropic 在"GPU 显存成本"和"用户对话节奏"之间挑出来的一个折中——绝大多数交互式对话两轮之间间隔 < 1 分钟,5 分钟足够覆盖思考+打字的天然停顿;再长就要占用大量显存,定价就只能涨。
Claude Code 是个"长会话、长前缀"的典型场景:CLAUDE.md 几十 KB、MCP 工具列表几十个、历史回合几十条——每条新消息上去前的前缀往往 50k~150k token。Claude Code 在底层 API 调用里默认会自动放好 cache_control 断点,把这部分变成可缓存前缀。这就是为什么社区博客经常出现「同样跑 30 分钟,账单从 $20 降到 $3」的截图——不是模型变便宜了,是命中率从 0% 拉到 90%+。
上下文预算说的是"这次对话里,总共能装多少 token"。它有两层口径:
把这两层和 prompt cache 放一起想,就能看清整张图:预算决定你能装多少;cache 决定装的这些东西是不是几乎免费地复用。两者一起优化才是省钱的正解。
这张图里最容易被忽略的一格是 H(auto-compact)——压缩之后前缀整段被改写,下一轮 100% miss、需要重新写入缓存,是一次"隐性大额支出"。后面的"常见误区"会专门拆这点。
/cost 看真实账单和命中率Claude Code 2.1.92 起 /cost 被重写过,会按模型分别给出:本次会话的输入/输出 token、cache write 与 cache read 的拆分、估算的美元开销,以及 rate-limit 占用。这是最快确认"cache 到底有没有在工作"的入口。
# 在 Claude Code 交互界面里直接输入
/cost
预期输出(Pro 用户)大致长这样:
Total cost: $0.55
Total duration (API): 6m 19.7s
Total duration (wall): 6h 33m 10.2s
Total code changes: 0 lines added, 0 lines removed
Per-model breakdown:
claude-opus-4-7
Input: 12,430 tokens
Output: 3,210 tokens
Cache write: 86,540 tokens (1.25× input)
Cache read: 742,180 tokens (0.10× input) ← 这一行越大越好
判断命中率好不好的经验值:cache read / (cache read + cache write + 普通 input) > 0.7 就算良好;如果一直在 0.3 以下,多半是有人在频繁切话题或者 CLAUDE.md 经常被脚本改写。
Max / Team / Enterprise 订阅用户的额度是包月的,
/cost数据不直接对应账单,这种场景看/stats更合适,但 cache 命中率字段一样有参考价值。
/context 看上下文预算的占用/context 会列出当前会话的 token 都被谁占了——CLAUDE.md、MCP 工具定义、对话历史、思考 token 各自占多少。它是回答"我离 auto-compact 还有多远"和"哪个 MCP server 把窗口吃掉了"的关键命令。
/context
# 预期输出(节选)
Context usage: 142,830 / 200,000 tokens (71%)
System prompt + tools: 18,420 tokens
CLAUDE.md: 4,310 tokens
MCP tool definitions: 31,560 tokens ← 偏大,考虑禁用未用 server
Conversation history: 88,540 tokens
Headroom before compact: ~57,170 tokens
把 /context 的产出塞进 statusline,可以在每条消息上方实时看到 token 消耗,省得每隔几轮手动敲一次(参见 claude code statusline context 配置)。
Claude Code 默认已经会自动给前缀打 cache_control,但用户的对话节奏决定了命中率。两种典型节奏的差别:
# 反例:每条消息都让模型重新理解项目上下文
# (表面上每次都"补充背景",其实都在 cache miss)
> 帮我看一下 src/auth/ 下的登录逻辑
> 我们项目用 Next.js 14 + Prisma,登录走的是 NextAuth.js
> 顺便帮我审查一下安全性,注意我们要符合 GDPR
> ……(每轮新背景信息插在最前面,把前缀打散)
# 正例:把背景信息一次性写到 CLAUDE.md,然后专注于本轮任务
> 看一下 src/auth/signin.ts,按 CLAUDE.md 里的安全规约审查
> 把发现的问题按严重程度列出来
> 第二条问题给一个最小修复 patch
# 前缀(CLAUDE.md + 工具定义 + 历史)几乎不变,每轮都命中
经验规则:所有"几乎不变的项目背景"放 CLAUDE.md;所有"本次对话要用的临时上下文"放当前消息。前者进缓存,后者算到本轮 input。
/compact 是把历史对话压缩成摘要再继续。它能把会话从 180k token 压回 30k,让你不撞 auto-compact,但压缩当下会让前缀彻底改写,相当于丢掉所有缓存。所以它是一次"用一次 cache miss 换接下来几十轮的低占用"的取舍。
# 在快撞 context 上限时主动 compact,并指定保留重点
/compact 保留最近 10 轮代码变更和当前任务的目标,丢掉早期探索性讨论
# 也可以在 CLAUDE.md 里固化压缩偏好
# Compact instructions
# When you are using compact, please focus on test output and code changes
判断 compact 时机的简单原则:如果还能再撑 5 轮以上不撞 auto-compact,就别手动 compact——cache 是按"前缀完全一致 + 5 分钟内"这两个条件命中的,每次 compact 都意味着接下来一整段时间都是新缓存,账单和延迟都会先抬一档。
不同 CLI Agent 在 prompt cache / context 这条战线上的差异比想象中大,下面这张表只列三家最主流的厂商在 CLI 场景里的实际表现:
| 维度 | Claude Code(Anthropic) | Codex CLI(OpenAI) | Gemini CLI(Google) |
|---|---|---|---|
| Cache 触发方式 | 自动放 cache_control 断点(也允许显式) | 完全自动,不暴露任何控制 | 需要显式创建 CachedContent 对象(CLI 默认不开) |
| 默认 TTL | 5 分钟(可扩到 1 小时) | 5~10 分钟,闲时段会延长到 1 小时 | 1 小时(可自定义) |
| 最小可缓存 token | 2k(Sonnet 4.6) / 4k(Opus 4.7, Haiku 4.5) | 1,024 | 32,768 |
| 缓存读取折扣 | 输入价的 10%(≈ 节省 90%) | 输入价的 50% | 输入价的 25% |
| 是否对存储另外收费 | ❌ 不收 | ❌ 不收 | ✅ 按缓存大小 × 时长收存储费 |
| 命中率可见性 | /cost、/context、statusline | 无暴露,需要自己抓 API 响应里的 cached_tokens | 无暴露,需要自己读 SDK 返回 |
| 上下文窗口(CLI 默认模型) | Sonnet 4.6 / Opus 4.7 1M(Max+ 自动升 1M) | GPT-5 系列 200k~400k 不等 | Gemini 2.5 Pro 1M~2M |
| Auto-compact / 自动压缩 | 内置 auto-compact,可调 CLAUDE_CODE_AUTO_COMPACT_WINDOW;也可手动 /compact | 默认无;超出窗口直接报错或丢老消息 | 内置长上下文,但无明确"压缩"动作;超长时由 SDK 截断 |
核心区别一句话:Anthropic 的策略是"显式缓存 + 大幅折扣"(90% off),适合 Claude Code 这种长前缀、自动布断点的场景;OpenAI 走"无感自动 + 中等折扣"路线,CLI 用户基本不用关心;Google 走"长 TTL + 收存储费"路线,更适合那种"一份大文档反复问几小时"的检索场景,CLI 里反而不是甜蜜点。
| 误区 | 准确理解 |
|---|---|
| 以为切话题不影响 cache | 切话题会导致前缀里多出一段新背景或多出一次 /clear,cache 命中链立即断掉。一个项目里如果连续聊三个不相关的小任务,建议每个任务起独立 session(claude --rename + claude --resume),不要都塞在一个会话里 |
| 以为 read 大文件无所谓 | 一次 Read 把 8000 行日志整个塞进对话,会让接下来每一轮都把这 8000 行作为前缀重新算(即便有 cache,也是写入价 1.25×;cache 过期之后还得再付一次写入)。改成"用 hook / grep 先过滤再读"是性价比最高的优化 |
| 以为 max context = 实际可用预算 | 物理 1M / 200k 是窗口上限;实际可用预算还要扣掉 system prompt、工具定义、auto-compact 留白、思考 token 预算。/context 报的"剩余 headroom"才是真预算 |
以为 /compact 是越早越好 | compact 自身会触发一次 100% cache miss + 全量重写,是有显著成本的。在还能撑 5 轮以上时主动 compact,反而是浪费 |
| 以为 cache TTL 永远 5 分钟 | 每次命中会自动续期;只有"5 分钟内一次都没读"才会过期。一段对话里 30 分钟连续操作,前缀其实可以一直在缓存里 |
| 以为 MCP 工具挂得越多越好 | MCP 工具定义会进入 system 前缀(即便每个工具仅几百 token),10+ MCP 服务挂上来很容易把工具定义膨胀到 30k token 以上,每轮都是固定开销。用 /mcp 关掉不用的,能让真正可用预算多出 15~30% |
| 以为 1M 上下文等于"随便塞" | 大窗口不会让单条 token 变便宜——cache miss 之后的每一个 token 都是按 1× 输入价算。1M 窗口的真正用途是"装得下大型代码库的关键文件 + 长时间不撞 compact",不是"反正放得下就都塞进去" |
| 优势 | 劣势 |
|---|---|
| 省钱杠杆极大:cache 读取只要 0.1× 输入价,长会话整体成本能压到没缓存场景的 20~30% | 命中条件苛刻:前缀必须逐字节一致,CLAUDE.md 被脚本改一行、工具列表变一个、ttl 过期,全部 miss |
| 延迟也降一档:cache 命中省掉 prefill 计算时间,长前缀会话首 token 延迟从几秒降到亚秒级 | 观察成本不低:要理解 /cost 里 cache_write / cache_read 拆分,要看 /context 的细分占比,对新手不算友好 |
| Claude Code 默认就开:不用学协议、不用挂参数,自动放断点,自动续期 | auto-compact 是隐性炸弹:压缩瞬间清掉所有缓存,不少团队反复在长任务上踩这个坑 |
| TTL 可扩到 1 小时:长 agentic 任务(跑测试、等审查)期间不会把缓存等没了 | 1 小时 TTL 写入要 2× 基础价:用得不对反而比 5min cache 更贵;要看任务节奏决定 |
| 多家厂商都有同类机制:迁移到 Codex CLI / Gemini CLI 也能享受到(折扣比例不一样而已) | 跨 workspace 隔离:2026-02 起 cache 按 workspace 隔离,组织内多 workspace 的命中率会下降,需要重新合并工作流 |
参考答案:
cache 命中的硬条件是"前缀完全一致 + 5 分钟内"。如果你每轮都在最新一条消息里补充背景,对模型来说每一轮的前缀都和上一轮不一样——更准确地说,新加的背景信息会插在历史消息流的某个位置,让从这条往后的所有内容跟之前缓存的版本对不上。
cache 用的是逐字节比对,对不上就只能从头写一份新缓存。本来 cache_read 价格是输入的 10%,结果一下子变成 cache_write 的 125%,单价直接翻 12.5 倍。
正确做法是把"几乎不变的项目背景"沉淀到 CLAUDE.md,让它进入会话的固定前缀;而每轮消息只写"本轮要做的事"。这样前缀稳定,每条新消息都能高命中。
参考答案:
按"开会前、开会中、开会后"三个阶段拆:
开会前(设计 cache 友好的前缀):
/mcp),让工具定义不要膨胀。开会中(不打散前缀):
/context 实时观察占用,接近 75% 时再考虑 /compact,同时给 compact 指令明确保留点(比如"保留当前 patch 的 hunks 和测试目标,丢掉早期探索过程")。开会后(拆账):
/cost 里 cache_read 占比应该明显大于 cache_write;如果不是,说明前缀变化太频繁,下次复盘哪一步把前缀打散了。一句总结:让前缀稳定、让 verbose 远离主会话、按节奏选 TTL,最后用 /cost 复盘。
参考答案:
这是"产品定位 + 成本结构"两边一起决定的。
产品定位侧:Anthropic 把"长前缀、agentic 工作流"当作核心战略——Claude Code、Computer Use、Constitutional AI 评估这些场景共同点是"前缀很大、变化很慢"。给 cache 一个极激进的折扣,等于从定价层面把用户往这条路上赶:你越是把信息固化到 system / CLAUDE.md / 工具定义里,你越省钱。这跟 OpenAI 把 ChatGPT / Codex CLI 往"轻量交互、自动隐式优化"上推、Gemini 把 Vertex AI 往"长文档检索 + 收存储费"上推,是三种不同的定位。
成本结构侧:cache 读其实是把 KV cache 中间状态从显存里"挂回来"——主要消耗是显存占用和带宽,不是计算 FLOPs。一旦 GPU 利用率本来就高,多挂一个用户的缓存几乎是边际免费的。Anthropic 把折扣开到 10%,意味着他们已经把这部分成本摊薄到非常低。
对 CLI Agent 用户的策略意味着:
/clear,能在同一会话里复用就复用,能用 /compact 续命就别新开。更宏观地讲:cache 折扣激进意味着"信息组织得好不好"开始直接对应"账单大不大"。这跟过去"prompt 写得短就能省"的直觉不太一样——现在是"prompt 写得稳定(不变)才能省"。
优先展示同分类且标签更接近的内容,方便继续串联学习。
装包失败 / 权限报错 / API 限流 / context 超限 / hook 死循环等终端 Agent 高频问题的快速定位与处置
高危权限治理:dangerously-skip-permissions / 容器隔离 / CI 场景 / 团队规范的成体系做法,含真实事故案例