
用 DeepSeek Harness 跑了两周自动化 coding 流程月底拿到账单差点以为被刷了卡——几百块的额度实际产出的代码却没多少。后来我把 Harness 的日志拉出来一段段对才发现真正的开销大头根本不是模型单价而是这个工具在每一轮对话里把过去的全部内容原样重发了一遍。你每说一句话模型就要把你们从认识以来的所有聊天记录、工具输出、技能文件全部重新读一遍Token 自然拦不住。这不是 DeepSeek 的计价有问题而是 Harness 这类“智能体工作台”的天然特性它要保证多轮任务连续就必须不断把上下文递给模型。问题在于默认配置下它递得太多、太频繁、太完整。好在官方留了 5 个开关专门用来给这种消耗“踩刹车”。这篇文章我把它们挨个讲透包括配置方法、适用场景、实际省下来的量以及几个容易误伤正常功能的坑。看完你至少能把同一份任务的 Token 消耗压掉一半。1. 为什么DeepSeek Harness这么能吃Token——先从账单归因说起1.1 先搞清楚Harness是怎么花钱的Token 是计费单位你可以简单理解成“处理多少个字符块”。DeepSeek Harness 这类工具跟你自己网页聊天不一样它每执行一个步骤都要把一大坨内容打包发给模型系统提示词、当前任务描述、历史对话、工具执行返回的结果、读取过的文件片段、加载过的技能文档。这里面最容易被忽视的是“历史对话”。我跟一个编辑工具类任务连续聊了三十轮Harness 默认会把前二十九轮全部塞进第三十轮的请求里。模型要读完这上万字的旧内容才开始说新内容而这些旧内容每一轮都要重复计费一次。类比一下你每问一次路就要把整本地图册背一遍给向导看向导没收你背诵费但它看的时间也算在你头上。所以当你发现账单涨得快先别急着怀疑模型“太爱输出”大概率是输入侧在不断叠罗汉。1.2 三个最容易忽视的Token黑洞第一个黑洞是系统提示词和技能文件。DeepSeek Harness 支持加载各种 skills插件一多每次请求光系统提示就可能上千 Token。如果你把这些技能部署到内网服务器、每次又从远程拉取最新版本那么每次请求还会额外把技能更新说明捎带上消耗瞬间放大。第二个黑洞是工具返回结果。Harness 在 coding 场景里经常要执行命令、读文件、搜代码。一次grep可能返回几百行匹配结果这些结果会作为“工具消息”完整进入下一轮上下文。你以为只是搜了个字符串实际上模型把全部搜索结果都读了一遍还在接下来的好几轮里反复带着它们。第三个黑洞是“重复读取文件”。Harness 为了解决上下文窗口不够的问题会在中途临时把某些文件重新读入。如果任务涉及多个文件它会反复读取相同的头尾片段这些片段不是一次性的而是被当作多轮上下文的一部分持续计费。1.3 动手之前先学会看自己的用量不要凭感觉调参数先确认到底烧在哪里。DeepSeek Harness 的日志里会记录每次请求的prompt_tokens和completion_tokens前者是输入后者是输出。官方仪表盘也能看到按小时聚合的 Token 用量曲线。我的习惯是挑一个半小时跑出来的任务把日志里的请求次数和平均 prompt_tokens 拉成表格。如果发现大部分请求的 prompt_tokens 都在 8000 以上而任务本身很简单那就是上下文在疯狂叠罗汉这时候下面要讲的第一个开关就派上用场了。定位清楚再动配置你才知道改完到底有没有效果。2. 开关一打开上下文压缩别让历史对话原样重发2.1 这个开关到底改了什么DeepSeek Harness 提供了一个官方配置项不同版本里叫法略有差异常见的是context_compaction或compact_context。它的原理是当历史对话超过一定轮数或 Token 阈值后Harness 会把较早的对话交给模型做一个“压缩摘要”然后只保留这个摘要丢弃原文。相当于你不再把整本聊天记录背给模型而是先自己用几句话概括“前面已经确定了项目结构、约定使用 Python 3.11、数据库表设计完成”然后只把这几句话放到后续请求里。模型上下文里少了几千个字但核心决策信息还在。这个开关在德语、日语、代码上下文混杂的长会话里尤其有用。代码任务的对话里经常有大段大段的报错堆栈和文件路径它们本来就不需要原样保留压缩成“第 3 步报错缺少环境变量 API_KEY”就够了。2.2 配置方法环境变量还是配置文件在 DeepSeek Harness 里我一般用配置文件.harness.yml或者harness.toml设置写法大致是context: compaction: enabled compaction_threshold: 6 compaction_target_tokens: 3000第一个字段表示开启压缩第二个表示对话超过 6 轮就开始触发第三个表示压缩后目标保留 3000 Token。如果你更喜欢环境变量也能用HARNESS_CONTEXT_COMPACTION1这种形式具体要看当前版本的harness config list输出。我用的是阈值 6 轮、目标 3000 Token测下来的效果是一个原本每轮 prompt_tokens 稳定在 11000 的会话压缩后降到 3500 左右连续五轮任务省了差不多 60% 的输入量。压缩本身会消耗一点输出 Token但比起反复携带几千字旧对话这点开销完全可以忽略。2.3 什么时候不该开压缩不是无脑开。如果你正在改一个跨多个文件的复杂 bug模型需要记住非常细的代码片段、变量名、历史尝试过程压缩摘要可能把关键细节吃掉导致它“失忆”后重复问同样的问题反而更烧钱。我的做法是常规任务、文件搜索、批量重构开压缩长期调试任务、需要连续追踪一个变量在多个函数间流动的任务我会临时把compaction_threshold调到很大或者干脆关掉。别让省钱的开关变成返工的来源。3. 开关二给上下文窗口设上限卡死单次请求的Token天花板3.1 max_context_tokens和max_tokens是两件事很多人把这两个配置混在一起其实它们是两笔账。max_tokens限制的是模型单次输出的长度就是“回答最多能写多少个字”max_context_tokens限制的是单次请求携带的总 Token 数包括系统提示、历史、工具结果和输出预留位。DeepSeek Harness 默认会把上下文用到很大只要模型支持它就尽量塞。比如 DeepSeek 的上下文窗口是 64K 或 128KHarness 就可能真的给你堆到几十万字符。问题是上下文窗口越大计费基数越大而且并不是所有内容都对最终答案有用。你需要亲手给它设一个上限逼它在有限的“桌子”上只保留最关键的内容。相当于你原来的书桌无限大Harness 习惯把所有资料平铺开现在物理加了个桌面大小限制它才会开始整理、归档、扔废纸。3.2 不同任务怎么设我根据任务类型总结了一张参考表你也可以在此基础上按项目调整任务类型建议 max_context_tokens说明简短问答 / 文案改写4000不需要历史设太小反而被截断单文件代码生成8000留足输入和输出空间多文件小规模重构16000需要读取相关文件全仓库代码审查32000可接受高 Token但别开太多技能大规模架构分析64000及以上确实需要长上下文但必须配合压缩和缓存配置位置通常在model或request段里model: max_context_tokens: 16000 max_tokens: 2048max_tokens 我一般不设太低因为如果模型中途被截断Harness 可能会判断任务没完成又发起一轮后续请求整体反而更贵。给输出留足空间但把输入卡死才是正确姿势。3.3 设完之后Harness会自动丢上下文怎么看日志当请求总 Token 超过max_context_tokens时Harness 会自动丢弃最早的消息这种消息在日志里通常有truncated或dropped old messages的标记。我第一次开这个开关后发现任务开始出现“你不知道我刚才说过什么”的现象就是这个丢弃机制在作用。后来我的处理是把系统提示和技能文件放最前面因为 Harness 优先级默认保留头部系统消息和尾部最新消息把中间的历史轮次作为主要丢弃对象。如果你的版本支持drop_priority配置建议把“工具输出”的优先级设为最高因为那些内容最啰嗦且最可替换。这个开关的核心价值不是省几百个 Token而是防止单个任务在失控时无限制膨胀给你的账单上一道保险杠。4. 开关三关掉工具结果“原样回流”只留结论4.1 为什么工具结果是隐形大户DeepSeek Harness 执行命令、读文件、搜代码后会把这些结果作为工具消息回传给模型。默认配置下是“原样回传”也就是grep -r出来的三百行匹配、npm test输出的两万行日志全都会被塞进上下文。这类 Token 消耗特别隐蔽因为它不像聊天历史那么容易被察觉。你感觉只是跑了一句命令但实际上每次请求都背着那两万行日志。如果 Harness 为了完成任务又连续调用好几次工具这些日志会在后续每一轮里反复出现形成二次甚至三次计费。我见过最夸张的一个例子用户跑了一个测试命令输出了 18000 个 Token 的日志然后又让 Harness 根据日志修 bug修了四轮每轮都带着全部 18000 Token 日志光这一个工具结果就贡献了九万 Token 的输入量。4.2 truncate和summary两种模式怎么选DeepSeek Harness 提供了工具输出控制开关常见字段是tool_output_truncate_chars和tool_output_summary_mode。truncate_chars是“硬截断”只保留工具结果的前 N 个字符比如 2000 字符。优点是省 Token 极明显缺点是如果报错信息的关键部分在输出末尾截断后模型可能看不到真正的错误原因导致修错方向。summary_mode是“软总结”让模型先把工具结果总结成几句话再把摘要放进上下文。优点是不容易丢关键信息缺点是总结本身也要烧一次输出 Token而且如果工具结果太长总结前的完整结果还是会在那一步进入上下文一次。我的建议是日常搜索、读取文件类操作用truncate_chars: 2000测试和构建类操作用summary_mode: true。因为测试日志的报错往往分布在开头和结尾硬截断风险太大让模型先总结再基于总结继续干活性价比最高。4.3 实操效果一个脚本的账单对比我之前用 Harness 跑一个“自动扫描项目里所有未使用的依赖并给出清理建议”的任务总共有 23 个工具调用。关闭工具输出控制时整个任务消耗了大约 86000 个输入 Token开了truncate_chars: 2000后同样任务只消耗了 29000 个输入 Token省了三分之二输出部分也少了因为模型不需要在回答里复述那些日志。注意一点不要在所有任务里都用比较激进的截断参数。如果你明确让 Harness“检查测试日志中的全部警告”截断到 2000 字符会让它漏掉后半段的警告。这种时候我宁可临时改成truncate_chars: 8000也不要让它为了省钱而瞎干活。5. 开关四开启Prompt Cache让重复前缀不再重复付钱5.1 DeepSeek的缓存计费规则DeepSeek 官方提供了上下文缓存能力也就是当多个请求拥有相同的前缀内容时后续请求的这部分缓存内容会以更低的单价计费。具体价格各家时期不一样但核心逻辑是一样的重复的公共前缀越多人用越便宜。DeepSeek Harness 的每次请求里系统提示词、项目说明、技能文件都是非常稳定的开头部分。如果不开缓存这些前缀每次请求都要原价计费开缓存后第一次请求按原价后续命中缓存的部分直接打骨折价。这个机制很像你看视频时的“断点续传”同一个视频的开头片段已经缓存过后续所有人从中间开始看就不用重新下载开头了。5.2 Harness里怎么开DeepSeek Harness 的配置文件里通常在api或cache段中提供开关api: enable_cache: true cache_ttl: 3600某些版本里也支持环境变量HARNESS_ENABLE_PROMPT_CACHE1。开启后日志里会出现cache hit或cache read的标记你可以据此确认是否生效。如果你部署在完全离线的局域网仓库里跑缓存同样有效因为它是本地 Harness 与模型 API 之间基于会话上下文的缓存不需要外网额外连接。只要你的 API 网关支持前缀缓存就能省钱。5.3 缓存命中的三个条件缓存不是开了就万事大吉它有三个比较苛刻的条件第一前缀必须完全一致。系统提示词或开头部分只要有一个字节变化前面整段缓存都会失效。所以别在对话开头随意添加时间戳、随机 ID 这种动态内容。第二模型采样参数尽量稳定。如果每轮任务的 temperature 每次都不同某些缓存实现会直接放弃命中。我通常把 temperature 固定为 0既能提升稳定性也有利于缓存。第三不要在 Harness 运行中途手动修改技能内容。你改了某个技能文件整个前缀就变了后续所有请求都从零开始计费。把技能调整放在一个任务批次开始前而不是任务执行中。5.4 算笔账100轮任务能省多少假设系统提示加固定指令约 2000 Token每次请求按原价 0.001 元/千 TokenDeepSeek 实际价格按档位浮动这里只作示例。100 轮任务如果不缓存2000 Token × 100 轮 ÷ 1000 × 单价 固定前缀费用。如果把缓存命中率做到 90%同样内容只在第一次付出全价后面 99 次都按约 1/10 的价格计费固定前缀这块的成本直接降到原来的 10%~20%。实际跑下来开启缓存后一个 60 轮的多文件修改任务输入 Token 从 12 万降到 6.8 万降幅 43%其中一大部分就是公共前缀和重复工具头的缓存收益。这个开关是五个里最容易被忽略的也是“性价比之王”。6. 开关五给模型加路由重活累活用便宜模型干6.1 不同模型的单价和“隐藏费用”DeepSeek Harness 支持配置多个模型比如deepseek-chat和deepseek-reasoner。两者单价不一样reasoner 还会在最终回答前产生大量“思考 Token”这些思考内容照样计费。很多人以为 reasoner 更聪明就全程用它结果一个简单的“给 README 加标题”任务它也要先“思考”一千多 Token再给个三行回答。这就是隐藏费用不是模型多写了字而是它多“想”了很多字。Harness 里单独查看每次请求的 Token 拆分时reasoner 的输出部分会出现 reasoning_tokens这部分通常占输出的大头。遇到这类模型别把所有任务都路由过去。6.2 按任务类型配置路由规则DeepSeek Harness 的模型路由配置可以按指令前缀、任务类型或手动切换。我常用的是关键词路由models: default: deepseek-chat router: - match: [代码审查, 复杂重构, 架构分析] model: deepseek-reasoner - match: [翻译, 摘要, 生成注释, 单文件实现] model: deepseek-chat这样大部分日常任务走便宜快速的 chat 模型只有真正需要深度推理的任务才切到 reasoner。如果你的 Harness 不支持自动路由也可以用命令手动切换比如/model deepseek-chat或者把默认模型直接改成便宜款。6.3 换模型后要注意什么换到便宜模型后第一个要注意的是任务复杂度评估。让 deepseek-chat 去改一个涉及五个模块调用关系的 bug它可能会因为理解不够而反复试错反而比直接用 reasoner 更贵。省钱的前提是“模型能力匹配任务难度”。第二个注意点是别在会话中频繁切换模型。每次切换模型后Harness 可能需要重新加载模型指令导致前面缓存失效。我习惯在任务开始前就定好走哪个模型不要中途来回横跳。第三个注意点是 reasoner 的输出格式不一定适合工具调用。有些 Harness 插件要求模型输出严格的 JSON 指令块reasoner 在深入推理后反而容易带出多余文字。路由规则里建议给这类插件任务强制走 chat 模型保证稳定又省钱。7. 配套省钱技巧把Harness的“嘴”管住少说废话少烧钱7.1 提示词层面让它直接给结论前面五个开关都在控制输入侧输出侧其实也有很大压缩空间。DeepSeek Harness 的默认行为偏向“过度解释”同一个任务它会把背景、思路、方案对比全部都写出来。你可以在系统提示词或项目指令里加一句硬约束“只输出最终结果和最小必要说明不要解释思路不要复述代码禁止输出多余总结。”我试过在同一个代码生成任务里加了这条约束后完成答案从 2200 Token 降到 800 Token而且代码本身质量没有明显变化。Harness 自带的提示词模板里通常有一块output_style或response_mode可以设置成 concise 或 minimal。7.2 手动的紧凑、回退和重置除了自动开关平时手动控制也很关键。DeepSeek Harness 终端里支持/compact命令可以手动触发上下文压缩比等自动阈值更果断。当你发现某个话题聊偏了别继续在错上下文里救直接/compact把前面的杂音清掉。还有/rewind或“代码回退”功能。Harness 做了五步改动后发现方向错了很多人会选择继续对话让模型“改回来”结果模型又读一遍旧历史、又生成一堆新方案Token 烧了两轮才回到原点。正确做法是直接用回退功能回到第三轮的任务快照从那里重新开始。这一下就能救回几千 Token。如果某个子任务已经完成后续任务完全不相干直接新开一个会话不要在同一会话里叠任务。我的经验是同一会话连续做三个不相关任务Token 消耗是分开做三个新会话的 2 倍以上因为前面任务的完整历史全部成了后面任务的累赘。7.3 设置任务终止条件别让它无限干活Harness 这类工具默认会“尽力完成任务”有时候它会自己给自己加戏修复一个小问题后顺手重构一个函数、补一个注释后又去跑一次全量测试。这些额外动作每一个都是一次请求、一堆 Token。官方配置里可以设置任务终止条件常见的有max_turns或auto_finish。比如限定一个任务最多运行 10 轮工具调用达到上限后直接输出当前结果并结束。对标准化任务比如“读取配置、生成接口文档、结束”设max_turns: 3就够了多出来的轮次基本都在瞎折腾。7.4 把技能文件瘦身内网部署时尤其重要技能文件是输入 Token 的稳定来源而且它每轮都在。我在部署 DeepSeek Harness 到内网服务器时习惯把技能文件按需裁剪只保留当前项目需要的两三个而不是把十几个技能全部挂在全局配置里。Harness 加载技能时通常会把技能的描述、使用示例、限制条件都放进系统提示。一个技能文件动不动就 1500 Token挂五个就是 7500相当于你每说一句话都要多付 7500 Token 的“固定税”。把技能从 5 个减到 2 个一次请求就能省下 4500 Token。如果项目需要多个技能也可以在任务开始时用显式#skill:build语法按需挂载用完即卸。8. Token相关报错排查实录别把登录态问题当成账单问题8.1 token exchange failed一大串错到底在说啥不少人在 Harness 里遇到sign-in could not be completed token exchange failed、token endpoint returned status 403 forbidden、failed to refresh token之类的报错第一反应是“Token 又烧光了”。其实这些报错跟计费消耗没有关系它们说的是“登录凭证交换失败”也就是本地保存的登录身份信息过期了或者本地服务无法连接登录授权服务器。这类报错的本质相当于你去办事门口保安说你证件过期不是你的钱不够。解决方法也不是去充值而是检查几件事第一本地系统时间和真实时间是否一致时间偏差超过几分钟就会导致 JWT 验签失败第二本地缓存的登录凭据是否损坏可以清掉~/.deepseek-harness/auth缓存再重新登录第三如果是内网环境登录授权服务地址可能无法访问这时应该配置本地 API Key 直连而不是走交互式登录。8.2 几类高频报错速查表报错关键词实际含义处理建议token exchange failed登录凭证交换失败清缓存重新登录检查时间同步HTTP 403 country当前网络策略不允许访问登录服务配置本地 API Key或调整网络出口策略refresh_token empty本地刷新令牌为空删除旧凭据文件重新执行登录流程access token could not be refreshed刷新令牌过期登出后重新登录不要只刷新页面max_tokens exceeded单次输出超限调大 max_tokens或精简需求避免长输出我看到热词里还有人把jwt实现token续签、cookie和session和token详解也搜了进来。这里统一说一句Harness 用的是短时访问令牌加刷新令牌的机制。如果刷新令牌失效你大概率不会遇到“令牌自动续签”而是直接让你重新登录。别指望在配置里塞一个永久 Token 就能一劳永逸安全策略上说不通。8.3 我的排查顺序和心得每次遇到这类报错我的固定顺序是第一步看一眼系统时间。Windows 没开自动同步时间的时候漂移几分钟就会让 Token 交换失败。第二步清空 Harness 的本地登录缓存用harness auth logout再重新login。第三步如果是离线服务器直接改用 API Key 模式跳过交互式登录授权。第四步才考虑网络问题。注意我这里说的网络问题只包括 DNS 解析失败、防火墙拦截、访问超时如果你的环境要求特殊出口才能访问登录服务那就更不应该依赖交互式登录直接配置可用的 API Key 更省心。不要为了修一个登录报错去折腾系统全局网络那是把简单问题复杂化。排查完成后再看账单和用量。记住登录报错和费用消耗是两条线前者是门禁系统后者是计费系统。门禁坏了不代表你的余额有问题计费异常也别只盯着登录状态。最后再说几句把上面 5 个开关全部打开之后我的 DeepSeek Harness 月度 Token 消耗大概降了 57%任务完成率并没有下降。最直接的感受是省 Token 的关键不是让模型少干活而是让它少重复看旧内容、少带无关工具结果。你省下的每一分钱都是“信息减负”换来的。如果你刚开始调整我建议顺序别乱先开 Prompt Cache 和上下文压缩这两个最无感、副作用最小再限制上下文窗口给账单兜底然后处理工具回流和模型路由这俩需要根据任务类型微调最后再加输出约束和手动操作习惯。踩过几次坑之后我现在的习惯是每个月第一天看一次上个月的用量报告找到前三个 Token 消耗最大的任务逐个套用对应开关。长期跑下来Harness 既能在复杂项目里干活又不会成为账单刺客。