为多模型 API 网关构建租户感知的 /v1/models 目录
将模型发现视为授权和路由准备合同。构建租户感知的 /v1/models 目录,仅列出每个 API 键可通过每个受支持的 API 表面使用的模型。
网关不应返回 GET /v1/models 中每个连接的提供商已知的每个模型。它应该返回经过身份验证的 API 密钥已获得授权并且在操作上能够调用的模型。
当一个API密钥提供对多个 LLM 提供商的访问时,这种区别很重要。上游目录的原始联合可以包含团队策略禁止的模型、租户计划下不可用的模型、缺少健康凭证、与请求的 API 不兼容或未部署在所需区域中的模型。这些条目会产生损坏的模型选择器和运行时错误,而发现本应防止这些错误。
实际合同更为严格:每个广告模型都必须通过与实际请求相同的准入检查。
定义“可用”的含义
提供商的存在只是一个输入。仅当所有必需条件都满足时,模型才应出现在密钥的默认目录中:
- 网关已为该模型配置了公共产品。
- 租户、团队和 API 密钥有权使用该产品。
- 适用的商业计划允许其使用。
- 政策允许模型、提供商、区域和数据处理模式。
- 至少存在一个兼容的上游部署或路由。
- 该路线有可用的提供商凭据。
- 该路线至少支持目录中公布的一个API表面。
- 根据网关的运行状况政策,路由已准备好运行。
表示为集合运算:
visible_models(key) =
configured_products
∩ tenant_entitlements
∩ team_grants
∩ key_grants
∩ commercial_rights
∩ policy_eligible_routes
∩ compatible_deployments
∩ operationally_ready_routes
这是一项建议,而不是关于 OpenAI 架构的声明。标准架构并未定义所有这些特定于网关的控件。它们属于网关的控制平面和目录编译器。
无需代理即可规范提供程序发现
事实:提供商发现 API 公开了不同的概念。 OpenAI 的模型列表提供标识符和基本元数据,但不是每个 API 表面的完整功能矩阵。 Anthropic 区分生命周期状态,并且在检索模型或别名时可以返回更丰富的功能信息。 Gemini 公开令牌限制和支持的生成方法等字段。 Microsoft Foundry 可能需要 model 字段中的部署名称,并且即使底层模型存在,部署也可能与特定的 API 不兼容。
因此,直接转发提供商响应并不是一个持久的设计。将每个提供商 API 视为调节源。将其观察结果转换为内部记录,然后将其与网关配置和租户政策相结合。
使用规范目录记录
有用的内部记录将公共合约与上游实现分开:
{
"catalog_revision": "cat_2026_11_05_0182",
"public_model_id": "reasoning-large",
"lifecycle": "active",
"api_surfaces": ["chat.completions", "responses"],
"input_modalities": ["text", "image"],
"output_modalities": ["text"],
"limits": {
"context_tokens": 200000,
"max_output_tokens": 32000
},
"capabilities": {
"tools": true,
"structured_output": true,
"batch": false
},
"entitlement_profile": "advanced-reasoning",
"routes": [
{
"provider": "provider-a",
"target_type": "deployment",
"target_id": "prod-reasoning-east",
"region": "us-east",
"state": "ready"
}
]
}
请勿通过标准公共端点公开target_id、凭据引用或内部路由状态。这些字段是控制平面数据。让它们可用于路由准入、支持工具和使用归因。
单独的 ID、别名和部署
公共模型 ID 是客户合同。提供程序模型 ID 标识上游模型系列或版本。部署名称标识运营商创建的服务资源。它们不可互换。
在路由之前将公共别名解析为不可变目录修订版本。在使用事件中记录请求的 ID 和解析的目标。如果别名稍后发生更改,支持人员仍然可以重建哪个部署处理了先前的调用。
编译经过身份验证的密钥的目录
目录编译器应接收经过身份验证的主体,而不仅仅是租户 ID。同一租户可能拥有生产密钥、开发密钥、受限客户密钥以及具有不同模型授权的服务帐户。
确定性编译顺序是:
- 加载不可变的基本目录修订版。
- 解决租户成员身份、团队成员身份和特定于密钥的授予问题。
- 应用计划、地理位置、数据驻留和提供商限制。
- 删除没有有效凭据或兼容部署的路由。
- 使用当前运行状况快照评估路线准备情况。
- 将幸存路线聚合到公共模型记录中。
- 仅返回至少一条幸存路线支持的 API 个表面。
当团队授权和关键授权同时存在时,使用交集语义。分配给受限团队的密钥不应仅仅因为租户拥有更广泛的计划而恢复更广泛的访问权限。这使得软件团队的 AI 模型访问控制可预测并减少意外泄露。
保持列表和检索行为相同
GET /v1/models/{model} 必须运行与列表操作相同的授权谓词。否则,攻击者可以通过比较成功、禁止和未找到的响应来枚举隐藏标识符。
对于密钥无法看到的模型,返回与未知模型相同的公共错误。不要透露其他租户是否可以使用它、哪个提供商托管它,或者哪个权利可以解锁它。管理 API 可以向授权操作员公开更详细的原因。
明确表示API兼容性
模型的存在并不意味着支持每个端点。聊天完成、响应、嵌入、图像生成、实时、批量和Anthropic消息具有不同的请求和流式传输合同。
因此,路线准入应同时接受模型和API表面:
admit(key, public_model_id, api_surface, request_features)
结果应标识兼容的目录修订版和一条或多条符合条件的路线。例如,模型可以支持 chat.completions 但不支持 responses,或者仅在缺少内置工具时支持响应。当兼容性取决于请求的功能时,单个布尔值(例如 supports_responses)可能不够。
建议:发布保守功能。仅当网关可以在符合条件的路由集中强制执行该功能或可以选择确定性支持该功能的路由时,才通告该功能。请勿从提供者家族名称推断图像输入、工具调用或结构化输出。
添加元数据时保持SDK兼容性
保持OpenAI兼容客户端所需的标准字段稳定:
{
"id": "reasoning-large",
"object": "model",
"created": 1793836800,
"owned_by": "gateway",
"x_gateway": {
"catalog_revision": "cat_2026_11_05_0182",
"lifecycle": "active",
"api_surfaces": ["chat.completions", "responses"],
"input_modalities": ["text", "image"],
"availability": "available"
}
}命名空间扩展可降低冲突风险,但某些客户端会丢弃未知字段。如果应用程序需要详细的选择数据,请提供带有版本化架构的单独的经过身份验证的模型信息端点。保持 /v1/models 对于 SDK、命令行工具和模型选择器来说足够小。
选择稳定或经过健康过滤的列表
存在两种合理的可用性政策。
运行状况过滤目录:当前没有运行状况良好的路线时隐藏模型。这可以最大程度地减少失败的调用,但目录可能会在事件期间发生波动并使客户端选择无效。
稳定目录:在报告availability: temporarily_unavailable的同时继续列出授权产品。这对于自动化和迁移工具来说更容易,但客户端仍可能尝试调用,除非他们理解扩展。
实际的默认设置是隐藏未部署、禁止、停用或凭证不合格的模型,同时保留暂时不可用的模型,并为受信任的客户端提供显式状态。如果现有客户端无法解释状态元数据,则最小兼容性端点可以忽略不可用的条目。
预测:更丰富的模型选择客户端将越来越依赖于功能和可用性元数据。在该行为广泛可靠之前,服务器端路由许可必须保持权威。
缓存已编译的目录而不提供过时的授权
尽可能在请求路径之外编译目录。缓存键应至少包含:
(tenant_id, key_id, entitlement_version, catalog_revision, policy_revision)
当团队成员资格、模型授权、定价计划、提供商凭据、部署状态或路由政策发生更改时,受影响的条目将失效。较短的生存时间值并不能替代撤销事件:即使是短暂的陈旧窗口也可能会暴露新禁止的模型。
提供商协调可以是异步的。在提供商控制平面中断期间,保留最后已知的目录,记录其观察时间,并防止新的不确定路由变得合格。这样可以保持列表的响应能力,而不将过时的发现视为新路线可用的证据。
将目录作为入场合同进行测试
最强的一致性属性很简单:对于返回到键的每个模型和 API 表面,路线准入必须在相同的目录和运行状况修订版下成功。
添加自动化测试:
- 允许的密钥查看和检索其分配的模型。
- 禁止键既看不到列表条目,也看不到可检索的元数据。
- 团队限制会缩小而不是扩大关键访问权限。
- 仅聊天部署不会针对响应进行广告。
- 已禁用的凭据将删除其依赖路由。
- 解析为预期的不可变目录修订版本的别名。
- 已退役的型号从默认目录中消失。
- 授权、成员资格或政策更改后缓存失效。
- 未知和隐藏的模型 ID 会产生难以区分的公共错误。
- 每个公布的功能都至少有一个符合条件的路由。
综合探测可以添加路由有效的证据,但它们会消耗配额、可能需要花钱,并且无法涵盖所有功能组合。将它们用于代表性路由类别,并将它们与部署状态、凭据检查和真实流量运行状况相结合。
记录足够的证据来解释决策
对于每个接受或拒绝的请求,记录目录修订、请求的公共模型 ID、API 表面、解析的路线、功能合同、政策修订和结构化准入原因。避免仅出于此目的存储提示内容。
实现顺序很简单:定义规范记录、构建提供程序协调器、编译每个键视图、创建列表并检索共享一个授权谓词、将路由准入连接到同一修订版,并在启用缓存之前添加负面测试。一旦这些部分就位,/v1/models 就成为“这个键可以调用什么?”的可靠答案。而不是松散过滤的库存。