10. 调用接口
完整版章节。内容按 2026.10 主线代码核对;具体入口以当前许可、账号权限和交付环境为准。
业务应用和开发工具通过网关的模型调用接口使用模型。网关在入口完成鉴权、授权、配额与流量规则判断,把请求转换为上游供应商的接口格式,并把响应和错误按调用方使用的协议返回。本章面向接入网关的开发人员和技术负责人,功能属于基础功能许可。
10.1 Base URL 与鉴权
Base URL 由网关的公开访问地址加固定前缀组成。成员在模型广场的模型详情「首次调用 API」区域可直接复制当前环境的地址(第 8.3 节)。下表中 <网关地址> 指该访问地址:
| 协议 | Base URL | 鉴权方式 |
|---|---|---|
| OpenAI | <网关地址>/api/v1/agent-gateway/openai/v1 | Authorization: Bearer <API 密钥> |
| Anthropic | <网关地址>/api/v1/agent-gateway/anthropic | x-api-key: <API 密钥>,也接受 Authorization: Bearer |
| Gemini | <网关地址>/api/v1/agent-gateway/gemini | x-goog-api-key: <API 密钥> 或查询参数 ?key=,也接受 Authorization: Bearer |
规则:
- 同一请求同时携带两种凭据且取值不同时,网关返回 400,不会择一使用;
- 凭据可以是成员创建的 API 密钥,也可以是启用「业务系统调用」后的身份源令牌(第 9.5 节);
- 请求中的模型名(OpenAI、Anthropic 为请求体的
model字段,Gemini 为路径中的模型名)填写模型广场或模型列表接口返回的模型名。模型必须属于这把 Key 绑定的模型服务,否则返回 404,错误码LLM_MODEL_NOT_AVAILABLE; - 可选请求头
x-zenova-conversation-id用于指定会话归属;不携带时由网关自动识别会话,识别顺序与取值要求见第 10.9 节; - 请求体上限为 32 MiB,语音转写文件上传为 25 MiB。
10.2 接口清单
OpenAI 兼容接口(路径相对于 OpenAI Base URL):
| 方法与路径 | 用途 | 流式 |
|---|---|---|
POST /chat/completions | 对话,支持工具调用 | 支持 |
POST /responses | OpenAI Responses | 支持 |
POST /completions | 文本补全 | 不支持 |
GET /models、GET /models/{model} | 列出或查询本 Key 可用的模型 | 不适用 |
POST /embeddings | 向量嵌入 | 不适用 |
POST /rerank | 重排序 | 不适用 |
POST /images/generations | 图像生成 | 不适用 |
POST /audio/speech | 语音合成 | 不适用 |
POST /audio/transcriptions | 语音转写(文件上传) | 不适用 |
GET /audio/transcriptions/realtime | 实时语音转写(WebSocket) | 不适用 |
POST /decisions、POST /systemone | 批量判断 | 不适用 |
Anthropic 原生接口:POST /v1/messages(支持流式),GET /v1/models。
Gemini 原生接口:POST /v1beta/models/{model}:generateContent、POST /v1beta/models/{model}:streamGenerateContent,同时接受 /v1/models/... 路径;GET /v1beta/models 列出模型。不支持 countTokens 等其他方法,调用返回 404。
模型必须具备对应用途(第 4.6 节)。模型或其供应商不支持所调用的接口时返回 400,错误码 MODEL_ENDPOINT_UNSUPPORTED;批量判断接口在所选上游不支持判断时返回 400,提示“该模型不支持此接口”。
10.3 协议自动转换
对话类接口支持四种协议:OpenAI Chat Completions、OpenAI Responses、Anthropic Messages、Gemini generateContent。调用方可以用其中任一协议调用任一对话模型,不必与供应商的「模型请求格式」一致:
- 入站协议与上游格式相同时,网关原样转发请求与响应;
- 不同时,网关把请求转换为上游格式,再把响应(包括流式事件)转换回入站协议;
- 转换中有字段无法在上游格式中表达而被丢弃时,响应头
x-zenova-conversion-dropped列出被丢弃的部件,多个标识以逗号分隔,例如anthropic.tool.web_search,responses.store。原样转发的请求不带该响应头。
嵌入、重排序、图像、语音和批量判断接口只提供 OpenAI 兼容格式,不做协议转换。
因此,Claude Code 可通过 Anthropic 接口、Gemini CLI 可通过 Gemini 接口、Codex 可通过 Responses 接口使用网关上的任意对话模型。各工具的环境变量见第 8.3 节「获取 API 密钥并发起首次调用」。
10.4 流式输出、重试与心跳
开启流式:OpenAI 与 Anthropic 接口在请求体中设置 "stream": true;Gemini 使用 :streamGenerateContent 方法。
重试与切换:
- 网关只在上游返回首个内容之前重试或切换目标,内容一旦开始输出就不再重试,避免重复内容;
- 同一目标的重试次数与可重试错误类型取供应商的「统一重试策略」(默认最多重试 2 次,第 4.4 节);
- 只有在流量规则中配置了故障转移时,网关才会切换到备用档位的其他模型(第 15 章,需要动态路由许可)。
心跳:流式请求在 10 秒内仍未得到上游首个内容时,网关先返回 200 响应头并开始发送心跳,此后的失败以流内错误帧交付;流式输出过程中,网关每 15 秒插入一条心跳。Anthropic 协议使用 event: ping 事件,其他协议使用 SSE 注释行 : keepalive,标准客户端会忽略注释行。中间代理或负载均衡的空闲超时应大于 15 秒。
流内错误:流式输出开始后发生失败时,网关发送一条与所选协议错误体同形的流内错误帧,再正常结束流。已输出的内容与用量照常计费。护栏在流式输出中途拦截时,流以协议的终结帧结束,并在终结帧中带 safetyIntervention 字段(kind 为 stream_cut)。
10.5 嵌入与重排序
嵌入:POST /embeddings,请求体包含 model 和 input。按输入 Token 计费。
{ "model": "your-gateway-model", "input": "把这段文字变成向量。" }重排序:POST /rerank,请求体包含 model、query 和 documents。按搜索次数计费:上游返回搜索次数时采用该值,否则按“1 次查询加每 100 个文档 1 次”计算;价格按每千次搜索设置。
{ "model": "your-gateway-model", "query": "退款进度", "documents": ["订单已发货。", "退款将在三个工作日内到账。"] }10.6 图像与语音
| 接口 | 关键参数 | 计费 |
|---|---|---|
POST /images/generations | model、prompt、n | 按返回的图片张数 |
POST /audio/speech | model、input、voice | 按 input 的字符数(Unicode 字符),价格按每百万字符设置 |
POST /audio/transcriptions | multipart/form-data,字段 model、file | 按音频时长,价格按每分钟设置 |
语音转写只读取音频文件头计算时长,不解码整段音频;无法识别格式时返回 400,提示“无法识别音频格式”。
实时转写使用 WebSocket:
- 连接
GET /audio/transcriptions/realtime?model=<模型名>,可选language(ISO-639-1 语种代码,如zh,缺省自动识别)。 - 子协议为
zenova.transcription.v1。凭据放在Authorization头;浏览器无法设置该头时,把凭据作为第二个子协议携带,服务端不会回显。 - 以二进制帧发送 16 kHz、单声道、16 位小端 PCM 音频。网关按停顿切段,每段作为一次转写请求独立鉴权、计费,并以
{"type":"transcript","text":"…","final":true}文本帧返回。 - 客户端可发送
{"type":"input_audio_buffer.commit"}立即切段,发送{"type":"session.finish"}结束会话;服务端推完全部段后发送{"type":"finished"}并关闭连接。出错时发送{"type":"error","code":"…","message":"…"}并关闭。
10.7 批量判断
批量判断对一段内容同时回答多道是非、选择或评分题,适用于分类、审核等场景。调用前需在模型的能力配置中声明「判断」用途。
POST /decisions 请求体包含 model、input(被判断的内容)和 questions。每道题包含 name、instructions 和 type:
predicate:是非题,答案为概率;choice:选择题,choices至少 2 项,每项包含value和description;score:评分题,levels至少 1 级,每级包含label和description。
{
"model": "your-gateway-model",
"input": "这笔订单被扣了两次款。",
"questions": [
{ "name": "is_complaint", "instructions": "这是不是一条投诉?", "type": "predicate" },
{ "name": "department", "instructions": "应该交给哪个部门?", "type": "choice",
"choices": [ { "value": "billing", "description": "付款、发票和退款。" },
{ "value": "other", "description": "以上都不是。" } ] }
]
}POST /systemone 是同一用途的另一种请求格式:用 state 放被判断的内容,questions 为按题名索引的对象。
限制:
- 一次请求最多 256 题,题名不能重复;
- 超过所选上游的单批上限时,网关按上限拆分并发送,再按题名合并答案,每一批单独记一条用量;
- 图片只能以
data:地址放入内容,不接收图片的上游返回 400; - 缺题、多题或答案不在选项内时,网关拒绝并指出具体题目;
- 不同上游给出的判断分数不能直接比较。
计费按 Token,同时计输入和输出。
10.8 错误格式与错误码
错误按调用方使用的协议返回:
| 协议 | 错误体形状 |
|---|---|
| OpenAI | {"error": {"message", "type", "code", "reason", "request_id"}} |
| Anthropic | {"type": "error", "error": {"type", "message", "reason"}, "request_id"} |
| Gemini | {"error": {"code", "message", "status", "details"}} |
reason 是稳定的错误码,HTTP 状态和是否可重试都由它决定,业务系统应按 reason 处理错误,不要解析 message 文本。常见错误码:
| reason | HTTP 状态 | 含义与处理 |
|---|---|---|
UNAUTHENTICATED | 401 | 凭据缺失、无效或已过期,检查 Key 状态与鉴权头 |
PERMISSION_DENIED | 403 | 已认证但无权执行此调用,检查可用范围与授权有效期 |
CONTENT_POLICY_BLOCKED | 403 | 护栏拦截,调整内容后重试 |
LLM_MODEL_NOT_AVAILABLE | 404 | 模型不存在或不在本 Key 的模型服务中 |
MODEL_ENDPOINT_UNSUPPORTED | 400 | 模型不支持所调用的接口 |
VALIDATION_FAILED | 400 | 请求格式或参数错误 |
POOL_EXHAUSTED | 429 | 额度池用尽,错误详情说明对象与周期(第 7.6 节) |
MODEL_SERVICE_QUOTA_HARD_REJECT | 429 | 超出模型服务可用额度 |
MONTHLY_TOKEN_EXCEEDED | 402 | 租户本月 Token 上限已用尽,由平台管理员在「租户管理」中调整(第 23.8 节) |
BILLING_UNAVAILABLE | 503 | 网关暂时无法确认租户额度状态,可稍后重试 |
TRAFFIC_RATE_LIMITED | 429 | 命中流量规则的限速,可稍后重试 |
TRAFFIC_CIRCUIT_OPEN | 503 | 流量保护熔断打开,可稍后重试 |
LLM_RATE_LIMITED | 429 | 上游限流,可稍后重试 |
LLM_UPSTREAM_SERVER_ERROR | 502 | 上游服务错误,可稍后重试 |
LLM_OVERLOADED | 503 | 上游过载,可稍后重试 |
响应头:
x-request-id:网关侧请求标识,与 OpenAI、Anthropic 错误体中的request_id相同,Anthropic 协议还同时返回request-id。向管理员反馈问题时附上该值;x-should-retry:true或false,表示重试是否可能改变结果;Retry-After(秒)与retry-after-ms(毫秒):仅在错误可重试且网关知道等待时长时返回。可重试的 429 若没有其他等待时长,返回Retry-After: 1;网关数据面尚未就绪而返回 503 时,也带Retry-After。
错误体中的 message 是随版本可能调整的说明文字,多数为英文;管理控制台和能力中心按 reason 显示中文说明。完整的错误码清单、各协议的错误体与流式终结帧形态,见随产品发布的文档站中的错误参考页。
10.9 会话识别
网关把同一场对话的多次调用归入同一个会话,供会话列表与会话详情(第 20.3 节)、会话诊断(第 20.4 节)、按会话计数的限额(第 15.4.3 节)和会话切换保护(第 15.7.4 节)使用。会话与请求标识 x-request-id 无关:请求标识每次调用各不相同,不影响会话归属。
网关按以下顺序识别会话,命中一项即停止:
- 请求头
x-zenova-conversation-id:调用方显式指定的会话编号。 - 客户端自带的会话编号:Claude Code、Codex、OpenCode 等客户端在请求中携带的会话编号,无需额外配置。
- Responses 续接与会话:使用 OpenAI Responses 接口并携带
previous_response_id时,续接请求归入上一轮所在的会话,并沿用上一轮的识别方式;未携带previous_response_id但请求体带有conversation时,按该值识别。 - 首条用户消息:以上信息均未提供时,网关按对话中的首条用户消息识别同一对话的多轮请求。
能够自行控制请求的调用方(例如自建的 Agent 平台或业务系统)可以携带请求头 x-zenova-conversation-id,精确指定会话归属。取值要求如下:
- 使用 UUID,或使用由字母、数字、
-、_组成且不少于 22 个字符的编号。 - 最长 128 个字符;取值不符合上述格式或超过长度上限时,请求返回 400。
- 同一对话的全部请求携带相同取值,不同对话使用不同取值。
使用时注意以下限制:
- 按首条用户消息识别的会话只用于会话归并与展示,不参与按会话计数,也不启用会话切换保护。需要这两项功能时,应携带
x-zenova-conversation-id,或使用自带会话编号的客户端。 - 按首条用户消息识别要求对话历史保持完整。调用方截断、摘要或改写早期消息(包括首条用户消息)后,后续请求可能被识别为新的会话;同一调用方、同一终端用户发起的首条用户消息完全相同的两场对话,可能被归入同一会话。对会话归属有精确要求时,应显式携带请求头。
- 使用 Responses 续接时,
previous_response_id必须原样回传网关下发的响应编号(形如resp_zr2.…)。回传其他取值,或回传其他凭据获得的响应编号,请求返回 400,错误码invalid_previous_response_id。 - Responses 续接依赖上一轮所在供应商保存的响应。上一轮所在的供应商或供应商账号当前不可用(错误码
provider_account_continuation_unavailable),或上一轮响应经协议转换生成、上游供应商未保存该响应(错误码response_continuation_unrestorable)时,无法凭previous_response_id续接。此时请求的input若已携带完整上下文(包含此前的助手回复、工具调用或工具结果),网关去掉previous_response_id后照常转发;否则返回 409,调用方应在input中携带完整上下文后重试,或开启新对话。