当我为了省 Token、保账号,用剪贴板操控 DeepSeek 网页版时,才真正理解了为什么 OpenAI 要彻底抛弃 Chat 协议,也要强推这套有状态的 Responses。
1. 引言:一个“魔怔”开发者的自白
故事的起点很荒诞。
几个月前,我跟朋友吹牛,说一个月消耗多少 Token 才算“大手子”。朋友晒出的账单是月烧 3 亿 Token,我嘴上说“这不就是随便的事吗”,心里却在盘算:怎么才能让自己的 Token 统计数字也暴涨?
于是我开始折腾一个奇怪的项目:用 DeepSeek 网页版当大脑,让 Claude Code 当手,自己在中间搭一个反代,把 Claude Code 发出的 Anthropic Messages 协议请求,翻译成对 DeepSeek 网页版的模拟操作。
这项目听起来很完美:DeepSeek 网页版靠 conversation_id 自动维护上下文,我每次只需要把最新一句话发过去,Token 消耗小、行为特征低调、还能绕过 API 费用。我甚至专门研究了怎么模拟人类打字延迟、怎么随机间隔、怎么避免并发请求——一切为了保号。
但很快我发现了一个致命问题:OpenAI 官方的 Codex,底层用的是 Responses 协议,不是 Chat Completions。而 DeepSeek 根本不支持 Responses。所有民间接入方案全部失效。
为了弄懂为什么,我开始深挖 Chat 和 Responses 的区别。这一挖不要紧,我彻底理解了什么叫“协议即架构”——也明白了为什么我必须自己造轮子。
2. 我的反代方案是怎么运作的
在聊协议之前,先交代清楚我的架构。
核心思路:
- 大脑(DeepSeek 网页版):负责所有推理和理解,通过 conversation_id 自动维护上下文。
- 手(Claude Code + Tauri 工具):负责执行工具调用——读文件、写文件、跑命令。
- 翻译官(我的本地代理):把 Claude Code 发来的 Anthropic 格式请求,转换成对 DeepSeek 网页版的简单消息;再把 DeepSeek 的回复翻译回 Anthropic 格式。
保号措施:
- 不开流式:一次请求一次回复,干净利落,没有长连接特征。
- 维持单一长会话:整个工作过程只用一个 conversation_id,绝不并行开新会话。
- 剪贴板法:用朋友项目的剪贴板交互模块操作 DeepSeek 网页版,行为模式完全像一个手动复制粘贴的正常用户。
关键代码逻辑:
defget_last_user_message(messages):formsginreversed(messages):ifmsg["role"]=="user":returnmsg["content"]return""每次收到 Claude Code 的全量历史,我只取最后一条用户消息,发给 DeepSeek。其余全部丢弃。
3. Chat Completions 协议:“无状态”的原罪
在折腾反代的过程中,我每天都在和两种协议打交道。
Anthropic Messages API 和 OpenAI Chat Completions API,本质上是一类东西:无状态的对话协议。
什么叫无状态?就是每次 API 请求,你都必须把整个对话历史全量发送过去。模型不存储任何上下文,全靠你喂。
这带来三个问题:
第一,Token 浪费恐怖。Claude Code 每次调用工具后,都会把完整历史重新组装成 messages 数组发给我。虽然我只取最后一条发给 DeepSeek,但 Claude Code 和代理之间的本地传输,也是实打实的几万 Token。我心想:这要是在公网上跑,早就触发风控了。
第二,上下文管理全靠自己。多步骤任务需要几十轮交互,每轮都全量发送历史,很快就会触及模型上下文上限。开发者必须自己实现历史的裁剪、总结、管理——这些都是额外的工作量。
第三,工具调用是“瘸腿”的。Chat Completions 的 function calling 只是一个“信号”:模型说“我想调工具了”,然后开发者自己在外层写死循环,手动处理“调用→获取结果→再次推理”的循环。这就像你让一个将军指挥战斗,但将军的命令只能传达到通信兵,通信兵得自己跑去找炮兵、自己看地图,然后回来再问将军下一步怎么办。
4. 沙箱谜题:云端还是本地?
在研究 Codex 的时候,我一度被“沙箱”这个概念搞懵了。
我问自己:Codex 要配置的沙箱到底是什么?是本地 Docker 容器,还是 OpenAI 服务器上的虚拟机?
答案很明确:服务器端的,跑在 OpenAI 的云端,不在你本地。
运作方式就像给你分配了一台临时的“云电脑”:
- 临时且独立:每次提交任务,云端新建独立沙箱,自动装好 JDK、Python 等环境。任务结束或超时,立刻销毁。
- 代码是“拷贝”上去的:不是直接改你本地文件,而是把你 GitHub 仓库的代码拷到沙箱里,改完测完再推回 GitHub。
- 默认断网,绝对隔离:沙箱环境默认互联网断开,除非明确授权。
但更让我震惊的是:这个云端沙箱不是 OpenAI 自己的数据中心,而是第三方托管的。E2B、Cloudflare、Daytona 这些沙箱提供商负责执行环境,OpenAI 只负责调度模型。两者物理分离,责任也分离——代码在沙箱里跑出问题,是沙箱厂商的锅,不是 OpenAI 的锅。
我瞬间理解了:这和我用剪贴板方案操作 DeepSeek 网页版的思路一模一样。都是在用“隔离”换“安全”。只不过 OpenAI 用云端沙箱,我用剪贴板隔断。
5. Responses 协议:“有状态”的革命
搞清楚了沙箱,再来理解为什么 Codex 必须换协议,就豁然开朗了。
Responses 协议的核心突破是引入服务端状态管理。
旧协议(Chat)的痛苦模式:
请求1: [用户指令] 响应1: [我要调工具] → 你手动执行工具 请求2: [用户指令, 旧响应1, 工具结果] ← 重复历史! 响应2: [继续] → 你手动执行工具 请求3: [用户指令, 旧响应1, 工具结果, 旧响应2, 新工具结果] ← 更长了!新协议(Responses)的优雅模式:
请求1: [用户指令] 响应1: [response_id: resp_001, 我要调工具] → 沙箱自动执行工具 请求2: [previous_response_id: resp_001, "然后呢?"] 响应2: [自动拼接历史,继续]关键变化就两个:
- input 不叫 messages:Chat 协议用 messages 数组,Responses 用 input。命名差异反映了定位差异——一个是“对话历史”,一个是“任务输入”。
- previous_response_id:这个东西让服务端自动拼接历史,你不需要再发全量历史了。
这彻底解决了无状态协议的三大痛点。更重要的是,Responses 内置了工具调用循环——模型请求调工具,沙箱自动执行,结果自动返回,模型继续推理。整个“思考-行动-观察”循环在服务端完成,不用你管。
6. 为什么 DeepSeek 不支持 Responses?
理解了 Responses 的优势,下一个问题就是:为什么 DeepSeek 不跟进?
答案很直接:Responses 协议强依赖服务端沙箱能力。DeepSeek 的 API 只是一个文本推理接口,没有内置沙箱。要实现 Responses,意味着要从零搭建一整套云端执行环境——这不仅是技术投入的问题,更是商业模式的根本差异。
OpenAI 选择把“手”也做成官方服务(云端沙箱),让你用 Responses 协议一体调用。DeepSeek 选择只做“大脑”,把“手”留给开发者自己实现。
这恰好解释了为什么我必须继续搞自己的反代项目。当官方平台不提供“有状态执行”能力时,通过协议翻译和外部工具链来补全这套“手”的能力,就是唯一的出路。
7. 结语:协议即架构,架构即选择
回头看我的“反代保号”之路,最初只是想省点 Token、让统计数字好看点。但深入了解 Chat 和 Responses 的差异后,我意识到:
协议不是简单的接口格式,而是架构哲学的外化。
Chat Completions 代表的是“无状态、纯推理”的传统 AI 交互——模型只负责想,做不做、怎么做都是你的事。Responses 代表的是“有状态、带执行”的新范式——模型既能想又能做,你要做的就是给任务、看结果。
OpenAI 用 Responses 协议,把“手”锁在云端沙箱里,既保障了安全,也绑定了生态。DeepSeek 坚持 Chat 协议,把“手”的自由度还给了开发者,但也把保号、安全、调度这些脏活累活全留给了你。
而我这个“魔怔”开发者,选择用剪贴板模拟和协议翻译,在两者之间走出一条自己的路:用有状态网页版的便利,结合无状态协议的灵活,搭一套既安全又能干活的私人 Agent 框架。
这或许就是独立开发者的浪漫:不满足于官方给的沙箱玩具,非要自己用“反代”和“剪贴板”这种土法子,造一个真正能碰本地文件、跑命令行、还不会封号的 AI 工作流。
本文作者正试图用一个 DeepSeek 网页版、一个 Tauri 剪贴板工具、和一个不到 200 行的 Python 代理,取代昂贵的 API 订阅。目前还在保号的路上继续努力。