基于 Git commit 的集体 AutoResearch,TaoToken Key 放在哪

发布时间:2026/9/18 16:50:33
基于 Git commit 的集体 AutoResearch,TaoToken Key 放在哪 上周把集体 AutoResearch 的编排脚本从单机搬到git worktree之后我在三个并行分支里几乎同时撞上了401 authentication_error: invalid x-api-key——原因很朴素Key 被写进了仓库根目录的.envworktree 一建出来就连同文件一起被复制其中一个分支的 pre-commit 还把它带进了历史。这篇把 Key 从 Git 里彻底剥离出来的整套做法记录一遍接入统一走 TaoToken官网入口与配置说明Base URL 固定填https://taotoken.net/apiKey 用占位符YOUR_API_KEY。1. 为什么 Git 驱动的集体 AutoResearch 必须先把 Key 赶出仓库先对齐一下这套系统的形态。原论文里描述的那类系统核心思路是把 Git 仓库当成智能体之间的共享记忆仓库里的提交记录本身就是一条只追加的有向无环图每个节点是一次产出、一条洞察或一轮验证任何一个节点都能被单独检出并重跑。换句话说commit 不是日志而是记忆单元。多个 agent 各自在自己的分支或 worktree 上推进通过 merge / rebase 把各自的结论汇回主干后来者读git log就能拿到前人的全部上下文不用额外维护一套向量库。这个设计很优雅但它对可复现的要求是硬性的既然每条记录都声称可检出复现那么任何人git checkout commit之后跑一遍脚本就应该能重新触发同样的模型调用、拿到同一量级的输出。问题就出在这里——可复现要求调用参数完整落盘而 API Key 恰恰是最不该落盘的那一个。我在迁移过程中踩到的三个典型翻车方式基本覆盖了大多数团队会遇到的情况第一种.env被提交。本地调试时顺手在仓库根写了.env.gitignore没配好某次git add -A就带进去了。之后每个新建的git worktree、每个 clone 出来的副本都带着一份明文 Key。更麻烦的是 agent 本身就是读仓库的它执行grep -r API_KEY .做上下文收集时会把 Key 原样塞进 prompt然后这条 prompt 又变成下一个 commit 的内容形成自污染循环。第二种项目级配置文件写死。为了图省事把凭证直接写进项目目录下的工具配置文件。这类文件通常和源码放在一起agent 生成新分支、做git stash、跑git worktree add时都会被复制。一旦某个分支被 push 到共享远端Key 就等于公开了。第三种多环境共用一把 Key。主干验证、夜间批量实验、沙箱复现脚本全用同一个凭证。结果是配额无法归因——你不知道这个月消耗掉的是哪个 agent 的哪一轮实验出了异常调用也无法只吊销其中一条链路。这三种情况的共同解法只有一个方向Key 只存在于仓库之外仓库里只留怎么读 Key的约定。这个约定就是环境变量 工具侧配置接下来分工具讲。在动手之前先到官网把凭证准备好taotoken.net 控制台入口创建出来的 Key 只在创建时完整显示一次建议命名成能区分用途的形式比如autoresearch-main、autoresearch-nightly后面做配额归因会轻松很多。记住两件事Base URL 一律是https://taotoken.net/api这个地址不要带任何查询参数Key 的占位符本文统一写作YOUR_API_KEY。2. 环境隔离模型把凭证放在 worktree 之外的三个层级新版型的隔离思路是按生命周期分三层而不是按目录分。第一层Shell 环境最外层。所有 agent 进程都从父 shell 继承环境变量。这一层不落盘、不进 Git缺点是重启终端就没了所以需要配合.envrc或系统密钥环做持久化。第二层direnv / 密钥管理项目级但被忽略。.envrc放在仓库根目录但必须写进.gitignore。direnv 的好处是只对当前目录生效cd进去自动加载、cd出去自动卸载worktree 之间互不干扰。第三层工具配置只放引用不放值。Claude Code 的settings.json、Codex 的config.toml只声明从哪个环境变量读真正的值永远在上两层。推荐的仓库目录约定大致是这样autoresearch-repo/ ├── .gitignore # 忽略 .envrc / .env / *.key ├── .envrc.example # 模板进 Git里面是占位符 ├── .claude/ │ └── settings.example.json # 模板进 Git ├── scripts/ │ ├── run_agent.sh # 读环境变量不读文件里的明文 │ └── record_commit.sh # 把用量写进 commit message ├── experiments/ # agent 产出进 Git └── .exp/ # 临时用量统计进 Git 但会定期归档关键点是模板文件进 Git真实文件不进。.envrc.example里面写的是export TAOTOKEN_API_KEYYOUR_API_KEY新人 clone 之后cp .envrc.example .envrc再填自己的 Key然后direnv allow即可。.gitignore至少要覆盖这些# 凭证与本地环境 .env .env.local .envrc *.key *.pem # 工具本地覆盖配置 .claude/settings.local.json .codex/auth.json # 实验过程中的临时产物 .exp/tmp/ *.log再加一道保险装一个 pre-commit 钩子做密钥扫描。用gitleaks或git-secrets都行目的不是防手滑而是防止 agent 在自动补全上下文时顺手把 Key 写进新文件。钩子脚本本身也可以提交进仓库这样每个 worktree 都自动带上#!/usr/bin/env bash # scripts/pre-commit-secret-scan.sh set -euo pipefail if git diff --cached --name-only | xargs -r grep -lE (sk-[A-Za-z0-9]{16,}|YOUR_API_KEY) 2/dev/null; then echo [blocked] 暂存区疑似出现明文凭证请改用环境变量注入 2 exit 1 fi echo [ok] 暂存区未发现明文凭证安装方式把它软链到.git/hooks/pre-commit或者用core.hooksPath指向仓库内的钩子目录这样所有 worktree 共享同一份钩子不需要每个 worktree 单独装。3. 最小可复现验证用一条命令确认 Base URL 与 Key 都对在改任何工具配置之前先用最原始的方式验证一次避免后面出问题时分不清是网络、是 Key 还是工具配置的锅。这一节的命令由你在本地终端执行不要把数据库连接串或生产凭证交给任何 agent。先把环境变量注入当前 shellexport TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_API_KEYYOUR_API_KEY # 确认变量已生效只打印前缀避免完整 Key 进 shell 历史 echo ${TAOTOKEN_BASE_URL} echo ${TAOTOKEN_API_KEY:0:8}...然后发一次最小请求。注意路径拼接方式Base URL 后面接/v1/messages不要把版本段重复写进变量里。curl -sS ${TAOTOKEN_BASE_URL}/v1/messages \ -H x-api-key: ${TAOTOKEN_API_KEY} \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: YOUR_MODEL_ID, max_tokens: 64, messages: [ {role: user, content: 只回复两个字可用} ] } | head -c 600几个判断口径返回体里出现正常内容 → 凭证与地址都没问题可以进入工具配置环节具体可用的模型 ID 从模型对话页查不要凭记忆填。401/authentication_error→ Key 复制不完整或者环境变量没被当前终端继承常见于在 IDE 内置终端和新开的系统终端之间来回切换。404→ 大概率是地址拼错了。最常见的两种把https://taotoken.net/api写成了带?utm_source...的页面地址或者变量里已经带了/v1代码里又拼了一次。超时 → 先确认本机出口网络正常再检查是否有全局代理把请求劫持到了别的地址上。验证通过后建议把模型 ID 也固化成一个环境变量避免每个 agent 的脚本各自写死一份export TAOTOKEN_MODEL_IDYOUR_MODEL_ID4. Claude Codesettings.json 与 ANTHROPIC_* 的正确写法Claude Code 读的是ANTHROPIC_*系列变量这一点和 Codex 完全不同千万不要混用。最稳的做法是放在用户级配置~/.claude/settings.json里让 Key 彻底远离仓库{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_MODEL: YOUR_MODEL_ID, ANTHROPIC_SMALL_FAST_MODEL: YOUR_FAST_MODEL_ID, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1 } }如果团队希望配置跟着仓库走那就只提交一份模板.claude/settings.example.json内容里所有敏感值都写成占位符真实文件由开发者本地生成并被.gitignore排除。这样 agent 在仓库里永远读不到真实 Key。不想动配置文件的话纯环境变量也完全可行。配合 direnv 的使用方式# .envrc已被 .gitignore 忽略 export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_API_KEYYOUR_API_KEY # 映射给 Claude Code export ANTHROPIC_BASE_URL${TAOTOKEN_BASE_URL} export ANTHROPIC_AUTH_TOKEN${TAOTOKEN_API_KEY} export ANTHROPIC_MODELYOUR_MODEL_ID export ANTHROPIC_SMALL_FAST_MODELYOUR_FAST_MODEL_IDcd进仓库执行一次direnv allow之后每次进入目录都会自动加载、离开自动清理worktree 之间天然隔离——这一点对并行跑实验特别重要不同 worktree 可以指向不同的 Key用配额来区分实验身份。一个容易忽略的细节Claude Code 会把工作目录下的文件内容读进上下文所以.envrc即使在.gitignore里也要确认它没有被 agent 的全仓库检索步骤扫到。稳妥做法是把 Key 放在仓库上一级目录的.envrc里或者在检索命令里显式排除。5. Codexconfig.toml 不能套用 ANTHROPIC_*Codex 走的是另一套配置体系用config.toml声明 provider字段名和 Claude Code 毫无关系。把ANTHROPIC_*塞给 Codex 是最常见的无效配置之一表现出来就是配置改了但请求还是打到原来的地方。正确写法是先在配置文件里声明一个自定义 provider再用环境变量提供凭证# ~/.codex/config.toml model YOUR_MODEL_ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api/v1 env_key TAOTOKEN_API_KEY wire_api chat要点逐条说明model_provider的值要和下面 section 名taotoken一致写错就等于没生效。base_url这里按 OpenAI 兼容风格带上/v1与 Claude Code 那套的ANTHROPIC_BASE_URL不带/v1不同这是两套协议的路径差异不是笔误。env_key只声明变量名不写值。真正的值由 shell 或.envrc注入export TAOTOKEN_API_KEYYOUR_API_KEY如果你的实验脚本需要区分不同用途的 Key可以在启动 Codex 前临时覆盖TAOTOKEN_API_KEY${AUTORESEARCH_NIGHTLY_KEY} codex exec 读取 experiments/ 下最新一条 commit 的结论并给出下一步假设这种每次进程单独注入的方式最适合 agent 编排父进程不持有 Key子进程用完即释放不会残留到任何一个 worktree 的配置里。6. CC Switch一份配置管理多套供应商与环境当你在主干验证、夜间批量、沙箱复现之间来回切换时手改配置文件很容易改出不一致。CC Switch 这类工具的价值就是把这套切换收敛成一个界面它的核心只需要填三样东西我把它叫作三件套字段填什么说明供应商名称taotoken-main/taotoken-nightly自定义用于区分用途Base URLhttps://taotoken.net/api不加 UTM、不加尾部斜杠API KeyYOUR_API_KEY每套环境用不同的 Key使用时有三个注意点第一不同用途用不同 Key。主干用一个、夜间批量用一个、复现脚本用一个。这样在控制台看用量时可以直接按 Key 归因出现异常调用也能精准吊销单条链路而不是一刀切全停。第二切换后回到仓库做一次快速验证。切换只改了工具侧配置环境变量里可能还残留旧值两者冲突时通常以显式设置的环境变量为准容易造成我明明切了但没生效的错觉。第三不要把 CC Switch 的配置目录纳入仓库。它是用户级工具配置里含明文 Key一旦被 agent 的仓库遍历扫到就会进上下文。把它放在 home 目录下仓库侧只保留模板。配置好之后回到项目目录跑一次真实调用确认链路cd votre-autoresearch-repo claude -p 列出 experiments/ 目录下最近三次提交的标题不要修改任何文件如果这条命令能正常返回说明供应商切换、Base URL、Key 三者已经打通可以开始接入 commit 驱动的实验循环了。7. 把用量写进 commitGit 侧的可复现脚手架前面说过这套系统的记忆单元是 commit所以用了哪个模型、消耗了多少 token、基于哪个 Base URL这些信息应该随 commit 一起落盘——但 Key 本身绝不能进去。一个可行的做法是实验脚本在调用完成后把非敏感元数据写进.exp/meta.json并追加到 commit message 里。#!/usr/bin/env bash # scripts/run_and_record.sh set -euo pipefail : ${TAOTOKEN_API_KEY:?请先在仓库外注入 TAOTOKEN_API_KEY} : ${TAOTOKEN_BASE_URL:https://taotoken.net/api} : ${TAOTOKEN_MODEL_ID:?请先指定 TAOTOKEN_MODEL_ID} EXP_ID$(date %Y%m%d-%H%M%S) mkdir -p .exp/${EXP_ID} # 1) 调用 agent产出实验结论此处替换为你的编排命令 # 推荐把 prompt 与输出都落到 .exp/${EXP_ID}/ 下便于检出复现 your_agent_cli --model ${TAOTOKEN_MODEL_ID} \ --input experiments/queue/next.json \ --output .exp/${EXP_ID}/result.md # 2) 记录非敏感元数据模型、地址、用量 cat .exp/${EXP_ID}/meta.json JSON { exp_id: ${EXP_ID}, model: ${TAOTOKEN_MODEL_ID}, base_url: ${TAOTOKEN_BASE_URL}, input_tokens: ${INPUT_TOKENS:-0}, output_tokens: ${OUTPUT_TOKENS:-0}, key_alias: autoresearch-main } JSON # 3) 提交commit message 只带元数据不带凭证 git add experiments .exp/${EXP_ID} git commit -m exp(${EXP_ID}): model${TAOTOKEN_MODEL_ID} in${INPUT_TOKENS:-0} out${OUTPUT_TOKENS:-0}注意key_alias记录的是别名而不是 Key 本身。这样就同时满足了两个条件审计时能查到这条结论是用哪把 Key 跑出来的而检出这个 commit 的人拿不到任何凭证。并行实验用 worktree 隔离命令示例# 每个 agent 一个独立工作区环境变量互不污染 git worktree add ../ar-agent-01 -b exp/agent-01 git worktree add ../ar-agent-02 -b exp/agent-02 cd ../ar-agent-01 direnv allow ./scripts/run_and_record.sh复现某条历史结论时检出对应 commit 后重跑即可git log --oneline -n 10 git checkout commit-id direnv allow ./scripts/run_and_record.sh因为meta.json里固化了模型 ID 和 Base URL复现时不会出现作者当时用的是哪个模型这种无法回答的问题。8. Token 消耗表给集体 AutoResearch 做一次预算测算多 agent 并发跑实验最容易失控的不是代码而是配额。下表按单 agent 跑完一轮完整提出假设 → 生成脚本 → 判读结果 → 提交验证循环来估算数值来自一次实际编排的抽样口径你可以按自己的 prompt 长度等比放大。环节单轮调用次数平均输入 tokens平均输出 tokens小计 tokens文献与历史 commit 摘要403,500700168,000假设生成与去重204,00090098,000实验脚本生成256,0001,500187,500结果判读与置信度打分305,000600168,000验证落库与 commit 摘要153,00040051,000单 agent 单轮合计130——672,500按这个口径往外推并发规模单轮总消耗约说明1 个 agent0.67M tokens适合开发调试4 个 agent2.7M tokens小规模并行验证8 个 agent5.4M tokens需要按 Key 分配配额8 个 agent × 每日 4 轮21.5M tokens/天建议拆多把 Key 做归因几条控制成本的实操建议第一给历史 commit 摘要做缓存。同一批历史上下文会被多个 agent 重复读取把它固化成一份文件并只在有新 commit 时增量更新能省掉很大一块输入。第二按 Key 设置独立的预算视图。主干、夜间、复现三把 Key 分开看用量哪条链路超支一眼可见。第三把生成脚本这一步的输出上限压住。它是单次输出最大的环节很多跑飞的脚本其实是模型在自由发挥给它一个明确的模板和长度上限能显著降低消耗。第四给一轮实验设硬性止损。在编排脚本里加计数器超过阈值直接终止并把状态落成一条aborted的 commit而不是继续烧配额。9. 高频报错对照表现象常见原因处理方式401 authentication_errorKey 未注入当前 shell / 复制不全重开终端后echo ${TAOTOKEN_API_KEY:0:8}确认404 not_foundBase URL 多写/v1或误填了带参数的页面地址统一用https://taotoken.net/apiCodex 报 provider 不存在model_provider与 section 名不一致检查两处拼写是否都为taotokenClaude Code 仍走旧地址环境变量覆盖了配置文件清理 shell 中残留的ANTHROPIC_BASE_URL多 worktree 互相串 Key.envrc写在共享路径或被提交确认.envrc在.gitignore中每 worktree 独立direnv allowcommit 里出现疑似明文凭证pre-commit 钩子未安装用core.hooksPath统一挂载钩子10. 小结与下一步回到最初那个问题集体 AutoResearch 把 Git 当共享记忆每条结论都是可检出的 commit那么 Key 该放在哪答案是把 Key 放在仓库的外面——shell 环境、direnv、用户级工具配置三层任选其一或组合使用仓库里只留模板、只留别名、只留用量元数据。这样 agent 之间共享的是结论和参数而不是凭证。落地顺序建议按这个节奏走先用一条 curl 确认地址与凭证再把 Claude Code 和 Codex 的配置分别改好注意两套协议不要混用接着用 CC Switch 管起多环境切换最后把用量写进 commit message让每一轮实验都可归因、可复现、可止损。需要的话可以从这几个入口继续想先确认可用模型和实际输出效果去模型对话直接试一轮确定要长期跑批量实验看Coding Plan的配额与计费方式准备给主干、夜间、复现分别建 Key在API Keys 控制台创建并命名Claude Code 的完整环境变量与配置说明在Claude Code 文档里配置前扫一遍能少走不少弯路。最后再强调一次两个不要变的值Base URL 是https://taotoken.net/apiKey 的占位符是YOUR_API_KEY——前者不进 Git后者更不进。把这两个约定守住多 agent 并行跑再久仓库历史也依然是干净、可复现的。