1. 为什么要把 OpenHands 接到统一 Key 上
OpenHands 是一个能自己动手的 AI 编程工具:你给它一个任务,它会拆解步骤、写代码、在沙箱里跑命令、遇到不懂的还会去浏览网页查资料,最后把结果交给你。它和普通代码补全最大的区别在于「自主执行」——命令真的会被跑起来,网页真的会被打开检索,代码真的会写进文件。适合谁?适合想把重复性工程任务(拉代码、装依赖、跑测试、查报错、改配置)交给 Agent 去跑的人,也适合想研究多智能体协作的开发者。
但很多人卡在第一步:模型通道。OpenHands 默认要你填某个厂商的 API Key,一旦你想换模型、想统一管理额度、想让多个工具共用一套凭证,就得反复改配置。我试过把 OpenHands 的模型出口统一指向 TaoToken 的 API 通道,一套 Key 同时喂给对话、编码和 Agent 场景,配置一次就能长期用。这篇就把完整流程拆开:从拿 Key、写 config.toml 骨架、填 settings.json 关键字段,到启动后怎么验证「命令执行」和「网页检索」真的走通了,最后把常见报错一个个排掉。
核心检索词先摆出来:OpenHands 怎么接入统一 Key、自动执行命令怎么配、网页浏览检索走哪条通道、生成代码用哪个模型名。下面按可跟做的顺序来。
2. TaoToken 前置准备:拿 Key 与确认通道
TaoToken 在这里扮演的是「统一模型出口」的角色:OpenHands 不直接连各家厂商,而是把请求发到 TaoToken 的 API 地址,由它转发到具体模型。这样做的好处是凭证只有一份,换模型只改一个字段,额度也集中看。
第一步,打开官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 注册并登录。登录后进控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在 API Keys 页面创建一个新 Key。建议按用途命名,比如openhands-agent,方便以后区分是哪个工具在用。
创建完立刻复制,Key 通常只完整显示一次。拿到后先别急着填进 OpenHands,用一条 curl 确认通道本身是通的:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的Key" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-3-5-sonnet-20241022", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 16 }'返回里出现choices字段和一段文本,说明 Key 和通道都没问题。如果返回 401,是 Key 复制不全;返回 404,多半是模型名写错。这一步先过,后面 OpenHands 里出问题就能快速定位是工具侧还是通道侧。
注意:API 基础地址用
https://taotoken.net/api,不要带任何查询参数。模型名以控制台「模型列表」里实际可用的为准,别照抄旧文档。
3. 可复制配置:config.toml 骨架与 settings.json 字段
OpenHands 的模型配置有两个落点:一个是运行时的config.toml,一个是界面保存的settings.json。前者决定 Agent 用哪个 LLM,后者保存你在 Web UI 里填的凭证。两个都对齐,才不会出现「界面显示已配置、实际请求还是旧地址」的情况。
先看config.toml骨架。把它放在 OpenHands 的配置目录(Docker 运行时一般是挂载出来的~/.openhands-state下):
[core] workspace_base = "./workspace" max_iterations = 30 cache_dir = "/tmp/cache" [llm] # 统一走 TaoToken 的 API 通道 model = "claude-3-5-sonnet-20241022" base_url = "https://taotoken.net/api" api_key = "sk-你的Key" api_version = "" # 生成代码与命令执行都依赖这个温度,Agent 场景建议偏低 temperature = 0.2 max_input_tokens = 200000 max_output_tokens = 8192 # 网页浏览检索时,模型需要多轮工具调用,超时给足 timeout = 300 [agent] # 允许 Agent 自动执行命令、读写文件、浏览网页 enable_browsing = true enable_cmd = true enable_editor = true关键点解释:base_url指向 TaoToken 的 API 根路径,OpenHands 会自动拼/v1/chat/completions;enable_browsing、enable_cmd、enable_editor三个开关分别对应网页浏览、自动执行命令、生成/修改代码三类操作,缺一个对应能力就哑火。
再看settings.json里要核对的关键字段。这个文件由 Web UI 保存,路径通常在~/.openhands-state/settings.json:
{ "llm_model": "claude-3-5-sonnet-20241022", "llm_api_key": "sk-你的Key", "llm_base_url": "https://taotoken.net/api", "agent": "CodeActAgent", "language": "zh", "sandbox": { "runtime_container_image": "docker.all-hands.dev/all-hands-ai/runtime:0.18-nikolaik", "use_host_network": false }, "security": { "confirmation_mode": false, "enable_auto_lint": true } }llm_base_url和config.toml的base_url必须一致,这是最容易踩的坑:只改了一个,另一个还在指旧地址,请求就会飘。confirmation_mode设为false表示命令自动执行不逐步确认,调试阶段可以先设true观察每一步。
启动命令沿用官方镜像,把状态目录挂出来让配置持久化:
docker run -it --rm --pull=always \ -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.18-nikolaik \ -e LOG_ALL_EVENTS=true \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ~/.openhands-state:/.openhands-state \ -p 3000:3000 \ --add-host host.docker.internal:host-gateway \ --name openhands-app \ docker.all-hands.dev/all-hands-ai/openhands:0.18启动后访问http://localhost:3000,在设置页确认模型名、Key、Base URL 三项和文件里一致。
4. 验证请求:命令执行与网页检索是否走通
配置填完不代表能力可用,得用具体动作验证三类操作。下面三个测试从易到难,建议依次跑。
4.1 验证生成代码
在对话框输入:「在当前工作区创建一个hello.py,打印 1 到 10 的平方,然后运行它」。观察 Agent 是否先写文件、再执行python hello.py。如果它只回复代码文本而不落盘,说明enable_editor没生效或沙箱没起来。
4.2 验证自动执行命令
输入:「列出当前目录所有文件,统计有多少个 .py 文件,把结果写进 count.txt」。这一步会触发ls、find、重定向等命令。成功标志是终端事件流里能看到实际命令和输出,且count.txt真的生成。如果命令一直卡在「等待确认」,检查confirmation_mode是否为false。
4.3 验证网页浏览检索
输入:「去网上查一下 Python 3.12 里itertools.batched的用法,给一个可运行示例」。这一步会触发浏览动作。成功标志是事件流里出现访问网页、抓取内容的记录,并且最终示例能跑通。如果它直接凭记忆回答、没有任何浏览事件,说明enable_browsing没开,或者模型不支持工具调用。
想单独确认通道侧没问题,可以在容器里再打一次 API:
docker exec -it openhands-app curl https://taotoken.net/api/v1/models \ -H "Authorization: Bearer sk-你的Key"能列出模型清单,说明容器网络到 TaoToken 是通的,剩下的问题都在 OpenHands 配置层。
5. 本篇常见错排查
报错一:401 Unauthorized。九成是 Key 问题。检查config.toml和settings.json里的 Key 是否一致、有没有多余空格、是不是复制时漏了尾部字符。重新在控制台生成一个再试。
报错二:404 model not found。模型名写错,或者该模型在你的账号下不可用。去控制台模型列表核对准确名称,注意日期后缀。
报错三:命令不执行,一直转圈。多半是沙箱没起来。检查 Docker 是否正常运行、/var/run/docker.sock是否挂载、runtime 镜像是否拉取成功。看容器日志里有没有sandbox相关错误。
报错四:网页浏览无反应。先确认enable_browsing = true,再确认所选模型支持工具调用。部分轻量模型不支持 function calling,浏览能力会静默失效,换一个支持工具调用的模型即可。
报错五:改了配置不生效。OpenHands 会缓存设置。改完config.toml后重启容器,并在 Web UI 里重新保存一次设置,让settings.json同步。
报错六:请求超时。Agent 多轮工具调用耗时长,把timeout调到 300 以上。网络抖动也会导致超时,重试一次通常能过。
排障时如果怀疑是接入层问题,直接对照接入文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 核对字段;需要重新签发凭证就去 API Keys 页面 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。
6. 按场景选对入口,把配置固化下来
三类操作验证通过后,建议把配置固化:config.toml纳入版本管理(Key 用环境变量注入,别硬编码),settings.json只保留非敏感字段。这样换机器时复制配置、注入 Key 就能跑。
如果你主要是排障和接入调试,重点看 API Keys 和接入文档两个入口;如果只是想先验证模型对话是否正常,用模型对话页面 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite 快速试一句;如果你打算长期跑编码和 Agent 任务,用量会比较大,Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 更适合按周期管理额度。Claude Code 相关场景可以看 https://taotoken.net/claude-code?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite 。
最后留一个实用习惯:每次改完配置,先跑 4.1 那个「生成并运行 hello.py」的最小用例。它同时覆盖生成代码和自动执行命令两条链路,30 秒内能确认配置没退化。网页检索单独用 4.3 验证。两个都过,这套 OpenHands + 统一 Key 的组合就可以放心交给日常任务了。