1. 为什么在 opencode 终端里跑 python 会先撞上 401 和本地代理失败
很多人第一次在 opencode 桌面端的终端里敲python xxx.py,脚本本身没问题,但一发起模型请求就报错。最常见的两类:一类是401 Unauthorized,另一类是local proxy failed或者connection refused。这两个报错看着不一样,根子上其实是同一件事——请求的 endpoint 没走对通道。
先说清楚 opencode 是什么。它是一个把终端、编辑器、AI 助手揉在一起的开发工具,你可以在它的内置终端里直接执行 shell 命令,包括python、pip、git这些。它的定位不是替代你的编辑器,而是让你在一个窗口里完成「写代码 → 跑命令 → 调模型」的闭环。适合谁?适合已经在用 Conda 管环境、又想让脚本里的模型调用统一走一个 Key 通道的人。
问题出在哪?opencode 里跑的 python 脚本,如果用了 OpenAI SDK 或者 requests 去请求模型,默认会读环境变量OPENAI_BASE_URL或者代码里写死的https://api.openai.com/v1。在国内网络环境下,这个默认地址大概率连不上,于是 SDK 会尝试走系统代理,代理配置不完整时就抛local proxy failed;如果代理通了但 Key 不对,就抛401。还有一种情况是环境变量里残留了旧的HTTP_PROXY,python 进程继承了它,请求被转发到一个已经失效的本地端口,同样报local proxy failed。
我试过在一个 pytorch 环境里跑一个简单的对话脚本,终端里python --version正常,pip list也正常,但一执行到client.chat.completions.create就卡住,十几秒后报APIConnectionError,底层是local proxy failed。当时以为是网络问题,后来发现是.bashrc里有一行export HTTP_PROXY=http://127.0.0.1:7890,而那个端口早就没进程在监听了。把这一行注释掉,再把 endpoint 换到 TaoToken 的统一通道,问题直接消失。
所以排查顺序应该是:先确认 python 解释器是不是你要的那个环境,再确认环境变量里有没有残留代理,最后把 endpoint 和 Key 统一改到 TaoToken。这三步做完,401和local proxy failed基本都能定位到具体来源。下面按这个顺序拆开讲,每一步都给可复制的命令和配置。
2. 把 opencode 的 python 链路接到 TaoToken 统一 Key 通道
TaoToken 在这里扮演的角色是一个统一的模型调用入口。你不需要在脚本里分别配 OpenAI、Anthropic 的地址,而是把 Base URL 指向 TaoToken 的 API 地址,用同一个 Key 去调不同模型。官网是https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=,API 地址是https://taotoken.net/api。注意 API 地址后面不加 UTM 参数,直接用在代码和环境变量里。
为什么要在 opencode 终端里做这件事?因为 opencode 的终端本质上就是一个 shell,你在里面export的环境变量,会被之后启动的 python 进程继承。这意味着你可以在终端里一次性设好OPENAI_BASE_URL和OPENAI_API_KEY,然后直接python script.py,脚本里不用改任何硬编码地址。这对多环境切换特别友好——pytorch 环境、base 环境、临时 venv,只要在启动前 export 一次,全都走同一个通道。
具体要设两个变量。第一个是 Base URL,指向 TaoToken 的 API 根路径。第二个是 API Key,从 TaoToken 控制台生成。生成 Key 的入口在https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite,登录后创建一个新 Key,复制出来。这个 Key 就是后面所有请求的凭证。
如果你用的是 OpenAI 官方 SDK,它默认读OPENAI_API_KEY和OPENAI_BASE_URL这两个环境变量。所以最省事的做法是在.bashrc里写死,或者在每次开终端时手动 export。写死的好处是持久,坏处是换 Key 要改文件;手动 export 的好处是灵活,坏处是每次都要敲。我一般把 Key 放在一个单独的.env文件里,用source加载,这样既持久又方便替换。
还有一个细节:opencode 自己的配置文件里,provider字段可以留空,permission.bash设为allow,这样它才允许你在终端里执行命令。这个配置和 python 的 endpoint 是两回事,前者管的是 opencode 能不能跑 bash,后者管的是 python 请求发到哪。很多人把这两个搞混,以为改了 opencode 配置就能解决 401,其实 401 是 python 进程里的 Key 问题,跟 opencode 的 provider 配置无关。
把这两层分清楚之后,操作路径就很清晰了:opencode 配置只保留最小可用项,python 的 endpoint 和 Key 通过环境变量注入。下面一节给具体的可复制片段。
3. 可复制的环境变量与配置文件片段
先看 opencode 的全局配置。文件位置一般在用户目录下的.config/opencode/config.json,Windows 上可能是C:\Users\你的用户名\.config\opencode\config.json。内容保持最小:
{ "$schema": "https://opencode.ai/config.json", "provider": {}, "permission": { "bash": "allow" } }这个配置的作用只有一个:让 opencode 允许执行终端命令。provider留空是因为我们不在这里配模型通道,模型通道交给 python 的环境变量。
接下来是.bashrc。Windows 上 opencode 用的终端通常是 Git Bash 或 WSL 风格的 shell,.bashrc位置在C:\Users\你的用户名\.bashrc。如果你用的是 Conda 环境,先确认解释器路径。假设你的环境是pytorch27,路径是C:\Users\IASBING\.conda\envs\pytorch27,那么在.bashrc里加两段:一段绑定 python 和 pip,一段设置 TaoToken 的 endpoint 和 Key。
# 绑定 Conda 环境的 python 和 pip python() { /c/Users/IASBING/.conda/envs/pytorch27/python.exe "$@" } pip() { /c/Users/IASBING/.conda/envs/pytorch27/Scripts/pip.exe "$@" } # 清理可能残留的代理变量 unset HTTP_PROXY unset HTTPS_PROXY unset http_proxy unset https_proxy # 设置 TaoToken 统一通道 export OPENAI_BASE_URL="https://taotoken.net/api" export OPENAI_API_KEY="sk-你的TaoToken密钥"注意OPENAI_BASE_URL的值是https://taotoken.net/api,不要在后面加/v1,也不要加 UTM 参数。OpenAI SDK 会自己在后面拼/chat/completions这类路径。Key 从控制台复制,替换掉sk-你的TaoToken密钥。
如果你不想把 Key 明文写在.bashrc里,可以单独建一个~/.taotoken.env:
export OPENAI_BASE_URL="https://taotoken.net/api" export OPENAI_API_KEY="sk-你的TaoToken密钥"然后在.bashrc末尾加一行source ~/.taotoken.env。这样 Key 文件可以单独设权限,也方便用脚本替换。
保存之后,在终端执行:
source ~/.bashrc hash -rhash -r是清掉 shell 对命令路径的缓存,确保新的python()函数生效。然后验证:
type -a python python --version python -c "import sys; print(sys.executable)"预期输出里,type -a python第一条应该是python is a function,sys.executable应该指向C:\Users\IASBING\.conda\envs\pytorch27\python.exe。如果第一条是 WindowsApps 里的 python,说明函数没生效,检查.bashrc是否 source 成功。
环境变量设好之后,python 脚本里就不用再写base_url和api_key了。OpenAI SDK 会自动读。如果你用的是 requests 直接发请求,那就手动读os.environ["OPENAI_BASE_URL"]和os.environ["OPENAI_API_KEY"],拼到 header 和 URL 里。
4. 运行 python 脚本验证请求与预期输出
配置写完,得用一个真实脚本验证。建一个test_taotoken.py,内容如下:
import os from openai import OpenAI client = OpenAI( base_url=os.environ.get("OPENAI_BASE_URL"), api_key=os.environ.get("OPENAI_API_KEY"), ) resp = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "user", "content": "用一句话说明你收到的请求走的是哪个通道"} ], ) print(resp.choices[0].message.content)在 opencode 终端里执行:
python test_taotoken.py预期输出是一段模型返回的文本,说明请求成功。如果报401,说明 Key 不对或者没读到;如果报local proxy failed,说明代理变量没清干净;如果报model not found,说明模型 ID 写错了,换成 TaoToken 支持的模型 ID。
再验证一下环境变量是否真的被 python 读到:
python -c "import os; print(os.environ.get('OPENAI_BASE_URL')); print(os.environ.get('OPENAI_API_KEY')[:8])"预期输出第一行是https://taotoken.net/api,第二行是 Key 的前 8 位。如果第一行是空的,说明.bashrc没 source 成功,或者你开了一个新的终端窗口但没重新加载。
还有一个常见验证动作是检查 python 进程有没有继承代理变量:
python -c "import os; print({k:v for k,v in os.environ.items() if 'PROXY' in k.upper()})"预期输出是空字典{}。如果里面有HTTP_PROXY或HTTPS_PROXY,说明.bashrc里的unset没生效,或者系统级环境变量里还有残留。Windows 上系统级环境变量优先级有时高于.bashrc,需要在「系统属性 → 环境变量」里也删掉。
跑通之后,你可以把test_taotoken.py换成自己的业务脚本,比如批量处理数据、调用模型做摘要、跑 Agent 流程。只要环境变量在,脚本里不用改任何地址。如果脚本里用了langchain或llama-index,它们也读OPENAI_BASE_URL和OPENAI_API_KEY,同样生效。
验证模型是否可用,可以在终端里直接调模型对话页面确认 Key 的额度状态:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite。如果那边能正常对话,说明 Key 没问题,终端里的报错就纯粹是环境变量或代理的问题。
5. 本篇常见报错排查:401、local proxy failed、reading choices、OAuth
报错一:401 Unauthorized。这个最直接,Key 不对或没读到。先在终端里echo $OPENAI_API_KEY,看有没有值。如果是空的,检查.bashrc里的export有没有写错,或者source有没有执行。如果有值但还报 401,去控制台确认这个 Key 是否被禁用或额度耗尽。还有一种情况是 Key 里带了空格或换行,复制的时候多选了字符,重新复制一次。
报错二:local proxy failed或connection refused。这是代理变量残留。执行env | grep -i proxy,看有没有HTTP_PROXY、HTTPS_PROXY、ALL_PROXY。有的话在.bashrc里unset掉,然后source ~/.bashrc。Windows 上还要检查系统环境变量,因为 Git Bash 会继承系统级变量。如果确实需要代理才能上网,那要把代理指向一个可用的本地端口,而不是已经失效的端口。但更推荐的做法是直接走 TaoToken 的通道,不依赖本地代理。
报错三:Error reading choices或reading 'choices'。这个通常出现在 SDK 解析响应时,说明返回的 JSON 结构不对。原因可能是 Base URL 写成了https://taotoken.net/api/v1,导致路径重复拼接,返回了 404 页面而不是 JSON。把OPENAI_BASE_URL改成https://taotoken.net/api,不要带/v1。另外检查模型 ID 是否正确,有些模型 ID 在 TaoToken 上叫法不同,用控制台里列出的 ID。
报错四:OAuth相关错误。如果你在 opencode 里配了 OAuth 登录,但 python 脚本走的是 API Key,两者会冲突。OAuth 是 opencode 自己用来登录的,python 脚本不读 OAuth token。解决办法是确保 python 进程只读OPENAI_API_KEY,不要读OPENCODE_TOKEN之类的变量。在.bashrc里显式设置OPENAI_API_KEY,覆盖掉可能存在的其他变量。
如果你用的是 Claude Code 或 Cline MCP 这类工具,配置里要写全三件套:Base URL、Key、Model ID。比如 Cline 的 MCP 配置:
{ "mcpServers": { "taotoken": { "command": "npx", "args": ["-y", "@taotoken/mcp-server"], "env": { "OPENAI_BASE_URL": "https://taotoken.net/api", "OPENAI_API_KEY": "sk-你的TaoToken密钥", "OPENAI_MODEL": "gpt-4o-mini" } } } }Codex 的auth.json里也要写全:
{ "openai": { "baseURL": "https://taotoken.net/api", "apiKey": "sk-你的TaoToken密钥", "model": "gpt-4o-mini" } }CC Switch 切换配置时,同样确保这三个字段都指向 TaoToken。缺任何一个都会导致 401 或模型找不到。
排查顺序建议:先echo环境变量,再env | grep -i proxy,然后python -c打印sys.executable和os.environ,最后用一个最小脚本发请求。每一步的输出都对照预期,基本能定位到具体哪一层出了问题。
6. 长期编码与 Agent 场景的接入建议
如果你只是偶尔跑个脚本,上面的环境变量方案就够了。但如果你要在 opencode 里长期做编码、跑 Agent、批量调模型,建议把配置做得更稳一点。
第一,把 Key 和 endpoint 放在独立的 env 文件里,不要直接写进.bashrc。这样换 Key 的时候只改一个文件,不用动 shell 配置。文件权限设成只有自己能读。
第二,给不同的项目建不同的 Conda 环境,每个环境的.bashrc里绑定各自的 python 路径,但OPENAI_BASE_URL和OPENAI_API_KEY共用同一套。这样切换环境时,模型通道不变,只有解释器变。
第三,如果你用 Coding Plan 做长期编码任务,可以在https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite看套餐详情,把 Key 的额度规划好。Agent 场景下请求量大,提前确认额度比跑到一半报 401 要省事。
第四,opencode 的终端里可以写一个run.sh包装脚本,自动 source env、激活 Conda、执行 python。这样每次不用手动敲一堆命令:
#!/bin/bash source ~/.taotoken.env source ~/.bashrc python "$@"然后chmod +x run.sh,之后用./run.sh test_taotoken.py就能跑。
第五,定期检查环境变量有没有被其他工具覆盖。有些 IDE 或终端插件会自己设OPENAI_BASE_URL,导致你的配置被顶掉。在脚本开头打印一次os.environ.get("OPENAI_BASE_URL"),确认走的是 TaoToken 的地址。
接入文档在https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite,里面有不同语言和框架的示例,遇到 SDK 版本差异时可以对照。API Key 管理在https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite,可以创建多个 Key 分别给不同项目用,方便排查是哪个项目出的问题。
最后一步,把test_taotoken.py跑通之后,直接在你的业务脚本里 import OpenAI,不用再写 base_url 和 api_key。终端里python your_script.py,请求就会走 TaoToken 的统一通道。如果哪天报错了,回到第 5 节按顺序排查,基本十分钟内能定位。