1. 从 StepContext 日志看 AGENTS.md:它不是文档,是每轮系统上下文
在 Codex 的 StepContext 调试日志里,AGENTS.md 不是一份躺在仓库里的静态说明,而是会被 Resource Loader 重新装配进每轮系统上下文的运行时输入。我把model_provider切到 TaoToken(https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=agents-md-stepcontext)之后,第一件想验证的事不是模型能不能跑,而是 AGENTS.md 里的工具边界描述到底让每轮请求多背了多少 token。因为只要 StepContext 引用了当前 TurnContext,并把这一刻选中的环境、Capability Roots、Tool Router 与 AGENTS.md 一起捕获,那么规则文件的每一次膨胀,都会直接变成模型入口的输入成本。
很多团队维护 AGENTS.md 的方式,和写 README 没区别:想到什么补什么,项目规范、目录说明、命令示例、历史踩坑全往里塞。结果是模型每轮都能看到一套很“完整”的世界观,但 Tool Router 实际注册的工具可能只有四五个,大量 schema 描述和权限声明在上下文中反复出现,既没有改变 Agent 的动作空间,也没有提高任务通过率。TaoToken 在这里只提供模型入口,Base URL 填https://taotoken.net/api,Key 使用YOUR_API_KEY;它不替 Agent 决定工具边界,工具边界仍然由 Harness、AGENTS.md 与 Tool Router 共同描述。我们需要观察的是:AGENTS.md 写了什么、Resource Loader 装了什么、StepContext 捕获了什么、每轮请求又为这些内容付了多少 token。
这篇内容围绕一条可复现路径展开:先拿到 AGENTS.md 加载记录,再做工具边界对照,最后记录 Token 消耗观察。你不需要改模型权重,也不需要把生产库接到 Agent 里,只需要在本地仓库、本地终端和模型入口之间建立可审计的链路。
2. Resource Loader 的装配顺序:SYSTEM.md、AGENTS.md、Skills 与 Prompt Templates
Resource Loader 的职责不是“让模型自己去磁盘里感知”,而是发现、解析、装配当前 Session 可用的系统资源。不同 Harness 的命名可能不同,但典型资源包括:系统级指令文件、项目级 AGENTS.md、技能文件、提示词模板、环境描述、工具白名单。它们不会自动变成模型能力,而是先形成一份系统上下文,再与用户输入、历史消息、工具 schema 一起送入下一轮请求。
要复现 AGENTS.md 加载记录,先在本地仓库做一次资源盘点。下面命令只读取文件,不连接任何数据库或远程服务:
# 在项目根目录执行,列出可能被 Resource Loader 发现的规则文件 find . -maxdepth 4 \( -name "AGENTS.md" -o -name "SYSTEM.md" -o -name "SKILL.md" -o -name "*.prompt.md" \) -print | sort # 查看文件大小与行数,先建立“上下文预算”直觉 wc -c -l $(find . -maxdepth 4 \( -name "AGENTS.md" -o -name "SYSTEM.md" -o -name "SKILL.md" \) -print)然后再用一个本地脚本估算这些文件进入系统上下文后的字符成本。字符数除以 3 到 4,可以作为英文与代码混合文本的粗略 token 估算;中文密度更高时,实际值会变化。它不精确,但足够让你发现“哪份规则文件正在吃掉预算”:
# local_context_budget.py from pathlib import Path CANDIDATES = ["AGENTS.md", "SYSTEM.md", "SKILL.md"] root = Path(".").resolve() for name in CANDIDATES: for path in sorted(root.rglob(name)): if ".git" in path.parts or "node_modules" in path.parts: continue text = path.read_text(encoding="utf-8", errors="ignore") chars = len(text) rough_tokens = chars // 4 print(f"{path.relative_to(root)}\t{chars} chars\t~{rough_tokens} tokens")如果你用的是 Codex 这类会捕获 StepContext 的 Harness,可以在日志里搜索StepContext、Tool Router、AGENTS.md、Capability Roots等关键词。重点不是日志格式,而是确认三件事:
- AGENTS.md 是在 Session 启动时加载,还是每次 Turn 都重新解析。
- 工具边界描述是随 AGENTS.md 一起进入系统上下文,还是只存在于 Tool Router 的注册表里。
- 当前 StepContext 是否包含后台配置变化后的旧文件内容。
Resource Loader 的装配顺序通常决定了优先级。系统级指令可能先进入,项目级 AGENTS.md 后进入;技能文件与提示词模板可能按需加载,也可能被显式装配。若顺序不明确,同一个工具既有全局声明、又有项目声明、还有临时提示词声明,模型看到的就会是一套互相重叠的规则。此时 StepContext 虽然自洽,但自洽的是一份臃肿的上下文。
TaoToken 官网(https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=agents-md-loader)提供的是模型入口,不介入 Resource Loader 的本地装配逻辑。也就是说,AGENTS.md 加载记录必须在你自己的仓库和 Harness 日志里完成,TaoToken 负责的是当这些上下文组装完成后,请求以哪个 Base URL、哪个 Key、哪个模型标识进入推理。
3. 工具边界对照:AGENTS.md 声明、Tool Router 注册与真实可调用
AGENTS.md 决定工具边界,但“写了”不等于“注册了”,“注册了”也不等于“模型一定会用”。更常见的情况是:AGENTS.md 里写了十几个工具名和权限说明,Tool Router 实际只注册了 read、write、edit、bash;模型每轮却要为那十几个描述付 token。要做工具边界对照,可以维护一张本地表格,把三类事实分开记录。
| 工具/能力 | AGENTS.md 是否声明 | Tool Router 是否注册 | 系统上下文中的描述成本 | 当前 StepContext 可调用 |
|---|---|---|---|---|
| 文件读取 | 是,声明只读 | 是,注册为 read | 约 120 tokens | 是 |
| 文件写入 | 是,声明需审批 | 是,注册为 write | 约 160 tokens | 是,受 Approval 约束 |
| 局部编辑 | 是,声明仅限工作区 | 是,注册为 edit | 约 180 tokens | 是 |
| Shell 命令 | 是,声明需沙箱 | 是,注册为 bash | 约 220 tokens | 是,受 Sandbox 约束 |
| 浏览器访问 | 是,写了完整说明 | 否,未注册 | 约 300 tokens | 否 |
| 数据库查询 | 是,写了连接示例 | 否,未注册 | 约 260 tokens | 否 |
| 子 Agent 调度 | 是,写了调度规则 | 视 Profile 而定 | 约 200 tokens | 仅主 Agent 可用 |
这张表暴露的问题很直接:未注册的工具描述仍然可能被 AGENTS.md 带进系统上下文,成为纯成本。更稳妥的写法是让规则文件只描述当前 Profile 真正需要的能力,把“未来可能用到的工具”挪到按需加载的技能文件或模板里。
一个更窄的 AGENTS.md 示例:
# AGENTS.md - 项目规则 ## 工具边界 - 允许:read、edit、bash(仅工作区) - 禁止:网络下载、生产配置修改、凭据读取 - 写入前必须说明目标文件与变更原因 - bash 命令如果涉及删除、安装、迁移,必须请求审批 ## 上下文规则 - 只引用与当前任务相关的文件 - 历史工具输出超过 200 行时,先摘要再继续 - 不把完整日志复制进下一轮请求 ## 输出要求 - 先给变更计划,再执行工具 - 最终说明修改文件、验证命令、未完成事项这份文件没有列一堆不存在的工具,也没有把数据库连接、浏览器自动化、子 Agent 调度全写进去。Tool Router 注册什么,AGENTS.md 就描述什么;审批与沙箱再决定这些工具在实际执行时的边界。TaoToken 的模型入口不会替你扩大或缩小这个边界,它只承接已经装配好的请求。
在 Codex 的 StepContext 里,工具边界和 AGENTS.md 是同一时刻被捕获的。后台配置即使发生变化,已经开始的那一步仍然面对一套自洽的工具与环境。这个设计对调试很友好:你可以把某一步的 AGENTS.md 快照、Tool Router 注册表、实际工具调用记录放在一起对照,判断某次越界是因为规则文件写得太宽,还是因为 Tool Router 注册了不该注册的能力。
4. 把模型入口切到 TaoToken:Claude Code 与 Codex 的配置不能混用
确认资源装配与工具边界之后,下一步是把模型入口切到 TaoToken。注意:Claude Code 和 Codex 的配置方式不同,不能把ANTHROPIC_*环境变量套到 Codex 上,也不能把 Codex 的config.toml当成 Claude Code 的 settings.json 使用。两者的 Base URL 都可以指向https://taotoken.net/api,但协议字段、环境变量名和配置文件位置要各自遵守。
Claude Code 使用 settings.json,常见做法是在env字段中设置 Anthropic 兼容入口:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "claude-sonnet-4-5" } }把这段配置放到 Claude Code 会读取的 settings.json 中,然后重启会话。若你使用 CC Switch 管理多套配置,可以把它拆成“三件套”:
- 供应商名称:TaoToken
- Base URL:
https://taotoken.net/api - API Key:
YOUR_API_KEY
这样切换供应商时不需要改 AGENTS.md,也不需要重装 Harness。模型入口变了,工具边界仍由本地规则文件与 Tool Router 决定。
Codex 使用 config.toml,配置形态不同:
# ~/.codex/config.toml model = "gpt-5.6-sol" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"然后在本地 shell 中导出 Key:
export TAOTOKEN_API_KEY="YOUR_API_KEY"这里再次强调:Codex 不读取ANTHROPIC_AUTH_TOKEN,Claude Code 也不应把model_providers.taotoken当作自己的配置。混淆的结果通常是 401 或 404:要么 Key 没被正确读取,要么请求路径被拼到了错误的协议端点上。排障时先确认“哪个客户端、哪个配置文件、哪个环境变量”,再检查 Base URL 是否为https://taotoken.net/api。
TaoToken 官网(https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=agents-md-provider)可以领取 Key 并查看模型入口说明。把 Base URL 填到模型入口后,AGENTS.md 的加载、StepContext 的捕获、Tool Router 的注册仍然发生在本地 Harness 中。TaoToken 只提供模型入口,这个边界越清楚,排障时越不容易把配置问题误判成模型问题。
5. Token 消耗观察:系统上下文、工具 schema 与历史如何分摊每轮请求
切完模型入口后,最重要的可复现产出是 Token 消耗观察。不要只看总 token,要把每轮请求拆成几个账本:系统指令、AGENTS.md、工具 schema、对话历史、工具结果、当前用户输入。下面是一份示例记录表,字段可以根据你的 Harness 日志调整:
| 轮次 | 系统指令 | AGENTS.md | 工具 schema | 历史消息 | 工具结果 | 本轮输入合计 | 备注 |
|---|---|---|---|---|---|---|---|
| 1 | 420 | 310 | 680 | 0 | 0 | 1410 | 首次加载,工具 schema 最全 |
| 2 | 420 | 310 | 680 | 260 | 180 | 1850 | 开始出现历史与工具输出 |
| 3 | 420 | 310 | 680 | 520 | 640 | 2570 | 工具输出未裁剪 |
| 4 | 420 | 310 | 680 | 900 | 120 | 2430 | 对旧输出做了摘要 |
| 5 | 420 | 310 | 680 | 1100 | 90 | 2600 | 接近压缩阈值 |
这张表里,AGENTS.md 和工具 schema 是“固定成本”,历史与工具结果是“增长成本”。如果固定成本过高,每一轮都在为同一批描述付费;如果增长成本失控,任务后期会被旧工具输出拖垮。更合理的优化顺序是:
- 先把 AGENTS.md 压到只描述当前 Profile 真正可用的工具与禁止事项。
- 再检查 Tool Router 注册表,删除未注册但仍在系统上下文里出现的工具描述。
- 对超过阈值的工具结果做摘要,而不是完整塞回下一轮。
- 用 Compaction 或 Session 投影保留关键事实,释放窗口。
- 最后才考虑换模型或调大上下文窗口。
可以用下面的本地脚本,把某次会话的日志按“段”统计字符数。它不解析生产库,只读取你导出的文本日志:
# token_ledger.py from pathlib import Path log = Path("step-context.log").read_text(encoding="utf-8", errors="ignore") sections = { "AGENTS.md": log.count("AGENTS.md"), "Tool Router": log.count("Tool Router"), "StepContext": log.count("StepContext"), "system": log.count("system"), } for key, count in sections.items(): print(f"{key}: {count} 次出现") # 粗略估算整份日志的字符规模 print(f"日志字符数: {len(log)}")真正要记录的不是出现次数,而是每次装配后的实际文本长度。你可以在 Harness 的请求构造层加一段本地日志:请求发出前,把 system 部分、工具 schema 部分、历史部分分别计算字符数并落盘。这样经过几轮任务后,就能画出“固定成本 vs 增长成本”的曲线。AGENTS.md 写得越宽,固定成本越高;工具输出越不裁剪,增长成本越陡。
TaoToken 的模型入口提供的是调用通道,不会改变你的上下文装配策略。也正因如此,Token 消耗观察必须建立在本地 Harness 的日志上。你看到的每一轮输入,都是 Resource Loader、StepContext、Tool Router 与 Session 管理共同投影出来的结果。
6. 排障:AGENTS.md 不生效、工具越界与接口 401/404
排障时先区分三类问题:规则没被加载、工具边界没被约束、模型入口没被正确调用。它们的症状很像,但修复位置完全不同。
症状一:改了 AGENTS.md,模型行为没变化。先检查 Resource Loader 的加载记录。AGENTS.md 是否在项目根目录?是否被.gitignore影响?Harness 是否只在 Session 启动时加载,而当前会话没有重启?对于 Codex,StepContext 是否捕获了旧快照?对于 Claude Code,项目级规则文件可能不是 AGENTS.md,而是 CLAUDE.md 或 settings.json 中的指令字段,不要默认两者同名。
症状二:AGENTS.md 写了禁止,模型仍然调用了某个工具。先看 Tool Router 是否注册了该工具。如果注册了,规则文件只是自然语言约束,模型可能忽略;真正的边界要靠 Approval 与 Sandbox。若工具不该出现,应从 Tool Router 或 Profile 中移除,而不是只在 AGENTS.md 里写“禁止”。工具边界对照表在这里最有用:把“声明”“注册”“可调用”三列分开,问题会立刻暴露。
症状三:配置 TaoToken 后出现 401 或 404。401 通常表示 Key 没被读取或格式不对。Claude Code 检查ANTHROPIC_AUTH_TOKEN,Codex 检查TAOTOKEN_API_KEY是否导出到当前 shell。404 通常表示 Base URL 或协议路径不对。两个客户端都先把 Base URL 设为https://taotoken.net/api,不要在末尾误加/v1/messages或/v1/chat/completions,除非你确认当前客户端要求这样做。Codex 的wire_api要与实际协议匹配;Claude Code 的 Anthropic 兼容配置不要写成 Codex 的 provider 结构。
症状四:CC Switch 切换后配置串了。回到三件套:供应商名称、Base URL、API Key。确认切换的是目标客户端的配置,而不是只改了全局环境变量。如果同一台机器同时跑 Claude Code 与 Codex,建议用不同的 Key 名称或不同的 Profile,避免ANTHROPIC_*与TAOTOKEN_API_KEY互相覆盖。
症状五:Token 消耗突然升高。先看 AGENTS.md 是否被重复装配,再看工具 schema 是否随 Profile 变化,最后看工具输出是否未裁剪。StepContext 捕获的是当前步的快照,如果后台配置在任务中途变化,已经开始的步仍然使用旧快照;新步可能加载新规则,导致同一任务内出现两套成本结构。记录每次装配的字符数,比猜“模型是不是变贵了”更可靠。
7. 可复现产出清单与下一步
把上面的步骤跑完,你至少会得到三份可复现产物:
- AGENTS.md 加载记录:本地
find结果、字符数统计、StepContext 日志中的装配快照。 - 工具边界对照:AGENTS.md 声明、Tool Router 注册、实际可调用能力的三列对照表。
- Token 消耗观察:按轮次拆分的系统上下文、规则文件、工具 schema、历史与工具结果账本。
有了这三份材料,再决定是否调整模型入口。TaoToken 只提供模型入口,不替代 Resource Loader,也不替 Tool Router 做工具治理。把 Base URL 填https://taotoken.net/api、Key 填YOUR_API_KEY之后,你仍然需要在本地维护 AGENTS.md 的边界,记录 StepContext 的装配结果,观察每轮请求的成本结构。
如果你还没有 Key,可以从 TaoToken 官网(https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=agents-md-final)领取,然后在对应客户端中完成配置。接下来的路径可以按需选择:
- 先做一次模型对话,确认入口连通:https://taotoken.net/models/detail/chat?utm_source=taotoken_aicg_blog_end&utm_content=agents-md-chat
- 需要长期跑 Coding Agent,查看 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=agents-md-plan
- 创建和管理 API Keys:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=agents-md-keys
- Claude Code 接入文档:https://taotoken.net/doc/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=agents-md-doc
AGENTS.md 决定工具边界,StepContext 决定这一步看见什么,Token 账本决定这套规则是否值得。模型入口只是链条中的一段;把加载记录、边界对照和消耗观察做实,才能让 Agent 在长期使用中少背无关上下文,也少做越界动作。