1. OpenClaw 浏览器自动化里那些被 Key 拖垮的调用链
OpenClaw 是一个把浏览器操作封装成工具调用的自动化框架,你可以用browser({ action: "navigate" })这类指令驱动真实 Chrome 完成导航、填表、截图、抓取。它适合需要批量操作网页、做数据采集、跑回归测试的开发者,也适合把网页操作接进 Agent 工作流的人。但真正上手之后,很多人卡住的地方不是浏览器本身,而是散落在各处的 API Key。
我见过最典型的场景是这样的:OpenClaw 负责打开页面、定位元素、点击提交,页面里的内容处理又要调模型做摘要或抽取,于是项目里同时存在 OpenClaw 的 gateway token、模型服务的 key、可能还有另一个工具的 key。每个工具一套鉴权,配置文件写三份,环境变量命名还不统一。结果就是调用链在第三步断掉——浏览器动作成功了,模型调用返回 401,整个任务卡死,日志里只有一句unauthorized。
这种断裂不是配置写错,而是架构上把「浏览器控制」和「模型调用」当成了两个互不相干的系统。OpenClaw 的openclaw.json管的是 gateway 和 browser profile,模型侧管的是另一套 endpoint 和 key。两边都要维护,任何一边轮换密钥,另一边就得跟着改。多人协作时更麻烦,A 改了 key 没同步,B 拉下来跑不通,排查半天发现是环境变量没更新。
TaoToken 在这里的作用是把模型侧的鉴权收敛成一个统一入口。你不再需要为每个工具单独申请和轮换 key,而是用同一个 Key 去访问兼容的模型接口,OpenClaw 的浏览器动作和后续的模型处理走同一条鉴权链路。这样调用链从「浏览器 → 模型 A → 模型 B」变成「浏览器 → 统一网关 → 任意模型」,断点少了一个数量级。
具体来说,OpenClaw 的 browser 工具负责页面交互,模型调用负责理解页面内容、生成下一步动作、或者对抓取结果做结构化。这两段如果共用一套 Base URL 和 Key,配置就只需要维护一份。下面我会先讲 TaoToken 的接入准备,再给出可直接复制的 OpenClaw 配置片段,然后跑一个完整的浏览器自动化任务验证链路是否打通,最后把常见的报错对照列出来。
需要提前说明的是,OpenClaw 的浏览器 profile 配置和模型 Key 配置是两个层面的事。profile 决定用哪个浏览器实例、是否复用登录态;Key 决定模型调用能不能过鉴权。两者都配好,调用链才完整。很多人只配了 profile 就以为万事大吉,结果模型那一步直接 401,还以为是浏览器没启动。
2. TaoToken 前置准备:统一 Key 与 Base URL 的获取
在改 OpenClaw 配置之前,先把模型侧的鉴权信息准备好。TaoToken 提供的是兼容 OpenAI 风格的接口,所以你需要的是三样东西:Base URL、API Key、以及你要调用的 Model ID。这三样在 OpenClaw 的模型配置里会用到,在环境变量里也会用到。
Base URL 固定为https://taotoken.net/api,注意这里不带任何查询参数,就是干净的接口根地址。API Key 需要你在控制台里创建,创建之后只显示一次,复制下来存到安全的地方。Model ID 取决于你要用哪个模型,比如做网页内容摘要和结构化抽取,选一个上下文够长、指令跟随稳定的就行。
创建 Key 的入口在控制台的 API Keys 页面,路径是https://taotoken.net/console/api-keys。进去之后点新建,给它起个能认出来的名字,比如openclaw-browser-auto,方便以后按项目区分。创建完立刻复制,页面刷新后就看不到了。
拿到 Key 之后,建议先不要急着写进 OpenClaw 配置,而是用环境变量验证一次。这样能排除 Key 本身的问题,避免后面在 OpenClaw 里排查半天发现是 Key 复制错了。验证方式很简单,用 curl 发一个最小的 chat completions 请求:
export TAOTOKEN_API_KEY="sk-你的实际key" export TAOTOKEN_BASE_URL="https://taotoken.net/api" curl -s "$TAOTOKEN_BASE_URL/v1/chat/completions" \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "reply with ok"}], "max_tokens": 10 }'如果返回里能看到choices数组和正常的 content,说明 Key 和 Base URL 都没问题。如果返回 401,先检查 Key 有没有多余空格、是不是复制完整;如果返回 404,检查 Base URL 是不是写成了带/v1的完整路径——注意 TaoToken 的 Base URL 是https://taotoken.net/api,具体路径在调用时补/v1/chat/completions。
这一步过了之后,把这两个环境变量写进你的 shell 配置文件,比如~/.zshrc或~/.bashrc,这样 OpenClaw 启动时能直接读到。Windows 用户可以在系统环境变量里加,或者用 PowerShell 的$env:临时设置。环境变量命名建议统一用TAOTOKEN_API_KEY和TAOTOKEN_BASE_URL,后面 OpenClaw 配置里引用这两个名字,轮换 Key 的时候只改环境变量,不动配置文件。
如果你还要用 Coding Plan 跑长期的编码或 Agent 任务,可以在控制台里单独看 Coding Plan 的入口,它和按量调用的 Key 是分开管理的。浏览器自动化这种短任务用按量 Key 就够了,长期跑的 Agent 再考虑 Coding Plan。
3. 可复制配置:openclaw.json 与模型 Key 的对接写法
OpenClaw 的配置文件在~/.openclaw/openclaw.json,Windows 下是C:\Users\你的用户名\.openclaw\openclaw.json。这个文件同时管 gateway、browser profile 和插件。我们要做的是在保留 browser 配置的同时,把模型调用的 Base URL 和 Key 接进来。
先看完整的配置结构。下面这份可以直接复制,把sk-你的实际key替换成你自己的,其余字段按需调整:
{ "gateway": { "mode": "local", "auth": { "mode": "token", "token": "your-gateway-token" }, "remote": { "token": "your-gateway-token" } }, "browser": { "enabled": true, "defaultProfile": "openclaw", "headless": false, "profiles": { "openclaw": { "driver": "openclaw", "cdpPort": 18800, "color": "#4ECDC4" }, "my-logged-in-chrome": { "driver": "existing-session", "attachOnly": true, "cdpUrl": "http://localhost:9222", "color": "0000FF" } } }, "models": { "default": { "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的实际key", "model": "gpt-4o-mini" } }, "plugins": { "entries": { "browser": { "enabled": true } } } }这里有几个点要说明。gateway.auth.token和gateway.remote.token必须保持一致,这是 OpenClaw 内部 gateway 的鉴权,和模型 Key 是两回事,不要混。browser.profiles里我保留了托管模式和已登录 Chrome 模式两个 profile,托管模式用openclaw,已登录模式用my-logged-in-chrome,后面验证时两个都会用到。
models.default这一段是模型调用的入口。baseUrl写https://taotoken.net/api,apiKey写你创建的那个 Key,model写你要用的 Model ID。如果你不想把 Key 明文写在配置文件里,可以把apiKey的值改成环境变量引用,比如"apiKey": "${TAOTOKEN_API_KEY}",OpenClaw 启动时会从环境变量里读。这样配置文件可以进版本库,Key 留在本地环境变量里。
如果你同时要驱动多个模型,比如一个做摘要、一个做代码生成,可以在models下面加多个条目:
"models": { "default": { "baseUrl": "https://taotoken.net/api", "apiKey": "${TAOTOKEN_API_KEY}", "model": "gpt-4o-mini" }, "coder": { "baseUrl": "https://taotoken.net/api", "apiKey": "${TAOTOKEN_API_KEY}", "model": "claude-3-5-sonnet" } }调用时指定model: "coder"就会走第二个条目。Base URL 和 Key 是共用的,只有 Model ID 不同,这就是统一 Key 的好处——加模型不用加鉴权配置。
改完配置后重启 gateway:
openclaw gateway restart重启后看日志确认没有报错:
openclaw logs --follow如果日志里出现gateway connect failed: unauthorized,那是 gateway token 的问题,检查auth.token和remote.token是否一致。如果出现模型相关的 401,那是models.default.apiKey的问题,检查 Key 是否正确、环境变量是否被读到。
4. 验证请求:一次完整的浏览器自动化任务
配置改完,跑一个完整的任务来验证调用链。这个任务包含浏览器导航、页面快照、表单填写、模型处理四个环节,能覆盖大部分实际场景。
先确认 gateway 在跑,浏览器 profile 可用:
openclaw gateway status然后启动浏览器,用托管模式:
browser({ action: "start", profile: "openclaw" })检查状态,确认running和cdpReady都是 true:
browser({ action: "status" })返回类似这样:
{ "enabled": true, "profile": "openclaw", "running": true, "cdpReady": true, "pid": 18680, "cdpPort": 18800, "userDataDir": "C:\\Users\\xxx\\.openclaw\\browser\\openclaw\\user-data" }接下来导航到一个页面并获取快照。这里用百度做例子,因为结构简单、元素稳定:
browser({ action: "navigate", url: "https://www.baidu.com" }) browser({ action: "snapshot" })快照会返回页面结构,类似:
- document: - link "新闻" [ref=e1] - textbox [ref=e13] - button "搜索" [ref=e14]拿到 ref 之后填表单并点击:
browser({ action: "act", request: { kind: "type", ref: "e13", text: "OpenClaw 浏览器自动化" } }) browser({ action: "act", request: { kind: "click", ref: "e14" } }) browser({ action: "wait", timeMs: 1500 }) browser({ action: "snapshot" })到这里浏览器动作全部完成。接下来是模型处理环节——把快照里的搜索结果文本抽出来,调模型做结构化。这一步验证的就是 TaoToken 的 Key 有没有生效:
const snapshotText = `搜索结果页面快照内容...`; const response = await fetch("https://taotoken.net/api/v1/chat/completions", { method: "POST", headers: { "Authorization": `Bearer ${process.env.TAOTOKEN_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ model: "gpt-4o-mini", messages: [ { role: "system", content: "从搜索结果中提取前三条标题和链接,输出 JSON 数组。" }, { role: "user", content: snapshotText } ], max_tokens: 500 }) }); const data = await response.json(); console.log(data.choices[0].message.content);如果这一步返回了结构化的 JSON,说明整条链路通了:浏览器导航成功、快照获取成功、模型调用鉴权通过、结果返回正常。如果模型这一步报 401,回到第 3 节检查models.default.apiKey和环境变量;如果报reading choices,说明返回体里没有choices字段,通常是请求体格式不对或者模型名写错了。
最后关掉浏览器:
browser({ action: "stop" })整个流程跑通一次,后面就可以把这段逻辑封装成函数,换不同的 URL 和模型重复使用。托管模式的浏览器生命周期是自动管理的,gateway 在跑的时候浏览器保持运行,gateway 关闭时自动清理,不需要手动 kill 进程。
5. 常见报错对照:401、local proxy failed 与 reading choices
配置和验证过程中最容易撞上的几个报错,这里逐个对照。每个报错都给出触发条件和排查路径,照着查基本能定位。
401 unauthorized是最常见的。分两种情况:一种是 gateway 的 401,日志里写gateway connect failed: unauthorized,原因是gateway.auth.token和gateway.remote.token不一致。解决方法是把两个字段改成同一个值,然后openclaw gateway restart。另一种是模型调用的 401,返回体里写invalid api key或unauthorized,原因是models.default.apiKey不对,或者环境变量TAOTOKEN_API_KEY没被读到。检查方法是先在终端里echo $TAOTOKEN_API_KEY确认变量有值,再用第 2 节的 curl 命令单独验证 Key。
local proxy failed通常出现在 gateway 启动阶段,日志里写local proxy failed to start或类似。原因是本地端口被占用,或者 gateway 进程残留。OpenClaw 的 gateway 默认监听本地端口,如果之前有进程没退干净,新进程起不来。解决方法是先openclaw gateway stop,确认没有残留进程,再openclaw gateway restart。Windows 下可以用netstat -ano | findstr :端口号查占用,macOS/Linux 用lsof -i :端口号。
reading choices是模型返回体解析失败,报错类似Cannot read properties of undefined (reading 'choices')。原因是返回的 JSON 里没有choices字段。常见触发条件有三个:请求体里model字段写了一个不存在的 Model ID;messages格式不对,比如少了role或content;Base URL 写错,请求打到了别的路径返回了 HTML 而不是 JSON。排查方法是把请求体打印出来,用 curl 单独发一次,看返回的原始内容是什么。如果返回的是 HTML,说明 URL 不对;如果返回 JSON 但没有choices,看error字段里的提示。
OAuth 相关报错一般出现在已登录 Chrome 模式。如果你用my-logged-in-chromeprofile 去操作需要登录的网站,而 Chrome 的远程调试端口没开或者登录态失效,会报Could not connect to Chrome或OAuth token expired。解决方法是先完全关闭 Chrome,再用--remote-debugging-port=9222重新启动,确认http://127.0.0.1:9222/json/version能返回版本信息。如果登录态确实过期了,手动在 Chrome 里重新登录一次,再跑自动化。
Element not found是元素 ref 失效。快照里的 ref 是动态生成的,页面刷新或跳转后 ref 会变。解决方法是每次操作前重新snapshot,用最新的 ref。不要缓存 ref 跨页面使用。
timeout是页面加载慢或模型响应慢。浏览器侧可以在配置里加agents.defaults.timeoutSeconds,默认 300 秒,改成 600 秒:
{ "agents": { "defaults": { "timeoutSeconds": 600 } } }模型侧如果响应慢,检查是不是选了太大的模型或者max_tokens设得过高。浏览器自动化里的模型调用一般不需要很长的输出,max_tokens设 500 到 1000 就够。
把上面这些报错对照表存下来,下次遇到直接查。大部分问题集中在鉴权和端口两件事上,Key 对了、端口通了,链路基本就稳了。
6. 把统一 Key 接进你的 OpenClaw 工作流
配置跑通之后,日常使用就是重复「导航 → 快照 → 操作 → 模型处理」这个循环。统一 Key 的价值在多人协作和长期维护时才真正体现出来:Key 只有一份,轮换时改一个环境变量,所有工具同时生效;新加一个模型只需要在models里加一个条目,不用重新走鉴权流程。
如果你要把这套接进 CI 或者定时任务,建议把TAOTOKEN_API_KEY放在 CI 的 secret 里,配置文件里用${TAOTOKEN_API_KEY}引用,这样配置文件可以进版本库,Key 不落盘。OpenClaw 的 gateway 在 CI 环境里用 headless 模式跑,把browser.headless设成 true,避免没有显示环境时启动失败。
长期跑的 Agent 任务,比如每天定时采集某些页面并做摘要,可以用 Coding Plan 的额度,比按量调用更可控。浏览器自动化本身不消耗模型额度,只有模型处理那一步消耗,所以额度规划主要看模型调用的频率和 token 量。
接入文档在https://taotoken.net/doc,里面有各语言的调用示例和参数说明。API Keys 管理在https://taotoken.net/console/api-keys,轮换 Key 的时候从这里新建再替换环境变量。模型对话的调试入口在https://taotoken.net,可以快速试不同 Model ID 的返回效果,确认哪个模型适合你的页面处理任务。
最后提醒一个实操细节:OpenClaw 的 browser profile 和模型配置是独立的,改模型 Key 不需要重启浏览器,但改openclaw.json里的 browser 部分需要openclaw gateway restart。如果你只轮换了TAOTOKEN_API_KEY环境变量,重启 gateway 让新变量生效就行,浏览器实例不用动。这样日常维护的成本就压到了最低——一个 Key,一份配置,一条调用链。