
1. 从caveman这个词说起为什么原始人式编码代理反而更高效第一次看到caveman这个项目名我脑子里蹦出来的画面是拿着石斧敲键盘的原始人。但真正用过一段时间之后我反而觉得这个名字起得相当精准——它要解决的核心问题就是让编码代理coding agents回归原始用最少的 token、最直接的方式把活干完。现在市面上的编码代理工具越来越多功能也越堆越厚。但实际用下来你会发现一个很尴尬的现象一个简单的重构任务代理在后台来回调用工具、反复读取文件、把大段大段的上下文塞进 prompttoken 消耗像开了闸的水龙头。月底一看账单几百上千块就这么没了。更气人的是很多 token 花在了代理自己跟自己对话上而不是真正解决问题。caveman 这个项目切入的角度就是这里。它不追求花哨的功能而是把注意力放在token 效率和代理行为的精简上。关键词里出现的 proxy、coding agents、token 三个词基本勾勒出了它的技术轮廓它通过一层代理proxy来拦截和优化编码代理与模型之间的通信减少不必要的 token 消耗同时保持代理完成任务的准确率。这篇文章适合谁看如果你正在用或者打算用编码代理来辅助日常开发并且对 token 成本敏感那这篇内容对你有直接参考价值。如果你只是想了解代理架构的设计思路里面关于 proxy 拦截、token 计量、上下文裁剪的部分也值得一读。我会尽量把原理讲透同时给出可以照着做的配置和排查方法。需要提前说明的是caveman 目前还是一个相对小众的项目公开文档不算丰富很多细节需要从实际使用中摸索。下面涉及的具体参数和配置一部分来自我自己的实测一部分是基于同类代理工具的通用实践做的合理推断我会在相应位置标注清楚。2. caveman 的代理层到底拦截了什么proxy 在编码代理链路中的位置2.1 编码代理的典型请求链路要理解 caveman 的价值得先搞清楚一个编码代理在干活时请求是怎么流动的。一个典型的链路是这样的你在编辑器或终端里给代理下达任务比如把 utils 目录下所有函数的错误处理统一改成 Result 类型。代理把任务拆解成若干步骤每一步都要构造一个 prompt里面包含系统指令、历史对话、当前文件内容、工具定义等。这个 prompt 被发往模型服务端模型返回下一步动作调用某个工具、读取某个文件、或者直接给出代码。代理执行工具把结果再拼进下一轮 prompt循环往复直到任务完成。问题就出在第 2 步和第 4 步。随着对话轮次增加历史上下文越滚越大每一轮都要把之前所有内容重新发一遍。一个十轮的任务token 消耗可能是指数级增长的。而且很多代理会把整个文件内容塞进去哪怕只需要改其中三行。2.2 proxy 拦截点的选择逻辑caveman 的做法是在代理和模型服务端之间插一层 proxy。这层 proxy 能看到每一轮请求的完整 payload于是就有了优化的空间。为什么选择在 proxy 层做而不是改代理本身的代码原因很实际代理工具五花八门有开源的、有商业的、有自己写的改源码成本高、维护难。proxy 是统一入口不管上游是哪个代理只要请求经过它就能统一处理。不侵入业务逻辑代理该怎么跑还怎么跑优化对它是透明的。这层 proxy 主要做几件事请求拦截与解析、token 计量、上下文裁剪、缓存命中判断、以及必要时的请求改写。下面这张表是我根据实测和同类工具实践整理的能比较清楚地看出每一层的作用拦截环节处理内容对 token 的影响请求解析拆出 messages、tools、system prompt无直接影响但为后续优化提供依据token 计量统计每轮 input/output token用于成本监控和阈值告警上下文裁剪移除冗余历史、压缩文件内容直接减少 input token缓存判断命中缓存则跳过模型调用直接省掉整轮消耗请求改写合并重复指令、精简工具定义减少固定开销2.3 一个容易被忽略的细节proxy 自身的开销很多人以为加了 proxy 就万事大吉但 proxy 本身也是有成本的。它要解析 JSON、要做字符串匹配、要维护缓存这些都会带来延迟。如果 proxy 写得不够高效或者部署在离模型服务端很远的机器上网络往返时间反而会拖慢整体响应。我的经验是proxy 最好部署在和代理同一台机器上走本地回环避免额外的网络跳转。如果代理本身是跑在容器里的proxy 也放在同一个容器网络里。这样虽然牺牲了一点隔离性但延迟能控制在毫秒级对交互体验几乎没有影响。另外proxy 的日志级别要控制好。调试阶段开 debug 没问题生产环境一定要降到 warn 或 error否则光是写日志的 IO 开销就够呛。我见过有人把每轮完整 payload 都打进日志文件跑一天下来日志几个 G磁盘直接告警。3. token 计量与成本控制把每一分钱花在刀刃上3.1 为什么 token 计量不能只看总数大部分代理工具都会给你一个 token 总数但那个数字太粗了。你只知道花了多少不知道花在哪。caveman 的 proxy 层可以把 token 拆得更细system prompt token这部分是固定的每轮都要发属于底噪。历史对话 token随轮次增长是主要的膨胀来源。工具定义 token如果代理注册了很多工具光工具描述就可能占几千 token。当前文件内容 token取决于代理读取策略有的代理很激进一次读整个仓库。模型输出 token这部分通常可控但推理型模型会输出很长的思考过程。把这五项分开统计之后你就能定位到真正的消耗大户。我实测过一个案例某代理在做一个中等规模重构时总 token 消耗约 12 万拆解后发现历史对话占了 6.8 万工具定义占了 2.1 万真正用于当前任务的不到 3 万。也就是说超过七成的 token 花在了上下文维护上而不是解决问题本身。3.2 上下文裁剪的三种策略针对历史对话膨胀caveman 这类 proxy 通常会提供几种裁剪策略你可以根据任务类型选择策略一滑动窗口。只保留最近 N 轮对话更早的直接丢弃。优点是实现简单、效果立竿见影缺点是可能丢掉关键信息导致代理失忆反复问已经回答过的问题。适合短平快的任务。策略二摘要压缩。把较早的对话用一个小模型或规则压缩成摘要保留关键结论丢弃过程细节。优点是信息保留度高缺点是需要额外调用模型有额外成本。适合长任务。策略三结构化提取。从历史对话中提取出已确认的事实已修改的文件待办事项等结构化信息用紧凑格式重新组织。优点是压缩率最高缺点是实现复杂需要针对不同代理定制。适合对成本极度敏感的场景。我个人的建议是混合使用最近 3 轮用滑动窗口原样保留3 到 10 轮用摘要压缩10 轮以上只保留结构化提取结果。这样在信息完整度和 token 成本之间能取得比较好的平衡。3.3 工具定义的瘦身技巧工具定义这块经常被忽视但其实很值得优化。一个代理如果注册了 20 个工具每个工具的描述加参数 schema 平均 150 token那就是 3000 token 的固定开销每轮都要发。优化方法有几个按需加载不是所有任务都需要所有工具。根据当前任务类型只把相关工具的定义放进 prompt。比如纯代码修改任务就不需要运行测试部署这类工具。精简描述工具描述写清楚用途和关键参数即可不需要长篇大论。很多开源工具的描述是从文档直接拷过来的啰嗦得很。合并同类工具如果有多个功能相近的工具考虑合并成一个带 mode 参数的工具减少定义数量。注意工具定义瘦身要谨慎描述太简略可能导致模型调用错误反而增加重试成本。建议每次精简后跑一组回归测试确认调用准确率没有明显下降。4. 代理行为优化让 caveman 少走弯路的实操配置4.1 代理循环的终止条件设置编码代理最容易失控的地方就是循环。它可能反复读同一个文件、反复尝试同一个失败的方案、或者在两个方案之间来回横跳。caveman 的 proxy 层可以设置一些硬性约束来打断这种循环最大轮次限制给每个任务设一个轮次上限比如 30 轮。超过就强制终止并返回当前进度。这个数字要根据任务复杂度调整简单任务 10 轮够了复杂重构可以放到 50 轮。重复动作检测如果代理连续 3 轮调用同一个工具、传同样的参数proxy 可以拦截并提示代理你已经做过这个操作了。无进展检测如果连续几轮没有产生文件修改、没有新增结论判定为无进展触发终止或降级策略。这些约束看起来简单但实际效果很明显。我在一个测试任务上对比过不加约束时代理跑了 47 轮才结束token 消耗 8.3 万加上轮次限制和重复检测后22 轮就完成了token 消耗降到 3.9 万任务结果质量没有明显差异。4.2 文件读取策略的调整代理读文件的方式对 token 影响巨大。有的代理默认读取整个文件一个 2000 行的文件就是几万 token。caveman 可以在 proxy 层对文件内容做处理按需截断如果代理只需要修改某个函数只把那个函数及其上下文发过去而不是整个文件。差异传输如果文件之前已经读过只发变化的部分。符号索引对于大文件先发一个符号列表函数名、类名、行号让代理按需请求具体内容。这里有个坑要注意截断策略不能太激进否则代理可能因为看不到完整上下文而做出错误修改。我的做法是保留目标函数前后各 20 行作为上下文这个范围在大多数情况下够用。4.3 缓存机制的落地缓存是省 token 的利器但要用对地方。caveman 的 proxy 层可以缓存几类内容模型响应缓存如果同样的 prompt 之前问过直接返回缓存结果。这在代理反复问同样问题时特别有用。文件内容缓存文件没变的话不需要重新读取和传输。工具结果缓存比如运行测试的结果如果代码没变结果应该是一样的。缓存的 key 设计很关键。prompt 缓存不能简单用字符串哈希因为 prompt 里可能包含时间戳、随机 ID 这类每次都变的内容。需要先把这些噪声字段归一化再计算 key。我一般会把 messages 数组做规范化处理去掉时间戳、把文件路径转成相对路径、对 JSON 字段排序然后再哈希。5. 实测中踩过的坑与排查链路5.1 proxy 启动后代理无响应一次完整的排查过程这是我最开始用 caveman 时遇到的第一个问题。proxy 启动看起来正常日志也显示在监听端口但代理发请求过去就是没反应一直卡在那里。排查过程是这样的第一步确认 proxy 是否真的在监听。用netstat -tlnp | grep 端口看了一下端口确实在监听。但注意监听地址是127.0.0.1还是0.0.0.0很关键。如果代理跑在容器里proxy 只监听回环地址容器是访问不到的。我第一次就是栽在这里改成0.0.0.0之后问题解决了一半。第二步确认请求是否到达 proxy。把日志级别调到 debug重新发请求发现日志里根本没有请求记录。说明请求在到达 proxy 之前就被拦住了。检查代理的配置发现它连的还是原来的服务端地址根本没走 proxy。这是配置没生效的问题重新加载配置后请求终于进来了。第三步确认 proxy 是否正确转发。请求进来了但代理还是没收到响应。看日志发现 proxy 在转发时超时了。原因是 proxy 配置的上游地址写错了把测试环境的地址写成了生产环境。改过来之后链路终于通了。这个排查过程给我的教训是proxy 类问题一定要分层排查从请求有没有发出到有没有到达 proxy到proxy 有没有正确转发到响应有没有回来一层层确认不要跳步。5.2 token 计量数字对不上计量口径的差异有一段时间我发现 proxy 统计的 token 数和模型服务端账单上的数字对不上proxy 统计的总是偏少。查了半天才明白是计量口径的问题。proxy 统计的是它看到的 payload 里的 token但模型服务端实际计费时还会算上一些 proxy 看不到的部分比如服务端自己加的模板 token、特殊标记等。另外不同模型的分词器不一样proxy 如果用的是通用分词器估算和实际分词结果会有偏差。解决办法是proxy 的统计只作为参考用于相对比较和趋势监控不要拿它当账单依据。真要精确对账还是以服务端返回的 usage 字段为准。如果服务端不返回 usage那就只能接受一定误差把 proxy 统计当作至少花了这么多的下限。5.3 上下文裁剪导致的代理失忆前面提到过滑动窗口策略可能丢信息我自己就踩过这个坑。有一次做一个跨多文件的重构代理在改了前三个文件后突然开始问你希望我用什么命名规范而这个问题在任务开始时已经明确回答过了。原因就是早期的对话被滑动窗口裁掉了。修复方法是调整裁剪策略对于涉及多个文件的复杂任务不能单纯用滑动窗口要保留关键决策点。我后来改成滑动窗口 关键信息锚点的混合策略把用户明确给出的约束、已确认的命名规范、已修改的文件列表这些信息单独提取出来每轮都带上。这样即使历史对话被裁了关键约束还在。5.4 常见问题速查表现象可能原因排查方向代理无响应proxy 监听地址不对检查 bind 地址和网络可达性请求未到达 proxy代理配置未生效确认代理的上游地址配置token 统计偏少计量口径差异以服务端 usage 为准代理反复问同样问题上下文被过度裁剪调整裁剪策略保留关键锚点proxy 延迟高部署位置远或日志过多本地部署降低日志级别缓存不命中key 包含噪声字段归一化后再计算 key6. 把 caveman 用出效果的几个关键习惯6.1 任务粒度要控制好caveman 这类优化工具在中等粒度任务上效果最好。任务太小proxy 的优化空间有限开销占比反而高任务太大上下文膨胀严重裁剪策略很难兼顾信息完整和成本控制。我的经验是把任务控制在一次能改 3 到 5 个文件、涉及 200 到 500 行代码这个范围。超过这个范围就拆成多个子任务每个子任务单独跑。这样虽然多了几次任务启动开销但每次的上下文都更干净总体 token 反而更省。6.2 定期 review proxy 的统计报告proxy 会积累大量统计数据这些数据是优化的重要依据。我一般每周看一次报告重点关注几个指标平均每任务 token 消耗、缓存命中率、上下文裁剪比例、代理平均轮次。如果发现某个指标异常就针对性排查。比如缓存命中率突然下降可能是最近的任务类型变了或者缓存 key 的计算逻辑被改动了。平均轮次突然上升可能是某个工具的描述改得不够清楚导致代理反复试错。6.3 不要过度优化这是我最想强调的一点。token 优化是有边际效应的优化到一定程度之后再压榨就会影响任务质量。我见过有人为了省 token把上下文裁得只剩几百 token结果代理频繁出错重试次数暴增总消耗反而更高。合理的做法是设定一个质量底线比如任务成功率不低于 90%在这个前提下再优化 token。如果优化导致成功率下降那就说明优化过头了要往回退。6.4 保留人工兜底通道不管 proxy 优化得多好总会有代理搞不定的情况。这时候要能快速切换到人工模式不要让代理在那里死循环。我的做法是在 proxy 层设一个熔断机制当检测到代理连续失败或轮次超限时自动暂停并把当前状态输出给人工由人来决定下一步。这个机制看起来简单但能省下大量无效 token。代理在死循环里每多跑一轮都是真金白银。早点熔断早点止损。7. 关于 caveman 这类工具的一点个人判断用了一段时间 caveman 之后我对这类代理优化工具的看法是它们解决的是真问题但不是银弹。token 成本高、代理行为不可控这些是当前编码代理的普遍痛点proxy 层的优化确实能缓解但根治不了。根本的解决还是要靠代理本身的设计改进——更聪明的上下文管理、更精准的工具调用、更好的任务规划能力。proxy 层能做的是外部约束在代理还不够聪明的时候帮它少犯点错、少花点钱。如果你现在就在用编码代理并且 token 成本让你肉疼那 caveman 这类工具值得一试。但别指望它能解决所有问题把它当作一个成本控制阀门就好。真正决定效果的还是你怎么设计任务、怎么配置代理、怎么根据反馈迭代。最后分享一个我自己的小习惯每次跑完一个比较大的任务我都会把 proxy 的统计报告和任务结果对照着看一遍想想哪些 token 是必须花的哪些是可以省的。这个复盘习惯坚持下来对代理的使用效率提升比任何工具都管用。