我喜欢用 Codex,但它用不了 DeepSeek,所以我做了一个本地网关
作者因喜欢Codex但希望使用DeepSeek模型,发现两者协议不兼容,于是开发了本地网关AgentGate。该工具将Codex的Responses API请求转换为DeepSeek支持的Chat Completions格式,并进一步实现智能路由:纯文本任务自动走DeepSeek,含图片的多模态任务自动切换至KimiCoding,解决了AI编程中工具与模型协议碎片化的问题,让用户专注代码开发。
最近我开源了一个小工具,叫 AgentGate。
它不是我一开始就规划好的大项目。
也不是因为看到 AI Agent 很火,所以硬要做一个相关产品。
它最开始的起点非常具体:
我比较喜欢用 Codex,但我想让 Codex 用 DeepSeek。
结果发现,没那么简单。
Codex 走的是 OpenAI Responses API。DeepSeek 主要是 OpenAI Chat Completions 兼容接口。
两边协议不一样。
也就是说:
我喜欢 Codex 的使用体验。我也想用 DeepSeek 的模型能力和成本优势。但它们中间接不上。
这个问题听起来不大。
但对我这种每天用 AI 写代码的人来说,它很实际。
我不想因为想用 DeepSeek,就放弃自己顺手的工具。也不想每次切模型,都去改一堆配置、环境变量、Base URL、API Key。
所以我最后做了一个本地网关。
让 Codex 可以通过本地入口去调用 DeepSeek。
这个工具就是 AgentGate。
一开始,只是想让 Codex 用上 DeepSeek
我平时比较喜欢 Codex 的使用方式。
它更适合放在开发流程里用。
比如分析代码、修改文件、执行任务、根据上下文推进开发,这类体验对我来说比较顺手。
但模型这件事,我不想被单一 Provider 绑死。
有时候我想用 OpenAI。有时候我想试 Anthropic。有时候我想用 DeepSeek。有时候也会看 Kimi、MiniMax、OpenRouter 或其他兼容接口。
不同模型有不同特点。
有的推理强。有的速度快。有的价格低。有的更适合日常代码任务。有的多模态能力更好。
所以我希望工具和模型之间不要绑定得太死。
工具我可以继续用顺手的工具。模型我可以根据场景切换。
但真正动手的时候发现,问题不只是换一个 API 地址。
Codex 发出来的是 Responses API 请求。DeepSeek 接收的是 Chat Completions 格式。
中间需要有人做协议转换。
这就是 AgentGate 最早的核心能力:
把 Codex 的 Responses API 转成 DeepSeek 能理解的 Chat Completions 请求。
这样 Codex 还是 Codex。
DeepSeek 还是 DeepSeek。
中间由 AgentGate 负责翻译。
对我来说,这个价值很直接:
我可以继续用自己喜欢的工具,同时用上自己想用的模型。
真正的问题不是模型,而是协议接不上
以前我会更关注模型本身。
哪个模型更强。哪个模型更便宜。哪个模型上下文更长。哪个模型代码能力更好。哪个模型回答更稳。
这些当然重要。
但做 AgentGate 之后,我越来越明显地感觉到:
AI 编程工具真正麻烦的地方,不只是模型能力,而是整个接入链路太碎。
有的工具走 Responses API。有的工具走 Anthropic Messages API。有的工具走 Chat Completions。有的 Provider 支持原生协议。有的 Provider 只支持兼容接口。有的模型支持 reasoning_content。有的模型支持 tool_use。有的支持图片。有的不支持图片。
如果只是偶尔玩一下,这些差异可以忍。
但如果每天都用,它就会变成负担。
因为你真正想做的事情是写代码、改项目、推进任务。
不是研究每个工具和每个 Provider 的协议细节。
我想让 Codex 做一个任务。
我关心的是:
它能不能读懂上下文。能不能正确修改代码。能不能稳定执行。能不能在失败时有办法恢复。
但背后要处理的东西很多。
请求格式要转换。模型名要映射。工具调用要适配。流式输出不能断。错误信息要能看懂。失败之后最好能切到备用 Provider。
这些都不是用户最想关心的事。
但如果不处理好,用户每天都会被它们打断。
所以 AgentGate 的第一个价值,不是“多做了一层代理”。
而是:
把这些分散的协议差异收进本地网关里。
做着做着,又发现 DeepSeek 不支持多模态
最开始,我把重点放在 Codex 接 DeepSeek 上。
文本任务跑通之后,体验已经顺了很多。
但很快又遇到一个新问题:
DeepSeek 不支持多模态图片请求。
这个问题在 AI 编程场景里其实挺常见。
比如你想让 Agent 看一张 UI 截图。看一个报错页面。看一个产品原型。看一个设计图。看某个界面布局哪里不对。
这时候,请求里就可能带图片。
如果后面的 Provider 不支持 Vision,多半就会直接失败。
那怎么办?
最简单的做法是:
不用图片。
但这个方案不对。
因为问题不是用户不该发图片。
也不是 Codex 不该处理图片。
真正的问题是:
不同 Provider 的能力不一致。
DeepSeek 可以很好地处理很多文本和代码任务。但它不支持多模态。KimiCoding 这条线我验证下来,可以正常承接多模态请求。
所以更合理的做法不是让用户每次手动判断。
而是让网关判断。
纯文本任务,可以优先走 DeepSeek。带图片的任务,自动跳过 DeepSeek,切到支持多模态的 KimiCoding。
这就是 AgentGate 后来做 Vision 感知路由的原因。
文本走 DeepSeek,图片走 KimiCoding
现在我自己比较确定的一条使用链路是:
Codex 文本任务走 DeepSeek。 Codex 图片 / 多模态任务走 KimiCoding。
这个体验比手动切换要自然很多。
因为我不用每次都想:
这个请求有没有图片?DeepSeek 能不能接?要不要手动换 Provider?配置文件要不要改?模型名是不是又要换?
这些都应该交给工具处理。
所以 AgentGate 会在路由时判断请求里有没有图片。
如果是纯文本,就可以走 DeepSeek。如果包含图片,就跳过不支持 Vision 的 Provider,自动走 KimiCoding 这类支持多模态的 Provider。
这个功能听起来像技术细节。
但在真实使用里,它解决的是注意力问题。
因为我本来是在写代码。
我不想在任务中途停下来,去想这次应该用哪个 Provider。
一个好的本地工具,应该把这些判断尽量吸收掉。
后来我又做了透明代理
一开始做协议转换,是因为 Codex 和 DeepSeek 协议不一致。
但做着做着,我又发现:
不是所有请求都应该转换。
有些情况下,客户端和上游 Provider 本来就是同一种协议。
比如 Chat Completions 到 Chat Completions。或者某个 Provider 本身就支持对应协议。
这种时候,如果还强行拆开重组,反而增加风险。
所以 AgentGate 里除了协议转换,还有透明代理。
透明代理的意思是:
能不改请求体,就不改请求体。
只做必要的事情:
替换目标地址。注入 Provider API Key。处理模型映射。记录请求日志。做本地认证。必要时做失败转移。
请求和响应本身尽量原样透传。
这点对稳定性很重要。
因为协议转换越多,出问题的地方就越多。
能透明代理,就透明代理。必须转换,才做转换。
这也是我现在做工具时越来越重视的原则:
不要为了显得能力强,就把简单事情复杂化。
工具应该尽量站在用户前面挡复杂性,而不是制造新的复杂性。
智能切换不是为了炫技,而是为了少中断
AgentGate 后来还做了 Provider Chain 和智能切换。
这个功能最开始也不是为了好看。
而是因为日常使用 AI 编程工具时,经常会遇到各种不稳定。
比如:
某个 Provider 限流。某个模型超时。某个接口返回 5xx。某个模型不支持当前输入。某个服务临时不可用。
如果每次都要用户手动切换,那就很累。
尤其是 AI 编程任务经常不是一次简单问答。
它可能正在读文件。正在理解项目结构。正在分析问题。正在生成修改方案。正在连续执行多步任务。
中间突然因为 Provider 问题断掉,非常影响体验。
所以我希望 AgentGate 能做一部分自动处理。
比如:
A Provider 失败,就尝试 B Provider。某个 Provider 不支持图片,就不要把图片请求发给它。某个 Provider 连续失败,就先进入冷却。不同协议可以有不同的 Route Profile。Codex、Claude Code、OpenCode 可以分别配置自己的路由链。
这样做的目的不是“功能更多”。
而是为了让工作流更稳。
AI 编程工具真正影响效率的地方,往往不是某一次回答快了几秒。
而是它能不能稳定地支撑你持续工作。
现在验证比较稳的链路
目前我自己验证下来,比较确定的是这几条:
场景 | 路由方式 | 状态 |
Codex → AgentGate → DeepSeek | Responses API 转 Chat Completions | 已验证可用 |
Codex 文本任务 → DeepSeek | 协议转换 | 已验证可用 |
Codex 图片 / 多模态任务 → KimiCoding | Vision 感知智能切换 | 已验证可用 |
DeepSeek 不支持图片时自动跳过 | Vision 路由 | 已验证可用 |
KimiCoding 作为 Vision Provider | 多模态请求承接 | 已验证可用 |
Chat Completions 客户端 → AgentGate | 透明代理 | 已验证可用 |
这条线对我来说已经比较清楚了。
我不是为了做一个抽象的“AI 网关”才做 AgentGate。
而是因为我有一个很具体的需求:
我喜欢用 Codex,但我想用 DeepSeek。
后来又遇到一个更具体的问题:
DeepSeek 不支持多模态,所以图片请求要自动切到 KimiCoding。
再后来才慢慢演化出:
协议转换。透明代理。多 Provider 管理。智能切换。请求日志。客户端配置管理。
这些功能不是一开始拍脑袋列出来的。
它们是从真实使用问题里长出来的。
这个项目也让我重新理解了“真实需求”
前面我写过一篇文章,讲一个需求值不值得做,要看它是不是真痛、高频、离钱近、会不会带偏、是不是当前阶段该做。
AgentGate 对我来说,就是一个很好的例子。
它的需求不是想象出来的。
我自己每天真的会用 AI 写代码。我真的喜欢 Codex 的体验。我真的想用 DeepSeek。我真的遇到了协议不通。我真的遇到了 DeepSeek 不支持多模态。我真的不想每次手动切 Provider。我真的需要请求日志来定位问题。
这些问题足够具体,也足够高频。
所以我才愿意把它做成工具。
这和很多“看起来很有用”的需求不一样。
有些需求只是听起来合理。
但你不一定真的会每天用。不一定真的愿意为它投入时间。不一定真的能说清楚它解决哪个具体问题。
AgentGate 的起点不是这样的。
它一开始就能说清楚:
我要让 Codex 用上 DeepSeek。我要让不支持图片的 DeepSeek 自动让路。我要让图片请求走 KimiCoding。我要减少 AI 编程过程中的配置和切换成本。
这个问题越具体,产品越容易收敛。
边界也很重要
AgentGate 还有一点我比较在意:
它不是 Codex 的替代品。
也不是 Claude Code 的替代品。也不是 OpenCode 的替代品。更不是一个新的 IDE。
它只是一个本地网关。
Codex 还是 Codex。Claude Code 还是 Claude Code。OpenCode 还是 OpenCode。
AgentGate 只负责它们和 Provider 之间的连接问题。
这个边界必须守住。
因为一个工具一旦边界不清楚,很容易越做越重。
今天想做模型切换。明天想做聊天界面。后天想做 IDE。再后来想做插件市场、团队管理、云同步、工作流平台。
每个方向看起来都有价值。
但如果什么都做,最后很可能什么都不够锋利。
所以我现在对 AgentGate 的定位很克制:
本地模型网关与 Provider 切换工具。
它要解决的是连接、转换、路由、日志、配置这些问题。
不是重新定义 AI 编程工具。
边界清楚,项目才不容易失控。
开源之后,才是真正开始验证
现在 AgentGate 已经开源。
但我不觉得这意味着它完成了。
更准确地说,它只是进入了下一轮验证。
因为我自己的使用场景,只能代表一部分情况。
别人可能主要用 Claude Code。别人可能主要用 OpenCode。别人可能接的是 OpenRouter。别人可能用的是自建 OpenAI 兼容接口。别人可能更关心成本。别人可能更关心稳定。别人可能更关心多模态。别人可能更关心请求日志和诊断。
这些场景会反过来验证 AgentGate 的边界和能力。
哪些能力是通用的。哪些只是我自己的习惯。哪些地方还不够简单。哪些配置还太复杂。哪些错误提示还不清楚。哪些 Provider 需要继续适配。
这也是我现在比较接受的一种产品路径:
先解决自己的真实问题。再开源出来接受真实反馈。再根据反馈持续修正。
不要一开始就假设自己什么都想清楚了。
很多产品不是规划出来的,而是在真实使用里慢慢修出来的。
写在最后
AgentGate 对我来说,不只是一个开源小工具。
它更像是我这段时间使用 AI 编程工具之后,沉淀出来的一个真实解法。
一开始只是:
我喜欢 Codex,但我想用 DeepSeek。
后来变成:
DeepSeek 不支持多模态,那就让图片请求自动走 KimiCoding。不同协议不兼容,那就做协议转换。能直通的请求不要乱改,那就做透明代理。Provider 会失败,那就做智能切换。问题不好排查,那就做请求日志。客户端配置麻烦,那就做一键配置。
它不是从一个宏大的概念开始的。
而是从一个很小、很具体、但反复出现的问题开始的。
这也是我现在越来越相信的一点:
好的工具,不一定一开始就很大。
它可以先解决一个真实卡点。先让自己用得上。再慢慢验证别人是否也需要。最后再根据真实使用不断修正。
AgentGate 就是这样来的。
我喜欢用 Codex。我想用 DeepSeek。我不想被协议卡住。我也不想因为 DeepSeek 不支持多模态,就每次手动切到 KimiCoding。
所以我做了一个本地网关。
它不一定复杂,但它解决了我每天真的会遇到的问题。
对一个人做产品来说,这可能就是最好的起点。
