1. AGENTS.md 越写越长,每一轮对话都在为它重复付费
维护一个跑了三年以上的后端仓库,AGENTS.md 从十几行涨到两百多行,编码助手每一轮请求都会把它重新读进去一遍。TaoToken 的 Key 与用量页面能把这类重复开销显示出来,先在 TaoToken 官网 获取 Key,然后把 Base URL 改成https://taotoken.net/api,后面的每一次调用都能在同一个控制台里看到消耗。
这不是一个关于"提示词写得好不好"的问题。它更接近一个成本问题:规则文件里的每一行,都会在每一轮对话中重新进入上下文。你和模型来回二十轮,两百行规则就被发送了二十次。上下文窗口是有限的,被规则挤占的位置,本来应该留给真实的代码片段、报错堆栈和表结构定义。更糟的情况是,当规则文件长到一定程度,模型开始在规则内部互相冲突的条款之间摇摆,输出反而更不稳定。
我在仓库里做的调整可以拆成两件事:把 AGENTS.md 从"表达愿望的散文"压缩成"可以被判定是否遵守的条目";把编码工具的后端地址换成统一入口,让 Token 消耗变得可观测、可对比。第二件事先做,因为它提供了度量手段。没有度量,压缩就是凭感觉删字,删掉的可能恰好是那条救过你一次的规则。
2. 先算清楚 AGENTS.md 的 Token 占用与加载路径
压缩之前需要知道两件事:这份文件到底被读了几次,以及它到底占多少 Token。
加载路径决定了重复次数。Codex CLI 会从仓库根目录一路向下查找 AGENTS.md,把沿途找到的内容合并进上下文,~/.codex/AGENTS.md则提供全局默认值。Claude Code 用的是 CLAUDE.md,层级包括项目根目录的./CLAUDE.md、用户目录的~/.claude/CLAUDE.md,以及子目录中的 CLAUDE.md,后者会在访问该目录时补充载入。两者的共同点是:根目录那份文件会在几乎每一轮请求中重复出现。
占用大小可以用字符数先做粗略估算:
wc -m AGENTS.md wc -l AGENTS.md如果希望得到接近真实的数字,用 tiktoken 编码后计数:
import tiktoken encoding = tiktoken.get_encoding("cl100k_base") with open("AGENTS.md", encoding="utf-8") as handle: text = handle.read() print(len(encoding.encode(text)))把结果乘以一轮对话的平均请求次数,就是这份文件每天实际产生的输入量。做过这个乘法之后,删字的动力会变得具体。两百行规则文件通常在数千字符量级,二十轮对话下来,重复发送的内容规模足够放下好几个真实源文件。这也解释了一个常见现象:规则越多,模型越容易忽略其中某几条,因为注意力被分散在大量低价值条目上。
压缩的判断标准可以按下面三类执行:
第一类,每次请求都必须携带的规则。回答风格、改动边界、错误处理方式,这些跨目录通用,留在根文件。
第二类,只在特定子系统中成立的规则。某个服务的数据库迁移流程、某个模块的日志格式,放到对应子目录的 AGENTS.md 或 CLAUDE.md,需要时才载入。
第三类,能交给工具执行的规则。缩进、引号风格、导入顺序、测试覆盖率,全部交给格式化工具与持续集成流程。模型不需要记住这些,工具执行的结果比模型记忆更可靠。
3. 精简后的 AGENTS.md 片段:规则改成可判定的条目
压缩的核心动作是替换表达方式。原来的写法往往是"希望你谨慎一些,不要过度设计,注意项目已有约定",这种句子无法判定是否被遵守,模型读完也得不到明确指令。改成每条规则一行、祈使句开头、动词在前、可以对照检查。
下面是我现在使用的根目录 AGENTS.md 片段,可以直接复制后按仓库情况删改:
# 仓库约定 ## 回答方式 - 直接给出结果。不写开场概述,不写结尾总结。 - 一个任务只给一个方案。用户明确要求多个方案时,给出的方案必须互相独立。 - 使用完整词语,禁止单个字的缩写。 - 不列举被排除的选项,只报符合条件的结果。 - 不使用比喻、口号、行业黑话。 ## 代码改动 - 只修改用户指定的文件。改动前重新读取文件当前内容。 - 不新增接口、配置项、依赖,除非用户明确要求。 - 需要恢复代码时手动编辑文件,禁止使用 Git 回滚。 - 禁止使用 sed、perl 或临时脚本批量改写源码,逐处手动编辑。 - 中间产物写入 .scratch/ 目录,该目录已加入 .gitignore。 - 禁止读写 /tmp 目录。 ## 依赖 - 需要的库直接 import,禁止用 try-except 包住 import。 - 不要求最小化依赖。不要自行实现已有库提供的功能。 ## 错误处理 - 出错就地抛出,不捕获,不做兜底,不返回默认值。 - 实现与测试中禁止使用 mock 数据绕过真实依赖。 ## 执行 - 不进入计划模式,除非用户明确要求。 - 不主动启用图像识别功能。 - 不在 Bash 中内联长命令,先写成脚本文件再执行。 - 不手动解析成熟文件格式,使用第三方库。 ## 完成标准 - 功能实现后必须运行、测试、迭代到正确为止,禁止把测试交给用户。 - 修改后不保留错误痕迹,代码与文档中不写历史错误记录。这份文件和最初的两百行版本相比,条目数量减少了,但覆盖面没有下降。差别在于每一条都能回答"有没有做到"。判断"模型是否写了开场概述"很容易,判断"模型是否过度设计"则不可能,后者留在文件里只会制造噪音。
子目录的规则文件应当保持极短。一个常见做法是只写该目录特有的三到五条,例如:
# 支付模块 - 金额计算一律使用 decimal 类型,禁止使用浮点数。 - 新增数据库字段必须同时提供回滚用的迁移文件。 - 对外接口的字段变更需要同步更新 docs/payment-api.md。4. 把 Base URL 指向 TaoToken:Claude Code 与 Codex 两套配置
规则压缩之后,下一步是让请求走统一入口,这样 Token 消耗才能被对比和追踪。Key 的申请入口见 TaoToken 官网,拿到之后把 Base URL 设置为https://taotoken.net/api。
Claude Code 使用 Anthropic 风格的变量。可以通过环境变量临时设置:
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_AUTH_TOKEN="YOUR_API_KEY" export ANTHROPIC_MODEL="claude-sonnet-4-5"更稳妥的方式是写进~/.claude/settings.json,或者项目内的.claude/settings.json,避免每次打开终端都要重新导出:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "claude-sonnet-4-5" } }模型名称以控制台中列出的名称为准,示例里的值需要替换。项目级配置文件会被提交到仓库,因此不要把真实 Key 写进去,.claude/settings.json要么加入.gitignore,要么只放非敏感字段,Key 通过环境变量注入。
Codex 的配置方式完全不同,它使用 TOML 格式,并且走 OpenAI 兼容接口。不要把ANTHROPIC_*变量套到 Codex 上,两边读取的变量名与协议都不一样。Codex 的配置写在~/.codex/config.toml:
model = "YOUR_MODEL_NAME" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"配套的环境变量:
export TAOTOKEN_API_KEY="YOUR_API_KEY"env_key填写的是保存 Key 的环境变量名称,Codex 启动时会读取这个变量的值作为鉴权凭据,配置文件里因此不会出现明文 Key。wire_api的取值取决于服务端支持的接口形式,以官方文档说明为准。
两套配置可以同时存在于同一台机器上。Claude Code 读它自己的 settings.json,Codex 读 config.toml,只要 Base URL 都指向https://taotoken.net/api,用量就会汇总到同一个账号下。
5. CC Switch 三件套:Base URL、API Key、模型名称
如果同时维护多个项目,或者需要在不同供应商之间来回切换,手动改配置文件容易出错。CC Switch 这类切换工具把配置抽成条目,切换时重写 Claude Code 的配置文件。使用它时需要填写的三件套是固定组合:
第一项,Base URL,填写https://taotoken.net/api。这一项决定了请求发往哪里。
第二项,API Key,填写从控制台创建的 Key。创建入口在 API Keys 页面。
第三项,模型名称。这一项最容易填错,因为切换工具通常不会校验模型是否存在,只有发起请求时才会返回错误。
三项之外通常还有一个显示名称字段,仅用于在列表里区分条目,可以写成"TaoToken 主力"之类的标识。
切换完成之后,建议打开一次 Claude Code 并让它读取仓库文件,确认它确实按新的 AGENTS.md 执行。一个快速的检查方式是问一个会触发风格约束的问题,例如让它给出某个函数的实现,观察回答里是否出现了开场概述。
6. 终端问答对照:同一句提问在压缩前后的输出差别
规则压缩带来的变化在具体对话中最明显。下面是同一个提问在两种规则下的输出对照。
提问:
订单查询接口在并发 50 的时候返回 500,日志里只有一行 panic,帮我定位。压缩之前的输出形态:先来一段"这是一个较为典型的高并发场景,可能由多种原因导致"的铺垫,接着列出三套方案,分别命名为快速排查、稳妥修复、长期治理,每套方案下面又有若干子步骤,收尾再补一段与问题无关的寒暄。真正能执行的命令藏在第三段,读者需要自己从中挑出有用的部分。
压缩之后的输出形态:
先确认 panic 位置。在仓库根目录执行: go test ./internal/order/... -run TestQuery -race -count=1 如果本地无法复现,抓取线上 goroutine 快照: curl -sS http://127.0.0.1:6060/debug/pprof/goroutine?debug=2 > .scratch/goroutine.txt 把 panic 那一行的完整调用链贴出来,我继续往下看。差别在于:后者直接给出可执行命令,说明预期产出,并把下一步需要的输入交代清楚。没有铺垫,没有并列方案,没有收尾。这种回答不是靠模型"更聪明"实现的,它来自 AGENTS.md 里那几条关于回答方式的约束。
另一个对照场景是方案选择。提问"这个查询接口慢,怎么优化",压缩后的规则会要求只给一个方案。模型会先看执行计划,再给出具体改动,例如添加复合索引并说明字段顺序依据。如果给出的方案确实不适用,用户可以直接反馈,模型在新的上下文里重新判断。并列三个方案看似周全,实际结果是用户需要自己完成筛选工作,而筛选所需的现场信息模型本来就能通过读代码获得。
7. 验证与排障:401、404 与模型名称错误
配置完成之后,先在 模型对话页面 手动发一句话,确认 Key 有效、模型可用。这一步能把账号问题和本地配置问题分开,省掉大量来回排查。
本地工具启动后如果报错,按状态码判断:
401 Unauthorized:Key 本身无效、已过期,或者变量名写错。Claude Code 读的是ANTHROPIC_AUTH_TOKEN,Codex 读的是env_key指定的那个变量名。用echo $ANTHROPIC_AUTH_TOKEN检查变量是否真的导出到了当前 shell,很多情况下问题出在只写进了配置文件却没有重新加载。
404 Not Found:Base URL 的路径部分不对。常见原因是多写了或漏写了路径段,或者把 Anthropic 风格和 OpenAI 风格的地址混用。确认配置里填的是https://taotoken.net/api,末尾不要自行追加其他路径。
模型不存在的报错:模型名称与控制台列表不一致。切换工具和配置文件都不会校验这一项,只能通过实际请求暴露。
回答明显变短或被截断:先检查 AGENTS.md 的规模。规则文件过大时,可用于代码内容的上下文被压缩,模型会开始省略细节。回到第 2 节的计数方法重新评估,继续合并或下移规则。
排障过程中建议保持一次只改一个变量。先确认 Key,再确认 Base URL,最后确认模型名称,每一步都用最小请求验证。
8. 把配置提交进仓库之前的收尾清单
在把规则文件和工具配置提交之前,有几项需要确认。
确认.gitignore已经包含.claude/settings.json、.scratch/以及任何保存真实 Key 的文件。Key 通过环境变量注入,仓库里只保留占位符YOUR_API_KEY。
确认根目录规则文件的每条内容都能判定。逐条读一遍,凡是无法回答"如何检查是否遵守"的条目,要么改写为可判定的形式,要么删除。
确认子目录规则文件只包含该目录特有的内容。与根目录重复的条目直接删掉,重复意味着同一段文字会被载入两次。
确认 Claude Code 和 Codex 的配置没有互相污染。两边使用不同的变量名和不同的文件格式,检查时分别打开~/.claude/settings.json和~/.codex/config.toml核对。
需要长期高频调用编码助手,可以看 Coding Plan 的额度方案。Key 的创建与管理在 API Keys 页面,Claude Code 的完整接入步骤在 Claude Code 文档。整套配置的起点仍然是 TaoToken 官网,Base URL 统一填https://taotoken.net/api。