伪缓存与心跳税:如何烧掉你的钱¶
证据等级:F(源码直接证明)
分析基线:4f843556
一句话¶
OpenAI 的 prompt caching 被一行代码明确关闭:supports_cache_control = normalized_provider == "qwen"。只有 Qwen 受益。与此同时,每 4 小时一次的心跳不分 idle/running,触发完整 LLM 会话,无并发控制。
1. 伪缓存¶
各厂商缓存策略¶
| 厂商 | 缓存 | 实际效果 |
|---|---|---|
| OpenAI | 禁用 | 每轮重传全部 prompt |
| Anthropic | 静态前缀 | 动态内容永远重发 |
| Qwen | 启用 | 唯一受益者 |
固定开销¶
System prompt: ~6,000 tokens
Tools: ~5,000 tokens
─────────────────────────
每轮固定: ~11,000 tokens(无缓存命中)
2. 心跳税¶
# heartbeat.py:473,512
if state in ("idle", "running"): # 无差别
create_task(heartbeat_session()) # 无并发控制
- 无 lock、semaphore、rate limiting、jitter、backpressure
- 固定 4 小时间隔
你以为的 ping-pong,实际是负重奔跑¶
心跳的本意是"你还活着吗"——一次轻量存活检查。但这里的实现是:
- 组装完整上下文:soul.md + memory.md + skills/ + tools + enterprise_info + focus + triggers → 全部拼进一个 system message,然后发给 LLM
- LLM 认真回复:模型收到 ~20K tokens 的完整上下文,生成一段有意义的回复
- 回复被丢弃:没有人读取这个回复,不做任何处理
这不是心跳——这是每 4 小时让 LLM 把整个 Agent 的"人格 + 记忆 + 能力"读一遍,然后写一段读后感,再扔掉。
对比:一个正确的心跳应该是什么¶
正确的心跳:
echo pang → "pang"
2 tokens
实际的心跳:
→ 组装 soul + memory + skills + tools + enterprise_info + focus + triggers
→ 发给 LLM
← LLM 生成一段认真的回复
→ 回复被丢弃
~20,000 tokens
从 2 到 20,000——一万倍起步。不是优化不够,是根本没意识到心跳不应该进 LLM。
成本估算¶
1 Agent × 6 次/天 × ~20K tokens/次 = ~120K tokens/天
100 Agent × 6 次/天 × ~20K tokens/次 = ~12M tokens/天
仅心跳,不含用户实际使用。
换算成钱¶
输入:12M tokens/天
输出:~0.2M tokens/天
输入价格 输出价格 每天 每月
Claude Sonnet 5 $3/1M $15/1M ~$39 ~$1,170
Claude Opus 4.8 $5/1M $25/1M ~$65 ~$1,950
100 个 Agent,什么正事都不干,光心跳。Sonnet 一个月烧掉一千多美元,Opus 翻倍。
换算一下:Sonnet 一个 Agent 的心跳 ≈ $11.70/月。两个 Agent 的光心跳就够订一个 Claude Pro($20/月)。用 Opus 的话,一个 Agent 就够了。
而一个正确的心跳只需要 echo pang——2 tokens。
3. 叠加效应¶
伪缓存 + 心跳:每 4 小时,每个 Agent 重传 ~20K tokens 的完整上下文——这正是缓存本应避免的。
心跳 + 无并发控制:所有 Agent 同时重启 → 所有心跳同时触发 → API 被 DDoS。
心跳 + 无 jitter:心跳间隔固定,全部 Agent 同时到期。
心跳 vs Dashboard:两个灾难,完美错位¶
心跳每 4 小时烧 20K tokens,但从不更新 agent.status。
Dashboard 这边呢?每 15 秒自动刷新一次,一天 43,600 次 HTTP 请求。但它读的数据库字段,心跳从来没写过。
心跳:6 次/天 × 20K tokens = 120K tokens/天 → 不更新 status
Dashboard:2,880 次刷新/天 × 42 请求/次 = 43,600 请求/天 → 读到的是心跳从未更新过的数据
一个烧钱不产出,一个刷屏看不到真相。
两个都在拼命工作,方向完全错开。
4. 与 AI Coding 的关系¶
== "qwen"不可能是故意设计:这是最简实现——只为测试过的厂商开启缓存,其余"先不管"- 心跳逻辑是逐任务叠加的:先写"每 4 小时触发",再写"判断状态",最后无人补并发控制
- AI 不会主动优化成本:心跳、缓存、并发——这些是跨任务的系统属性,AI 在每个任务里只看到局部需求
关键代码¶
| 文件 | 行号 | 内容 |
|---|---|---|
client.py |
2599 | supports_cache_control = normalized_provider == "qwen" |
heartbeat.py |
473 | if state in ("idle", "running"): |
heartbeat.py |
512 | create_task(...) 无并发控制 |
heartbeat.py |
282 | _build_heartbeat_instruction() → 组装心跳指令 |
heartbeat_runtime.py |
81 | enqueue_heartbeat_runtime() → 入队为 runtime run |
worker_service.py |
224 | RuntimeModelStepService(prompt_builder=build_agent_context) → 默认用完整上下文构建器 |
model_step_service.py |
1208 | self._prompt_builder(...) → 调用 build_agent_context,组装 soul + memory + skills + enterprise_info + focus + triggers |