
1. 为什么我要把 Fetch 和 Playwright 塞进同一个 Trae 智能体API 文档和 API 测试这两件事长期被拆成两条流水线一边是手写 Markdown 或 Swagger 注释另一边是 Postman 集合或 Jest 脚本。结果是文档写完就过期测试脚本里的断言和文档里的示例字段对不上联调时后端说“我返回的是user_id”前端说“文档写的是userId”。我试过用纯 Fetch 脚本抓响应再手写文档也试过只用 Playwright 跑端到端但两者割裂时文档里的示例响应永远是“理想态”不是真实抓下来的那一份。这个 Trae 智能体的思路很直接用 Fetch 做“探针”真实请求一遍接口把状态码、响应头、响应体原样落盘再用 Playwright 做“回放器”把同一批请求放进真实浏览器上下文里跑断言验证的不只是 JSON 结构还有跨域、Cookie、重定向、CORS 预检这些只在浏览器里才暴露的问题。最后把两份数据合并成一份文档示例代码里的响应片段直接来自 Fetch 的实测结果测试报告里的失败用例直接指向 Playwright 的 trace。适合谁用如果你手里有一组 REST 接口文档靠人肉维护测试靠手动点或者你已经在用 Trae 但只把它当补全工具那这套配置能让你在一个智能体里完成“抓取—生成—验证—回放”闭环。核心检索词就三个Fetch 抓真实响应、Playwright 驱动浏览器验证、Trae 智能体做编排。下面所有配置和脚本都可以直接复制唯一需要你替换的是自己的接口地址和模型通道。2. 前置准备TaoToken 统一 Key 与 Trae 的 MCP endpoint 改造Trae 智能体本身不绑定模型供应商它通过 MCPModel Context Protocol或 OpenAI 兼容通道去调模型。默认情况下你可能在 Trae 里填的是某家官方 endpoint但一旦你要在智能体里同时跑 Fetch 抓取和 Playwright 回放模型调用量会上去尤其是让模型去解析 OpenAPI 片段、生成断言、总结失败原因时。这时候把 MCP endpoint 改到 TaoToken 的统一通道好处是 Key 和 Base URL 只维护一份智能体里所有模型调用走同一个入口不用在多个供应商之间切换配置。TaoToken 的 API 地址是https://taotoken.net/api注意这个地址不带任何查询参数直接作为 Base URL 用。官网入口在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content里面可以拿到 API Key 和查看当前支持的模型 ID。你需要在 TaoToken 控制台创建一个 Key然后回到 Trae 的 MCP 配置或模型设置里把原来的 endpoint 替换掉。这里有个容易踩的坑Trae 的 MCP 配置分两种形态一种是 JSON 格式的mcp.json一种是 TOML 格式的config.toml取决于你用的是 Trae 的哪个版本或插件形态。不管哪种核心三件套都是 Base URL、API Key、Model ID。Base URL 填https://taotoken.net/apiKey 填你在控制台生成的sk-开头的字符串Model ID 填你打算让智能体调用的模型标识比如claude-sonnet-4-20250514或gpt-4o这类具体以 TaoToken 控制台展示的为准。如果你用的是 Claude Code 形态的 Trae 插件配置会落在~/.claude/settings.json或项目级的.claude/settings.json里里面有一个env段需要写ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY。如果是 Codex 形态配置在~/.codex/auth.json字段是OPENAI_BASE_URL和OPENAI_API_KEY。下面第三节我会给出三种形态的可复制片段你按自己实际用的那个抄。改完 endpoint 之后Trae 智能体里所有需要模型推理的步骤——比如让模型读 OpenAPI 的paths段、生成 Playwright 断言、把 Fetch 的响应体转成文档示例——都会走 TaoToken 通道。这样你不需要在智能体代码里硬编码多个 Key也不用担心某个供应商的额度突然用完导致整个文档生成流程中断。3. 可复制配置Trae 智能体 MCP endpoint 三件套这一节给的是可以直接粘贴的配置片段。先明确一点Trae 智能体的“智能”部分依赖模型调用而 Fetch 和 Playwright 是本地 Node.js 脚本两者通过智能体的工具调用tool use串起来。所以配置分两层一层是 Trae 的模型通道配置一层是智能体项目里的package.json和脚本骨架。3.1 Trae MCP 配置JSON 形态如果你在 Trae 里用的是mcp.json来注册模型服务把下面这段里的your-api-key换成 TaoToken 控制台生成的 Keymodel-id换成你要用的模型标识。注意baseUrl结尾不要带斜杠也不要带/v1TaoToken 的兼容层会自动处理路径。{ mcpServers: { taotoken: { command: npx, args: [-y, taotoken/mcp-server], env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: your-api-key, TAOTOKEN_MODEL_ID: model-id } } } }如果你不想用 MCP server 包而是直接让 Trae 走 OpenAI 兼容通道那就在 Trae 的模型设置里填{ provider: openai-compatible, baseUrl: https://taotoken.net/api, apiKey: your-api-key, model: model-id }3.2 Claude Code 形态的 settings.jsonTrae 如果以 Claude Code 插件形态运行配置落在settings.json的env段。路径通常是~/.claude/settings.json项目级则是.claude/settings.json。把下面片段合并进去{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: your-api-key, ANTHROPIC_MODEL: model-id } }3.3 Codex 形态的 auth.jsonCodex 形态的配置在~/.codex/auth.json字段名不同但三件套逻辑一样{ OPENAI_BASE_URL: https://taotoken.net/api, OPENAI_API_KEY: your-api-key, OPENAI_MODEL: model-id }3.4 智能体项目的 package.json 与脚本骨架在 Trae 里新建一个智能体项目目录初始化package.json把 Fetch 和 Playwright 的依赖装进去。Node.js 18 以上自带全局fetch但为了在 Playwright 测试文件里也能用建议显式装node-fetch作为兜底。Playwright 装playwright/test即可不需要装浏览器二进制的话可以跳过npx playwright install但要做真实浏览器回放就必须装。{ name: trae-api-doc-agent, version: 1.0.0, type: module, scripts: { fetch: node scripts/fetch-spec.js, test: playwright test, doc: node scripts/gen-doc.js }, dependencies: { node-fetch: ^3.3.2 }, devDependencies: { playwright/test: ^1.44.0 } }Fetch 脚本骨架scripts/fetch-spec.js作用是读 OpenAPI 文件、逐个请求接口、把真实响应落盘到fixtures/目录import fs from node:fs/promises; import path from node:path; const SPEC_PATH process.env.SPEC_PATH || ./openapi.json; const OUT_DIR ./fixtures; const BASE_URL process.env.API_BASE_URL || http://localhost:3000; async function loadSpec() { const raw await fs.readFile(SPEC_PATH, utf-8); return JSON.parse(raw); } async function probe(pathname, method GET) { const url ${BASE_URL}${pathname}; const res await fetch(url, { method }); const body await res.text(); let json null; try { json JSON.parse(body); } catch {} return { url, method, status: res.status, headers: Object.fromEntries(res.headers.entries()), body: json ?? body }; } async function main() { const spec await loadSpec(); await fs.mkdir(OUT_DIR, { recursive: true }); const results []; for (const [pathname, methods] of Object.entries(spec.paths || {})) { for (const method of Object.keys(methods)) { if (method parameters) continue; const result await probe(pathname, method.toUpperCase()); results.push(result); const safeName ${method}_${pathname.replace(/\//g, _)}.json; await fs.writeFile(path.join(OUT_DIR, safeName), JSON.stringify(result, null, 2)); } } await fs.writeFile(path.join(OUT_DIR, _summary.json), JSON.stringify(results, null, 2)); console.log(probed ${results.length} endpoints); } main().catch(err { console.error(err); process.exit(1); });Playwright 测试骨架tests/api.spec.js作用是读fixtures/_summary.json对每个接口回放请求并断言状态码和关键字段import { test, expect } from playwright/test; import fs from node:fs; const summary JSON.parse(fs.readFileSync(./fixtures/_summary.json, utf-8)); for (const item of summary) { test(${item.method} ${item.url} 回放验证, async ({ request }) { const res await request.fetch(item.url, { method: item.method }); expect(res.status()).toBe(item.status); const body await res.json().catch(() null); if (body typeof body object) { expect(body).toHaveProperty(id); } }); }这三个片段合在一起就是“Fetch 抓取 Playwright 回放 Trae 编排”的最小可运行单元。Trae 智能体的角色是在你运行npm run fetch之后读fixtures/_summary.json让模型生成文档的“响应示例”段落并在 Playwright 测试失败时读 trace 给出排查建议。4. 验证请求从抓取到回放的端到端跑通配置写完之后需要一次真实的端到端验证确认 Fetch 抓到的响应和 Playwright 回放的结果一致并且 Trae 智能体能正确读取这些数据。我拿一个本地跑的用户服务做例子接口是GET /users/1返回{ id: 1, name: Alice, email: aliceexample.com }。第一步准备一个最小的openapi.json只写一个 path{ openapi: 3.0.0, info: { title: Demo API, version: 1.0.0 }, paths: { /users/1: { get: { summary: 获取用户信息, responses: { 200: { description: 成功, content: { application/json: { schema: { type: object, properties: { id: { type: integer }, name: { type: string }, email: { type: string } } } } } } } } } } }第二步设置环境变量并跑 Fetchexport API_BASE_URLhttp://localhost:3000 export SPEC_PATH./openapi.json npm run fetch跑完之后fixtures/目录下会出现get__users_1.json和_summary.json。打开get__users_1.json你应该看到类似这样的内容{ url: http://localhost:3000/users/1, method: GET, status: 200, headers: { content-type: application/json; charsetutf-8, content-length: 72 }, body: { id: 1, name: Alice, email: aliceexample.com } }这个body就是真实抓下来的响应不是手写的示例。接下来 Trae 智能体读这个文件让模型把body转成文档里的“响应示例”代码块同时根据headers里的content-type决定示例代码的语言标记。第三步跑 Playwright 回放npx playwright test tests/api.spec.js --reporterlist如果本地服务正常你会看到类似输出Running 1 test using 1 worker ✓ 1 tests/api.spec.js:7:3 › GET http://localhost:3000/users/1 回放验证 (45ms) 1 passed (1.2s)这个✓表示 Playwright 在真实请求上下文里重新发了一次请求状态码和id字段都匹配 Fetch 抓取时的结果。如果这里失败比如状态码从 200 变成 404说明接口在两次请求之间发生了变化或者 Fetch 抓取时用了缓存而 Playwright 没有。第四步让 Trae 智能体生成文档。在 Trae 对话框里输入类似这样的指令“读取 fixtures/_summary.json为每个接口生成 Markdown 文档包含请求方法、路径、状态码、响应示例响应示例直接使用 body 字段的内容。” 智能体会调用模型走 TaoToken 通道把 JSON 转成结构化文档。你可以在docs/目录下看到生成的api.md里面的响应示例和get__users_1.json里的body完全一致。这一步验证的核心是Fetch 负责“真实数据”Playwright 负责“真实回放”Trae 负责“真实编排”。三者串起来之后文档里的示例不再是编的测试里的断言不再是猜的。5. 常见报错排查401、local proxy failed、reading choices、OAuth这一节列的是我在把 MCP endpoint 改到 TaoToken 并跑 Fetch/Playwright 时实际遇到的报错以及对应的排查路径。每个报错都给出触发场景和修复动作。5.1 401 Unauthorized触发场景Trae 智能体调模型时返回 401或者 Fetch 请求目标 API 时返回 401。要区分是模型通道的 401 还是业务 API 的 401。如果是模型通道的 401检查TAOTOKEN_API_KEY或ANTHROPIC_API_KEY是否填对Key 是否以sk-开头是否在 TaoToken 控制台被禁用。常见错误是把 Key 填到了baseUrl字段里或者 Key 前后带了空格。修复方式是重新复制 Key确认baseUrl是https://taotoken.net/apiKey 单独放在apiKey字段。如果是业务 API 的 401检查 Fetch 脚本里有没有带Authorization头。很多内部接口需要 Bearer Token而 OpenAPI 文件里可能没写securitySchemes。修复方式是在probe函数里加一个headers参数从环境变量读 Tokenconst res await fetch(url, { method, headers: { Authorization: Bearer ${process.env.API_TOKEN} } });5.2 local proxy failed触发场景Trae 在启动 MCP server 时提示local proxy failed或connection refused。这通常是因为 MCP server 进程没起来或者端口被占用。排查步骤先在终端手动跑npx -y taotoken/mcp-server看是否报错。如果报EADDRINUSE说明端口被占换一个端口或杀掉占用进程。如果报Cannot find module说明包没装成功检查网络或换 npm 源。如果手动跑能起来但 Trae 里报 proxy failed检查 Trae 的 MCP 配置里command和args是否写对env里的变量是否被正确传递。另一个常见原因是 Trae 的代理设置和系统代理冲突。如果你在 Trae 设置里开了“使用系统代理”而系统代理指向了一个不可用的地址MCP server 启动时会连不上。修复方式是在 Trae 设置里关掉代理或者把NO_PROXY环境变量设为localhost,127.0.0.1。5.3 reading choices 报错触发场景Trae 智能体在解析模型返回时提示reading choices或Cannot read properties of undefined (reading choices)。这说明模型通道返回的 JSON 结构不是 OpenAI 兼容格式智能体按choices[0].message.content去读结果choices是 undefined。根因通常是 Base URL 填错了。比如填了https://taotoken.net/api/v1/chat/completions作为 baseUrl而智能体又在这个 baseUrl 后面拼/chat/completions导致请求路径变成/api/v1/chat/completions/chat/completions返回 404 或非标准结构。修复方式是 baseUrl 只填https://taotoken.net/api不要带/v1或/chat/completions。如果 baseUrl 正确但仍然报这个错检查模型 ID 是否在 TaoToken 控制台的支持列表里。填了一个不存在的模型 ID有些兼容层会返回错误对象而不是标准 choices 结构。修复方式是去 TaoToken 控制台复制准确的模型 ID。5.4 OAuth 相关报错触发场景Trae 提示OAuth token expired或invalid_grant。这通常发生在你用 Claude Code 形态的 Trae 插件且之前登录过官方账号缓存了 OAuth token。改到 TaoToken 通道后旧的 OAuth token 还在插件优先用 OAuth 而不是 API Key。修复方式是清掉本地 OAuth 缓存。Claude Code 形态的缓存通常在~/.claude/下的credentials.json或oauth.json删掉这两个文件然后重启 Trae。Codex 形态的缓存在~/.codex/下同样删掉auth.json里除OPENAI_BASE_URL和OPENAI_API_KEY之外的字段或者直接重建auth.json。如果删掉缓存后仍然报 OAuth 错检查 Trae 的设置里有没有“使用官方登录”的开关把它关掉强制走 API Key 模式。5.5 Playwright 回放时超时触发场景npx playwright test报Timeout 30000ms exceeded。这通常是因为 Fetch 抓取时接口响应很快但 Playwright 回放时接口变慢或者 Playwright 默认等待网络空闲。修复方式是在playwright.config.js里调大timeout或者在测试文件里给单个 test 加test.setTimeout(60000)。另一个原因是 Playwright 默认会等load事件而 API 请求没有页面加载可以改用requestfixture 而不是pagefixture前者不会等页面事件。test.setTimeout(60000);如果超时发生在request.fetch上检查目标 API 是否对 Playwright 的 User-Agent 做了限制。有些服务会拦截非浏览器 UA修复方式是在request.fetch的 options 里加headers: { User-Agent: Mozilla/5.0 }。6. 把通道固定下来TaoToken 在 Trae 智能体里的长期用法跑通一次端到端之后接下来要考虑的是怎么让这套配置稳定用下去。我的做法是把 TaoToken 的 Base URL 和 Key 写进项目级的.env文件而不是散落在 Trae 的全局设置里。这样每个智能体项目可以有自己的模型通道配置切换项目时不会互相干扰。.env文件内容TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYyour-api-key TAOTOKEN_MODEL_IDmodel-id API_BASE_URLhttp://localhost:3000 API_TOKENyour-business-token然后在 Trae 的 MCP 配置里用${env:TAOTOKEN_API_KEY}这种变量引用方式而不是硬编码。这样 Key 不会出现在mcp.json里提交到 Git 时也不会泄露。对于长期跑文档生成和测试回放的场景可以考虑把 Fetch 和 Playwright 放进 CI每次代码提交后自动跑一遍把fixtures/_summary.json和 Playwright 报告作为构建产物。Trae 智能体在本地读这些产物生成文档CI 里只跑脚本不调模型这样模型调用量可控文档更新和测试验证解耦。如果你需要更细粒度的模型调用控制比如让文档生成用便宜模型、失败分析用强模型可以在 Trae 智能体里配置多个 MCP server每个指向 TaoToken 的不同模型 ID。Base URL 都是https://taotoken.net/api只是TAOTOKEN_MODEL_ID不同。智能体根据任务类型选择对应的 server。最后提醒一点Fetch 抓取和 Playwright 回放都会真实请求你的业务 API如果接口有写操作POST/PUT/DELETE务必在测试环境跑或者用 OpenAPI 里的x-test-only标记过滤掉写接口。文档生成阶段只读fixtures/里的落盘数据不会触发额外请求所以文档生成可以放心在本地跑。