1. 从 401 到容器重启丢 Key:trueforge 认证链的故障面
把 trueforge 跑起来时,最容易被忽略的不是 agent loop,而是认证。你npx @truefoundry/trueforge@latest起服务,聊天 UI 能打开,但模型调用报401 invalid api key;或者本地跑通了,一做成 Docker 服务,重启后 Key 没了;又或者 MCP 工具能连,但沙箱执行器读不到模型凭据。这些现象背后通常是同一个问题:模型认证、工具认证、运行时凭据被塞在一个.env里,没有分层。
从应用安全工程师视角,第一步是把 TaoToken 作为模型供应商接进来。先访问 TaoToken 官网(https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=trueforge_env_intro)创建账号并获取 API Key。注意,Key 生成后只显示一次,别顺手粘进docker-compose.yml或前端配置文件。然后,把 Base URL 固定为https://taotoken.net/api,这个地址只用于服务端工具配置,不加 UTM 参数。模型请求由 trueforge 的 agent loop 发起,Token 也由认证后的 agent 模型调用消耗,所以 Key 的权限范围要按“模型调用”而不是“全账号”来设计。
这一节先给结论:trueforge 的认证管理不要硬写。你需要三样东西——环境变量模板、认证配置片段、Key 轮换检查表。下面按可复现顺序展开。
2. 最小可用环境变量模板:TaoToken Key 不进代码库
先做环境变量。建议把模型认证与工具认证拆成两组变量,即使第一版只有一个 Key,也不要混名。你可以先到 TaoToken 官网(https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=trueforge_env_key)生成一个专用 Key,再回到服务端写入.env。
# .env.example # 模型认证:trueforge 调用大模型时使用 TAOTOKEN_API_KEY=YOUR_API_KEY TAOTOKEN_BASE_URL=https://taotoken.net/api # 运行时隔离:给 trueforge 容器/进程读取 TRUEFORGE_MODEL_PROVIDER=openai-compatible TRUEFORGE_MODEL_NAME=your-model-name # 工具认证:MCP server 或内部检索工具使用,独立 Key MCP_INTERNAL_SEARCH_TOKEN=YOUR_MCP_TOKEN # 审计与日志:不要记录完整 Key LOG_LEVEL=info LOG_REDACT_KEYS=true真正的.env不要提交:
cp .env.example .env chmod 600 .env printf ".env\n.env.*\n*.pem\n" >> .gitignore如果 trueforge 用 Docker Compose 启动,让容器通过env_file读取,而不是在command里写:
services: trueforge: image: your-trueforge-image env_file: - .env environment: - TAOTOKEN_API_KEY=${TAOTOKEN_API_KEY} - TAOTOKEN_BASE_URL=${TAOTOKEN_BASE_URL} read_only: true user: "10001:10001" security_opt: - no-new-privileges:true这里的关键不是 Compose 语法,而是边界:TAOTOKEN_API_KEY只进入模型调用进程;MCP_INTERNAL_SEARCH_TOKEN只进入工具进程;日志层做脱敏。很多“Key 泄露”不是被黑客拖库,而是调试日志把Authorization: Bearer打进了 stdout。
如果你在服务器上手动验证,可以本地执行:
set -a source .env set +a curl -sS https://taotoken.net/api/models \ -H "Authorization: Bearer ${TAOTOKEN_API_KEY}" \ -o /tmp/models.json这个命令只用于确认认证链通不通,不要把它放进 agent 可调用的工具列表。工具一旦能执行任意 curl,Key 就可能被带出去。
3. 模型认证片段:OpenAI-compatible provider 如何指向 TaoToken API
trueforge 支持任意模型提供商,包括兼容 OpenAI 的端点。接入 TaoToken 时,核心是让模型 provider 从环境变量读取两个值:TAOTOKEN_BASE_URL和TAOTOKEN_API_KEY。
不同版本的 trueforge 配置文件字段可能不同,下面给的是通用结构。你需要到实际配置文件里把字段名对齐,但原则不变:YAML/JSON 里只留变量名,不留明文 Key。
# 示例:模型 provider 片段(字段名以你安装的 trueforge 版本为准) model: provider: openai-compatible name: taotoken base_url: ${TAOTOKEN_BASE_URL} api_key: ${TAOTOKEN_API_KEY} model: ${TRUEFORGE_MODEL_NAME} timeout_ms: 60000 max_retries: 2如果 trueforge 的某部分只接受运行时注入,而不是 YAML 插值,就在启动脚本里做映射:
#!/usr/bin/env bash set -euo pipefail : "${TAOTOKEN_API_KEY:?missing TAOTOKEN_API_KEY}" : "${TAOTOKEN_BASE_URL:?missing TAOTOKEN_BASE_URL}" export OPENAI_BASE_URL="${TAOTOKEN_BASE_URL}" export OPENAI_API_KEY="${TAOTOKEN_API_KEY}" exec npx @truefoundry/trueforge@latest注意,这里只是把 TaoToken 的 Key 映射给兼容 OpenAI 的 provider。不要因为 trueforge 支持 Anthropic、Gemini 就同时把ANTHROPIC_API_KEY、GEMINI_API_KEY全塞进去。多供应商并存时,每个 provider 单独命名变量,例如:
TAOTOKEN_API_KEY=YOUR_API_KEY TAOTOKEN_BASE_URL=https://taotoken.net/api TAOTOKEN_MODEL=your-model-name在应用安全层面,推荐给模型 Key 单独建一个“环境级”凭证,而不是复用个人控制台 Key。这样当 agent 被 prompt injection 诱导去发请求时,损失范围只限于模型调用额度,不会牵出控制台权限。
如果你要在 TypeScript 代码里检查配置是否完整,可以写一个启动前校验,而不是等到请求失败:
function assertModelEnv() { const required = ["TAOTOKEN_API_KEY", "TAOTOKEN_BASE_URL"]; for (const key of required) { if (!process.env[key]) { throw new Error(`Missing required env: ${key}`); } } if (!process.env.TAOTOKEN_BASE_URL!.startsWith("https://")) { throw new Error("TAOTOKEN_BASE_URL must be https"); } } assertModelEnv();这段代码不调用模型,只做配置门禁。它的价值是让错误在启动阶段暴露,而不是在用户提问时才出现401。
4. 工具认证与模型认证分离:MCP、沙箱、审批各自的凭据边界
trueforge 把 MCP 工具、技能、沙箱、审批、上下文管理都接管了。对认证管理来说,这不是“少写代码”,而是“多了一条安全边界”。
模型认证解决的是“谁可以调用大模型”;工具认证解决的是“这个 agent 可以代表谁去访问哪个工具”。两者不能用同一个 Key。原因很直接:模型 Key 泄露后,攻击者至少可以消耗额度、探测模型;工具 Key 泄露后,攻击者可能读写内部文档、触发代码执行、甚至访问业务系统。把两者分开,才能做最小权限和独立轮换。
一个工具侧的环境变量模板:
# MCP 内部检索工具:只读凭据 MCP_SEARCH_BASE_URL=https://internal.example.com/search MCP_SEARCH_TOKEN=YOUR_MCP_TOKEN MCP_SEARCH_SCOPE=docs:read # 沙箱执行器:不要挂载宿主机敏感目录 SANDBOX_IMAGE=your-sandbox-image SANDBOX_TIMEOUT_SECONDS=30 SANDBOX_NETWORK=none # 审批回调:独立签名密钥 APPROVAL_CALLBACK_SECRET=YOUR_CALLBACK_SECRET在 trueforge 的工具配置里,MCP server 的凭据应该由运行时注入,而不是写在SKILL.md或前端可读的配置里。若你的 MCP server 需要访问数据库,请只给它只读账号,并明确禁止 agent 直连生产库。SQL 和运维命令由读者在本地或受控终端执行,agent 只拿结果,不拿写权限。
一个常见的错误配置是:为了让 agent “更方便”,把数据库连接串直接塞进 MCP server 的env,然后让 agent 生成 SQL 并执行。这样做等于把生产库的写权限交给了一个可能被 prompt injection 影响的执行循环。正确做法是分三层:
- agent 只调用一个“查询建议”工具,输出 SQL 文本;
- 审批流由人工在受控界面确认;
- 实际 SQL 由读者本地或专用只读执行器执行,结果再回灌给 agent。
trueforge 的人工检查点正好可以用在这里。把“执行 SQL”这个动作设为需要审批,审批通过后也只调用只读账号。工具认证的 scope 要写成read,不要为了省事写admin。
5. Claude Code、Codex、CC Switch 三件套的配置差异
很多团队同时在用 trueforge、Claude Code、Codex,还有 CC Switch 做配置切换。这里最容易踩的坑是变量名串台:把ANTHROPIC_*套到 Codex 上,或者把 Codex 的config.toml当成 Claude Code 的 settings.json 改。下面分开写。
Claude Code 用settings.json和ANTHROPIC_*系列变量。典型配置:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "your-model-name" } }这里ANTHROPIC_AUTH_TOKEN放的是 TaoToken 控制台生成的 Key 占位符。不要把ANTHROPIC_BASE_URL写成带 UTM 的官网地址;UTM 只用于文档链接,Base URL 保持https://taotoken.net/api。
Codex 用config.toml,不要写ANTHROPIC_*。示例:
model = "your-model-name" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY"然后在 shell 或密钥管理里导出:
export TAOTOKEN_API_KEY=YOUR_API_KEYCC Switch 三件套通常指全局配置、项目级配置、凭据引用这三类文件。无论你用哪一版 CC Switch,原则都是:三件套里只放环境变量名和 base URL,不放明文 Key。建议做一张对照表:
| 工具 | 主配置 | 认证变量 | Base URL |
|---|---|---|---|
| Claude Code | settings.json | ANTHROPIC_AUTH_TOKEN | https://taotoken.net/api |
| Codex | config.toml | TAOTOKEN_API_KEY | https://taotoken.net/api |
| trueforge | 模型 provider 配置 | TAOTOKEN_API_KEY | https://taotoken.net/api |
| CC Switch | 三件套中的 env 引用 | 指向系统环境变量 | 不重复写 Key |
这样切换工具时,只改配置引用,不复制 Key。应用安全工程师要特别检查:不要为了让 Codex 跑起来,把 Claude Code 的ANTHROPIC_AUTH_TOKEN改名为OPENAI_API_KEY就塞进去。变量名不对应,出错时日志会误导排查方向。
6. Key 轮换检查表:从创建到撤销的 9 个动作
Key 轮换不是“过 90 天换一次”这么简单。对 agent 系统,轮换要兼顾会话连续性和审计可追溯性。下面是一张可以直接贴到 runbook 的检查表。
| 阶段 | 动作 | 判定标准 |
|---|---|---|
| 1. 创建 | 在 TaoToken 控制台创建新 Key,命名带环境和用途,如prod-trueforge-model-2026q3 | 不与其他环境共用 |
| 2. 登记 | 记录 Key ID、创建人、用途、关联服务 | 不记录完整 Key 明文 |
| 3. 注入 | 通过 secrets manager / 环境变量注入,不写入代码库 | git grep无明文 |
| 4. 灰度 | 先切一个非关键 agent 实例,观察 401、429、延迟 | 错误率不高于基线 |
| 5. 全量 | 批量更新 trueforge 实例并滚动重启 | 无会话状态丢失 |
| 6. 观察 | 观察 24 小时,检查模型调用日志和工具调用日志 | 无异常来源 |
| 7. 撤销 | 在控制台禁用旧 Key | 旧 Key 请求全部 401 |
| 8. 审计 | 检查旧 Key 在禁用前是否有未知调用 | 无异常 IP、无越权工具 |
| 9. 复盘 | 更新轮换记录,必要时缩短周期 | 周期与风险匹配 |
轮换时特别容易忽略两点。第一,trueforge 的本地模式可能用 SQLite 存会话;如果你直接删容器,会话状态会丢。轮换 Key 之前先确认会话存储位置和备份策略。第二,MCP 工具 Key 和模型 Key 的轮换节奏可以不同,但必须在同一张表里登记。否则半年后没人知道哪个 Key 对应哪个工具。
如果你使用托管模式,Postgres + Redis 的环境里,建议把 Key 轮换和 OIDC 登录分开:OIDC 管“谁在使用 trueforge”,TaoToken Key 管“trueforge 用什么调用模型”。两者混淆会导致权限模型失控。
7. 生产边界与审计:本地模式、托管模式、日志脱敏
trueforge 的本地模式是一条命令起的单进程,默认没有登录,数据落在本地文件。官方定位是试用,不是生产配置,应该留在 localhost。如果你要把聊天 UI 共享给同事,或者让 agent 接内部知识库,请切到托管模式:Postgres + Redis + OIDC 登录。认证管理也要同步升级。
从应用安全视角,至少做四件事:
第一,环境变量不是保险箱。容器里/proc/1/environ可能被同主机进程读取,所以生产环境优先用 secrets manager 或编排平台的原生 secret。环境变量模板是第一层,不是唯一一层。
第二,日志脱敏。trueforge 会记录模型调用和工具调用。你需要确保Authorization、api_key、token字段被打码。可以在日志管道里加过滤规则:
# 示例:本地日志脱敏检查 grep -R "Bearer \|api_key\|TAOTOKEN_API_KEY" ./logs \ | sed -E 's/(Bearer )[A-Za-z0-9._-]+/\1***/g' \ | head -n 20第三,最小网络出口。模型请求只允许访问https://taotoken.net/api,工具请求只允许访问内部工具域名。不要给 agent 容器开放全量出网,否则 Key 泄露后的外传路径会很多。
第四,审批与审计分离。关键操作前的审批记录、工具调用记录、模型调用记录要能关联到同一个会话 ID。这样出现异常时,你能回答三个问题:谁触发的、调用了哪个模型、动了哪个工具。
8. 一次完整接入核对:从模型对话到 Claude Code 文档
最后给一条核对路径。先到 TaoToken 官网(https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=trueforge_env_checklist)确认账号和 Key 状态,然后按顺序做四步:
- 打开模型对话,验证 Key 能正常调用模型;
- 查看 Coding Plan,确认 agent 场景的用量和权限边界;
- 到 API Keys 页面创建或轮换专用 Key;
- 对照 Claude Code 文档,把配置写进对应工具。
四个深链如下,按你的实际工具选择:
- 模型对话:https://taotoken.net/models/detail/chat?utm_source=taotoken_aicg_blog_end&utm_content=trueforge_env_chat
- Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=trueforge_env_plan
- 创建 Key:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=trueforge_env_keys
- Claude Code 文档:https://taotoken.net/doc/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=trueforge_env_cc
核对清单可以压缩成一段:
[ ] .env 已加入 .gitignore,权限 600 [ ] TAOTOKEN_API_KEY 只存在于模型进程 [ ] TAOTOKEN_BASE_URL=https://taotoken.net/api,不带 UTM [ ] MCP 工具使用独立 Key,scope 最小化 [ ] agent 不直连生产库,SQL 由本地/只读执行器执行 [ ] Claude Code 使用 settings.json + ANTHROPIC_* [ ] Codex 使用 config.toml,不使用 ANTHROPIC_* [ ] CC Switch 三件套不存明文 Key [ ] Key 轮换表已登记 Key ID、用途、负责人 [ ] 日志已脱敏,模型调用与工具调用可审计trueforge 解决的是让 agent“跑起来、跑稳、跑安全”的脏活,而认证管理是其中最容易在演示阶段被跳过、在生产阶段爆发的一环。把 TaoToken Key 放进环境变量只是起点,真正的终点是:每个 agent、每个工具、每次调用都有清晰的凭据边界,Key 可以轮换,日志可以审计,故障可以定位。做到这些,你才敢让 agent 离开 localhost。