
1. 从 HarnessTax 这类对照实验说起同 Key 双跑才是可复现起点当你把 Claude Code 的ANTHROPIC_BASE_URL改成 TaoToken 的https://taotoken.net/api再跑 SWE-bench Lite 时最先遇到的往往不是模型答错而是401 invalid x-api-key或404 not foundBase URL 多写或少写了路径。要从同一把 Key 出发对比 Claude Code 与 Pi 的 Token 消耗先到 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_intro 创建 Key。本文不讨论“哪个模型更强”而是把 harness 当作变量同一个模型、同一把 TaoToken Key、同一批 SWE-bench Lite 任务分别交给 Claude Code 和 Pi 执行记录每次请求的 input、output、cache 与最终测试结果看看 Token 差值到底来自哪里。近期关于 HarnessTax 的讨论把这个问题推到了台前同一个模型换一个 coding agent harness系统提示、工具 schema、上下文裁剪、重试策略、失败回滚都会变。最终结果不只是“成功率高低”还包括“为了通过同样测试多花了多少 Token”。TaoToken 在这里只提供 Key 与 Base URL不参与评测也不改变 harness 的行为。因此如果你想复现类似对照必须自己控制变量同一把 Key、同一个模型 ID、同一套任务、同一轮重试策略。否则你看到的 Token 差异可能只是模型不同或限流重试造成的假象。这篇文章会给出四个可落地产物第一Claude Code 接入 TaoToken 的settings.json与 CC Switch 三件套配置第二Pi 接入同一把 Key 时先确认协议、再落环境变量的做法第三一个双跑脚本把同一批 SWE-bench Lite 任务分别喂给两个 harness第四一张 Token 差值表和一段样例任务日志告诉你从哪些字段读出“谁更省”。文末还有从模型对话、Coding Plan、创建 Key 到 Claude Code 文档的完整路径。需要提前说明Token 消耗低不等于更好。一个 harness 可能因为少读文件、少调用工具而省 Token但补丁没通过测试另一个 harness 可能多轮探索、重复读文件Token 花得多却把问题修好了。因此本文的比较口径是“通过测试的 Token 成本”而不是单次调用谁更短。2. 先拿一把同源 KeyTaoToken 控制台与 Base URL 的配置边界同 Key 双跑的第一步不是装 harness而是把供应商入口固定下来。你可以在 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_key 进入控制台在 API Keys 页面创建一把用于本次对照的 Key。建议单独建 Key不要和日常开发混用这样后面从 TaoToken 侧看请求日志时能清楚区分哪些调用来自 Claude Code哪些来自 Pi。创建入口在这里https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_keys 。拿到 Key 后先确认两件事模型 ID 以 TaoToken 模型详情页为准不要凭记忆写claude-sonnet-4-5或别的名字。模型对话页可以用来核对当前可用模型https://taotoken.net/models/detail/chat?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_model 。Base URL 在工具配置里统一写https://taotoken.net/api不要带 UTM 参数。UTM 只用于官网跳转统计不要写进ANTHROPIC_BASE_URL、OPENAI_BASE_URL或config.toml。Claude Code 常见环境变量如下。注意这是 Claude Code 的配置方式不要把它复制到 Codex CLI。Codex CLI 用config.toml命名和读取方式不同。# Claude Code 侧环境变量示例 export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_AUTH_TOKENYOUR_API_KEY export ANTHROPIC_MODELYOUR_MODEL_ID如果你更习惯用settings.json可以把它放在 Claude Code 的配置目录中。下面是一个最小示例YOUR_API_KEY和YOUR_MODEL_ID需要替换{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_MODEL: YOUR_MODEL_ID } }这里有一个常见坑有些环境里ANTHROPIC_API_KEY和ANTHROPIC_AUTH_TOKEN同时存在Claude Code 可能优先读取其中一个导致你改了 A 却实际走了 B。排障时先运行env | grep ANTHROPIC看清楚当前 shell 里到底有哪些变量再决定改哪一个。另一个坑是 Base URL 结尾斜杠。https://taotoken.net/api和https://taotoken.net/api/在部分工具里会被拼成不同路径前者通常更稳。如果你使用 CC Switch 管理多个供应商建议把“三件套”分开全局settings.json放默认 Base URL、默认模型、默认 Key 引用。项目级.claude/settings.json只放项目相关覆盖项不要放长期 Key。shell 环境变量放临时实验变量例如本次对照专用的ANTHROPIC_MODEL。切换供应商时只改 Base URL 和 Key不要把 Pi 的配置混进 Claude Code也不要把 Claude Code 的ANTHROPIC_*套到 Codex CLI。后面如果要加 Codex CLI 作为第三个 harness它应该单独走config.toml。3. 把 Claude Code 接到 TaoTokensettings.json 与 CC Switch 三件套Claude Code 的接入重点是“入口正确 模型名正确 环境干净”。先验证 CLI 能启动claude --version然后做一次最小对话测试。建议不要一上来就跑 SWE-bench Lite先用一个短提示确认请求能到达 TaoTokenclaude -p 只输出当前配置的模型名和 base url 是否已设置不要执行其他命令 --output-format json如果返回401优先检查 Key 是否完整、是否多复制了空格、ANTHROPIC_AUTH_TOKEN是否被其他变量覆盖。如果返回404优先检查 Base URLClaude Code 通常使用https://taotoken.net/api不要手动追加/v1/messages除非文档明确要求。如果返回模型不存在去 TaoToken 模型详情页核对模型 ID不要用站外文章里的旧模型名。settings.json的推荐写法是分层覆盖。下面这个示例假设你已经在 shell 里导出了TAOTOKEN_API_KEY避免把 Key 明文写进 JSON{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: ${TAOTOKEN_API_KEY}, ANTHROPIC_MODEL: YOUR_MODEL_ID } }注意不同版本的 Claude Code 对${VAR}展开支持不同。如果发现没有展开直接在本地 shell 导出变量或者使用 CC Switch 的密钥引用能力。不要把真实 Key 提交到 Git 仓库。CC Switch 三件套的操作顺序可以这样理解先在 shell 里导出本次实验专用的TAOTOKEN_API_KEY和TAOTOKEN_MODEL。在全局settings.json里写ANTHROPIC_BASE_URL与ANTHROPIC_MODEL。在项目级.claude/settings.json里只覆盖任务相关配置例如允许的工具、最大轮次、工作目录。跑claude -p时观察输出 JSON 里的usage字段。如果 Token 异常高先检查是否有历史会话被重复注入再检查工具调用是否陷入循环。Claude Code 的 harness 行为会显著影响 Token它会根据任务自动决定读哪些文件、跑哪些命令、什么时候总结。你要记录的不只是最终答案还包括中间工具调用次数。建议在双跑脚本里把stdout和stderr分开保存后面用usage字段和 TaoToken 侧日志交叉核对。如果你同时想跑 Codex CLI 作为对照记住它不读ANTHROPIC_*。Codex CLI 的config.toml应该单独写例如model YOUR_MODEL_ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat这段只用于 Codex CLI。不要把 Claude Code 的ANTHROPIC_BASE_URL写进这里也不要把 Codex 的model_provider写进 Claude Code 的settings.json。变量隔离是双跑实验可信的前提。4. 把 Pi 接到同一把 Key先确认协议再落配置Pi 作为 harness接入方式取决于它当前版本支持哪种协议。不要直接套用 Claude Code 的配置文件也不要假设它一定读取ANTHROPIC_*。正确顺序是运行pi --help或查看其本地文档确认它支持 OpenAI 兼容、Anthropic 兼容还是两者都支持。确认配置入口是环境变量、配置文件还是命令行参数。用同一把 TaoToken Key但只改 Pi 需要的那组变量。先用一句短提示验证请求能通再跑 SWE-bench Lite。如果 Pi 走 OpenAI 兼容可以用下面这组环境变量作为起点# Pi 若走 OpenAI 兼容协议 export OPENAI_API_KEYYOUR_API_KEY export OPENAI_BASE_URLhttps://taotoken.net/api export OPENAI_MODELYOUR_MODEL_ID如果 Pi 走 Anthropic 兼容协议则用它自己的变量名通常接近# Pi 若走 Anthropic 兼容协议 export ANTHROPIC_AUTH_TOKENYOUR_API_KEY export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_MODELYOUR_MODEL_ID再次强调上面两组变量不要同时导出到同一个 shell。否则 Pi 可能读到错误的协议入口表现成404或模型名不识别。最稳妥的做法是为 Claude Code 和 Pi 分别开两个终端或者用两个.env文件在脚本里显式加载。Pi 的 harness 风格可能和 Claude Code 不同。它也许更依赖本地工具、更少把完整文件内容塞进上下文或者相反更倾向于多轮探索。因此你不能只看“第一次请求的 input tokens”。要记录完整任务生命周期内的总消耗包括系统提示与工具 schema 的固定开销。每轮读文件、跑命令、看 diff 的增量。失败重试与上下文重放。最终补丁生成与总结。如果 harness 支持缓存还要看 cache read 与 cache creation。在接入完成后先用同一句短提示分别跑 Claude Code 和 Pi确认两者都返回正常结果再进入任务级对照。短提示测试的意义是排除 Key、Base URL、模型名这三类低级错误避免把接入失败误判成 Token 消耗差异。5. 双跑脚本同一批 SWE-bench Lite 任务同一把 Key分别跑 Claude Code 与 Pi下面给出一个可复用的双跑脚本框架。它不绑定具体 Pi 子命令而是把 Pi 命令抽成PI_CMD你按自己的 Pi 版本填入正确命令。脚本会为每个任务、每个 harness 建独立目录保存标准输出和错误日志。后续你可以从 Claude Code 的 JSON 输出、Pi 的日志、以及 TaoToken 控制台请求记录三个地方汇总 Token。先准备tasks.jsonl每行至少包含instance_id和problem_statement。SWE-bench Lite 的完整任务还需要仓库、base commit、测试补丁等但本文只关注“同一提示分别交给两个 harness”的 Token 对照所以先用最小字段跑通框架。#!/usr/bin/env bash set -euo pipefail # 同一把 TaoToken Key export TAOTOKEN_API_KEY${TAOTOKEN_API_KEY:-YOUR_API_KEY} export TAOTOKEN_MODEL${TAOTOKEN_MODEL:-YOUR_MODEL_ID} # Claude Code 侧 export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_AUTH_TOKEN$TAOTOKEN_API_KEY export ANTHROPIC_MODEL$TAOTOKEN_MODEL # Pi 侧按你的 Pi 实际协议二选一 # OpenAI 兼容 export OPENAI_API_KEY$TAOTOKEN_API_KEY export OPENAI_BASE_URLhttps://taotoken.net/api export OPENAI_MODEL$TAOTOKEN_MODEL # 如果你的 Pi 读取 anthropic 变量请改为对应变量并避免和上面同时导出 # export ANTHROPIC_AUTH_TOKEN$TAOTOKEN_API_KEY # export ANTHROPIC_BASE_URLhttps://taotoken.net/api PI_CMD${PI_CMD:-pi} # 如果你的 Pi 可执行文件不是 pi请改这里 TASKS_FILE${TASKS_FILE:-tasks.jsonl} OUT_DIR${OUT_DIR:-runs} MAX_TURNS${MAX_TURNS:-1} run_harness() { local harness$1 local task_id$2 local prompt$3 local outdir${OUT_DIR}/${harness}/${task_id} mkdir -p $outdir case $harness in claude-code) claude -p $prompt \ --output-format json \ ${outdir}/stdout.json \ 2 ${outdir}/stderr.log ;; pi) # 这里以 -p 为例请按 Pi 官方文档替换为正确的非交互参数 $PI_CMD -p $prompt \ ${outdir}/stdout.log \ 2 ${outdir}/stderr.log ;; *) echo unknown harness: $harness 2 exit 1 ;; esac } while IFS read -r line; do task_id$(printf %s $line | python3 -c import sys,json; print(json.load(sys.stdin)[instance_id])) prompt$(printf %s $line | python3 -c import sys,json; print(json.load(sys.stdin)[problem_statement])) run_harness claude-code $task_id $prompt run_harness pi $task_id $prompt done $TASKS_FILE这个脚本只解决“双跑”和“日志落盘”。要得到 Token 差值表你还需要一个汇总脚本。Claude Code 如果返回 JSON通常可以在usage字段里看到 input、output、cache 相关计数。Pi 如果不直接输出 usage就用 TaoToken 控制台的请求日志按时间窗口匹配。下面是一个汇总表模板instance_idClaude Code inputClaude Code outputClaude Code cachePi inputPi outputPi cacheClaude Code 通过Pi 通过Token 差值备注django__django-xxxxx回填回填回填回填回填回填是/否是/否以通过测试为口径sympy__sympy-xxxxx回填回填回填回填回填回填是/否是/否检查重试次数astropy__astropy-xxxxx回填回填回填回填回填回填是/否是/否检查缓存命中注意不要在表格里写来源不明的“倍数”“总量”“排名”。这张表的价值是让你自己跑出来的数据可追溯。每个数字都应该能在runs/目录或 TaoToken 控制台日志里找到对应记录。如果你要把结果写成结论建议至少记录三列total_tokens input output cache_creation cache_read、test_passed、retry_count。然后把任务分成两类比较一类是两个 harness 都通过另一类是只有一个通过。前者适合比 Token 效率后者更适合分析 harness 行为差异。6. 样例任务日志怎么读从 usage 字段到 harness 行为差异下面是一段 Claude Code JSON 输出的样例结构。数字字段用占位符表示实际值请从你的日志中读取{ type: result, subtype: success, result: 已生成补丁并运行目标测试, usage: { input_tokens: input_tokens, cache_creation_input_tokens: cache_creation_input_tokens, cache_read_input_tokens: cache_read_input_tokens, output_tokens: output_tokens }, num_turns: num_turns, duration_ms: duration_ms }读这段日志时不要只看input_tokens。更合理的总消耗近似为total_tokens ≈ input_tokens output_tokens cache_creation_input_tokens cache_read_input_tokens如果 harness 支持缓存cache_read_input_tokens可能代表复用了之前的前缀它不完全等同于新输入。你要看的是“本次任务实际新增了多少上下文”。在某些 harness 里多轮工具调用会把历史结果反复放回上下文导致 input 累加很快在另一些 harness 里工具结果会被摘要或裁剪单轮 input 更小但可能因为信息不足而多跑几轮。Pi 的日志格式可能不同。如果它输出的是普通文本你可以从两个地方补 Token 数据TaoToken 控制台的请求日志按时间窗口匹配 Pi 运行期间产生的请求。Pi 的详细模式如果支持--verbose或调试日志查看每次请求的原始 usage。分析差异时可以按下面四个方向归因系统提示与工具 schemaClaude Code 和 Pi 对工具的描述长度不同固定 input 开销不同。文件读取策略是整文件读入还是按符号/片段读取是并行读还是串行读。上下文管理历史消息是全部保留还是摘要、截断、分层压缩。重试与验证测试失败后是重新生成补丁还是只改一行是否重复跑同一命令。一个很常见的现象是Claude Code 在某类任务上 output tokens 更高因为它会写较长的计划、解释和总结Pi 可能 output 更短但在多轮工具调用后 input 累积更多。最终谁省 Token要看任务是否通过。如果 Pi 省了 20% Token 但测试没通过那这个节省没有意义如果两者都通过Claude Code 多花了 Token 但重试次数更少那它的“稳定成本”可能更低。样例日志的用途不是得出一个永恒结论而是让你能复盘。建议每个任务保留三个文件runs/ claude-code/ instance_id/ stdout.json stderr.log pi/ instance_id/ stdout.log stderr.log summary.csv然后把summary.csv用表格工具打开按test_passed过滤再按total_tokens排序。这样你得到的才是“在自己的环境、自己的 Key、自己的任务子集”上的结论。7. 常见报错与排障401、404、429、模型名映射同 Key 双跑时报错最容易把实验带偏。下面按错误码整理排查顺序。401 invalid x-api-key或401 unauthorized检查YOUR_API_KEY是否替换是否有多余空格。检查 Claude Code 侧是否同时存在ANTHROPIC_API_KEY和ANTHROPIC_AUTH_TOKEN两者冲突时先清掉一个。检查 Pi 侧是否错误地读取了另一个 shell 的 Key。确认 Key 没有过期或被删除。404 not found检查 Base URL 是否写成https://taotoken.net/api不要手动拼/v1/messages。检查是否把 UTM 参数写进了工具配置。UTM 只用于浏览器跳转不要写进ANTHROPIC_BASE_URL或OPENAI_BASE_URL。检查 Pi 的协议OpenAI 兼容和 Anthropic 兼容的路径可能不同混用会 404。429 too many requests这是限流不是 Token 消耗本身。重试会放大请求数进而放大 Token 统计。双跑脚本要记录retry_count否则你比较的可能是“谁被限流得更少”。如果是同一把 Key 同时跑两个 harness建议串行执行或者至少错开时间窗口。模型名映射错误不要用旧文章里的模型名。去 TaoToken 模型详情页确认当前模型 IDhttps://taotoken.net/models/detail/chat?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_model 。Claude Code 的ANTHROPIC_MODEL、Codex CLI 的model、Pi 的OPENAI_MODEL或对应变量三者要分别核对。如果模型名正确但提示不支持 tools检查协议是否匹配有些模型只在特定协议下支持工具调用。除了错误码还有一个隐性坑shell 环境污染。你在 A 终端导出了 Claude Code 的变量又切到 B 终端跑 Pi但 B 终端继承了 A 的ANTHROPIC_*于是 Pi 走了错误入口。解决办法是每个 harness 单独开终端或者在脚本里显式env -i清理再注入本 harness 需要的变量。8. 结论与可复用清单把“谁更省 Token”变成自己的数据回到最初的问题同一把 TaoToken KeyClaude Code 与 Pi 在 SWE-bench Lite 上谁更省 Token这个问题没有脱离任务集的统一答案。你能做的是把变量控制住然后让数据说话。可复用清单如下在 TaoToken 官网创建独立 Keyhttps://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_final 。Base URL 统一写https://taotoken.net/api不要带 UTM。Claude Code 用settings.json或ANTHROPIC_*CC Switch 三件套分层管理全局、项目、环境变量。Codex CLI 如果用单独写config.toml不要套ANTHROPIC_*。Pi 先确认协议再选择 OpenAI 兼容或 Anthropic 兼容变量不要和 Claude Code 混在同一个 shell。用双跑脚本给每个任务、每个 harness 落盘日志。从usage字段和 TaoToken 控制台日志汇总 total tokens、retry count、test passed。比较时先过滤“两者都通过”的任务再比较 Token只有一个通过的任务用来分析 harness 行为。不要写来源不明的倍数、总量、排名。你自己跑出来的表格才是可复现结论。如果 Token 异常高先查重试、上下文重放、工具循环再查模型和 harness 配置。如果你准备把 Claude Code 作为主力 harness可以从模型对话页确认模型再进入 Coding Plan 查看适合编码场景的套餐然后创建专用 Key最后对照 Claude Code 文档检查配置细节。路径如下模型对话https://taotoken.net/models/detail/chat?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_chatCoding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_plan创建 Keyhttps://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_keys_finalClaude Code 文档https://taotoken.net/doc/ClaudeCodeAnthropic?utm_sourcetaotoken_aicg_blog_endutm_contentharness_swebench_doc最后再强调一次TaoToken 只提供 Key 和 Base URL不参与 harness 评测也不改变 Claude Code 或 Pi 的行为。你看到的 Token 差值来自 harness 如何组织上下文、如何调用工具、如何重试与验证。把这套双跑脚本跑一遍你会得到比任何二手结论都更可靠的 Token 差值表。