编程 Agent 依赖模型发现、流式输出、工具调用、会话保持等深层 API 能力;作者梳理了「OpenAI 兼容」声明下各能力矩阵的真实覆盖情况,供接入方逐项核验。
许多 AI 提供商将某个端点描述为 OpenAI-compatible。通常这意味着现有客户端可以发送一个熟悉的请求,并收到一个看起来熟悉的响应。这很有用,但它不是一个完整的兼容性声明。
Coding agent 对 API 的使用程度远超一次性的聊天演示。它会发现模型、流式输出部分内容、发出 tool calls、重试失败、保存会话状态,还需要 usage 数据来解释发生了什么。一个提供商可能对一个简单请求返回 HTTP 200,但一旦 agent 使用了其中某个路径就会失败。
至少,提供商暴露了一个有文档的 base URL、接受一种熟悉的认证格式、理解带有 model 和 messages 的请求,并在可识别的响应结构中返回文本。一些提供商还暴露了 /v1/models、流式传输、tools 或更新的 Responses API。
重要的词是"一些"。兼容性是一个矩阵,不是一个是非标签。客户端可能依赖于简化实现中可选的字段。它们也可能使用与提供商文档示例不同的端点、模型标识符或重试策略。
Coding agent 将一个用户 prompt 转化为一连串的模型调用。它可能让模型检查文件、调用工具、解释结果、修改计划并继续流式传输。这在多个环节创造了提供商可能偏离客户端假设的点:
解决之道是一个小型、可重复的冒烟测试,而不是更长的模型列表。
使用 agent 将使用的确切 base URL 和认证方法进行测试:
curl "$BASE_URL/v1/models" \
-H "Authorization: Bearer $API_KEY"
记录状态码、响应时间和返回的 ID。从响应中选取一个 ID 用于后续测试。若提供商要求前缀、账户别名或不同拼写,这些都构成兼容性契约的一部分。
不要假设营销页面上的模型可以通过 API 调用。请求完成后,对比请求的模型、上游模型、日志中的模型和计费模型。
发送一个最简的 Chat Completions 请求,确认 roles、content、finish reason 和 usage 字段。然后分别测试 /v1/responses。成功的 Chat Completions 请求并不能证明 Responses 支持。
curl "$BASE_URL/v1/responses" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_ID","input":"Reply with OK"}'
对于真实的 agent,需要比较客户端实际读取的字段,而不仅仅检查文本是否出现在 JSON 的某个位置。Response IDs、output item types、status fields 和 usage 字段的位置都会影响对话状态和计费。
流式传输改变了故障模型。捕获每一条 SSE 事件,验证排序,确认流是否正常结束:
curl -N "$BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_ID","stream":true,"messages":[{"role":"user","content":"Count to three"}]}'
测试慢响应和下游断连。问自己:提供商是否继续生成?最终 usage 是否到达?网关是否一致地结束了请求?在客户端已收到文本或部分 tool-call delta 后,重试并非绝对安全。
发送一个确定性的 tool schema。检查 tool-call ID、index、name 和 argument 片段在流式和非流式响应中的表现。测试仅当客户端能重建一个完整的调用(无重复片段或乱序参数)时才通过。
然后发回工具结果并继续对话。某些端点接受 Chat Completions 中的 tool calls,但 Responses 中使用不同结构。这种差异对 coding agents 很重要。
使用发现阶段返回的确切模型 ID。测试大小写敏感性、前缀、别名和不支持的模型。清晰的错误比静默降级到其他模型更安全。
还要测试配置的基础 URL 带和不带 /v1 后缀的行为。验证路径拼接、重定向和凭证边界。一个对第一方 URL 工作的客户端可能仍然处理不好自托管或网关 URL。
记录无效请求、凭据缺失、未知模型、速率限制、超时和上游故障时的行为。捕获状态码、request ID 和 Retry-After 值(当存在时)。
重试规则应使用请求状态,而不仅仅依赖 HTTP 状态。在输出之前,重试可能是安全的。在收到部分文本、tool-call delta 或上游计费后,重试可能导致重复输出、重复执行或重复计费。网关应记录所选路由、尝试次数、下游输出状态、取消状态和最终计费来源。
记录提供商暴露的输入、输出、缓存读取、缓存写入、延迟、重试和最终计费。将这些值与请求日志对比。缺失 usage 不能证明零使用,公开页面上的价格也不足以在缺少模型 ID 和计费单位的情况下解释特定请求。
对于 coding agent,还要比较每个已完成任务的成本,而不仅仅是每百万 token 的成本。额外的修正轮次、重试或工具循环可能改变结果。
最终的分类应该是明确的:
不要基于第一个类别标记最后一个类别。
我在构建 Your Model(一个 OpenAI-compatible 多模型 API)时使用相同的兼容性检查清单。
披露:我是 Your Model 的构建者。