除了普通聊天,我还测了流式输出、工具调用、图片输入、预算统计、健康检查和打包产物。少测一条,发布后就可能在那里翻车。
做 Claude 到 OpenAI 的兼容代理时,我一开始也差点只盯着普通聊天接口。
但兼容代理的风险不在“能不能回一句话”。麻烦在于它夹在客户端和 provider 中间,很多能力在转换时都可能走样。
所以我更愿意在发布前列一份测试清单,而不是先写一堆部署说明。
单轮聊天只是冒烟测试
最基础的 /v1/messages 对话当然要测。它能验证:
- 服务是否启动。
- 请求能否进入代理。
- 模型名是否能映射到下游 provider。
- 响应能否转换回 Claude 风格。
这条链路通了,只能说明最短路径没断,离发布还差得远。
如果一个代理只测了普通文本输入,它可能在真实使用 Claude Code 时马上翻车。因为 Claude Code 不只是聊天窗口,它会发工具调用、流式请求、带系统提示的请求,也可能传图片或查询上下文预算。
流式输出要单独测
流式响应不是“把完整文本切成几段”这么简单。
OpenAI 风格的 SSE chunk 要被转换成 Claude 风格事件,至少要处理:
- message start。
- content block start。
- delta。
- content block stop。
- message stop。
- usage 或结束原因。
- 下游错误时的中断行为。
如果流式转换不稳,用户遇到的就不只是“慢一点”。CLI 可能会卡住,输出可能缺块,工具调用 JSON 可能不完整,甚至连结束事件都收不到。
所以流式测试必须独立存在。普通非流式响应通过,不代表流式协议也通过。
工具调用是第二条主路径
兼容代理只支持文本,就只能算”聊天代理”。要让 Claude Code 日常能用,工具调用必须纳入测试清单。
这里有两段转换:
Claude tool schema -> OpenAI toolsOpenAI tool calls -> Claude tool_use还要测工具结果回传:
Claude tool_result -> OpenAI tool message这一步很容易出错。比如 tool call id 对不上、参数 JSON 只收到半截、assistant 消息和 tool result 顺序不对,都会让后续对话失去上下文。
所以我会把“模型请求工具”和“工具结果继续对话”拆成一个完整用例,而不是只测第一段 tool_use。
图片输入也不能靠想象兼容
多模态输入看起来只是 content 里多一个 image block,但不同 API 对图片的表示方式并不一样。
Claude 请求里可能是:
type: imagesource: base64 + media_typeOpenAI 兼容接口里通常要转成 image_url 或对应的多模态消息结构。这里如果 media type、base64 前缀、content block 顺序处理错,文本请求仍然正常,图片请求却会失败。
所以哪怕只用一个极小的测试图片,也应该把”文本加图片”放进测试清单。
预算统计和健康检查是运维接口
对 CLI 用户来说,上下文预算统计可能没有普通对话显眼,但它影响预检查、截断策略和失败提示。
健康检查也一样。一个代理服务如果没有稳定的 /health 或连接测试接口,部署后就只能靠“发一条真实请求”判断服务是不是活着。这对本地调试还行,对服务器守护进程就太粗糙。
发布前至少要确认:
/health返回稳定结构。- 预算统计接口能接收 Claude 风格请求。
- provider 连接测试能区分服务活着和下游不可用。
这样出问题时,才能判断是代理挂了、配置错了,还是下游 provider 返回异常。
二进制打包是另一种兼容性
如果项目要交付给没有 Python 环境的机器,PyInstaller 这类二进制打包也要单独验证。
这不是简单地生成一个文件。FastAPI、Uvicorn、Pydantic、动态 import、配置文件加载,都可能在源码运行时正常,在打包后缺模块。
所以打包文档里需要明确:
- 目录版和单文件版分别怎么生成。
- 哪些 hidden imports 必须带上。
- 是否需要包含
src等数据文件。 - 目标机器需要多少内存和存储。
- 打包成果怎么用环境变量启动。
二进制交付的测试,不是确认文件生成就结束,还要用打包后的文件启动服务,并跑同一组接口。
我会保留的发布前清单
兼容代理发布前,我会至少保留这张表:
basic chat -> 普通文本请求和响应转换system message -> 系统提示进入下游消息streaming -> SSE 事件完整结束tool use -> 工具 schema 和 tool call 转换tool result -> 工具结果回灌后继续对话multimodal -> base64 图片输入转换budget counting -> 预算接口可用health check -> 服务和下游状态可区分binary packaging -> 打包产物能启动并通过冒烟测试这张清单不复杂,但它能阻止很多“看起来能跑”的发布事故。
我最后会看一件事:换 provider、换模型、换部署方式之后,客户端还能不能按预期工作。
确认到这一步,再发版本。
继续读