1. 为什么二开阶段必须先把 Key 通道收口
OpenClaw Edict 三省六部制这套系统,前两篇把部署启动和日常使用跑通之后,真正进入二次开发时,最先暴露的问题往往不是代码写不出来,而是模型访问通道太散。根目录看板主线里dashboard/server.py直接读环境变量,edict/backend的 FastAPI 服务层又有一套自己的配置加载逻辑,PyQt 启动器里还单独弹窗让用户输入 API Key,Agent 的SOUL.md旁边可能还挂着各自的模型配置。改一个模型,要在四五个地方同步,漏一处就出现「看板能跑、Worker 报 401」这种典型故障。
这一篇聚焦的就是这个收口动作:把 TaoToken 作为统一 Key/API 通道,在 Edict 的 config.toml 与 settings.json 两个配置骨架里落地,让 PyQt 前端、Agent 调度层、FastAPI 服务层都从同一份配置读取模型访问信息。适合已经能跑起 Edict、准备做面板扩展、Agent 扩展或调度改造的开发者。读完之后你应该能完成一次可复制的连通性验证,并且知道配置写错时该去哪个文件排查。
TaoToken 在这里的角色是统一模型访问入口,提供兼容 OpenAI 风格的 API 通道,Edict 各层只需要认一个 base_url 和一个 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 参数。
2. TaoToken 前置准备:Key 与通道确认
在动 Edict 的配置文件之前,先把 TaoToken 这边的访问凭证准备好。登录后进入控制台,在 API Keys 页面创建一个新的 Key。建议按用途命名,比如edict-dev、edict-prod,这样后面在 Edict 里做多环境配置时不会混。
创建完 Key 之后,你需要确认两件事:一是 API base 地址,二是可用模型列表。TaoToken 的 API 入口是https://taotoken.net/api,在 Edict 的配置里通常写成https://taotoken.net/api/v1这种带版本号的形式,具体取决于你调用的接口路径。模型列表可以在模型对话页面里直接试,确认你要用的模型名拼写正确,比如claude-sonnet-4-20250514这类完整标识,不要凭记忆写简写。
如果你打算长期在 Edict 上做编码类 Agent 的扩展,可以顺带看一下 Coding Plan 的额度说明,避免开发到一半发现调用量不够。控制台里能看到当前 Key 的用量和剩余额度,这个信息在排查「请求突然失败」时很有用——有时候不是配置错了,是额度用完了。
注意:Key 不要直接写进 Git 仓库里的配置文件。下面给的 config.toml 和 settings.json 骨架里,Key 字段建议用环境变量占位,实际运行时由启动脚本注入。
3. 可复制配置:config.toml 与 settings.json 骨架
Edict 的两条主线对配置文件的读取方式不一样,所以这里给两份骨架,你按自己改的那条线选用,或者两份都配上让它们指向同一个 Key。
3.1 config.toml 骨架(edict/backend 全栈线)
全栈线通常用 TOML 做服务层配置。在edict/backend/config.toml或项目约定的配置目录下,写入下面这段:
[llm] provider = "taotoken" base_url = "https://taotoken.net/api/v1" api_key = "${TAOTOKEN_API_KEY}" default_model = "claude-sonnet-4-20250514" timeout_seconds = 60 max_retries = 3 [llm.models] zhongshu = "claude-sonnet-4-20250514" menxia = "claude-sonnet-4-20250514" shangshu = "claude-sonnet-4-20250514" worker_default = "claude-sonnet-4-20250514" [scheduler] retry_max = 3 escalate_threshold_sec = 180这里的关键点是api_key用${TAOTOKEN_API_KEY}占位,实际值从环境变量读。base_url指向 TaoToken 的 API 入口,default_model和分角色模型都写完整模型名。[scheduler]段对应后面调度扩展会用到的重试和升级阈值。
3.2 settings.json 骨架(根目录看板线 + PyQt 启动器)
根目录看板主线和 PyQt 启动器更习惯读 JSON。在data/settings.json或启动器同级的配置目录下写:
{ "llm": { "provider": "taotoken", "base_url": "https://taotoken.net/api/v1", "api_key_env": "TAOTOKEN_API_KEY", "default_model": "claude-sonnet-4-20250514" }, "agents": { "zhongshu": { "model": "claude-sonnet-4-20250514" }, "menxia": { "model": "claude-sonnet-4-20250514" }, "shangshu": { "model": "claude-sonnet-4-20250514" } }, "launcher": { "host": "127.0.0.1", "port": 7891, "log_dir": ".runtime/prod/logs" } }注意这里用的是api_key_env而不是直接存 Key,PyQt 启动器读取时先查环境变量,查不到再弹窗让用户临时输入。这样既保留了桌面入口的便利性,又不会把密钥落盘到源码目录。
3.3 环境变量注入
无论用哪份配置,启动前都要把 Key 注入环境变量。Windows 下在启动脚本里加:
set TAOTOKEN_API_KEY=你的KeyLinux/macOS 下:
export TAOTOKEN_API_KEY=你的Key如果你用的是01_setup_prod_env.bat --sync这类引导脚本,可以把这行加在脚本开头,或者单独写一个env.local.bat并在主脚本里call它,避免 Key 进入版本控制。
4. 验证请求:一次可复制的连通性检查
配置写完不要直接启动整个 Edict,先用一个最小请求确认通道是通的。这一步能帮你把「配置错误」和「业务逻辑错误」分开。
4.1 用 curl 直接打 TaoToken API
curl -s https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 16 }'如果返回里有choices字段和正常内容,说明 Key 和 base_url 都没问题。如果返回 401,检查 Key 是否注入成功;返回 404,检查 base_url 路径是否多了或少了/v1。
4.2 用 Python 验证 Edict 配置加载
在 Edict 项目根目录下跑一段小脚本,确认配置文件能被正确解析:
import os, json, tomllib from pathlib import Path key = os.environ.get("TAOTOKEN_API_KEY") assert key, "TAOTOKEN_API_KEY 未注入" cfg_path = Path("edict/backend/config.toml") if cfg_path.exists(): with cfg_path.open("rb") as f: cfg = tomllib.load(f) print("toml base_url:", cfg["llm"]["base_url"]) print("toml model:", cfg["llm"]["default_model"]) s_path = Path("data/settings.json") if s_path.exists(): s = json.loads(s_path.read_text(encoding="utf-8")) print("json base_url:", s["llm"]["base_url"]) print("json key_env:", s["llm"]["api_key_env"])跑通之后,再启动 Edict 的完整栈:
docker compose -f edict/docker-compose.yml up -d postgres redis 03_start_prod_stack.bat --open-browser --migrate启动后打开看板http://127.0.0.1:7891,新建一个任务,观察活动流里 Agent 是否正常响应。如果任务能推进、日志里没有 401/403,说明统一 Key 通道已经生效。
4.3 PyQt 启动器侧的验证
如果你扩展了 PyQt 启动器,在edict_pyqt_ui.py里加一个「测试连接」按钮,点击后调用上面那段 curl 等价的请求,把结果打到日志窗口。核心逻辑可以这样写:
def test_connection(self): import os, requests key = os.environ.get("TAOTOKEN_API_KEY") if not key: self.log("[ERR] TAOTOKEN_API_KEY 未设置") return try: r = requests.post( "https://taotoken.net/api/v1/chat/completions", headers={"Authorization": f"Bearer {key}"}, json={"model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 16}, timeout=30, ) self.log(f"[OK] status={r.status_code}") except Exception as e: self.log(f"[ERR] {e}")这样启动器就不只是启停服务,还能在启动前先确认通道可用,减少「服务起来了但 Agent 不工作」的排查时间。
5. 本篇常见错排查
配置阶段最容易踩的坑集中在下面几类,按出现频率排。
第一类是 base_url 路径错误。TaoToken 的 API 入口是https://taotoken.net/api,但实际调用 chat completions 时通常要带/v1,写成https://taotoken.net/api/v1。如果配置里只写了https://taotoken.net/api,请求会打到错误路径返回 404。反过来,如果某些 SDK 会自动补/v1,你手动写了就会变成/v1/v1,同样 404。排查方法就是上面那段 curl,直接看返回。
第二类是 Key 注入失败。Windows 下set只在当前命令行窗口有效,如果你在 A 窗口 set 了,在 B 窗口启动 Edict,读到的就是空值。更稳妥的做法是写进启动脚本,或者用系统环境变量。PyQt 启动器如果是从桌面快捷方式启动,继承的环境变量可能和你终端里不一样,这也是为什么启动器里要保留弹窗输入作为兜底。
第三类是模型名拼写错误。TaoToken 的模型标识要用完整名称,简写或旧版本名会返回 model not found。在模型对话页面里复制模型名,不要手打。
第四类是配置文件优先级混乱。Edict 两条主线如果同时存在 config.toml 和 settings.json,要明确哪份生效。建议在服务启动日志里打印实际加载的配置路径和 base_url,一眼就能看出读的是哪份。
第五类是超时设置过短。Agent 调度涉及多轮调用,timeout_seconds设成 10 秒很容易在复杂任务上超时。建议至少 60 秒,重试次数 3 次。
提示:排查时先跑 curl,再跑 Python 配置加载脚本,最后才启动完整栈。顺序反了会把配置问题和业务问题混在一起。
6. 接入之后的下一步
统一 Key 通道配好之后,Edict 的扩展工作就有了稳定底座。接下来你可以按这个顺序推进:先补一个业务面板,走通「数据脚本 → 后端接口 → 前端组件」的完整链路;再新增一个 Agent,在SOUL.md里定义职责,在权限矩阵里注册;然后完善调度层的重试和升级策略,让任务卡住时能自动恢复。
如果你在接入过程中遇到 Key 或通道相关的问题,可以直接去 API Keys 页面重新生成一个 Key 对比测试,排除是 Key 本身的问题还是配置问题。接入文档里有各语言 SDK 的调用示例,对照着改 Edict 里的请求封装会快很多。长期做编码类 Agent 扩展的话,Coding Plan 的额度规划也值得提前看一下,避免开发中途断档。
配置这件事,一次收口,后面每次扩展都省事。