当 Codex 遇上 AI 中转站:写一个协议转换代理解决 Responses API 的兼容性困境

0 阅读5分钟

hero.png

让 OpenAI Codex CLI 与任何 Chat Completions API 无缝协作

背景:Codex 的新架构带来的兼容性难题

2025 年 4 月,OpenAI 正式开源了 Codex CLI——一个基于终端的 AI 编程助手。作为一个重度终端用户,我第一时间就尝试将其集成到我的工作流中。

然而,在配置过程中我发现了一个关键变化:Codex v0.130+ 默认使用 wire_api = "responses",也就是 OpenAI 的 Responses API(/v1/responses),而非传统的 Chat Completions API(/v1/chat/completions)。

这个设计决策的背后是 OpenAI 对新一代 API 的押注:Responses API 原生支持函数调用跟踪、多轮工具对话、自动_truncation 管理等更复杂的功能。但问题在于——绝大多数第三方 API 提供商目前只支持 Chat Completions API

我的实际困境

我手头有多个 AI 模型渠道的访问权限:

  1. 小米赠送的 Token——在 AI 社区很火的活动,赠送了大量额度,但只支持标准 Chat Completions 接口
  2. 自建的中转服务——基于 Calcium-Ion/new-api 搭建,方便统一管理多个上游渠道
  3. 第三方的聚合 API——支持多家模型,但同样是 Chat Completions 协议

当我兴冲冲地配置好 Codex,准备连接这些渠道时,得到的却是一串错误:

POST https://xxx/v1/responses
404 Not Found

{"error": {"code": "not_implemented", "message": "Responses API not supported"}}

经过深入排查,我发现 new-api——这个在中转站圈子里使用最广泛的开源项目——截至 v1.0.0-rc.4 仍不支持 Responses API。同样,小米赠送 Token 的官方渠道也仅实现了 Chat Completions 端点。

为了使用新版本的 Codex,我必须直接连接 OpenAI 官方——这意味着放弃已经积累的所有第三方渠道资源。

解决方案:协议转换代理

与其等待所有上游提供商适配 Responses API(这可能需要数月甚至更长时间),不如在本地搭建一个协议转换层

这就是 api2codex 诞生的原因——一个轻量级的 FastAPI 代理,实时将 Responses API 请求转换为 Chat Completions 请求,并将响应转换回来。

架构设计

architecture.png 整个转换流程包含三个关键环节:

环节转换内容
请求转换inputmessages, instructionssystem, developersystem, 工具格式扁平化 → 嵌套化
流式响应Chat Completions SSE → Responses API SSE 事件流
工具调用tool_calls 索引追踪 → function_call 事件序列

核心实现难点

1. 工具调用协议的差异

Responses API 和 Chat Completions API 在工具调用格式上有微妙但关键的差异:

Responses API(Codex 发送的):

{
  "type": "function",
  "name": "exec_command",
  "description": "...",
  "parameters": {...}
}

Chat Completions API(上游需要的):

{
  "type": "function",
  "function": {
    "name": "exec_command",
    "description": "...",
    "parameters": {...}
  }
}

如果不做这个转换,工具名称和描述都是空的,模型根本不知道该如何调用工具。

2. 多轮工具对话的消息重组

更复杂的是多轮对话。当 Codex 执行一个任务时,流程是:

  1. 用户请求 → 2. 模型决定调用工具 → 3. 工具执行 → 4. 结果返回模型 → 5. 模型生成最终回复

在 Responses API 中,工具调用和结果被表示为 function_callfunction_call_output 类型的 item。但在 Chat Completions API 中,这需要被重组为:

  • 助手消息:{role: "assistant", content: null, tool_calls: [...]}
  • 工具消息:{role: "tool", tool_call_id: "...", content: "..."}

我的实现使用了一个 pending_tool_calls 列表来收集连续的 function_call 项,在碰到其他类型的 item 时统一 flush,这样就确保了消息顺序的正确性。

3. 流式响应的实时转换

Codex 的终端界面是流式显示的,这意味着代理必须实时转换 SSE(Server-Sent Events)流。这包括:

  • response.created / response.in_progress —— 会话开始事件
  • response.output_text.delta —— 文本流
  • response.reasoning_text.delta —— 推理内容流
  • response.output_item.added / response.output_item.done —— 消息/工具调用开始结束
  • response.function_call_arguments.delta / response.function_call_arguments.done —— 工具参数流

每个工具调用需要被追踪索引,因为它们在 Chat Completions 的 delta.tool_calls 中是通过 index 字段分批到达的。

快速开始

安装运行

# 克隆仓库
git clone https://github.com/talkcozy/api2codex.git
cd api2codex

# 安装依赖
pip install -r requirements.txt

# 配置环境变量
export UPSTREAM_BASE_URL="https://your-api-provider.com/v1"
export UPSTREAM_API_KEY="sk-your-key"
export DEFAULT_MODEL="gpt-4o"

# 启动
python api2codex.py

代理默认监听 0.0.0.0:8000

配置 Codex

编辑 ~/.codex/config.toml

model = "gpt-5.5"
model_provider = "api2codex"

[model_providers.api2codex]
base_url = "http://127.0.0.1:8000/v1"
env_key = "CODEX_API_KEY"
wire_api = "responses"

设置占位符 API Key(实际认证由代理处理):

export CODEX_API_KEY="placeholder"

模型元数据配置

如果 Codex 提示 "Model metadata not found",需要创建 ~/.codex/model_catalog.json 来描述模型能力。一个简化示例:

{
  "models": {
    "gpt-4o": {
      "context_window": 128000,
      "max_output_tokens": 16384,
      "supports_functions": true,
      "supports_vision": true,
      "supports_streaming": true
    }
  }
}

局限与未来

当前版本实现了 Responses API 的核心功能:文本生成、流式传输、函数调用、多轮对话。但以下 Responses API 特性尚未实现

  • 自动 truncation —— 当上下文超过限制时的智能截断
  • 推理 effort 控制 —— reasoning.effort 参数映射
  • Web search 工具 —— 内置的网络搜索能力
  • 文件 attachment —— 上传文件到 Code Interpreter

这些功能大多需要上游 Chat Completions 提供商本身支持,或通过额外的代理层来实现。

为什么不等待官方支持?

你可能会问:既然 new-api 等项目迟早会支持 Responses API,为什么不直接等待?

我的看法是:

  1. 时间成本——从 OpenAI 推出 Responses API 到现在已经数月,主流中转项目仍未完整支持,等待可能意味着几个月无法使用新版 Codex
  2. 灵活性——协议转换代理让 Codex 可以对接任何 Chat Completions 兼容的端点,包括自托管模型、内部 API、甚至本地 LLM
  3. 理解价值——实现这个代理的过程让我深入理解了两种 API 的设计哲学差异,这种认知本身就有价值

结语

api2codex 是一个务实的解决方案。它不是要替代 Eventually 会出现的原生支持,而是作为一个桥梁,让我们现在就能用上手头的资源。

如果你也遇到了类似的困境——手上有小米 Token、自建了 new-api、或者有其他只支持 Chat Completions 的渠道——希望这个项目能帮到你。


项目地址: github.com/talkcozy/ap…

技术栈: Python, FastAPI, httpx, SSE streaming

许可: MIT