
1. 项目缘起为什么我要折腾一个叫 caveman 的东西第一次看到 caveman 这个词是在一个 AI 编程工具的讨论帖里。有人甩出一句用 caveman 跑 agenttoken 直接砍半底下跟了一堆人问怎么装、怎么配。我当时的第一反应是这名字起得挺有意思原始人嘛意思就是用最笨、最省的方式干活。后来自己上手跑了一段时间才真正理解它想解决的问题——AI coding agent 在长任务里 token 消耗失控。先说清楚 caveman 是什么。它不是某个大模型也不是某个 IDE 插件而是一个面向 AI coding agent 的轻量级 token 优化与代理层工具通常通过npx直接拉起不需要全局安装。它的核心定位很朴素在 agent 和模型服务之间插一层把冗余的上下文、重复的 prompt、无意义的工具返回结果做压缩和裁剪从而降低 token 用量、加快响应、减少费用。适合谁用三类人一是天天用 agent 写代码、月底看账单心疼的开发者二是本地跑小模型、上下文窗口吃紧的人三是想研究 agent 上下文管理机制的技术爱好者。我自己的场景是用 agent 做多文件重构一个任务动辄几十轮工具调用每轮都把整个文件树、历史对话、工具 schema 全塞进去token 用量像滚雪球。caveman 出现之前我只能手动精简 prompt累且容易漏。用了它之后最直观的感受是同样的任务token 用量降了大概四到六成而且因为上下文更干净模型跑偏的概率也低了。下面我把这套东西从设计思路到实操细节完整拆一遍包括我踩过的坑。2. 整体设计思路caveman 到底在省什么2.1 核心矛盾agent 的上下文为什么会爆炸要理解 caveman 的价值得先搞清楚 AI coding agent 的 token 都花在哪了。一个典型的 agent 循环是这样的用户给一个任务agent 把系统提示、工具定义、历史消息、当前文件内容、工具执行结果全部拼成一个巨大的 prompt 发给模型模型返回下一步动作执行再把结果追加进历史循环往复。问题就出在这个追加进历史上。每一轮的工具返回——比如读了一个 500 行的文件、跑了一次测试输出几百行日志——都会原封不动地留在上下文里。到第十轮的时候前面九轮的垃圾还在模型每次都要重新读一遍。这就是 token 爆炸的根源。我实测过一个中等规模的重构任务不做任何优化单次会话的累计 token 能到 80 万以上其中真正有用的信息可能不到两成。caveman 的设计思路就是针对这个它不改变 agent 的工作逻辑只在数据流经它的时候做减法。具体来说它拦截发往模型的请求对上下文做分层处理——哪些必须保留、哪些可以摘要、哪些可以直接丢弃用一套规则加轻量模型判断来决定。2.2 为什么选择代理层而不是改 agent 源码这里有个关键的方案选型问题优化 token你可以改 agent 本身的代码也可以在外面套一层代理。caveman 选了后者我认为这个选择非常务实。改源码的问题在于不同的 agent 框架不管是哪家的 CLI 工具还是自建脚本实现差异巨大你改了一个换一个就得重来。而且很多 agent 是闭源或者频繁更新的你改完下次升级就冲突。代理层的好处是解耦agent 以为自己在跟模型服务说话实际上中间隔了 caveman它做它的压缩agent 完全无感。你换 agent、换模型只要请求格式兼容caveman 都能接。代价也有就是多了一跳网络开销以及需要处理各种请求格式的兼容性。但从我实际使用来看这一跳带来的延迟本地通常几毫秒到几十毫秒远小于省下 token 带来的响应加速净收益是正的。2.3 通过 npx 分发轻量化的取舍caveman 用npx拉起而不是要求全局安装这个细节值得说。npx的机制是临时下载并执行包用完即走。对工具类项目来说这降低了尝试门槛——你不用污染全局环境不用担心版本冲突一条命令就能跑。但这里有个坑我要提前说npx每次执行如果本地缓存没有会去拉包网络不好的时候会卡住甚至失败。我遇到过npx拉取超时的情况后来学乖了第一次跑之前先确认缓存或者干脆本地npm install到项目里再调用。另外npx拉起的进程生命周期管理要小心别让它变成孤儿进程占着端口。提示如果你的环境对网络访问有限制npx首次拉包可能失败。建议提前在有网络的环境把包缓存好或者改用本地安装方式避免在关键任务中途卡住。3. 核心机制拆解token 是怎么被省下来的3.1 上下文分层三类信息的区别对待caveman 最核心的机制是上下文分层。它把进入模型的所有信息分成三类处理策略完全不同。第一类是不可压缩信息系统提示、当前任务描述、工具 schema 定义。这些是 agent 工作的基础动了就出错所以原样保留。第二类是可摘要信息历史对话、之前的工具调用记录。这些信息有用但不需要逐字保留caveman 会把它们压缩成简短摘要比如把读取了 utils.js 并发现第 42 行有个 bug压缩成一句结论。第三类是可丢弃信息大段的文件原文、冗长的日志输出、重复的报错堆栈。这些在提取出关键信息后就可以扔掉。这个分层的判断逻辑caveman 用的是规则加轻量模型结合的方式。规则负责明显的情况比如超过 N 行的输出直接截断模型负责需要理解语义的情况比如判断这段日志里哪几行才是真正的错误。我拆过它的处理流程整体是流式的不会把整个上下文一次性加载到内存里做全量分析这对大任务很友好。3.2 工具返回结果的裁剪策略工具返回结果是 token 消耗的大头caveman 在这块的裁剪最狠也最有效。我总结了几种它常用的策略文件读取截断读文件时如果文件超过阈值只保留开头和结尾若干行中间用省略标记。因为 agent 通常只需要知道文件结构和一个大概不需要全文。日志去重与聚合测试日志里重复的报错行会被合并计数比如同样的错误出现 37 次而不是贴 37 遍。堆栈精简报错堆栈只保留与当前项目相关的帧框架内部的帧折叠掉。二进制与资源文件跳过图片、编译产物这类内容直接不进入上下文。这些策略听起来简单但组合起来效果惊人。我做过对比测试一个包含大量日志的调试任务裁剪前后 token 用量差了将近 70%。3.3 与模型请求格式的兼容处理caveman 要工作必须能正确解析和改写发往模型的请求。不同模型服务的请求格式不完全一样尤其是工具调用tool call相关的字段。caveman 内部做了一层格式适配把不同来源的请求归一化后再处理处理完再转回原格式。这块是它最容易出问题的地方。我在使用中遇到过请求被改写后模型不认的情况排查下来是某个字段的嵌套层级被改动了。后来发现是版本兼容问题升级后解决。所以我的经验是caveman 的版本要和你用的 agent、模型服务版本大致匹配跨大版本混用容易出幺蛾子。4. 实操过程从零把 caveman 跑起来4.1 环境准备与依赖确认动手之前先把环境理清楚。caveman 依赖 Node.js 环境因为走npx分发。我建议 Node 版本不要太老至少 18 以上因为一些现代语法和内置模块需要。检查命令很简单node -v npm -v npx -v三个命令都能正常输出版本号说明基础环境没问题。如果npx报错通常是 npm 版本太旧或者 PATH 没配好。我遇到过 Windows 上npx找不到的情况最后是重装 Node 解决的。另外要确认你的 agent 工具支持自定义模型端点base URL。caveman 的工作方式是让你把 agent 的请求指向它它再转发给真正的模型服务。如果你的 agent 不支持改端点那 caveman 就用不了。这一点在动手前必须确认否则白忙活。4.2 启动 caveman 代理服务启动命令的基本形态是通过npx拉起然后指定监听端口和上游模型地址。我实际用的命令大概长这样npx caveman --port 8787 --upstream https://your-model-endpoint参数说明一下--port是 caveman 本地监听的端口agent 要连这个--upstream是真正的模型服务地址caveman 把处理后的请求转发到这里。启动成功后终端会打印监听地址通常是http://127.0.0.1:8787。这里有个细节端口别选太常见的比如 8080、3000容易和别的服务冲突。我一般用 8787 这种不太热门的。启动后先别急着接 agent用 curl 测一下代理是否通curl http://127.0.0.1:8787/health如果返回健康状态说明代理活着。这一步能省掉后面很多排查时间。4.3 把 agent 指向 caveman接下来改 agent 的配置把模型端点从原来的地址改成 caveman 的地址。不同 agent 改法不一样但本质都是找那个 base URL 或者 API endpoint 的配置项。改完重启 agent让它重新加载配置。改完之后agent 的所有请求都会先到 cavemancaveman 处理完再转发。这时候你可以在 caveman 的日志里看到每个请求的 token 用量对比——原始多少、压缩后多少。我第一次看到那个对比数字的时候还是挺震撼的一个读文件的请求从 12000 token 压到 3000 出头。注意改配置前先备份原配置。我有一次改错了字段agent 直接连不上模型排查了半天才发现是配置格式问题。备份能让你快速回滚。4.4 参数调优找到省 token 和保效果的平衡点caveman 有一些可调参数决定了压缩的激进程度。调得太保守省不了多少调得太激进模型可能因为信息不足而跑偏。我常用的几个参数和我的取值经验参数作用我的建议值说明文件截断阈值超过多少行开始截断200 行太小会丢关键代码太大省不了历史保留轮数保留最近几轮完整对话3 轮再往前的摘要化日志聚合开关是否合并重复日志开调试任务必开摘要模型用哪个模型做摘要小模型即可摘要不需要强模型省钱调参这事没有万能值得根据你的任务类型来。重构类任务对文件完整性要求高截断阈值就调大调试类任务日志多聚合开关一定要开。我一般会先跑一个小任务试水看压缩率和任务成功率再决定要不要调。5. 常见问题与排查实录5.1 代理启动失败与端口占用最常见的问题就是端口被占。报错通常是EADDRINUSE意思是地址已被使用。解决办法有两个换端口或者找到占用端口的进程干掉它。查占用进程lsof -i :8787Windows 上用netstat -ano | findstr 8787。找到 PID 后决定是杀还是换端口。我一般直接换端口省事。还有一种启动失败是npx拉包失败报网络相关错误。这种要么是网络问题要么是包名写错了。确认包名拼写然后检查网络。如果公司网络有代理限制需要配置 npm 的代理设置。5.2 请求转发后模型报错agent 连上了 caveman但模型返回错误这种情况通常是请求被改写后格式不对。典型表现是模型报参数错误或者直接 400。排查思路是先看 caveman 日志里转发出去的请求长什么样和原始请求对比找出被改动的字段。我遇到过一次caveman 把工具调用的参数结构改了导致模型不认。解决办法是升级 caveman 到匹配版本或者在配置里关掉那个改写选项。这类问题的根源基本都是版本不匹配所以保持 caveman 和 agent 版本同步是预防关键。5.3 token 没降反升的诡异情况有段时间我发现用了 caveman 之后 token 反而多了很困惑。排查下来是两个原因一是摘要本身也要消耗 token如果原文很短摘要反而更长二是某些请求格式 caveman 没识别原样转发还多了一层包装。解决办法是设置一个最小压缩阈值低于这个长度的内容不压缩直接透传。另外检查 caveman 是否真的识别了你的请求格式看日志里有没有passthrough透传的标记。如果有大量透传说明格式没匹配上需要调整配置。5.4 常见问题速查表现象可能原因排查方向解决启动报 EADDRINUSE端口占用lsof 查进程换端口或杀进程npx 拉包失败网络或包名错检查网络和拼写配代理或本地安装模型报 400请求格式被改坏对比转发前后请求升级版本或关改写token 不降反升短内容被摘要看日志压缩标记设最小压缩阈值agent 连不上端点配置错检查 base URL改回或修正配置响应变慢代理开销大测代理延迟调低压缩强度6. 我的实操心得与几个关键提醒6.1 先小后大别一上来就压狠了我踩过最大的坑就是一开始把压缩参数拉满结果 agent 因为上下文信息不足反复读同一个文件、反复问同样的问题总 token 反而更高。后来我学乖了新任务先用保守参数跑一遍看效果再逐步加码。压缩这事跟挤牙膏一样得一点点来找到那个刚好够用的点。6.2 摘要质量决定成败caveman 的摘要环节如果用太弱的模型摘要出来的东西可能丢关键信息。我的经验是摘要模型不用最强但也不能太弱至少得能理解代码语义。我试过用很小的模型做摘要结果它把这个函数有副作用摘要成了这个函数信息全丢了。后来换了个中等模型效果好很多成本也没高多少。6.3 日志要留着但别全留caveman 的日志是排查问题的命根子。我建议把日志级别调到能看清每个请求的压缩前后对比但日志文件本身要定期清理不然跑几天就几个 G。我一般配个轮转保留最近三天的。6.4 不是所有任务都适合压缩有些任务天生就不适合压缩比如需要精确逐行对比的任务、需要完整保留所有报错的任务。这种任务我一般会临时关掉 caveman或者把压缩强度调到最低。工具是为人服务的别为了省 token 把任务搞砸了。6.5 版本管理要上心caveman 这类工具迭代快版本之间行为可能变化很大。我现在的习惯是固定一个验证过好用的版本不盲目追新。等新版本稳定一段时间、社区反馈没问题了再升。升级前先在测试任务上跑一遍确认没问题再上生产任务。7. 后续可以怎么扩展caveman 这套思路其实可以往外延伸。比如你可以基于它的代理层加上自己的 token 用量统计和告警——超过阈值就提醒你任务可能失控了。也可以把多个 agent 的请求都汇聚到同一个 caveman 实例统一做压缩和监控这样能看清整个团队的 token 消耗分布。再往深了说上下文压缩这件事本身还有很多可挖的空间。现在的策略偏规则化未来如果能结合任务类型做自适应压缩——重构任务保留更多代码、调试任务保留更多日志——效果会更好。我自己在尝试的一个方向是根据 agent 当前所处的阶段探索阶段还是执行阶段动态调整压缩强度探索阶段多留信息执行阶段大胆压。这个思路目前还在试验等跑稳了再单独写一篇。最后分享一个我一直在用的小技巧给 caveman 的日志加个简单的可视化把每个任务的 token 压缩率画成曲线一眼就能看出哪个任务异常。这个用几行脚本就能搞定比翻日志高效多了。工具这东西用顺手了就得按自己的习惯改造别将就。