我做了一个本地 AI Gateway:Claude Code、Claude Desktop、Codex 统一接入 DeepSeek / Qwen / OpenAI
最近一段时间,我一直在做一个自己真正会用到的工具:




AI-Gateway
它解决的问题其实很简单。
现在做 AI 开发,很多人手里已经不只有一个客户端:
text
Claude Code
Claude Desktop
Codex
OpenCode
自研 Agent
各种 OpenAI / Anthropic Compatible 工具
模型也越来越多:
text
DeepSeek
Qwen
OpenAI
Kimi
GLM
MiniMax
Volcengine
SiliconFlow
......
结果就是------
每换一个客户端,要重新配一次 API。
每换一个模型,又要重新改 Base URL、Model、Key。
甚至同一个 Claude Code,今天连 DeepSeek,明天想换 Qwen,又是一套配置。
所以我最后想做一件事:
让所有 AI Agent,只接一个地址。
模型、Provider、路由、故障切换和密钥管理,全部交给 AI-Gateway。
最终我想要的架构
客户端以后不应该关心:
我现在用的是 DeepSeek,还是 Qwen?
它只需要知道:
text
http://127.0.0.1:8787
整体链路大概是:
text
Claude Code ───────┐
Claude Desktop ────┤
Codex ─────────────┤
OpenCode ──────────┤
Custom Agent ──────┘
↓
AI-Gateway
↓
Protocol Adapter
↓
Agent Identity
↓
Agent Policy
↓
Model Alias
↓
Router
↓
DeepSeek / Qwen / OpenAI / ...
我现在越来越认同一个思路:
Agent 不应该知道自己到底在使用哪个真实模型。
例如客户端只指定:
text
coding
AI-Gateway 可以自己决定:
text
coding
↓
DeepSeek
↓ 失败 / 限流
Qwen
↓
其它 Provider
客户端不用重新配置。
Claude Code:现在可以直接在 /model 里切不同厂商
这是这一版我最喜欢的功能之一。
以前 Claude Code 如果接第三方模型,往往是直接配置一个:
text
ANTHROPIC_BASE_URL
ANTHROPIC_MODEL
这样虽然能用,但 Claude Code 本身并不知道 Gateway 里还有什么其他模型。
这次我给 AI-Gateway 加了一层 Multi-Provider Model Discovery。
Claude Code 连接 AI-Gateway 后,直接执行:
text
/model
现在可以看到:
text
AI-Gateway · coding
DeepSeek · deepseek-chat
Qwen · qwen-plus
OpenAI · gpt-4o-mini


这意味着:
不用再改 Claude Code 配置文件,就可以直接切换不同厂商的模型。
两种模型使用方式
我在设计的时候,没有只做"选择某个模型"。
而是保留了两种模式。
第一种是:
text
AI-Gateway · coding
这是一个 Alias。
Claude Code 看到的是:
text
coding
但 AI-Gateway 后面可以自己路由:
text
coding
→ DeepSeek
→ Qwen
→ ...
例如我这次真实测试里:
text
Claude Code
→ AI-Gateway · coding
→ deepseek/deepseek-chat
→ 200 SUCCESS
第二种则是固定模型,例如:
text
Qwen · qwen-plus
这时候走的是 pinned route:
text
Claude Code
→ claude-gw-pin-qwen...
→ qwen/qwen-plus
不会随便跑到其他 Provider。
也就是说:
text
想让 Gateway 自动选
→ coding
想固定某个模型
→ Qwen / DeepSeek / OpenAI
两种需求都能满足。


更有意思的是:Claude Desktop 也接通了
Claude Code CLI 跑通之后,我又遇到了一个问题。
Claude Desktop 的 Code 页面怎么办?
最开始我以为 Desktop 和 Claude Code CLI 会共用同一套 Model Discovery。
后来实测发现不是。
Claude Code CLI 使用的是:
text
~/.claude/settings.json
+
Gateway Model Discovery
Claude Desktop 则有自己独立的第三方 Provider Profile 机制。
所以最后 AI-Gateway 又增加了一套独立的:
Claude Desktop Connector
整体链路变成:
text
Claude Desktop
↓
3P Profile
↓
AI-Gateway · coding
↓
127.0.0.1:8787/claude-desktop
↓
Desktop Role Mapper
↓
coding
↓
Existing Router
↓
DeepSeek / Qwen / ...


最终效果:Claude Desktop 里真的出现了 AI-Gateway
真实测试的时候,我把 Claude Desktop 从原来的 CC Switch 配置临时切换到了 AI-Gateway。
重启 Claude Desktop 后,在 Code 的 Models 里成功出现:
text
AI-Gateway · coding

然后创建新的 Local Code Session,发送:
text
Reply only: DESKTOP_FINAL_OK
Claude Desktop 正常返回:
text
DESKTOP_FINAL_OK
与此同时 AI-Gateway 后台收到的真实运行信息是:
text
agent: claude-desktop
desktopRole: SONNET
alias: coding
provider: deepseek
model: deepseek-chat
status: success
也就是说,这不是单纯把一个名字显示在 Desktop UI 里。
真实链路确实是:
text
Claude Desktop
→ AI-Gateway
→ coding
→ Router
→ DeepSeek

为什么我没有直接写死 Claude Desktop 版本?
这个问题我在开发过程中也考虑了很久。
Claude Desktop 的第三方 Profile 结构,本身具有一定版本敏感性。
如果简单写:
text
if version == xxx:
使用某个配置
那这个产品很快就会随着 Claude Desktop 更新而失效。
所以我后来专门做了一层:
Universal Compatibility Engine
设计原则是:
Capability First,Version Second。
也就是说,版本号只作为参考。
AI-Gateway 更关注的是:
text
配置目录结构是什么?
configLibrary 是否存在?
_meta.json 是什么结构?
当前 appliedId 是谁?
支持哪些 Role Family?
当前 Profile 属于谁?
配置结构有没有变化?
然后再决定:
text
FULL
LIMITED
PROBE_REQUIRED
UNSUPPORTED
而不是盲目写配置。
这套兼容层目前已经覆盖:
text
Sonnet
Opus
Haiku
Fable
Versioned Model IDs
Anthropic-prefixed IDs
Unknown Role Reject
但当前 Public Beta 的 Desktop 用户模型仍然只暴露:
text
AI-Gateway · coding
我暂时没有急着把十几个模型全部塞进 Desktop。
稳定优先。
CC Switch 用户也不用卸载 CC Switch
这个也是我自己实际使用时非常在意的一点。
我的 Claude Desktop 原本就是 CC Switch 在管理。
所以 AI-Gateway Connector 从设计开始就要求:
不能为了接入 AI-Gateway,把用户原来的 CC Switch 配置删掉。
现在的流程是:
text
当前:
CC Switch
↓
接入:
AI-Gateway
↓
需要时恢复:
CC Switch
AI-Gateway 会保留原有 CC Switch Profile。
【截图 6:当前 Provider = CC Switch / 接入 AI-Gateway】
点击接入前,页面会告诉用户:
text
当前 Provider:CC Switch
目标 Provider:AI-Gateway
CC Switch Profile:保留
配置备份:加密
需要重启 Claude Desktop:是

真正切换之后,用户也可以:
text
恢复到 CC Switch
"能恢复"比"能接入"更重要
这个功能开发过程中,其实还真抓到过一个 Restore UI 的 Bug。
第一次真实 UI E2E:
text
Detect PASS
Plan PASS
Apply PASS
Desktop PASS
Runtime PASS
Restore FAIL
最后定位是异步确认之后 UI button reference 失效,导致 Restore API 根本没有真正发送。
这个问题如果只做 backend test,是发现不了的。
修复之后,我重新从真实环境完整跑了一遍:
text
UI 检测
→ 接入计划
→ 加密备份
→ Apply
→ 重启 Desktop
→ AI-Gateway · coding
→ 真实请求
→ Runtime Verified
→ UI Restore
→ 恢复 CC Switch
最终:
text
Restore Byte Identical: YES
CC Switch Re-Activated: YES
AI-Gateway Profile Removed: YES
也就是说,恢复后的文件和接入前原始文件:
SHA-256 完全一致。
这也是我现在比较坚持的一点:
一个真正可以给别人用的 Connector,不只是"能接进去"。
还必须:
能安全退出来。
它不是一个简单的 API Proxy
从外面看,AI-Gateway 好像就是:
text
localhost:8787
然后转发 API。
但现在实际上里面已经逐渐变成一套 Agent Runtime Gateway:
text
Protocol Adapter
↓
Agent Identity
↓
Agent Policy
↓
Virtual Model
↓
Model Alias
↓
Router
↓
Failover
↓
Provider
上层 Connector 则负责:
text
Claude Code CLI
Claude Desktop
Codex
OpenAI Compatible Agent
Anthropic Compatible Agent
Provider 目前可以继续扩展:
text
DeepSeek
Qwen
OpenAI
Kimi
GLM
MiniMax
Volcengine
SiliconFlow
Custom OpenAI Compatible
......
但是 Router 不需要为某一个 Provider 写大量特殊逻辑。
密钥也不应该到处复制
以前我自己配置多个 AI 工具的时候,一个让我很不舒服的问题就是:
text
API Key
会散落在各种:
text
settings.json
.env
config.toml
IDE Settings
CLI Profile
AI-Gateway 的思路是:
Provider Secret 应该由 Gateway 统一管理。
Windows 下现在使用:
text
DPAPI CurrentUser
做本地 Secret Store。
而像 Claude Desktop 接入时需要的 Local Gateway Token,也和真正的 Provider API Key 分离。
所以 Claude Desktop 拿到的只是:
text
AI-Gateway Local Token
而不是:
text
DeepSeek API Key
Qwen API Key
OpenAI API Key
这样上层工具不需要知道真正的 Provider Credential。
目前测试到什么程度?
当前这一版完成最终功能闭环后:
text
695 / 695 PASS
包括:
text
Core
Streaming
Admin
Providers
Clients
Connectors
Release
Installer
Discovery
Claude Desktop
Desktop Compatibility
Desktop Product UI
同时:
text
Router Changes: 0
Provider Core: 0
Runtime Core: 0
Protocol Core: 0
Secrets Core: 0
真实 E2E 过程中也检查了:
text
Real API Key Leakage 0
Desktop Token Leakage 0
Authorization Leakage 0
Prompt Leakage 0
Assistant Content Leak 0
产品页面现在也不再把 Claude Code 和 Desktop 混在一起
现在"开发工具接入"里:
text
Claude Code CLI
和:
text
Claude Desktop
是两个独立 Connector。
因为它们底层其实完全不是一回事。
Claude Code CLI 主要是:
text
settings.json
+
Gateway Discovery
+
/model
Claude Desktop 是:
text
3P Profile
+
Compatibility Detection
+
Desktop Role Mapping
+
Runtime Verification
如果产品层把两个东西都写成一个"Claude Code",用户遇到问题时会非常难理解。



我为什么做这个项目?
因为我自己现在同时在用:
text
Claude Code
Codex
多个国产模型 API
自研 AI Agent
用久之后会发现:
真正麻烦的不是"怎么调用一个 API"。
真正麻烦的是:
怎么让越来越多 Agent,共享一套稳定、安全、可切换的模型基础设施。
所以我现在对 AI-Gateway 的定义已经不是:
API 转发工具
而是:
AI Agent Runtime Gateway
理想状态下:
text
Agent 不关心 Provider
Agent 不保存 Provider Key
Agent 不负责 Failover
Agent 不负责模型迁移
这些应该下沉到 Gateway。
当前版本:Public Beta
目前准备发布的是:
text
AI-Gateway v2.5.0-beta.2
这一版主要新增两块:
text
Claude Code CLI
Multi-Provider Model Discovery
以及:
text
Claude Desktop
Adaptive Connector
Claude Desktop 这里我特别说明一下:
我不会宣传"所有 Claude Desktop 版本 100% 兼容"。
因为这套 3P Profile 本身属于版本敏感机制。
AI-Gateway 现在采用的是:
自动检测 Claude Desktop 配置结构和兼容能力,在未知版本或配置结构发生变化时要求重新验证,而不是盲目修改用户配置。
我觉得这种方式更适合一个真正准备给别人使用的软件。