跳到主要内容
版本:Dev

发布说明

本页汇总 AISIX 网关、控制面、控制台和部署包中面向用户的变更,按版本从新到旧排列。

如果一次升级跳过了若干版本,其间每个版本的升级说明依然适用。请按从旧到新的顺序阅读——从你当前版本的下一个版本开始,一直读到目标版本。支持的升级路径和升级顺序参见升级 AISIX。

发布产物包括 docker.io/api7/aisix 网关镜像、docker.io/api7/aisix-cp-* 下的控制面镜像、aisix-cp Helm Chart 和离线安装包。

1.9.0​

发布日期: 2026 年 11 月 6 日

本版本让每位用户都可以从自己的 MCP 客户端登录上游 MCP 服务器,并让 OIDC 身份提供方可以从已验证的令牌中提供成本归因标签。用量记录现在能显示失败请求发送和收到的内容、每个请求的最后一次尝试,以及请求给平台带来的成本。请求日志查询的计数、翻页和语句耗时现在有固定上限。上游失败以上游自己的文字及其 code、param 返回给调用方,被上游拒绝的 Realtime 会话现在会告知客户端并记录为失败。

完整的 AISIX Cloud Admin API 端点和 Schema 对比,请参阅 1.8.0 到 1.9.0 的变更(英文)。

行为变化​

以下变化可能需要更新客户端、用量记录和导出内容的使用方,以及 provider_key 预算。

上游错误响应携带文字、code 和 param​

上游失败时,error.message 现在是上游的文字,而不再是把上游整个错误体写成的 JSON 字符串。这适用于 /v1/rerank(包括 Cohere)、/v1/audio/speech、/v1/audio/transcriptions、/v1/audio/translations、/v1/images/edits 和原生 /v1/responses(包括流式)。4xx 现在还携带上游的 code 和 param,5xx 两者都不携带。状态码不变。

变更前:

{"error":{"message":"{\"error\":{\"message\":\"bad\",\"type\":\"invalid_request_error\",\"code\":\"bad_param\",\"param\":\"x\"}}","type":"upstream_error"}}

变更后:

{"error":{"message":"bad","type":"upstream_error","param":"x","code":"bad_param"}}

升级网关前,请修改在这些路由上从 error.message 解析 JSON 的调用方:把 error.message 当作文字读取,把 error.code 和 error.param 当作字段读取。访问日志的 error 和失败记录的 error_message 显示为 upstream returned HTTP 500: bad,完整内容采集的 response 字段仍然保存上游发送的原始响应体。

相关变化:

  • 其他形态的错误体,覆盖所有路由。 {"message":"x"}、{"error":"x"}、{"detail":"x"} 或 {"detail":{"message":"x"}} 形态的响应体现在都读取为 x,包括此前返回原始响应体文字的 chat、completions、embeddings、images、messages、count tokens 和桥接的 responses。空白字段不再遮盖后面字段的文字。非 JSON 响应体仍然是发送时的文字。
  • /v1/decisions。 4xx 现在携带上游的 code 和 param。超过 64 KiB 的错误体不再解析,调用方会以文字形式收到它的前 1 KiB。
  • Azure OpenAI 密钥。 在 /v1/chat/completions 和 /v1/responses 上,部署不存在时现在返回 code: model_not_found,此前不返回 code。4xx 现在携带 param,数字形式的 error.code 现在以字符串返回。状态码、error.type 和 error.message 不变。音频和 Realtime 仍然携带 Azure 自己未经转换的 code,/v1/messages 仍然省略 code。
  • /v1/videos。 在 POST /v1/videos、GET /v1/videos/{id} 和 GET /v1/videos/{id}/content 上,对所有视频服务提供方:
    • error.message 是上游的文字,不再带 code: 前缀。从 message 中解析 code 的客户端必须改读 error.code。
    • 4xx 携带上游的 code 和 param,以及 DashScope 顶层的字符串 code。error.type 仍为 upstream_error。5xx 只携带文字。
    • 字面文字 upstream error 不再出现。非 JSON 响应体或没有文字字段的 JSON 以文字形式返回。空响应体或空白消息使用状态兜底文字,例如 upstream returned 400 Bad Request。
    • 上游的 Retry-After 现在会在 429 时传给调用方。在任何会触发模型冷却的状态上,它还决定冷却时长,并控制同一目标的重试节奏。这也包括 poll 和 content 请求,因此 poll 上的一次 429 最多可能让该模型的新提交暂停冷却设置的 max_seconds。
    • 超过 64 KiB 的错误体不再解析,调用方会以文字形式收到它的前 1 KiB。
    • 响应体无法完整读取的非 2xx 响应现在按状态码处理;此前是 502 upstream_decode_error,既不重试也不计入冷却。消息使用状态兜底文字,4xx 保留状态码,5xx 返回 502,429 保留 Retry-After,重试和冷却都按该状态处理。
    • 失败记录和访问日志把消息限制在 1 KiB,只有 code 没有文字的响应体不再上报 code。

/v1/files、/v1/batches、微调路由和透传路由仍然按上游发送的内容原样转发非 2xx 响应。

inject 透传路由移除所有凭证请求头​

credential_mode: inject 的透传路由现在会在转发前移除所有入站凭证请求头:authorization、x-api-key、api-key、x-goog-api-key、cookie、proxy-authorization、x-amz-security-token、x-amz-date 和 x-amz-content-sha256。这不再由服务提供方密钥的 strip_headers 决定,x-* 或 * 这样的通配符也不能把它们放回来。

升级网关前,请在 forward_client_headers 中按确切名称列出路由仍需转发的每个请求头,包括曾在服务提供方密钥上取消剥离 cookie 的情况。如果列出的请求头正是路由注入凭证所用的请求头,上游收到的将是调用方的值,而不是注入的值。credential_mode: forward_client 不变。

控制台现在始终在服务提供方密钥的 strip_headers 中保存 authorization、cookie 和 x-api-key,即使这次保存改的是其他字段。因此,通过 API 取消剥离 cookie 的密钥一旦在控制台中保存,在低于 1.9.0 的网关上也会停止转发它。

失败记录携带真实文字和更多内容​

现在每条失败记录都会在 error_message 中说明失败原因,与 content_mode 无关。这段文字可能回显调用方发送的内容或上游返回的内容,并进入控制面存储、OTLP 和 SLS,包括 metadata_only 模式。当上游或解析器回显时,监控模式护栏匹配到的值,或者护栏运行前的校验错误引用的值,可能出现在这里。护栏自身的拒绝仍然不携带匹配到的内容。上游失败显示为 upstream returned HTTP <status>: <upstream text>。

在 content_mode: full 下,所有端点、所有状态码的失败记录现在都携带请求体和它自己的响应体:

  • 导出内容现在包含上游 401 和 403 响应的请求体,以及网关拒绝(例如禁止使用的模型)的请求体。
  • 在护栏完成之前失败的记录携带未脱敏的请求体。
  • 每次回退尝试都会重复携带请求体,因此失败流量的导出量会增长。
  • 配置了完整内容导出器时,网关会在应答前读取 A2A 代理的错误体,因此较慢的代理最多可能把应答延迟到该代理的超时时间。

升级网关前,请检查谁能读取用量记录和导出内容,以及你能承受多少导出量。

Vertex AI Gemini 的 max 和 xhigh effort 可能返回 400​

在 Vertex AI Gemini 2.5 或更高版本上请求思考的调用方,现在会在所用协议的推理字段中收到推理内容。流的第一个事件可能是推理内容,而不是文本。

Gemini 没有与 max 或 xhigh 对应的设置。在默认不思考的模型上,例如 gemini-2.5-flash-lite、gemini-2.5-flash-image 或 gemini-3.5-transcribe,上游会返回 400 Thinking_config.include_thoughts is only enabled when thinking is enabled,而 1.8.0 返回 200。网关会透传这个错误,因此请为这些模型选择受支持的 effort。

输出护栏不扫描思考文本。在 Vertex AI Gemini 模型上配置了输出护栏的部署,现在会把这段未经扫描的文本传给请求它的调用方。

上游 200 响应中报告错误时变为失败​

在受影响的路径上,顶层 error 带有内容的 2xx 响应或流式帧现在属于带内上游失败。调用方会收到 502 或内嵌的 4xx,错误类型为 upstream_in_band_error。

  • Completions 和图像生成此前以携带错误对象的 200 返回。
  • 原生 /v1/responses 对裸错误信封此前也是如此。status: "failed" 的 response 对象仍然作为应答转发。
  • /v1/messages/count_tokens 不再把这样的响应体当作计数转发。
  • 其他有类型的路径此前返回 502 upstream_decode。
  • 透传路由仍然转发上游的字节和状态码,现在还会记录这次失败。
  • /v1/realtime 遵循自己的规则,见升级说明。
  • error 为 null、{} 和 "" 时不算失败。

导出内容的结构变化​

完整内容的 OTLP、SLS 和 Datadog 记录的使用方需要注意以下变化:

记录变化
Chat 提示词携带客户端发送的每个内容块。多块文本是多个文本部分,而不是拼接成的一个部分。
Base64 媒体小负载不再保留原文。提示词、MCP tools/call 的参数和结果以及透传请求体中可识别的媒体内容会替换为 [aisix: base64 data uri omitted, N bytes]。data URI 保留其 MIME 类型开头。
图像端点b64_json 会被替换,因此响应字段不再是完整的响应 JSON。
MCP 工具结果此前因图像而溢出到 aisix.content.response 的结果,现在完整保留在 gen_ai.tool.call.result 下。
Vertex AI Gemini 的 provider_request_id现在保存 responseId,不再为空。
能力不支持的 501 记录新增 error_class: config,OTLP 服务端 span 报告 error.type: config 而不是 501。
endpoint 指标标签/mcp/{server}/ 下没有路由提供服务的路径报告 other,而不是 /mcp/{server}。

调用方仍然会收到媒体内容。对象存储不携带内容,不受影响。

provider_key 预算累计平台成本​

provider_key 预算现在累计每个用量事件的 upstream_cost,为 null 时回退到 cost_usd。模型组价格和低峰折扣不再影响它,价格为 0 的模型组现在也会消耗它。其他预算范围不变,已经累计的花费不会减少。

不需要修改任何预算。在使用模型组价格的环境中,密钥预算的增长速度会变化:模型组价格高于目标模型价格时增长变慢,低于时增长变快。因此硬限制会在不同的时间达到。

升级说明​

以下说明适用于升级到 1.9.0。

AISIX Enterprise:cp-api 必须配置主密钥​

当 AISIX_CLOUD_MASTER_KEY 为空时,cp-api 现在会在启动时退出,发生在打开数据库或运行迁移之前。此前它会以降级模式启动并报告健康。官方 Chart 和 Compose 部署已经要求配置这个密钥,因此标准部署没有变化。

密钥确实为空的部署会反复重启,直到把它设置为与数据面管理器上 AISIX_DPMGR_MASTER_KEY 相同的值。常见原因是升级 1.8.0 Chart 时,某个 extraEnvVars 覆盖丢失了这个变量。

AISIX Enterprise:审计和访问日志遵循 auth.trusted_proxies​

cp-api 现在用与登录会话和限流相同的方式解析审计事件及其访问日志中的客户端地址。此前它相信客户端提供的任何 X-Forwarded-For,因此地址可以伪造。

如果部署在代理之后但没有配置 auth.trusted_proxies(Helm:api.trustedProxies;Compose:AISIX_TRUSTED_PROXIES),升级后审计事件和访问日志记录的是代理的地址。请在升级前配置它。配置了可信代理后,不再读取 X-Real-IP,IPv4 映射地址记录为纯 IPv4,整条链都由代理组成时记录连接的对端。

带点的声明名优先按字面读取​

identity_claim、bound_claims、声明映射的 match[].claim 和新增的 tag_claims 现在先把整个字符串当作一个顶层声明名读取,然后才按点逐层查找。https://acme.com/dept 这样此前都无法读取的名称现在可以解析。如果令牌同时带有字面的 a.b 声明和嵌套的 a: {b},a.b 现在解析为字面声明。不需要修改配置。

AISIX Enterprise:恢复时被拒绝的旧备份需要重新导出​

导出内容不再携带只被备份时间窗口之外的审计记录引用的前成员。升级前导出且带有这类用户的备份,仍然会以 409 OUT_OF_SCOPE_ROWS 被拒绝,因此请重新导出。要把这些人带回来,请用 audit_since 扩大时间窗口,它会把审计记录和相关人员一起返回。

输出护栏在没有文本的响应上运行​

输出护栏链现在也会在没有文本的响应上运行。这包括 chat 流式暂存、两种 /v1/messages 流、/v1/responses 桥接、流结束时的监控扫描,以及缓冲的转录文本。文本匹配类护栏匹配不到内容,会放行这样的响应。

custom 脚本由自己决定。无条件拦截的脚本现在也会拒绝空流或只有图像的流,以及空的转录文本。ctx.segments 可能为空,在 fail-closed 规则上抛出异常的脚本会拒绝响应。请检查读取 ctx.segments[0] 的脚本。

AISIX Enterprise:控制面数据库连接和首次价目同步​

每个数据面管理器副本都会为网关共享存储单独打开最多 8 个数据库连接的连接池。请对照数据库的连接数上限检查。

启动后的首次价目同步现在会等待后台索引构建,最多 2 分钟。在它运行之前,新安装的价目和服务提供方列表为空,升级的安装保留之前的值。

Realtime:被拒绝的会话会告知客户端并记录为失败​

上游始终没有放行的 /v1/realtime 会话,无论以哪种方式被拒绝,现在都会告诉客户端原因并记录为失败。不需要修改配置。靠匹配 failed to connect to the upstream realtime endpoint 这句话识别握手被拒绝的客户端必须停止这样做。把 Realtime 拨号挂起统计到 502、把 OpenAI 密钥错误的会话统计到 200,或把握手被拒绝统计到 502 的告警和看板,会看到这些会话的归类发生变化。

客户端的 WebSocket 升级仍然在拨号之前成功。除最后一行外,客户端的 error 帧之后都跟着关闭码 1011,原因为 upstream connect failed,与之前相同。

发生的情况客户端的 error 帧记录的状态和类别
握手被 4xx 拒绝上游的文字及其 code 和 param上游的状态码,因此 401 的 outcome 为 client_error,429 为 rate_limited;upstream_status
握手被 5xx 拒绝只有上游的文字502;upstream_status。记录的文字中是真实状态码。
握手以 2xx 或 3xx 应答但没有升级,或状态码超过 599响应体的文字,或 upstream returned 200 OK 这样的兜底文字502;upstream_status
握手被拒绝且响应体为空或无法读取upstream returned 500 Internal Server Error 这样的状态兜底文字按其状态码处理。文字为 upstream returned HTTP <status> with no error detail in the response 或 upstream returned HTTP <status>: failed to read response body: <reason>。
拨号超过 upstream.connect_timeout_msfailed to connect to the upstream realtime endpoint504;timeout,文字为 upstream request timed out after <n>ms: ...
完全没有应答,例如传输、DNS 或 TLS 失败failed to connect to the upstream realtime endpoint502;transport
升级被接受,然后在任何其他帧之前出现 error 事件网关不发送。客户端收到上游的帧及其关闭码。连接断开且没有 Close 帧时仍以 1011 关闭。状态来自事件,见下文;upstream_in_band,文字为 upstream reported an in-band error: <upstream text>

最后一行的状态来自事件:invalid_api_key 为 401;rate_limit_exceeded 和 insufficient_quota 为 429;invalid_model 和 model_not_found 为 404;其他 invalid_request_error 为 400。400-499 的数字 code 按原值使用,500-599 的为 502,其余都是 502。这些状态适用于记录的 status_code、访问日志,以及请求指标的 status 和 outcome 标签。

  • 冷却。 带状态码的握手拒绝或会话拒绝,现在遵循 trigger_statuses 和 honor_retry_after,而不是 trigger_on_transport。在默认列表下,OpenAI 密钥错误的会话现在会让模型进入冷却,400 或未知模型不会。拨号超时现在遵循 trigger_on_timeout,因此 trigger_on_transport: false 不再能在拨号挂起时保持模型可用。没有状态码的会话拒绝遵循 trigger_on_transport。
  • aisix_deployment_*。 成功样本现在等待第一个不是 error 事件的帧或会话结束,而不是在 101 时采样。被拒绝的会话计一次失败、不计成功。在任何帧之前被上游失败结束的会话现在计为失败。
  • 失败记录。 握手被拒绝时,content_mode: full 下的 response 是上游发送的原始响应体,upstream_response_headers 携带导出器列出的请求头。provider_request_id 从响应的 request-id 请求头读取,upstream_latency_ms 是拨号耗时,OTLP span 携带服务器地址。会话被拒绝时,content_mode: full 下的 response 保存发送时的错误帧。
  • 握手响应体。 网关现在会读取被拒绝握手的完整响应体,最多 64 KiB,并受模型流式时间预算限制。因此错误帧不再取决于响应体的大小和时序。停滞的响应体最多可以在拨号之后把客户端的帧再推迟一个流式预算。没有预算时,只要上游停滞且客户端未离开,就会一直推迟。

已经可用的会话不受影响。第一个可用帧之后的 error 事件不会让它变成失败,例如 OpenAI 针对错误的客户端事件发送、会话仍保持打开的事件。

新功能​

MCP:按用户向上游服务器进行 OAuth 登录​

type: mcp 的 MCP 服务器新增 auth_type: oauth2_authorization_code。每位用户从自己的 MCP 客户端登录上游,网关随后用该用户的令牌调用上游。上游令牌不会到达客户端,客户端的 Authorization 也不会到达上游。

  • 无需网关凭证即可登录。 当环境中恰好有一个启用了 login 的 OIDC 身份提供方时,客户端只需服务器的 URL 即可连接。否则,客户端需要提供网关凭证。
  • 多个网关共享。 凭证通过数据面管理器加密存储在控制面中,刷新在各网关之间协调。
  • 管理。 MCP 服务器表单新增 已连接用户 面板。新的 Admin API 端点可以列出和断开凭证,权限为 mcp_server_credentials。断开或任何清除操作之后,已缓存令牌的网关最多还可以继续使用它 5 分钟。
  • 什么情况下用户需要重新登录。 删除 OIDC 身份提供方,或修改它的 issuer 或 identity_claim,会移除它存储的上游令牌。删除 MCP 服务器、修改它的 url、client_id、token_url、authorization_url 或 registration_url,或把它的 auth_type 从 oauth2_authorization_code 改走,也是如此。把环境从 allowed_environments 移除时,只移除该环境的令牌。控制台会对 OIDC 身份提供方的这些修改给出警告。
  • 网络。 代理监听器在 /.well-known/、/mcp/{server}/ 和 /mcp-oauth/ 下提供新路径,前置代理必须路由它们。outbound.ssrf_protection 覆盖上游指向其他 authority 的 OAuth 文档和端点。

此功能需要 1.9.0 网关。环境中注册了更早版本的网关时,控制面返回 422 DP_INCOMPATIBLE。更早版本的网关会忽略 login,保存时会返回警告。

MCP:带路径前缀的资源 URL​

mcp_resource_url 可以带路径前缀,例如 https://host/aisix/mcp,用于位于按前缀路由并剥离前缀的前置代理之后的网关。普通的 /mcp URL 行为不变。

此功能需要 1.9.0 网关。环境中注册了更早版本的网关时,保存带前缀的 URL 会返回 422 DP_INCOMPATIBLE。如果更早版本的网关在带前缀的 URL 保存之后才注册,该网关上的 OAuth 发现处于关闭状态。此后任何改写该环境 MCP 认证设置的保存都会被拒绝,直到网关升级或在同一请求中清除该 URL。

认证:从 JWT 声明读取成本归因标签​

OIDC 身份提供方现在可以用 tag_claims 把已验证令牌的声明映射为标签,让标签跟随身份提供方,而不必在每个 API Key 上维护。用量事件、标签预算和 tag: 限流条件都读取这个结果。

  • 声明会覆盖同名标签键,优先级依次为声明、API Key、团队、成员。不会回写到 API Key。
  • 字符串、数字及其数组会转为文本。数组会排序、去重并用 , 连接。无效值不产生结果,该键保留其他层级给出的值。
  • 每个标签键都必须已在组织中声明。被 OIDC 身份提供方使用的键不能删除(409 TAG_KEY_IN_USE)。
  • 多个令牌共用一个 API Key 时,带 key 标签的 aisix_budget_* gauge 反映最近一次请求的判定。批处理归因记录携带观察到批处理完成的调用方的标签。
  • 标签值建议现在包含最近 30 天用量中出现的值,面向有权读取用量的调用方。

低于 1.9.0 的网关会忽略 tag_claims,保存时返回 field_ignored 警告。

可观测性:每个请求的最后一次尝试​

用量事件新增 is_final_attempt,日志 页面新增 每个请求只看最后一条 筛选器,用量事件列表和导出也可以用 final_attempt_only 实现。它为每个请求显示一行。

  • 默认关闭。
  • 筛选后的行不会汇总被隐藏尝试的 token 或成本,因此不要用它们计算花费。
  • 升级前的记录和来自更早版本网关的记录总是会返回,因此更早版本网关上的回退请求仍然显示每次尝试。

可观测性:请求计数器的 error_source​

aisix_llm_requests_total、aisix_proxy_requests_total 和 aisix_proxy_failed_requests_total 新增默认的 error_source 标签:upstream、aisix,成功或调用方离开时为空。{error_source!="aisix"} 给出不含网关自身拒绝的调用量,而状态码做不到这一点,因为双方都会返回 429。

已经为这些指标族列出标签的指标标签配置不会自动包含它,请显式添加。在双方都会返回的状态码上,这个标签最多让失败序列翻倍。

成本分析:平台成本和价格档位​

用量事件现在记录 upstream_cost、price_tier_index 和 price_tier_max_input_tokens,出现在事件列表、CSV 导出和日志详情中。成本分析 可以从模型组下钻到目标模型,并排显示计费成本和平台成本,也可以在 GET /usage_analysis 上使用 group_by=target_model。平台成本只存在于升级后记录的事件中,因此更早的时间范围在下钻中显示的数额会少于模型行。

Vertex AI:Chat Completions 返回 Gemini 生成的图像​

/v1/chat/completions 现在在 message.images 和 delta.images 中返回 Gemini 图像输出,客户端的 modalities 会转为 generationConfig.responseModalities。图像模型可能在最终图像之前返回中间的思考图像,因此请读取最后一项作为最终图像。

  • /v1/messages 和 /v1/responses 仍然丢弃图像,因此只有图像的回答在这两个端点上是空的 200。
  • 输出护栏不扫描图像,也不会因图像而拦截。
  • 与图像相关的 Gemini 结束原因现在以 content_filter 结束。
  • 带图像的响应,无论来自哪个上游,都不会存入响应缓存。
  • 生成的图像数据不会进入用量事件、访问日志和导出器。

控制台:文档链接​

控制台在宽度至少 1280 像素的屏幕上新增全局文档入口,并在各页面新增主题链接,在设置卡片上新增链接。它还新增了服务提供方配置指南,以及 日志 页面上的故障排查和错误类别指南。

改进​

  • 日志页面: 页面先加载行,再单独计数。总数上限为 10,000+,翻页限制在前 10,000 行内,计数超时时总数显示为未知。新增的 失败(4xx/5xx) 状态建议由新索引支持。
  • 成员: 成员选择器和团队成员列表在服务端搜索和翻页,适用于有数千名成员的组织。GET /members 新增 team_id、exclude_team_id 和 status;GET /teams/{team_id}/members 新增 q 和翻页;POST /members/lookup 和 GET /members/me 是新增端点。
  • 搜索错误: 搜索被拒绝时,价目页面和成员选择器显示服务端的消息,而不是通用的加载失败。
  • 网关内存: 原生 /v1/responses、/v1/messages、/v1/messages/count_tokens、/v1/rerank 和 JSON /v1/audio/speech 请求,如果唯一的改写是模型名,在关闭内容采集时峰值内存大约少用一份请求体大小。
  • 失败诊断: 空的上游错误现在显示为 upstream returned HTTP <status> with no error detail in the response,状态码 400 及以上的每条失败记录和访问日志行都会说明失败原因。转发非 2xx 的透传和作业记录新增 error_class: upstream_status。带内失败现在在 error_message 和访问日志的 error 中显示为 upstream reported an in-band error: <message>,流式和非流式请求一致,此前访问日志显示 in-band stream error。流的结束错误帧保留其文字。
  • 网关日志: 出站失败现在记录根本原因,例如证书不受信任,而不只是 error sending request。
  • Vertex AI Gemini 和 Bedrock Converse: Chat 和非流式 Messages 响应不再返回空的 id。
  • 服务提供方密钥表单: 请求头剥离列表的说明已本地化,表单也解释了其他凭证请求头。

修复​

  • 一个带 NUL 字节或无效文本的用量事件不再导致同批其余事件丢失。过长的 requested_model 不再让整个部署的用量汇总停止;入口现在把它截断为 256 个字符。
  • 当 User-Agent 含有数据库拒绝的字节时,审计记录不再丢失,请求也不再以 500 失败。登录会话同样能处理这种输入。
  • AISIX Enterprise: 恢复组织时,如果导入期间另一个连接提交了事务(例如价目同步),不再以 409 OUT_OF_SCOPE_ROWS 失败;与该同步发生死锁时也不再以 500 IMPORT_FAILED 失败。
  • AISIX Enterprise: 组织导出在中途失败时,现在下载会失败,而不是保存一个被截断的文件并报告成功。
  • 用量和审计导出在中途失败时,现在下载会失败,而不是以一个较短的文件结束。
  • cp-api 在没有主密钥时创建或更新带凭证的护栏不再 panic,因为它不会在没有主密钥的情况下启动。
  • 上游返回失败状态、发送部分响应体后停止发送,不再让流式请求无限期挂起。这覆盖 OpenAI、Anthropic、Azure、Vertex AI 和 Bedrock Chat Completions 路径上的流式 /v1/chat/completions、/v1/messages、/v1/responses、语音和转录。读取现在受模型流式预算限制,超出后调用方收到状态兜底文字,例如 502 upstream returned 500 Internal Server Error,记录显示 failed to read response body: timed out after <n>ms。上游的状态码和 Retry-After 仍然决定重试和冷却。timeout: 0 的模型没有流式预算,因此它的读取仍然不受限。
  • A2A agent card 不再根据链式的 X-Forwarded-Proto(例如 https,http)生成错误的 URL。现在读取第一跳,不区分大小写,http 或 https 之外的值会被忽略。
  • 必须修改密码的会话现在会直接进入密码页面,控制台不会先发送会被服务端拒绝的请求,/login?next= 目标在修改密码后也会保留。

API 变化​

以下变化会破坏现有的 AISIX Cloud Admin API 调用方。

方法和路径破坏点需要的修改
GET /environments/{env_id}/usage_eventstotal 在 10,000 处停止,并带 total_is_capped: true。如果计数超过 5 秒预算,total 和 total_is_capped 不出现,但仍返回行。偏移量 (page-1)*limit 达到 10,000 或以上时返回 400 INVALID_REQUEST。行查询超过 30 秒时返回 503 QUERY_TIMEOUT。使用 GET /environments/{env_id}/usage_summary 或 GET /usage_analysis 获取精确总数。缩小时间范围以访问更早的行。
GET /environments/{env_id}/usage_events/exportX-Export-Total 和 JSON total 上限为 50,001。计数超时时在第一个字节之前返回 503 QUERY_TIMEOUT。第一个字节之后的失败会切断连接。把传输错误视为导出失败。遇到 503 时缩小范围。
GET /members、GET /environments/{env_id}/api_keys、GET /provider_keys、GET /environments/{env_id}/rate_limits、GET /model_pricing超过 256 字节的 q 返回 400 INVALID_REQUEST,此前返回 200。限制按字节计算,因此非 ASCII 文本更快达到上限。缩短 q。
GET /environments/{env_id}/usage_events 和 /exportrequested_model(除非 requested_model_exact=true)、mcp_tool、a2a_method、jwt_subject、jwt_claim_mapping 和 branded_provider 超过 256 字节时返回 400。缩短筛选值。
所有 cp-api 路由查询参数的名称或值,或解码后的路径,含有 NUL 字节或无效 UTF-8 时返回 400 INVALID_REQUEST,发生在认证之前,处理函数不读取的参数也如此。SCIM 路由返回 SCIM 错误。其中一些此前返回带空结果的 200、401、404 或 500。发送有效的 UTF-8。
搜索端点消息 q must be at most 256 characters 现在是 q must be at most 256 bytes。更新对消息文字的匹配。
PATCH /environments/{env_id}/oidc_providers/{oidc_provider_id}只含空白的 identity_claim 返回 400,此前返回 200 并保存该值。发送真实的声明名,或省略该字段。
PATCH /environments/{env_id}mcp_resource_url 的值带编码路径写法(例如 https://host/%6Dcp)或空查询、空片段(例如 https://host/mcp?)时返回 400。已存储的值不变。这些值此前就让网关上的 OAuth 发现处于关闭状态。发送规范的 URL。
不带 page_size 的 GET /members?q=...owner_count 现在是组织的总数,而不是匹配行中的数量。不要把它读作匹配的 owner 数量。
GET /budgets、GET /budgets/{budget_id}provider_key 预算的 spent_cents 现在累计每个用量事件的 upstream_cost,为 null 时回退到 cost_usd。此前累计 cost_usd。已经累计的花费不会减少。不要把它读作该密钥流量的计费成本。

1.8.0​

发布日期: 2026 年 10 月 29 日

预算现在由网关自己执行,依据控制面随配置推送的预算状态判定,因此控制面或数据库故障不再演变成全面的 429 budget_exceeded。provider_key 预算现在只会把该密钥对应的上游移出路由。控制台登录新增 TOTP 两步验证和组织密码策略。MCP 服务器可以代表调用方访问上游:转发调用方自己的 Token,或通过 Microsoft Entra ID On-Behalf-Of 流程换取下游 Token;新的 x-aisix-api-key 请求头用于携带网关密钥,让 Authorization 留给上游使用。网关支持来自可信负载均衡器的 PROXY protocol v1 和 v2 头,遇到不认识的启动配置键时只告警而不再拒绝启动,空闲时内存从约 120 MiB 降到 10 MiB 以下。每个代理路由现在都会上报适用于它的全部单请求指标族。数据面支持下限提升到 1.6.0。

行为变化​

流量控制​

  • 硬停预算在网关上判定。 网关不再为每个请求询问控制面。调高或调低限额立即生效;即使控制面不可达,阻断也会在周期边界解除;控制面或数据库故障约 10 分钟后不再拒绝流量。
  • provider_key 预算按上游凭证生效。 额度耗尽的服务提供方密钥只会移除使用它的路由目标,因此仍有其他目标的模型组可以继续服务;此前会拒绝整个请求。这种排除不占用 fallback 次数。所有候选目标都被排除时,调用方仍会收到 429 budget_exceeded。MCP 和 A2A 调用不受其约束。
  • 预算执行模式为 sticky 和 closed。 不再接受 open。默认的 sticky 在故障期间继续按最近一次推送的预算状态执行。closed 新增宽限期,即组织设置 budget_closed_grace_seconds(默认 600,范围 60 到 86400)。用量上报持续这么久未能送达控制面后,只有受预算约束的请求会收到 503 budget_unverified,其他请求继续服务,下一次上报成功即解除阻断。各模式与 1.7.1 的差异见升级说明。

认证​

  • 所有入口使用同一条入站凭证规则。 在允许匿名访问的 MCP 服务器上,空的 x-aisix-api-key、Authorization 或 x-api-key 请求头现在算作提供了凭证,因此会以 401 拒绝,而不再按匿名身份放行。在 gateway_key 透传路由上,存在但不是可用 Bearer 凭证的 Authorization 不再回退到 x-api-key。因 x-aisix-api-key 或 x-api-key 为空或格式错误而返回的 401 现在会指出该请求头,而不再是 Authorization。所有入口都接受 bearer <key> 和 BEARER <key>;密钥本身区分大小写。

可观测性​

  • /v1/chat/completions 的调试响应头默认关闭。 x-aisix-call-id、x-aisix-served-by、x-aisix-route、x-aisix-cache、x-aisix-cache-layer 和 x-aisix-cache-similarity 只有在网关配置中设置 proxy.expose_debug_headers: true(Helm:config.proxy.expose_debug_headers)时才会发送。用量事件、访问日志、指标和链路追踪记录了同样的信息。x-aisix-request-id、server、x-ratelimit-* 和 retry-after 仍会发送。
  • 访问日志的四个字段改用用量事件的名称。 status 改为 status_code,error_kind 改为 error_class,model 改为 requested_model,latency_ms 改为 downstream_latency_ms。只写入新名称。
  • 移除 aisix_llm_spend_micro_usd_total。 只有 Realtime 曾经给它写入过值。请从控制面记录的成本或用量事件的 cost_usd 读取花费。

部署​

  • 双栈监听器把 IPv4 客户端报告为纯 IPv4 地址。 在 [::] 监听器上,客户端地址此前显示为 ::ffff:a.b.c.d,现在显示为 a.b.c.d,因此 proxy.real_ip.trusted_proxies、allowed_cidrs、透传来源白名单和 MCP source_cidrs 中的 IPv4 CIDR 能匹配到它。用量事件、OTLP client.address 和日志中也显示 IPv4 形式。
  • 以 PROXY 开头的连接会被当作 PROXY protocol 头读取。 如果对端不在 proxy.real_ip.trusted_proxies 中,连接会被关闭并记录 WARN;此前会收到 HTTP 400。
  • 数据面支持下限为 1.6.0。 控制台的数据面视图会把低于 1.6.0 的网关标记为 “Unsupported version”,并给出需要升级到的版本。保存配置时不再检查这类网关,因此它们可能无法加载新保存的配置。

新功能​

MCP​

  • 网关凭证请求头 x-aisix-api-key。 该请求头存在时,网关认证优先使用它,而不是 Authorization 和 x-api-key,因此调用方可以在其中发送网关密钥,把 Authorization 留给自己的上游 Token。所有 /v1/* 端点、/mcp、/mcp/{server}、/a2a、/v1/realtime 握手和 gateway_key 透传路由都接受该请求头,且永远不会转发给上游。值为空或无效时返回 401,网关不会改用其他请求头。
  • MCP 服务器认证类型“Delegate caller token”(oauth_delegate)。 对 mcp 和 openapi 服务器,网关会把调用方自己的 Authorization 请求头转发给上游,但仅当该请求头不是网关凭证时,也就是网关密钥通过 x-aisix-api-key 发送时。只有调用方的 MCP 访问规则能访问到的服务器才会收到它。
  • MCP 服务器认证类型“Token exchange (Entra OBO)”(oauth2_token_exchange,token_exchange_profile: entra_obo)。网关通过 Microsoft Entra ID On-Behalf-Of 授权,交换由 JWT 信任提供方验证过的调用方 Token,只把换得的 Token 发给上游。Token 会缓存到临近过期前,上游返回 401 时会重新交换一次。交换过程受服务器 timeout_ms 约束。
    • 在 /mcp/{server} 上,各类失败有各自的状态:401 token_exchange_subject_missing 或 token_exchange_subject_rejected、500 token_exchange_misconfigured,以及 503 token_exchange_unavailable。Entra 条件访问要求的升级认证会以 insufficient_claims 质询传给客户端。
    • 在聚合的 /mcp 上,交换失败的服务器只会丢失它自己的工具。
  • 两种认证类型都需要 1.8.0 网关。如果环境中注册了更早版本的网关,为该环境保存这类服务器会返回 422 DP_INCOMPATIBLE。

控制台与账号安全​

  • 两步验证。 每个账号可以在顶部栏的 Security 设置中启用 TOTP,并获得 10 个一次性恢复码;设置一次即覆盖所有组织。之后使用密码登录需要完成第二步验证。连续输错 10 次验证码会将该账号的第二因素锁定 15 分钟。
  • 组织可以要求两步验证。 owner 在组织设置的 Sign-in security 卡片中开启。未启用两步验证的成员(包括 owner),或会话尚未通过第二因素的成员,会在继续操作前被引导去启用或完成验证。通过组织自身单点登录打开的会话视为已满足要求。Admin Token 不受影响。成员列表会显示谁已启用。
  • 组织密码策略。 owner 可以设置密码最长有效期(1 到 365 天,默认关闭),到期后使用密码登录的成员必须设置新密码;还可以设置禁止复用最近 N 个密码(0 到 24,默认 5),该限制仅在设置了最长有效期时生效。密码到期前 7 天会显示提示横幅。已有账号的密码时长从账号最后一次更新起算,因此启用较短的有效期可能要求成员立即修改密码。
  • AISIX Enterprise: 运维人员可以用 cp-api two-factor reset --email <address> 重置其他账号的第二因素;控制台和 HTTP API 不提供此操作。启用两步验证需要控制面的主密钥(AISIX_CLOUD_MASTER_KEY)。

部署​

  • 网关启动配置忽略不认识的键。 拼写错误或已退役的键不再导致网关无法启动:它会被忽略,并在启动 WARN 中列出;日志级别屏蔽了告警时会写到标准错误输出。因其他原因加载失败的配置也会在错误中列出被忽略的键。已退役的 observability.metrics.otlp、observability.tracing 和 observability.usage_event 配置块已移除。
  • 所有代理监听器支持 PROXY protocol v1 和 v2,包括明文和 TLS 监听器。只有来自 proxy.real_ip.trusted_proxies 中套接字对端的头才会被采信;来自其他对端时,连接会被关闭并记录 WARN。网关自动识别,不带该头的连接可以在同一端口上继续工作,也不需要新的配置键。头中携带的地址就是用量事件、访问日志、allowed_cidrs、来源白名单、MCP source_cidrs 和按客户端 IP 哈希路由所看到的地址。

AISIX Cloud​

  • AISIX Cloud: AISIX Cloud 升级到新的正式版本后,组织 owner 会收到一封通知邮件,其中附有发布说明的链接。

改进​

  • 每个代理路由都会上报适用于它的全部单请求指标族。 aisix_request_e2e_latency_seconds 在除 /v1/realtime 外的所有路由上记录。首 Token 时间在流式音频、流式 /a2a 和不透明透传流上记录。Token 指标族在 /a2a 上记录;部署指标族在视频后续请求、Realtime 以及文件、批处理和微调路由上记录;限流剩余量 gauge 在配额检查处记录。401 和 403 拒绝在所有路由上计数,包括 /mcp。
  • 访问日志在所有端点上记录 Token 数。 非流式的 /v1/messages、/v1/embeddings、/v1/responses、/v1/completions、/v1/rerank、图像、音频、/v1/decisions 和 /a2a 日志行现在带有 prompt_tokens、completion_tokens 和 total_tokens,/v1/realtime 的会话结束日志行带有整个会话的总量。
  • Realtime 用量事件记录会话结束的原因。 上游结束会话时,事件会带上 error_class(transport 或 timeout),用量日志和导出器都能看到。
  • 新指标 aisix_usage_delivery_unhealthy_seconds 表示用量事件等待了多久仍未送达控制面。
  • 可以发现断开的配置 watch。 网关的 etcd watch 使用 HTTP/2 keepalive,因此静默断开的连接约 20 秒内就会被发现并恢复,而不会无限期错过配置更新。
  • 网关内存更低。 每个网关进程用于资源 schema 校验的内存从约 115 MiB 降到约 4 MiB;空闲网关分配的内存现在低于 10 MiB。

修复​

  • 已删除或修改的资源不再被写回网关。 多个 dp-manager 副本并发下发配置,或批量重新投射与删除操作竞争时,已删除的资源(例如某个 API Key)可能被写回并一直留在网关上。现在配置每次只由一个副本按顺序下发。
  • 组织级配置能一致地进入新环境。 在创建环境的同一时刻写入的团队 MCP 授权、价格覆盖以及团队和成员文档,可能缺失于该环境或残留在其中;对同一资源的两次并发编辑可能投射出过期的值。
  • 并发的组织编辑不再返回 500。 此前在同一组织中同时创建两个标签键,或同时修改组织币种时会出现该问题。
  • 非 owner 被拒的两步验证设置会说明涉及的内容。 非 owner 向组织设置发送 require_two_factor 时仍会收到 403 FORBIDDEN,但消息现在会说明涉及的是密码策略、两步验证要求还是两者,而不再总是说密码策略。控制台登录安全卡片的文案也已修正。
  • 网关的 TLS 库已更新到修复了四个上游安全公告的 rustls 版本。

API 变化​

以下 Cloud Admin API 变化会破坏现有调用方。

  • 拒绝包含多个 * 的模式。 创建或修改 MCP 访问规则、A2A 白名单条目、透传白名单条目(allowed_routes)、模型的 display_name 通配符或模型的 model_name 模板时,如果包含多个 *,现在会返回 400 INVALID_REQUEST,因为网关从未匹配或填充过这类模式。模型已存储的 display_name 或 model_name 仍可原样重新提交。MCP、A2A 和透传列表会整体校验,因此包含多个 * 的已存储条目必须在同一请求中删除。
  • POST /environments/{env_id}/passthrough_routes 和 PATCH /environments/{env_id}/passthrough_routes/{passthrough_route_id} 拒绝 identity_header: x-aisix-api-key,返回 400 INVALID_REQUEST。已存储该值的现有路由继续服务,但在修改 identity_header 之前无法保存。auth_header_name 仍可使用该名称。
  • POST /environments/{env_id}/observability_exporters 和 PATCH /environments/{env_id}/observability_exporters/{exporter_id} 拒绝 request_headers 和 upstream_response_headers 中的 x-aisix-api-key,返回 400。请将其从列表中删除。

升级说明​

以下说明适用于从 1.7.1 或更早版本升级。

网关(AISIX Enterprise 和 AISIX Cloud):

  • 如果客户端读取调试响应头,请重新开启。 设置 proxy.expose_debug_headers: true(Helm:config.proxy.expose_debug_headers),或者从用量事件、访问日志、指标或链路追踪中读取同样的信息。
  • 更新按字段名解析访问日志的程序。 解析 proxy request completed 日志行的程序必须改读 status_code、error_class、requested_model 和 downstream_latency_ms。
  • 让看板和告警不再使用 aisix_llm_spend_micro_usd_total。 仍在 observability.metrics.labels 中列出它的配置可以启动,但会告警。
  • 更新使用已变化指标标签的查询。 两条 /.well-known/oauth-protected-resource 路由有了各自的 endpoint 标签,不再是 other。A2A agent card 的获取从 endpoint="/a2a" 改为 endpoint="/a2a/{agent}/.well-known/agent-card.json",因此不再算作 Agent 调用。不再上报 aisix_component_entries{component="budget_cache"}。
  • 修改网关配置后检查启动时的 WARN 日志。 拼写错误的键现在会被忽略,而不会阻止网关启动。仍包含已退役的 observability.metrics.otlp、observability.tracing 或 observability.usage_event 配置块的配置可以启动,但会告警;请删除这些配置块。
  • 在 [::] 监听器上,把写成 ::ffff:a.b.c.d 的白名单条目改写为纯 IPv4。 这包括 proxy.real_ip.trusted_proxies、allowed_cidrs、透传来源白名单和 MCP source_cidrs。用量事件、OTLP client.address 和日志中的客户端 IP 也会变为 IPv4 形式。
  • 如果网关位于会发送 PROXY 头的四层负载均衡器之后,请把负载均衡器的地址加入 proxy.real_ip.trusted_proxies。 否则它的连接会被关闭。
  • 移除 AISIX_DP_BUDGET_STALE_MAX_SECONDS。 该变量已删除;仍设置它的网关可以启动,但会告警。
  • 不要再发送空的凭证请求头。 使用匿名访问的 MCP 客户端不能发送空的 x-aisix-api-key、Authorization 或 x-api-key 请求头;现在这类请求会以 401 拒绝,而不再按匿名身份放行。
  • 在 gateway_key 透传路由上,用 x-aisix-api-key 发送网关密钥。 Authorization 存在但不是可用 Bearer 凭证的请求不再回退到 x-api-key,而是收到 401。请把 Authorization 留给上游使用。
  • provider_key 预算在 1.8.0 网关上的含义改变。 /budgets 的结构不变,但硬停的 provider_key 预算现在只会移除使用该密钥的上游,而不再拒绝该服务提供方密钥所服务的调用方 API Key 上的所有请求。
  • 网关升级到 1.8.0 之前,会继续使用原来的逐请求预算检查,包括对 provider_key 预算拒绝整个调用方 API Key,以及原来的故障期行为。在有硬停预算或使用 closed 模式的环境中,1.6.x 或 1.7.x 网关会把新的预算文档计入 aisix_config_unknown_kind_resources;重新加载状态不受影响。

控制面:

  • 预算执行模式变化。
    • open:组织会被切换为 sticky,并且不再接受 open。
    • sticky:在 1.7.1 中,控制面不可达超过 600 秒后,所有请求都会收到 429。在 1.8.0 中,只有预算已经耗尽的请求会被阻断。
    • closed:宽限期(budget_closed_grace_seconds,默认 600)过后,只有受预算约束的请求会收到 503 budget_unverified。触发条件改为用量上报失败。
  • AISIX Enterprise: 从 1.6.0 或更高版本升级。 如果数据库最后由低于 1.6.0 的控制面运行,cp-api 1.8.0 会拒绝启动。请先把 1.5.x 安装升级到 1.6.x 或 1.7.x。如果仍要直接升级,请先备份数据库,然后设置 Helm 的 api.allowUnsupportedUpgrade: true、环境变量 AISIX_ALLOW_UNSUPPORTED_UPGRADE=1,或者对离线包运行 AISIX_ALLOW_UNSUPPORTED_UPGRADE=1 ./run.sh。使用部署包时,这也会删除 1.5.x 单独的 ui 容器。cp-api 拒绝启动时,run.sh 会给出数据库最后一次运行时的版本,并提示先把 .env 中的 AISIX_VERSION 改回该版本、去掉镜像固定设置,再按两步升级。
  • 升级低于 1.6.0 的网关。 它们会显示为 “Unsupported version”,并且可能无法加载此后保存的配置。
  • 改写包含多个 * 的规则。 已有数据不会迁移,这类条目仍然不起作用。请检查 MCP 访问规则、A2A 白名单、透传 allowed_routes,以及模型的 display_name / model_name 模式,尤其是 deny 规则,它们此前一直静默未生效。包含这类条目的 MCP、A2A 或透传列表在删除该条目之前无法保存。
  • 滚动升级期间,仍运行 1.7.x 的 dp-manager 副本不会获取新的下发锁,因此在所有副本都运行 1.8.0 之前,本版本修复的乱序下发仍可能发生。
  • AISIX Enterprise: aisix-cp Chart 不再兼容 1.5.0 版 Chart 的 values。
    • 把 AISIX_TRUSTED_ORIGINS 和 AISIX_AUTH_BEARER_SESSIONS 从 ui.extraEnvVars 迁移到 api.trustedOrigins 和 api.bearerSessions,或者迁移到 api.extraEnvVars。ui.extraEnvVars 和 ui.service 已移除。
    • <release>-ui Service 已移除。请把 NodePort、Ingress 或反向代理指向 <release>-api,它在所有路径上提供控制台。
    • 如果 api.extraEnvVars 或 dpm.extraEnvVars 覆盖了 1.5.0 版 Chart 自身渲染的变量,例如 AISIX_CLOUD_PUBLIC_BASE_URL 或 AISIX_CLOUD_DATABASE_URL,第一次 helm upgrade 到当前 Chart 时会把该变量从 Deployment 中删除。无论该 Release 最初何时安装,都适用这一点。升级前,请把该设置迁移到 values.yaml 中对应的键。数据库 URL 尤其如此:覆盖被删除后,cp-api 会连接 Chart 根据 values.yaml 推导出的数据库启动,并在其上执行迁移。如果该变量已经被删除,请用同样的 values 再运行一次 helm upgrade。参见升级 AISIX。

1.7.1​

发布日期: 2026 年 10 月 27 日

1.7.1 是补丁版本。网关现在按目标平台的文档处理每个请求字段:目标能承载的参数按调用方写法发送,上游自己的错误原样返回;目标无法承载的参数会被丢弃;在调用方自身协议中非法的值返回 400,并指出该字段。响应会完整返回,包括每个 choice、logprobs、refusal 和 annotations。旧版函数调用现在可用于 Claude、Vertex Gemini 和 Amazon Bedrock。流式 /v1/chat/completions 的用量在所有上游上都遵循 OpenAI 的 include_usage 约定。导出器接受任意主机的明文 http:// 端点。在控制面上,AISIX Enterprise 不再依赖 PostgreSQL 行级安全,删除仍被引用的资源在 PostgreSQL 18 上重新返回 409。Vertex AI 的 global、us 和 eu 位置现在会发往 Google 的正确端点。转录用量和延迟的记录更完整。控制台中每个纯图标按钮都有提示,日期和时间字段跟随控制台的语言。

行为变化​

端点与模型服务提供方​

  • 流式 /v1/chat/completions 的用量在所有上游上都遵循 stream_options.include_usage。 设置 include_usage: true 时,用量只发送一次,放在所有其他 chunk 之后单独的 chunk 中(choices: [])。未设置时,与 OpenAI 一样,任何 chunk 都不携带用量。此前,Claude(任何平台)、Vertex Gemini 以及在结束 chunk 上报告用量的 OpenAI 兼容上游,即使未设置 include_usage 也会在该 chunk 上显示用量。用量事件、TPM 限流和计费不变。需要从流中读取用量的客户端必须请求 include_usage。
  • 请求参数按目标平台的契约处理。
    • 目标定义的字段按调用方的写法发出,上游的拒绝连同状态码和消息一起返回给调用方。网关不再丢弃、改写或预先校验这些字段。
    • 在 Amazon Bedrock 的 Chat Completions 路由(Grok、GPT 5.6 及更高版本)上,以下字段现在按原样发送:n、stop、frequency_penalty、presence_penalty、Grok 的 reasoning_effort: "none",以及推理中的 GPT 的 temperature / top_p / logprobs / top_logprobs。此前它们会被丢弃。在 Converse 上,stop 以 stopSequences 发给每个模型,包括 Grok 和 GPT 5.6 及更高版本。AWS 拒绝其中某个字段时,调用方现在会收到 AWS 的 400。
    • 在 Bedrock Converse 上,OpenAI 模型(gpt-oss、GPT、Grok)按 AWS 文档通过 additionalModelRequestFields 接收以下字段:seed、各项 penalty、user、safety_identifier、logit_bias、parallel_tool_calls、metadata 以及 json_object 形式的 response_format。Cohere Command R 接收 seed 和各项 penalty,Jamba 接收各项 penalty。智谱 AI GLM 和 Kimi K3 接收 reasoning_effort。Nova 2 把 reasoning_effort: "none" 映射为关闭推理。Titan Multimodal Embeddings 映射 dimensions。
    • 在 Bedrock 上,函数的 strict 以 toolSpec.strict 传给 Converse。不支持 strict 的模型(例如 Nova Lite)现在会返回 Bedrock 的 400,此前请求会在去掉该字段后成功。GPT、Grok 和 Kimi K3 的输出上限不再被提高到 16。没有 user 或 assistant 轮次的请求会发往 Bedrock 并返回 Bedrock 的错误,而不再是网关的 400。Converse 的 temperature / top_p 保留精确的小数值。
    • Vertex Gemini 的 generationConfig 现在携带 max_completion_tokens、stop、seed、各项 penalty、n(作为 candidateCount)、logprobs / top_logprobs 以及 /v1/messages 的 top_k。reasoning_effort 在 Gemini 3 及更高版本上映射为 thinkingLevel,在 Gemini 2.5 上映射为思考预算。/v1/messages 的 thinking.budget_tokens 按原值发给 Gemini 2.5,超过模型上限的预算现在会收到 Vertex 的 400,此前请求会在不思考的情况下成功。service_tier 的 flex / priority 以 Vertex 的 Flex / Priority PayGo 请求头发送。在 Gemini 2.5 及更高版本上,函数的 parameters 以 parametersJsonSchema 原样发出,因此会保留 additionalProperties。每个 candidate 都作为一个带 logprobs 的 choice 返回,被 Gemini 拦截的提示词以 content_filter 结束。
    • 在发往 Claude 的 chat 请求(Anthropic、Vertex AI、Bedrock InvokeModel)上,seed、n、logprobs、logit_bias、各项 penalty、store 和 prompt_cache_key 等仅 OpenAI 支持的字段会被丢弃,不再到达 Anthropic 并导致 400。user 和 safety_identifier 变为 metadata.user_id,函数工具的 strict 会复制到 Claude 工具上。
    • 调用方自己设置 strict 的 json_schema 原样发出。只有在网关转换 /v1/messages 的 output_format 时自行设置了 strict,网关才会封闭该 schema。assistant 的 content: null 以 null 发送,temperature / top_p 保留调用方的小数值(0.7,而不是 0.699999988)。
    • 针对 OpenAI 推理模型的 max_tokens -> max_completion_tokens 重命名只在 OpenAI 自己的 API 上生效。例如,服务 openai/o3-mini 的 OpenRouter 密钥现在收到的是 max_tokens,这是 OpenRouter 文档中唯一的字段。
  • 在调用方自身协议中非法的值返回 400,并指出该字段。 这包括 JSON 合法但不符合请求结构的请求体(例如返回 max_tokens: invalid value: integer -1, expected u32 或 missing field messages,而不再是 invalid JSON request body),以及类型为数字、布尔值或对象的消息 content。为 Claude、Bedrock Converse 或 Vertex Gemini 转换的请求,还会因类型错误的 stop、tool_choice 或 reasoning_effort 被拒绝。Claude 和 Converse 会拒绝类型错误的 max_completion_tokens,以及缺少 id 或 function.name 的回放工具调用。Converse 和 Vertex Gemini 会拒绝非字符串的 service_tier 和格式错误的工具。这些情况此前会被静默丢弃、原样转发或读成空值。在 Bedrock Converse 上,不是非空字符串或字符串数组的 stop 也会被同样拒绝,不是非负整数的 max_completion_tokens 同理。单独的空字符串 stop 仍会被跳过,null 仍视为未设置。
  • 上游已经处理过的响应不会再执行一次。 网关无法解码的 2xx 现在直接返回 502。此前它会被重试、故障转移到模型组的下一个目标并计入冷却,因此请求会被计费两次。这也包括 /v1/images/edits。Decisions 模型组也不再对转换后不完整的响应做故障转移;调用方收到 502(unexpected decision response),该目标也不会进入冷却。凭证 Token 交换(Azure AAD、Vertex 服务账号)保留原有的重试行为。
  • anthropic-beta 默认转发给 Anthropic。 在发往 Anthropic 或 Anthropic 兼容端点的 /v1/messages 和 /v1/messages/count_tokens 上,调用方的 anthropic-beta 请求头现在会到达上游,无需列在服务提供方密钥的 forward_client_headers 中。服务提供方密钥通过 default_headers 或 forward_client_headers 设置的值仍然优先。anthropic-version 仍由网关固定,Bedrock 和 Vertex AI 上的 Claude 保留其平台的 beta 过滤。
  • 在 chat 上,Claude 的停止原因映射为 OpenAI 的取值。 refusal 现在是 content_filter,model_context_window_exceeded 是 length,pause_turn 是 stop;此前它们以原始结束原因出现。在来自 chat 上游的 /v1/messages 上,内容过滤或 OpenAI 的 refusal 以 refusal 结束,而不再是 stop_sequence,拒答文本作为一个文本块返回。
  • Anthropic 服务端工具不再提供给 chat 上游。 在转换为 chat 的 /v1/messages 上,web_search_*、web_fetch_*、code_execution_* 和 tool_search_tool_* 不再作为无参数的函数发送。客户端工具(bash_*、text_editor_*、computer_*)不变。
  • 来自 Anthropic 的错误消息使用 Anthropic 自己的文本。 在发往 Anthropic 的 /v1/messages 和 count_tokens 上,上游错误的 error.message 是 Anthropic 的消息,而不再是整个原始响应体的字符串。code 或 param 为数字的 OpenAI 形态上游错误也会保留其 message。

安全护栏​

  • 输入安全护栏会扫描以内容部分回放的推理。 chat 内容中的 Mistral thinking、Databricks reasoning 以及 Anthropic 形态的 thinking 部分,现在与 reasoning_content 一样参与判定,因此匹配它们的拦截规则会返回 422,此前这类请求会通过。脱敏规则会改写未签名的部分。带有非空 signature 的部分只扫描、不改写,与 /v1/messages 上带签名的 thinking 块相同:拦截规则仍会触发,但脱敏命中会原样转发。网关不会校验签名,因此如果这类文本不能到达上游,请使用拦截动作。在透传路由上,Mistral thinking 部分不再导致网关无法扫描请求体。
  • 输出安全护栏会扫描每个 choice。 输出安全护栏和脱敏现在覆盖每个 choice、refusal 文本以及旧版 function_call 的参数。脱敏不会改写 logprobs,因此请求了 logprobs 的调用方会收到未脱敏的上游 token 文本。

可观测性​

  • 导出器接受任意主机的明文 http:// 端点。 otlp_http 和 object_store 导出器的 endpoint 现在接受任意主机的 http://,例如内网采集器 http://otel-collector-dev:4318/v1/traces。此前只允许一组固定的测试主机。阿里云 SLS 的 endpoint 和 Datadog 的 site 保持原有限制。环境中注册了 1.7.0 或更早版本的网关时,保存这类端点会被拒绝,返回 422 DP_INCOMPATIBLE,因为这些网关会丢弃该导出器。

部署​

  • AISIX Enterprise: 部署模式配置错误由 cp-api 在启动时报告,不再由 aisix-cp Chart 报告。 以下配置不再导致 helm install / helm template 失败:api.deploymentMode 不是 on-premises / saas,saas 模式下缺少 twoDSN.enabled 或 api.smtp.host,以及在 saas 之外启用计费。改为 cp-api 拒绝启动,并在 Pod 日志中说明问题。Chart 的检查只读取 api.deploymentMode,因此当 api.extraEnvVars 设置了 AISIX_CLOUD_DEPLOYMENT_MODE 或 AISIX_BILLING_PROVIDER 时,它判断的是错误的值。cp-api 的每条拒绝现在都会说明值来自环境变量、配置文件 key 还是默认值。

改进​

  • 旧版函数调用可用于所有模型服务提供方。 所有目标都接受 functions / function_call 和 role: "function" 轮次,null 值视为未设置。OpenAI 协议的目标按原样接收。Claude(Anthropic、Vertex AI)、Vertex Gemini 以及 Bedrock InvokeModel 和 Converse 此前会返回 400,现在会以工具形式接收它们。响应以 message.function_call / delta.function_call 返回,finish_reason 为 "function_call"。旧版格式每轮只能容纳一次调用。

  • 响应完整返回。 来自 OpenAI 兼容服务提供方、Azure OpenAI、Vertex AI OpenAI 兼容端点和 Bedrock Chat Completions 的响应现在保留每个 choice,以及每个 choice 的 logprobs、refusal、annotations 和旧版 function_call,流式 delta 保留其 index。此前只保留第一个 choice。/v1/messages 和 /v1/responses 读取第一个 choice。响应缓存存储完整响应。

  • 内容为部分数组的响应可以端到端使用。 Mistral、Databricks 等以部分数组形式返回 content 的 OpenAI 兼容上游,现在流式和非流式都能正常使用。其文本会到达 /v1/messages、/v1/responses 和内容采集。其推理部分在 chat 上以 reasoning_content 中继,在 /v1/messages 上以 thinking 块中继,在 /v1/responses 上以 reasoning 条目中继;推理部分计入估算的补全 Token,并会被采集给导出器。在 /v1/responses 流中,跟在文本之后的推理现在会按顺序开启一个新条目,而不再追加到之前的条目上。

  • /v1/embeddings 会把 user 等字段转发给 OpenAI 协议的目标,并接受 token ID 输入([1, 2]、[[1, 2]]),此前这会返回 400。token ID 不携带文本,因此输入安全护栏会放行这类请求。Bedrock 和 Vertex AI 的 Embeddings 会以 400 拒绝 token ID。

  • Vertex AI 或 Bedrock 上 4.5 以下版本的 Claude 使用结构化输出时,仍走原生 Messages 路由,因此仅 Anthropic 支持的字段不再丢失。在工具调用打开期间流出的推理现在作为独立的 thinking 块保留。/v1/messages 的 top_k 和精确的 thinking.budget_tokens 会到达有对应字段的目标。

  • 相同请求的 Bedrock Converse 请求体逐字节一致。 JSON 键(包括工具 schema 中的键)现在按稳定的顺序发送。

  • Vertex AI 服务提供方密钥的密钥字段类型错误时,错误会指出该字段,例如 service_account_json must be a JSON object (the contents of the service-account key file), got a string,而不再是 "must be valid JSON"。

  • 服务提供方密钥表单会说明何时必须填写 API base 以及应填写的格式。 部分服务提供方没有默认端点:Google Vertex AI、Azure、自带端点(BYO)的服务提供方,以及 models.dev 未发布端点时的 OpenRouter 或其他服务提供方。对于它们,表单会把 API base 标记为必填,禁用的 Create 按钮会说明缺少该项。编辑时清空必填的 API base 会在保存前被阻止。API base 提示跟随服务提供方的协议:

    • Vertex AI 为不带路径的源(origin);
    • Azure 为资源端点;
    • Bedrock 为 bedrock-runtime 端点;
    • Anthropic 为 Anthropic 兼容的根路径;
    • 其他为 OpenAI 兼容的根路径。

    编辑表单显示同样的提示。输入框的占位符与提示给出的示例相同:服务提供方有自己的默认端点时使用该端点(例如 OpenAI 为 https://api.openai.com),否则使用协议示例。Amazon Bedrock 和自带端点的服务提供方不再显示 https://api.example.com。编辑表单始终显示占位符。

  • AISIX Enterprise: 控制面不再需要 PostgreSQL 行级安全。 数据库账户只需要拥有该数据库,不再需要 SUPERUSER、BYPASSRLS 和 CREATEROLE。被阿里云 DTS 等工具处理过的数据库不再导致 500 错误。

  • 控制台中每个纯图标按钮都有提示。 提示在鼠标悬停和键盘聚焦时显示。这包括行操作(例如 API Key 上的权限、禁用、轮换、编辑和吊销),也包括关闭、删除和复制按钮、拖动手柄、展开箭头以及 SSO 规则的移动按钮。禁用的按钮在已知原因时会说明为何禁用,例如声明映射最后一个条件上的 "A mapping needs at least one condition"、SSO 角色规则上的 "Already the first rule",以及 "Only organization owners can change single sign-on"。

  • 日期和时间字段跟随控制台的语言。 它们现在使用控制台自己的日期和时间选择器,而不再使用浏览器的选择器。这包括 API Key 过期时间、限流计划时间,以及日志、审计日志和成本分析中的自定义时间范围。月份和星期名称以及占位符跟随控制台的英文或中文设置,因此中文浏览器中的英文控制台不再显示 年/月/日 占位符。时间为 24 小时制。可选字段通过 Clear 清空。输入了一半的时间会保留上一个完整值,而不再清空字段;在 API Key 过期时间上,清空字段意味着“永不过期”。

修复​

  • 带 stream_options 的流式 ensemble 请求不再以 502 失败。 面板成员不再接收 stream_options;调用方仍会收到其用量 chunk。
  • 提前结束的 Claude chat 流按真实的输入和缓存 Token 计费。 发往 Anthropic 或 Vertex AI 上 Claude 的流在最终事件之前结束时(客户端断开或流内上游错误),现在会记录 Claude 报告的输入、缓存读取和缓存写入数量,而不再是估算的提示词和零缓存 Token。在第一段内容之前就结束的流仍按估算记录。
  • 透传流会根据服务端标注的用量帧计量,前提是协议解析器没有读到用量。只在 event: token_usage 帧上报告 Token 的服务端不再被记录为零 Token。
  • Vertex AI 位置 global 和多区域位置 us / eu 会发往 Google 的正确端点。 服务提供方密钥未设置 API base 时,global 现在发往 https://aiplatform.googleapis.com,us / eu 发往 https://aiplatform.{us,eu}.rep.googleapis.com,适用于所有 Vertex AI 路由(Gemini、Embeddings、Claude、合作伙伴模型、OpenAI 兼容端点)。此前它们发往并不存在的 global-aiplatform.googleapis.com 和 us-aiplatform.googleapis.com。us-central1 等区域位置不变。
  • 以 prompt_tokens / completion_tokens 报告的转录和翻译用量会被记录。 部分上游报告的是 chat 形态的计数,而不是 input_tokens / output_tokens,例如智谱 AI glm-asr-2512。它们的用量事件现在会获得 Token 计数和按 Token 计价的费用,适用于 /v1/audio/transcriptions(流式或非流式)和 /v1/audio/translations。报告转录字段名或时长的上游不受影响。
  • 按时长计费的转录会记录正确的时长。 流式 /v1/audio/transcriptions 现在记录上游在最终事件上报告的时长,只有在没有该值时才回退到上传文件的时长,与非流式请求一致;此前它只按文件时长计价。以流方式写出的 WAV 和 FLAC 文件现在会被测量时长,而不再记录为无时长;OpenAI 的 /v1/audio/speech 和输出到管道的 ffmpeg 会产生这类文件。过大而无法存储的时长会记录为未测量,并在网关日志中给出警告。升级后,这些请求记录的时长和费用会发生变化,此前记录为无时长的流式 WAV 和 FLAC 上传会开始计费。
  • 含有越界音频时长的用量批次不再丢失。 控制面此前会拒绝整个批次,网关重试后丢弃该批次,导致其中的其他事件全部丢失。越界时长现在存为 0 并记录日志,该事件的其余部分和整个批次都会保留。
  • 响应缓存命中导出与其回放的响应相同的输出。 缓存命中的用量事件现在携带已存储响应的 finish_reason,而不再为空。其 OTLP / Datadog Span 增加了全新响应会导出的 gen_ai.response.finish_reasons 和结构化的 gen_ai.output.messages(包括推理)。
  • 没有到达上游的请求不再报告上游延迟。 这包括响应缓存命中,以及在第一次上游尝试之前被拒绝的请求,例如输入安全护栏拦截、未知模型、限流或预算拒绝。它们的 upstream_latency_ms 和 upstream_ttft_ms 现在为 0(未测量),而不再是网关自己的处理耗时,适用于用量事件、导出器和逐次尝试的记录。downstream_latency_ms 仍报告调用方等待的时间。基于 upstream_latency_ms 的统计会因这些行而发生变化。
  • 不足 1 ms 的延迟报告为 1 ms。 这适用于 upstream_latency_ms、downstream_latency_ms、upstream_ttft_ms、逐次尝试的延迟和 Embedding 调用延迟。不足 1 毫秒时,它们此前会被报告为未测量;精确匹配的缓存命中,其调用方延迟通常就这么短。从未测量的延迟仍为 0 或不出现。
  • 没有延迟的日志行会明确说明。 在控制台日志中,只有调用方延迟的行(例如缓存命中或安全护栏拦截)会显示该延迟。两者都没有的行会显示 "No latency recorded for this row",而不再显示上游延迟提示,其详情面板显示 "—" 而不再是 "0 ms"。
  • 日志和概览中的中文延迟提示与英文一致。 调用方延迟提示现在说明,对非流式请求它是完整响应的时间,对流式请求是首 Token 时间。概览的延迟提示增加了“仅成功请求”。只有上游延迟的行,其后缀已翻译,不再显示 "up"。
  • models.dev 端点为模板的服务提供方需要显式设置 API base。 部分服务提供方发布的端点包含 ${DATABRICKS_HOST} 这样的占位符,目前包括 databricks、neon、snowflake-cortex、cloudflare-workers-ai 和 infomaniak。对于它们,服务提供方密钥表单会把 API base 标记为必填,并以模板作为占位符。不带 api_base 创建这类密钥现在会收到要求显式设置 api_base 的 400。对 databricks、neon 和 snowflake-cortex,这取代了此前针对调用方留空字段的 api_base must be ... an absolute HTTP(S) URL 错误。对 cloudflare-workers-ai 和 infomaniak,此前密钥会以模板作为 API base 创建,经由它的每个请求都会收到上游的 404。
  • 删除仍被引用的服务提供方密钥或 API Key 时,在 PostgreSQL 18 上重新返回 409(CREDENTIAL_IN_USE、KEY_IN_USE),而不再是 500。在 PostgreSQL 18 上,当无密码账户仍被其他组织引用时,移除成员、SCIM 删除和删除组织不再失败。
  • Vertex AI 服务账号密钥按网关的加载方式存储。 以字符串形式提交、内容为密钥文件的 service_account_json,现在会被解析并以对象存储,因此可以正常使用,不再导致每个请求以 401 失败。网关无法加载的密钥会在保存时被拒绝,返回指出该字段的 400。Azure OpenAI 的 Entra ID 凭证也按同样方式检查:包含 /、?、#、空白字符或 .. 的 tenant_id 或 client_id 会被拒绝,不是纯源(origin)的 authority_host 也会被拒绝。
  • null 可以清除模型上的 cooldown 和 auto_prompt_caching。 PATCH /environments/{env_id}/models/{model_id} 接受 null(以及 {})来清除任一配置块;此前会返回 400。创建时 null 视为未设置。
  • 并发编辑不再留下悬空引用。 一次写入引用另一个资源、而该资源同时被删除或重命名时,现在会收到写入自己的 4xx,或删除操作收到 409;此前会出现 500、引用已删除资源或丢失重命名。对同一资源的 SCIM User 和 Group 更新会串行执行,因此并发的重命名、成员替换和账户停用不再互相覆盖。
  • AISIX Enterprise: 数据库中存在其他工具的表时,cp-api 也能启动。 public 中不属于控制面的表和序列(例如阿里云 DTS 留下的表)不再使 cp-api 在启动时报 permission denied,也不再使数据导入以 MIGRATION_VERSION_MISMATCH 失败。
  • AISIX Enterprise: Chart 生成的首位管理员密码和安装说明跟随 cp-api 实际运行的模式。 当 api.extraEnvVars 把 AISIX_CLOUD_DEPLOYMENT_MODE 设置为字面值时,Chart 现在按该模式生成首位管理员密码并打印对应的安装说明,而不再按 api.deploymentMode。

API 变化​

本版本的 Cloud Admin API 变化不会破坏现有调用方。

升级说明​

以下说明适用于从 1.7.0 或更早版本升级。

  • 从 chat 流中读取用量需要请求 include_usage。 未设置 stream_options.include_usage: true、从 /v1/chat/completions 流的结束 chunk 读取用量的客户端,升级后将读不到用量。
  • 依赖网关丢弃参数的请求现在可能收到上游的 400。 在 Bedrock 上,这包括发给 Grok 或 GPT 5.6 及更高版本的 stop、发给推理中 GPT 的 temperature / top_p / logprobs、各项 penalty 和 n,以及发给不支持 strict 的模型的工具上的 strict。在 Vertex Gemini 2.5 上,这包括超过模型上限的 thinking.budget_tokens。请不要再向这些模型发送这些字段。
  • anthropic-beta 现在会到达 Anthropic。 未在 forward_client_headers 中列出该请求头的服务提供方密钥,会开始转发调用方的值。如果不能让调用方选择该值,请在 default_headers 中设置该请求头。
  • 重新保存以字符串形式存储 service_account_json 的 Vertex AI 服务提供方密钥。 升级前保存的密钥不会被迁移,在重新保存其凭证之前会继续以 401 失败。
  • 编辑未设置 API base 而创建的 cloudflare-workers-ai 和 infomaniak 服务提供方密钥。 1.7.1 之前,这类密钥会以 models.dev 的端点模板(包含 ${...})作为 API base 存储,经由它的每个请求都会收到上游的 404。升级不会改动这些密钥;请逐个编辑并设置真实的 API base。
  • AISIX Enterprise:
    • cp-api 首次启动时会从控制面的表上移除行级安全。 它会在日志中列出改动过的表,之后的启动不会再做任何操作。如果其中某张表由其他角色持有,启动会失败,错误中会列出需要 DBA 执行的 SQL。
    • 移除 database.admin_url(AISIX_CLOUD_ADMIN_DATABASE_URL)。 on-premises 模式下的 cp-api 现在会因该设置拒绝启动。请改为把 database.url 设置为数据库 owner 的 URL。在 saas 之外设置 twoDSN.enabled: true 时,cp-api 也会拒绝启动;其 Pod 日志中给出的是 database.admin_url,即 Chart 为此写入的 key,请设置 twoDSN.enabled: false。参见从 1.7.0 或更早版本升级。
    • cp_api_app 角色会保留;在没有其他用途后,DBA 可以删除它。

在 1.7.0 或更早版本的网关仍连接 1.7.1 控制面期间,以下说明适用:

  • 环境中注册了 1.7.0 或更早版本的网关时,旧测试主机以外的明文 http:// 导出器端点会被拒绝,返回 422 DP_INCOMPATIBLE。
  • 部分响应缓存条目对 1.7.0 或更早版本的网关来说是缓存错误。 1.7.1 网关可能写入包含多个 choice 或带 logprobs 的条目,共享该缓存的旧网关无法读取。其他条目不受影响。

已知问题​

  • ensemble 的评审模型是 Amazon Bedrock 上推理中的 GPT 5.6 或更高版本时,会收到 400。 评审请求总是发送 temperature: 0.2,而 AWS 会在模型推理时拒绝该字段。请使用其他评审模型。

1.7.0​

发布日期: 2026 年 10 月 22 日

组织现在可以按部门、业务组或子公司归因成本:为 API Key、团队和成员设置标签后,每一行用量都会带上请求解析出的标签。标签可用于预算、限流,以及新的组织级成本分析页面。定价新增组织币种(USD 或 CNY)、按输入长度分档的价格、模型组价格、模型组低峰折扣、按上游服务档位的价格,以及 1 小时缓存写入费率,Claude 模型默认按输入费率的 2 倍为其计费。网关提供两个决策端点 /v1/systemone 和 /v1/decisions,可由 TypeSafe、Microsoft Foundry、OpenRouter 和 OpenAI 提供服务。OTLP Span 现在遵循已发布的 OpenTelemetry GenAI 语义约定,OTLP、Datadog 和阿里云 SLS 导出器会携带包含推理和工具调用的结构化消息。每个导出器现在各自选择要记录的请求头和上游响应头。控制台的语言依次取浏览器内的选择、组织设置或浏览器语言,概览和用量页面改为从按小时汇总的数据加载。Amazon Bedrock 和 Vertex AI 上的 Claude 在 /v1/messages 和 /v1/messages/count_tokens 上原生提供服务,提示词缓存(包括 auto_prompt_caching)也在这些平台上生效。Bedrock 模型服务提供方凭证和 Bedrock 安全护栏可以使用 Bedrock API Key、AWS 默认凭证链或扮演的 IAM 角色进行认证。聊天请求中的图像、音频和文件现在会送达 Vertex Gemini、Anthropic、Vertex AI 上的 Claude 和 Bedrock,而不再被丢弃;经路由模型组的 /v1/responses 对话会留在产生其上下文的目标上。Bedrock 和 Realtime 流量现在遵循网关的代理环境变量,网关和控制面代调用方访问 URL 时由统一的 SSRF 防护设置管控。

行为变化​

可观测性​

  • OTLP Span 遵循 OpenTelemetry GenAI 语义约定(v1.41.1)。 基于旧名称的已保存查询和看板必须更新:
    • gen_ai.system 已移除,请改用 gen_ai.provider.name(托管平台优先,因此 Bedrock 上的 Claude 为 aws.bedrock)。
    • gen_ai.request.model 现在是发往上游的模型名。调用方发送的模型或模型组名称移到 aisix.requested_model。
    • 对于 Anthropic 形态的用量(Anthropic、Bedrock Converse,以及上报 cache_*_input_tokens 的透传路由),gen_ai.usage.input_tokens 现在包含缓存 Token。OpenAI 形态的用量不变。Datadog 导出器的 gen_ai.usage.input_tokens 也有同样变化,其 aisix.* 计数不变。
    • Span 名称变化:操作 Span 为 {operation} {上游模型}(例如 chat gpt-4o),而不再是 chat.completions;SERVER Span 为 POST /v1/chat/completions 等;MCP Span 为 tools/call {tool}。
    • 成功的 Span 不再设置状态,而不是设为 OK。4xx 不再把 SERVER Span 标记为错误,调用方挂断(499)在任何 Span 上都不算错误。
    • OTLP Span 上移除了 gen_ai.prompt / gen_ai.completion。设置 content_mode: full 时,内容以 gen_ai.input.messages、gen_ai.output.messages、gen_ai.system_instructions 和 gen_ai.tool.definitions 导出;不是消息列表、或被采集上限截断的内容仍放在 aisix.content.prompt / aisix.content.response 下。
    • aisix.client_source_ip / aisix.client_user_agent 改为 client.address / user_agent.original,它们与 http.request.header.* 一起移到 SERVER Span 上。
    • 只有尝试 Span 携带 gen_ai.operation.name / gen_ai.request.model,因此统计 GenAI Span 的追踪系统对每次尝试只计一次,而不是三次。
    • 资源属性 service.name 取 observability.service_name(默认 aisix),而不再是固定的 aisix-dp。
  • Datadog 和阿里云 SLS 导出器携带结构化内容(content_mode: full)。 在 SLS 上,prompt 被 input_messages(存在时还有 system_instructions 和 tool_definitions)取代,response 被 output_messages 取代,每个都是 JSON 字符串。在 Datadog 上,gen_ai.prompt 被 gen_ai.input.messages(以及 gen_ai.system_instructions 和 gen_ai.tool.definitions)取代,gen_ai.completion 被 gen_ai.output.messages 取代。输出消息按顺序包含 text、reasoning 和 tool_call 部分,finish_reason 使用约定中的取值(stop、length、tool_call、content_filter、error)。被截断或不是消息列表的一侧(Embeddings、图像、音频、任务、A2A、MCP)仍放在旧的扁平字段中并带有 content_truncated,因此一条记录可能两种形态并存。对象存储导出器不变。
  • observability.usage_event.request_headers 不再起作用。 请求头采集移到了各个导出器(见新功能)。仍设置该键的网关可以启动,会记录一条警告,并且在其导出器列出这些请求头之前不再记录它们。
  • 用量事件的 model_id 只指向自己执行派发的模型。 对于在选定目标之前就失败的模型组(routing 或 semantic)或 ensemble(护栏拦截、预算、入口级限流、模型被禁止、语义解析失败),以及 routing 或 semantic 模型组的响应缓存命中,/v1/chat/completions 和 /v1/messages 上的 model_id 现在为空,而不再是模型组的 ID;requested_model_id 仍指向该模型组。直接模型在 /v1/responses、/v1/embeddings 及其他单次调用端点上派发前的失败,现在带有该模型自己的 ID,而不再为空。1.6.x 及更早版本的网关保持旧的上报方式。用量事件查询见 API 变化。
  • 透传路由按其承载的协议计量用量。 被识别为 chat、Anthropic Messages、Responses、Completions、Embeddings、图像或 Rerank 的透传交换,会用该端点自己的用量解析器读取,并在 LLM 请求层(aisix_llm_requests_total、aisix_llm_request_duration_seconds、aisix_llm_* Token 指标族以及首 Token 时间 / 端到端延迟)中只计一次,endpoint="/passthrough_route",model 为请求体中的模型(未注册的名称归为 unresolved)。不再读取未识别流上的用量对象。智能体后端的 token_usage 帧不再把缓存读取计两次。同时带有 Chat 和 Anthropic 信封的缓冲响应,现在会被失败即拦截的输出护栏拒绝。透传访问日志的 total_tokens 现在与类型化端点一样包含缓存 Token。
  • /v1/responses 的用量事件携带 finish_reason(stop、tool_calls、length、content_filter,失败或取消的响应为空),由调用方收到的结果推导。
  • 只要模型服务提供方发送了请求 ID,就会记录 provider_request_id。 失败的上游尝试、/v1/messages/count_tokens 调用,以及响应本身没有 ID 的成功调用(Bedrock Converse 和 InvokeModel、Embeddings、音频、图像、Rerank),现在会在用量事件和访问日志中记录服务提供方的请求 ID 响应头(x-amzn-requestid、x-request-id、request-id、x-ms-request-id、apim-request-id、x-goog-request-id 或 cf-ray);响应对象自己的 ID 仍然优先。因此在失败的尝试上,它可能出现为 OTLP / Datadog 的 gen_ai.response.id。每次重试的尝试都带有自己的 ID。此前为空的 Bedrock Converse 响应 id 现在是该请求 ID。失败请求的访问日志行会写出请求实际发往的服务提供方,而不再是 unknown(在 /v1/chat/completions 上则是没有服务提供方);multipart 图像编辑和音频路由会写出请求的模型。
  • 服务提供方拒绝请求形态时归类为 invalid_request_error。 网关无法为目标服务提供方转换请求,或下载的媒体使请求超过 proxy.request_body_limit_bytes 时,用量事件、访问日志和导出器(OTLP aisix.error_class、Datadog、SLS)记录的 error_class / error_kind 为 invalid_request_error,而不再是 invalid_config。调用方收到的错误不变。
  • 所有上报 total_tokens 的端点族都会记录它。 Embeddings、Rerank、音频转录与翻译、图像生成与编辑、Realtime、批次完成归因,以及按这些族计量的透传路由,其用量事件现在带有上游上报的 total_tokens,此前为 null。Realtime 会话和 batch_completion 事件记录各次上报总数之和;只要有一次计入 Token 的调用没有上报总数,该字段就为 null。客户端响应、限流和 Prometheus 计数不变。

端点与模型服务提供方​

  • 图像、音频和文件会送达原生协议的上游。 /v1/chat/completions 中的 image_url、input_audio、file 等媒体部分(以及转换为 chat 的 /v1/messages / /v1/responses 中的媒体部分),现在会被转换为上游自己的媒体块,发往 Vertex Gemini、Anthropic、Vertex AI 上的 Claude 和 Bedrock(Claude InvokeModel 和 Converse),流式与非流式均适用;此前它们会被丢弃,调用方从一个根本没看到媒体的模型那里得到 200。上游无法接收的媒体(例如发给 Claude 的音频)现在会返回 400,并指出 messages[i].content[j]。Anthropic(https://)和 Vertex Gemini(https:// / gs:// 且媒体类型已知)仍直接接收 URL。其他 http(s) 媒体 URL 由网关下载后内联发送;其他协议或无法下载的 URL 返回 400 并指出该部分,消息中会去掉 URL 的查询字符串和片段。下载:

    • 拒绝解析到非公网地址的主机(回环、私有和 CGNAT 地址段、链路本地地址包括 169.254.169.254、IPv6 唯一本地地址等),每一跳重定向都会检查,除非该主机列在 outbound.ssrf_protection.allowed_hosts 中,或通过 outbound.ssrf_protection.enabled: false 关闭检查。检查开启时,即使由代理承载下载,主机也必须能从网关解析;
    • 与其他上游调用一样经过 HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY,按 upstream.tls(verify、ca_file)校验证书,并且从不转发调用方的请求头;
    • 每个 URL 的上限为 upstream.media_fetch.max_bytes(默认 50 MiB),与请求共享上游超时时间,并与请求体一起计入 proxy.request_body_limit_bytes(超出时同样返回 413 request_too_large)。

    网关新增的静态配置 upstream.media_fetch(enabled,默认 true;max_bytes)控制下载。设置 enabled: false 时,发往无法自行读取 URL 的上游的 URL 部分返回 400。地址检查由新增的顶层网关配置 outbound.ssrf_protection 负责(enabled,默认 true;allowed_hosts,默认为空,取值为 host、host:port 或 [v6]:port;环境变量为 AISIX_OUTBOUND__SSRF_PROTECTION__ENABLED 和 AISIX_OUTBOUND__SSRF_PROTECTION__ALLOWED_HOSTS)。它管控网关代调用方访问的每一个由调用方提供的 URL,目前即这些媒体下载;运维人员配置的 URL 不受影响。两者都已在 1.7.0 的 aisix Helm Chart values 中声明。使用兼容 OpenAI 端点的服务提供方仍和以前一样原样转发媒体部分。

  • 上游的错误信息会送达调用方。 来自所有 Amazon Bedrock 操作、Azure OpenAI 和 Vertex AI 的错误,以及来自所有服务提供方的 5xx 错误,现在携带上游自己的错误信息,而不再是固定的状态短语或 upstream returned <status>。这些文本可能包含账号 ID、ARN、部署或项目名称。没有错误信息的错误仍以其状态码命名。

  • Amazon Bedrock 和 Vertex AI 上的 Claude 原生应答 /v1/messages。 发往 Bedrock 上 Claude 模型(anthropic. 模型 ID,带或不带区域或推理配置文件前缀,或指向它的 ARN)或 Vertex AI 上 Claude 模型(claude-*)的 /v1/messages,会发往平台自己的 Anthropic Messages 路由(Bedrock InvokeModel / InvokeModelWithResponseStream,Vertex AI :rawPredict / :streamRawPredict),而不再经过转换,调用方收到的是平台的应答:带签名的思考和 signature_delta、redacted_thinking、上游消息 ID、原生停止原因、带缓存计数的流式 message_start 用量,以及 Bedrock 在 message_stop 上的 amazon-bedrock-invocationMetrics。metadata.user_id、context_management、tool_result 中的图像以及受支持的 anthropic-beta 值现在会送达模型。Bedrock 在流中途抛出的异常会变成带 Anthropic 错误类型的 Anthropic error 事件(throttlingException → rate_limit_error 等)。发往 Bedrock 的流式请求现在使用 InvokeModelWithResponseStream 而不是 ConverseStream,两者都需要 bedrock:InvokeModelWithResponseStream 权限。/v1/chat/completions 和 /v1/responses 不变,Bedrock 应用推理配置文件 ARN 也不变,发往 4.5 之前 Claude 系列的结构化输出请求仍走转换路径。

  • 发往 Amazon Bedrock 和 Vertex AI 上 Claude 的 anthropic-beta 会按平台支持的值过滤。 在 Bedrock 上,beta 值总是放在请求体的 anthropic_beta 中发送,从不作为请求头发送,这包括来自服务提供方凭证 default_headers 的值,以及 forward_client_headers 放行的请求头中的值;在 Vertex AI 上,它们仍留在请求头中。平台不支持的值会被丢弃,advanced-tool-use-2025-11-20 会被重命名为 tool-search-tool-2025-10-19。在发往 Bedrock 上 Claude 的 /v1/chat/completions 和 /v1/responses 上,请求体中不在该集合内的 anthropic_beta 值现在会被移除,而不再转发。在 Bedrock 上,interleaved-thinking-2025-05-14、claude-code-20250219、output-128k-2025-02-19、structured-outputs-2025-11-13、token-efficient-tools-2025-02-19、tool-examples-2025-10-29 和 thinking-token-count-2026-05-13 会被转发,因此 Bedrock 上的 Claude 4.x 现在会在 Claude Code 的工具调用之间进行思考。在 /v1/messages 上,服务提供方凭证 default_headers 中的 beta 值会与调用方的值以及请求体隐含的 beta 值合并后再过滤;在 /v1/chat/completions 和 /v1/responses 上,default_headers 与其他请求头一样优先于转发的值。

  • Amazon Bedrock 上的 GPT 5.6 及更新版本和 Grok 使用 Bedrock 的 Chat Completions 端点。 通过跨区域推理配置文件(global.、us. 等)访问的 openai.gpt-5.6 及更新版本(gpt-oss 除外)或 xai.grok-* 模型,会发往 Bedrock 兼容 OpenAI 的 /openai/v1/chat/completions,而不是 Converse,并使用同一服务提供方凭证签名。AWS 在该端点上拒绝的参数会被丢弃,而不是导致失败(n、stop;Grok 上的惩罚参数和 reasoning_effort: "none";GPT 推理时的 temperature、top_p、惩罚参数和 logprobs)。需要 Converse 专有功能的请求(Bedrock 安全护栏、性能或服务档位配置、top_k、既不是 text、也不是带 schema 的 json_schema 的 response_format、推理型 GPT 模型上的函数工具)仍走 Converse。远程图像 URL 会内联发送,按位置编号的工具调用 ID 会替换为唯一的 call_… ID。

  • Bedrock Converse 请求按调用方发送的内容构造。 在所有 Bedrock 发布方上:同一角色的连续轮次会被合并(此前工具结果之后紧跟用户消息会被 Bedrock 拒绝);stop 转为 stopSequences;max_completion_tokens 优先于 max_tokens;带 schema 的 response_format 会为所有发布方转为工具,包括此前忽略它的 Titan、AI21、gpt-oss 和未分类的发布方;reasoning_effort 按发布方映射(gpt-oss 和 DeepSeek V3、GPT 5.x / 6、Nova 2,其中 low、medium、high 以外的取值返回 400,其他发布方丢弃);top_k 会送达 Claude 和 Nova;parallel_tool_calls 会送达 Claude 4.5 及以上;guardrailConfig、performanceConfig、serviceTier 和 requestMetadata 会进入请求,OpenAI 的 service_tier 会映射为 serviceTier。不属于 Chat Completions 参数的顶层字段,现在会作为 additionalModelRequestFields 送达非 Claude 的 Converse 模型,而不再被丢弃。工具结果可以携带图像、文档和视频。没有工具可发送时,工具调用历史会以文本形式发送,而不再被拒绝。

  • Bedrock 错误与其他上游一样分类。 网关无法识别的 Bedrock 模型 ID 是不可重试的配置错误,因此模型组会在此停止,而不再故障转移到下一个目标。ModelErrorException 是可重试的上游错误(向调用方返回 502),ModelTimeoutException 是超时,上下文窗口溢出会带有 code: context_length_exceeded。

  • Amazon Bedrock 调用遵循代理环境变量。 Bedrock 运行时调用、Bedrock 安全护栏和 STS 调用现在与其他所有上游一样,经过 HTTP_PROXY / HTTPS_PROXY / ALL_PROXY,除非 NO_PROXY 覆盖该主机;此前它们直接连接。发往 AWS 凭证端点(实例元数据、ECS 和 EKS Pod Identity、本地回环地址上的凭证代理、配置的元数据端点)的请求始终直连。

  • Realtime 会话遵循代理环境变量。 /v1/realtime 现在通过 HTTPS_PROXY 连接 wss:// 服务提供方(通过 HTTP_PROXY 连接 ws:// 服务提供方),回退到 ALL_PROXY,除非 NO_PROXY 覆盖该主机;此前它直接连接。不支持 SOCKS 代理:会话会以一个 error 帧和关闭代码 1011 失败(访问日志中为 502)。

  • Realtime 会话会正常完成关闭。 /v1/realtime 现在会完成 WebSocket 关闭握手。正常关闭的客户端会收到自己的关闭代码和原因,而不再是 1006,上游也会收到客户端的代码和原因。上游关闭时,客户端会收到上游的代码和原因,原因不做脱敏、截断为 123 字节后转发。无法在 Close 帧中发送的关闭代码,在两个方向上都会变为 1011。恰好为 1002 "Protocol violation" 的 Close 帧也会变为 1011,因为网关无法把它与无效代码区分开;原因不同的 1002 会照常转发。除正常关闭(1000)外,任何结束之前都会先发送一个类型为 server_error 的 Realtime error 事件,说明发生了什么:上游的关闭代码和原因、网关无法转发的 Close 帧、不带状态码的关闭、连接失败及其原因,或者没有 Close 帧就结束的连接。关闭过程中到达的用量仍会计入。访问日志状态不变。

  • Responses 对话会留在产生它的模型组目标上。 在经路由模型组的 /v1/responses 上,携带加密推理(encrypted_content)或 previous_response_id 的后续轮次,会先发往产生它的目标,然后是同一服务提供方凭证上的其他目标,最后是其余目标。此前,当模型组的策略选中另一个部署或凭证时,它可能以 400 invalid_encrypted_content 或 404 失败。在其他目标上,推理条目会去掉加密内容后发送,并保留可读的摘要。为此,经路由模型组提供服务的响应,其响应 id 是一个不同于上游的 resp_… 值,非流式响应体和流式事件都是如此。客户端必须把收到的值原样发回。用量事件、访问日志和 OTLP 仍记录上游自己的响应 ID。直接模型不受影响。该行为始终开启。

  • 聊天用量按上游上报的原样携带 Token 明细。 在 /v1/chat/completions 的流式和非流式响应中,usage.prompt_tokens_details 和 usage.completion_tokens_details 现在带有上游上报的每个计数及其值,上报为 0 的也包括在内。这些计数包括 cached_tokens、reasoning_tokens、audio_tokens、image_tokens、text_tokens、accepted_prediction_tokens 和 rejected_prediction_tokens。上游没有上报的计数会省略,什么都没上报的明细对象也会省略。此前,为 0 的计数会被丢弃,所有计数都为 0 的对象不会出现,text_tokens、image_tokens 和预测计数从不转发。由响应缓存返回的响应仍只报告非零的 cached_tokens 和 reasoning_tokens。用量事件、指标和计费不变。

  • 流式聊天的用量在单独的分片中返回。 设置 stream_options.include_usage: true 时,流式 /v1/chat/completions 现在会在结束分片之后以一个仅含用量的分片结束。它的 choices 为 [],并且是唯一携带 usage 的分片,与 OpenAI 的发送方式一致。此前:

    • 来自 OpenAI 协议上游和 Bedrock Converse 时,该分片带有 [{"index":0,"delta":{}}];
    • 来自 Anthropic、Vertex AI 上的 Claude 和 Vertex AI 上的 Gemini 时,没有这样的分片,usage 跟随在结束分片上,Gemini 还可能在更早的分片上报告累计数。

    每个分片都读取 choices[0]、或从结束分片读取用量的客户端必须调整。不设置 include_usage 时没有任何变化:Anthropic 和 Vertex AI 的桥接仍在结束分片上报告用量,Bedrock Converse 仍不向客户端发送用量。用量事件和限流计量不变,提前结束的流也是如此。

  • 上游以 stop 结束的工具调用轮次报告为 tool_calls。 在所有 OpenAI 协议上游(OpenAI、Azure OpenAI、兼容 OpenAI 的服务提供方、Vertex OpenAI 端点)上,至少发出一个工具调用且以 stop 结束的轮次,现在在 /v1/chat/completions 上报告为 tool_calls,在 /v1/messages 上报告为 tool_use,流式与非流式均适用。这也包括 tool_choice 指定函数时 OpenAI 自己的回复。其他结束原因原样传递。

  • Bedrock 聊天在所有模式下都返回推理内容。 流式 Bedrock 聊天现在会返回推理内容(delta.reasoning_content、/v1/responses 上的 reasoning 条目,以及在 /v1/messages 上发往非 Claude 发布方时不带签名的 thinking 块;/v1/messages 上的 Claude 返回 Bedrock 自己的带签名思考,见上文),发往非 Anthropic 的 Bedrock 发布方的非流式聊天也是如此。

  • 只含系统消息的请求。 发往任意 Bedrock 模型、只含 system 或 developer 消息的请求,现在会在 /v1/chat/completions、/v1/messages 和 /v1/responses 上被网关以 400 invalid_request_error 拒绝,流式与非流式均适用,且不会向 Bedrock 发送任何内容。此前它会以 500 config_error 失败;对于发往 Bedrock 上 Claude 的非流式请求,则会到达 Bedrock 并以 400 返回,信息为 upstream returned 400(在 chat 和 responses 上为 upstream_error)。旧的 500 可重试,因此路由模型组会故障转移到下一个目标;新的 400 会结束故障转移链,即使模型组的 fallback_on_statuses 列出了 400 也是如此,该请求也不再计为健康检查失败。只含系统消息的 Vertex Gemini 请求现在会成功。

  • 不带 tool_call_id 的工具消息。 在 Anthropic、Bedrock /invoke 和 Vertex Claude 桥接上,400 信息不再带有 invalid upstream configuration: 前缀。Bedrock Converse 会把这样的消息作为工具结果转发,而不再静默丢弃。

  • 响应中的 service_tier。 由 OpenAI 形态上游提供服务的 /v1/chat/completions 现在会把上游的 service_tier 传给客户端(此前会被丢弃)。桥接到非 Responses 上游的 /v1/responses 现在报告上游实际提供服务的档位,或 "default",而不再回显调用方请求的档位。

  • ensemble 会为离开的调用方已产生的工作计费。 调用方放弃 ensemble 请求时,已经返回的 panel 成员和 judge 会在 499 行之前记录为用量行,已应答成员的 Token 会计入 Key、团队和成员的 Token 限额。

  • 失败的 ensemble 子调用有自己的用量行。 失败的 panel 成员或 judge 调用现在会记录一行零 Token 的用量(attempt_kind 为 panel 或 judge,带有其模型、状态、error_class 和 error_message);此前不会留下任何记录。行按 panel 槽位编号,因此某个成员失败时,它之后的每一行(后面的成员、judge 以及失败请求的最终行)的 attempt_index 会按失败成员数依次后移。Token 总数、计费和请求数不变。

安全护栏​

  • 语义安全护栏把不可用的向量化响应报告为 semantic_embed_upstream。 当向量模型返回的向量与请求不符(长度错误、返回 base64 而不是浮点数、向量数少于输入数)时,失败即拦截的 422 信息、护栏命中记录、guardrail_bypassed_reason 和 aisix_guardrail_bypasses_total{reason} 现在为 semantic_embed_upstream,而不再是 semantic_embed_unresolved;custom 护栏脚本中的 aisix.embed 会抛出 Upstream,而不再是 Unresolved。
  • 护栏日志行以 guardrail_name 命名护栏。 每一条关于某个护栏的网关日志行都会在 guardrail_name 下携带其配置名称,它取代了 row(以及掩码不一致警告中的 member、无效配置警告中的 name),不保留别名。在 Amazon Bedrock 护栏的日志行上,AWS 护栏标识记录为 bedrock_guardrail_id,而不再是 guardrail_id。所有端点上的「guardrail blocked …」警告现在也带有 guardrail_name;语义护栏的向量化失败会写出护栏名称和向量模型的显示名称,而不再是 guardrail="semantic" 和模型 ID;在 on_buffer_exceeded: fail_open 下未经扫描就放行的流式输出现在会记录日志。基于 row= 或 Bedrock 日志行 guardrail_id= 的日志查询必须更新。用量事件、指标和 Span 不变。
  • Amazon Bedrock 护栏的失败标签。 ApplyGuardrail 返回的非 429 的 4xx(AccessDeniedException、ValidationException、ResourceNotFoundException 等),以及在调用前就缺失或被拒绝的凭证,现在标记为 bedrock_config_error,而不再是 bedrock_5xx;每个 429 都标记为 bedrock_throttled。该标签出现在 guardrail_bypassed_reason、aisix_guardrail_bypasses_total{reason}、aisix_guardrail_latency_seconds 的 error_type 标签以及失败即拦截的拒绝信息中。5xx 和传输失败仍为 bedrock_5xx。

定价、用量与控制台​

  • Claude 的 1 小时提示词缓存写入按输入费率的 2 倍计费。 对于 Anthropic、Amazon Bedrock 和 Google Vertex AI 提供的 Claude 模型,有效期为 1 小时的缓存写入现在按当前生效输入费率的 2 倍计费,包括长上下文档位和服务档位。此前按缓存写入费率计费。组织价格可以在 Admin API 中设置 cache_write_1h_usd_per_1m,或在定价对话框的「1 小时缓存写入」字段中设置。它只作用于基础费率,长上下文档位和服务档位仍按各自输入费率的 2 倍计费。路由模型组价格、经 Azure AI Foundry 或转售商提供的 Claude,以及名称中不含 claude 的模型(例如 Bedrock 应用推理配置文件 ARN),1 小时写入仍按缓存写入费率计费。
  • 目录价格包含 models.dev 的长上下文分档。 models.dev 条目带有上下文长度分档的模型(例如 Bedrock global.openai.gpt-6-sol:272K 输入 Token 以内为 $2 / $10,以上为 $4 / $15),会在升级后的首次价格同步中把这些分档纳入目录价格。输入(含缓存读取和写入)超过某档阈值的请求,会整体按该档计费,因此费用比以前高,预算消耗更快。组织自己的价格不受影响。
  • 响应缓存命中不计费。 每个 cache_status: hit 的用量事件都按 0 计价,因此不再计入花费或预算。此前直接模型的缓存命中按模型的费率计价。回放的 Token 数和 cache_hit_saved_* 不变。
  • 概览和用量数据由按小时汇总的数据计算。 时间窗口按完整的 UTC 小时读取,一个请求只在其首次尝试所在的小时计一次,延迟分位数为近似值,数据比实时用量滞后约五秒。字段级细节见 API 变化。
  • 定价页面默认打开「使用中」。 完整目录移到「目录」标签页。
  • 预算告警 Webhook 携带 currency 字段,位于固定载荷的末尾,模板中也可以通过 {{ .currency }} 使用。
  • 对已不存在资源的引用显示为短 ID 和状态徽标(已删除、已移除或名称不可用),而不再显示完整 ID;完整 ID 在徽标的弹出框中。
  • 不提供 chat 服务的模型服务提供方的模型不能作为 chat 目标。 见 API 变化。

部署​

  • 打开的 Realtime 会话会让排空中的网关等待。 关闭时,网关现在会像对待流一样,等待打开的 /v1/realtime 会话关闭,以便记录其用量。请按最长的会话时长设置终止宽限期。
  • 排空后期到达的请求只服务一次。 在排空结束之后、经由排空结束前已接受的连接到达的请求,现在会以 Connection: close 应答,并且只向上游发送一次;此前它可能被发送两到三次(thread-per-core 模式),或在没有响应的情况下被关闭。已完成 TLS 握手但尚未发送请求的连接,现在会让排空一直等待,直到它发送请求、downstream.idle_timeout_secs 到期或客户端关闭连接。

AISIX Enterprise:

  • 控制面自身的出向调用使用统一的 SSRF 设置。 outbound.ssrf_protection(enabled;allowed_hosts:host、host:port 或 [v6]:port)现在管控 Playground 调用(包括语义路由测试和护栏试运行)、通知投递、MCP spec_url 获取以及 Azure AI Content Safety 测试连接。未设置时跟随部署模式(On-Premises 上关闭)。环境变量为 AISIX_CLOUD_SSRF_PROTECTION_ENABLED / AISIX_CLOUD_SSRF_PROTECTION_ALLOWED_HOSTS;Chart 中为 api.outbound.ssrfProtection.enabled / .allowedHosts。无效的 allowed_hosts 条目会让 cp-api 无法启动。它取代了 outbound.notify_allow_private_urls、outbound.playground_allow_private_ips、outbound.mcp_spec_allow_private_urls 和 outbound.guardrail_test_connection_allow_insecure(以及它们的环境变量和 Chart 中的 api.notifyAllowPrivateURLs、api.playgroundAllowPrivateIPs、api.mcpSpecAllowPrivateURLs、api.guardrailTestConnectionAllowInsecure),这些设置现在会被忽略,并在启动时记录警告。注意含义相反:旧设置为 true 表示允许私有地址;新设置 enabled: true 表示拒绝它们。防护开启时,会拒绝更多非公网地址段(例如 Azure 的 168.63.129.16),公网的 IPv4 映射 IPv6 地址不再被拒绝,并且连接只会发往经过检查的地址。Playground 调用和通知投递现在遵循 HTTPS_PROXY / HTTP_PROXY / NO_PROXY。

新功能​

成本归因​

  • 成本归因标签。 每个组织最多声明 32 个标签键(设置 → 标签键,/tag_keys),然后在 API Key、团队和成员上设置 key=value 标签。网关按键解析请求的标签——优先取 API Key 自己的值,其次是其团队的,再其次是其成员的——并连同 Key 的 team_id 一起写入每一行用量。导出器会携带它们:OTLP 为 aisix.tags.<key> 和 aisix.team_id,Datadog 为 aisix.tags,SLS 每个标签一个 tags.<key> 字段,对象存储为 tags。用量日志及其 CSV / JSON 导出携带 team_id 和 tags。标签从不作为 Prometheus 标签,也从不从请求中读取。
  • 标签预算。 预算的作用范围可以是 tag,scope_ref 为 <key>=<value>;它统计组织所有环境中的花费,并与其他作用范围一样以 hard_stop 执行。
  • 标签限流。 条件限流策略接受 tag:<key> 作为条件维度(==、~=、in、~~、~*)以及 group_by 维度,例如每个部门一个计数器。不带该标签的请求既不匹配该条件,也不匹配其否定条件,并且不受基于它的 group_by 约束。
  • 成本分析页面和 GET /usage_analysis。 组织级视图,展示一段时间内的成本、Token 和请求数,可按任意标签键、团队、成员、API Key、模型、环境或日期分组,支持筛选、下钻、「未设置」分组,并在按团队和标签分组时显示预算列。此后被删除的标签键,只要在该时间窗口的用量中出现,仍会显示并标记为已删除。

定价​

  • 组织币种。 设置 → 币种可为组织中的所有金额(价格、用量成本和预算)选择 USD(默认)或 CNY。修改时不做任何换算。在 CNY 组织中,models.dev 目录(USD)不用于计费或 least_cost 路由,只使用组织自己的价格。Admin API 字段名保持不变(*_usd_per_1m、cost_usd、limit_cents);名称中含 usd 的网关数值和指标使用组织币种。
  • 使用中价格视图。 GET /model_pricing?view=in_use 和定价页面的默认标签页会列出各环境实际使用的模型,标出未定价的模型,并提供「设置价格」操作。
  • 分档价格。 价格可以按输入 Token(含缓存读取和写入)携带 tiers。整个请求按其能放入的第一个 max_input_tokens 档位计费。
  • 模型组价格和低峰折扣。 路由模型可以携带自己的 price(可分档),对发往该模型组的请求取代实际提供服务的成员的价格;还可以携带 off_peak 时间表(IANA 时区、按星期的时间窗口、介于 0 与 1 之间的系数),为这些请求打折。两者都只影响控制面计费,不改变路由。
  • 按服务档位定价。 网关会记录上游实际处理请求的档位(用量事件中的 service_tier,OTLP / Datadog 的 aisix.service_tier,SLS 的 service_tier):OpenAI 及兼容上游的 service_tier、Anthropic 的 usage.speed / service_tier、Bedrock 的 serviceTier、Gemini 的 usageMetadata.serviceTier。价格可以携带 service_tier_prices 条目,按不区分大小写的档位名称匹配,并应用各自的费率和分档。目录价格会从 models.dev 导入服务档位模式;组织为某个模型设置的价格会取代目录中的该行,包括档位条目。用量日志详情会显示档位。

端点​

  • 决策端点 /v1/systemone 和 /v1/decisions。 /v1/systemone 接受 TypeSafe 的 System One 格式,/v1/decisions 接受 OpenAI 的 Decisions 格式。两者都可以由 typesafe、azure(Microsoft Foundry)、openrouter 或 openai 服务提供方凭证提供服务,格式一致时原样转发,不一致时转换问题和答案。支持直接模型、路由模型和通配别名,并具备故障转移、预算、限流、模型访问控制、用量事件(operation 为 systemone / decisions)和指标。这两个端点不运行安全护栏。TypeSafe 服务提供方凭证现在可以支撑直接模型,但不能在其上开启后台模型检查。价格中可选的 decisions 费率会在这两个端点上取代基础费率。

模型服务提供方​

  • Amazon Bedrock 和 Vertex AI 上的 Claude:/v1/messages/count_tokens 和提示词缓存。 /v1/messages/count_tokens 现在在两个平台上都可用于 Claude(此前返回 400):Bedrock 使用 CountTokens(权限 bedrock:CountTokens),对 CountTokens 拒绝的模型(例如仅支持跨区域的模型)回退到 Bedrock Mantle;Vertex AI 使用其 count-tokens 路由。网关新增的静态配置 upstream.bedrock.mantle_endpoint(默认为公共的区域 Mantle 主机)用于为 VPC 端点或 GovCloud 部署设置 Mantle URL,并已在 1.7.0 的 aisix Helm Chart values 中声明。提示词缓存现在在 Bedrock 和 Vertex AI 上的 Claude 的所有入口都生效:cache_control 标记在发往这些目标的 chat 转换中会被保留,并在 Converse 上变为 cachePoint 块(Claude 在 system、messages 和 tools 中;Amazon Nova 在 system 和 messages 中,不带 ttl)。发往 Bedrock 时,标记只保留 type 和 ttl;发往 Vertex AI 时会去掉 scope。auto_prompt_caching 现在可以设置在 Bedrock(anthropic. 模型 ID,包括带区域前缀的 ID 和 ARN)和 Vertex AI(claude-*)上的 Claude 模型上,并与在 Anthropic API 上一样生效;其他模型仍以 400 拒绝。Bedrock 上的部分 Claude 模型只接受 5 分钟缓存,请求 1h 时 Bedrock 会拒绝。
  • Bedrock 认证模式。 Bedrock 服务提供方凭证的密钥接受 auth_type:access_key(默认,与以前相同,可选 session_token)、api_key(Bedrock API Key,以 bearer Token 发送)或 default_chain(网关自身的 AWS 环境:环境变量、Web Identity / IRSA、ECS 任务角色或实例配置文件)。使用 access_key 或 default_chain 时,role_arn(可选 external_id、role_session_name)用于扮演 IAM 角色。Bedrock 安全护栏的 aws_credentials 新增 kind: api_key 和 kind: default_chain,static 新增 session_token 和角色字段。每次 Bedrock 调用都使用所选模式。缺失或被拒绝的凭证是不可重试的 401 authentication_error,并写出所用模式;STS 或元数据端点失败则可重试。控制台中的服务提供方凭证和安全护栏表单提供该模式及其字段,服务提供方凭证详情显示 bedrock_auth_type。
  • Amazon Bedrock 上的 Cohere Embeddings 接受调用方的 input_type、embedding_types(或 encoding_format),在 Embed v4 上还接受 dimensions,并按 Cohere 的计费单位报告用量。

可观测性​

  • 按导出器采集请求头。 每个可观测性导出器都接受 request_headers 和 upstream_response_headers(小写请求头名称;两个列表都拒绝凭证类请求头,upstream_response_headers 还拒绝 set-cookie)。每个导出器只记录自己的列表:OTLP 记录为 http.request.header.<name>,以及每次尝试的 http.response.header.<name>;Datadog、SLS 和对象存储记录为 request_headers / upstream_response_headers 映射。可在导出器表单或 Admin API 中配置。
  • 更多请求遥测。 用量事件和导出器新增 requested_model_id(调用方所访问模型条目的 ID,与实际提供服务的 model_id 并列)、api_key_name、gateway_overhead_ms(在网关内花费的时间,不含等待上游的时间)、upstream_tpot_ms(流上每个输出 Token 的时间),以及上游上报的音频和图像 Token 数(OTLP 上为 gen_ai.usage.{audio,image}.{input,output}_tokens)。上游上报拆分时,提示词缓存写入按缓存有效期拆分为 cache_creation_5m_tokens 和 cache_creation_1h_tokens(OTLP 为 aisix.cache_creation_5m_tokens / aisix.cache_creation_1h_tokens);cache_creation_tokens 仍为总数。Claude 模型上的 1 小时写入按行为变化 → 定价、用量与控制台中所述计费;其他缓存写入无论有效期多长,都按缓存写入费率计费。Admin API 的用量事件(GET /environments/{env_id}/usage_events)、用量导出和日志详情也会显示该拆分;在 CSV 中,这两列追加在最后。gen_ai.tool.definitions 现在携带每个工具的描述和参数。

控制台​

  • 选择控制台语言。 管理员可以设置组织语言(设置 → 语言:英文、中文或不设置),登录页面和顶栏中的语言选择器会保存每个浏览器的选择。在组织内,语言依次取选择器的选择、组织语言、浏览器语言,最后是部署默认值(i18n.default_locale、环境变量 AISIX_CLOUD_DEFAULT_LOCALE、Chart 值 ui.defaultLocale)。从邀请、设置密码或 SSO 链接打开的页面跟随所链接组织的语言。管理员发送的邀请和设置密码邮件跟随组织语言,未设置时使用部署默认值。

    AISIX Enterprise: 未设置选择器时,唯一组织的语言也适用于登录页面以及验证和重置密码邮件。

    AISIX Cloud: 登录页面以及验证和重置密码邮件只跟随选择器和浏览器。切换组织时,除非选择器有选择,否则语言会切换为该组织的设置。

改进​

  • 概览和用量页面从按小时汇总的数据加载,而不再扫描每一行用量,在大型环境中把 7 天和 30 天页面的加载时间从数秒缩短到约一百毫秒。Top API Key 显示 Key 名称。
  • Admin API 的拒绝信息会说明拒绝了什么以及原因。 422 DP_INCOMPATIBLE 会写出每个无法加载该设置的网关所在的环境,而不再是「在此环境中」。此前显示为 Doesn't match schema "not"、或只引用了允许形态之一的 schema 拒绝信息,现在会写出取值和原因:导出器凭证类请求头、含 __ 的 MCP 服务器名称、自定义角色权限、OIDC 绑定声明、限流时间表、维度(包括 tag:<key>)和条件取值。API Key 未知的 user_id 或 team_id,或不在所指定团队中的成员,会单独报告,而不再合并为一条信息。状态码和错误码不变。DP_INCOMPATIBLE 信息现在说明网关在最后一次心跳后 5 分钟内仍会被计入,因此刚升级或停止的网关可能在这段时间内仍被列出。
  • 网关配置错误会写出键名。 网关无法读取的配置值现在会以完整的点分键名使启动失败,例如 upstream.media_fetch.allowed_hosts。如果该键由 AISIX_* 环境变量设置,错误还会写出该变量。此前错误只是解析器的原始信息。
  • Bedrock 服务提供方凭证不再需要端点。 未设置时,控制面会保存凭证 region 对应的运行时端点(https://bedrock-runtime.<region>.amazonaws.com,中国区为 .amazonaws.com.cn);清空端点会重新推导,推导出的端点会随凭证轮换到新区域。
  • 登出按钮在登出成功后才离开页面,否则会显示错误供重试。
  • 对图像和不透明载荷的提示词估算更符合实际。 上游未报告用量时,图像按 OpenAI 的视觉分块公式估算,加密推理、签名、文件和音频不再作为文本计算 Token。携带截图或推理条目的已放弃请求,不再记录数十万个虚假的提示词 Token。

AISIX Cloud:

  • 当前组织按浏览器标签页保存。 在一个标签页中切换组织,不再改变其他已打开的标签页(此前它们的下一次写操作会落到新组织中);这些标签页会显示提示,让你选择切换或保持。

修复​

  • 在没有原生结构化输出的 Claude 模型(Anthropic、Bedrock /invoke、Vertex Claude)上开启思考的结构化输出请求,现在在流式时也会返回其非流式时返回的推理内容。
  • 以嵌套 error 事件失败的 Responses 流,现在会在用量事件和访问日志中记录上游的错误信息,而不再是全为 null 的信封。
  • 每个请求恰好产生一个 attempt_index 为 0 的用量事件:重试退避期间的取消、/v1/videos 在某次尝试成功后的失败以及 ensemble 的失败退出,不再写入第二个,随之产生的重复 Span 也已消除。
  • 定价对话框会在对话框内显示被拒绝的保存或重置,写出字段及其上限(例如「Completion price for tier 2 must be less than 100,000 USD per 1M tokens.」),而不再在对话框后面显示原始的校验文本。每个按 1M Token 计的价格输入框(定价对话框、模型组价格和模型自己的价格)都会说明其范围:不小于 0、小于 100,000、最多 10 位小数,并在保存前标出超出范围的值。
  • 网关重启后、或由另一个副本重新发送的批次归因用量行只保存一次,因此该批次不再在预算、用量和导出中被计算两次。
  • 控制台生成的网关 Helm 命令不再固定 image.tag,因此之后升级 Chart 时会运行 Chart 自己的网关版本。
  • 组织正在删除期间到达的写操作会被以 404 ORG_NOT_FOUND 拒绝,而不再以 500 失败或写入被删除的组织。
  • 某个查询被取消后紧接着复用同一数据库连接的控制面查询,可能在几毫秒内以 i/o timeout 失败,并在控制台请求上表现为 503。控制面的 PostgreSQL 驱动现已包含该修复。
  • 路径中把 / 编码为 %2F 的请求,现在与使用普通路径的同一请求一样按 Admin API schema 校验。
  • 在所有 Claude 上游(Anthropic API、Vertex AI 上的 Claude、Bedrock 上的 Claude)上,与聊天消息 content 并列的 cache_control、role: "tool" 消息上的 cache_control,以及 tool_calls[] 条目上的 cache_control,现在会应用到该消息的最后一个块、工具结果或工具调用上;此前会被丢弃。
  • Bedrock 上的 Claude 不再拒绝 thinking.display: "updates"(由 Claude Code 发送,此前会话中的第一个请求会以 400 失败);summarized 或 omitted 以外的 display 会被丢弃。携带 dangerous-tool-use-2026-09-03、thinking-binding-controls-2026-08-01 或 thinking-display-updates-2026-08-18 的请求(此前被 Bedrock 以 400 拒绝)现在会去掉这些值后成功。
  • 服务提供方凭证的 anthropic-beta 请求头中带有 Vertex AI 不支持的值时,发往 Vertex AI 上 Claude 的聊天请求不再以 400 失败;该值会被丢弃。
  • 发往 Claude 的聊天请求接受 stream_options、max_completion_tokens 和 stop。此前它们会以 400(「… Extra inputs are not permitted」)失败。这影响 Anthropic 及兼容 Anthropic 的服务提供方、Vertex AI 上的 Claude,以及 Amazon Bedrock 上 Claude 的非流式请求。stream_options 不再发往上游。max_completion_tokens 作为输出上限,同时发送时优先于 max_tokens,reasoning_effort 的思考预算也按它确定。stop 转为 stop_sequences,字符串作为只有一个元素的数组发送。调用方自己发送的 stop_sequences 优先于 stop,这在所有 Claude 路径上都成立,包括 Bedrock 上 Claude 的流式请求。Bedrock 上 Claude 的非流式请求发送的内容与 Anthropic 路径完全一致,上游不接受的取值会送达上游并被其拒绝。
  • 来自音频输出模型(例如 modalities: ["text","audio"])的流式 Chat Completions 现在会转发 delta.audio,以用量分片和 [DONE] 结束,并报告音频 Token。此前流会丢弃音频,并以 upstream_decode_error 结束。这影响 OpenAI 及兼容 OpenAI 的上游、Azure OpenAI,以及 Bedrock 和 Vertex AI 的兼容 OpenAI 路由。聊天输出安全护栏不会检查生成的音频及其转录文本。
  • 上游上报 "cached_tokens": null 或 "reasoning_tokens": null 时,请求现在会成功,该计数视为未上报。此前聊天补全会以 502 失败,透传路由上则不记录任何 Token。
  • 自定义角色:产品不提供的权限,现在在创建或更新角色时会被以 400 INVALID_REQUEST(「permission resource … is not available in this product」)拒绝。在 AISIX Enterprise 上是 billing,在 AISIX Cloud 上是 data_export。这取代了 1.6.0 中 POST 和 PATCH /roles 仍接受这些权限的行为。创建和更新的响应会省略此前保存的此类权限,与角色列表已有的行为一致。
  • 控制台的 Docker 安装片段改为用 docker logs -f ... 2>&1 | grep -m1 'etcd connected' 验证网关;此前它只读取标准输出,并等待一条网关从不打印的日志。
  • 未选择服务器时打开 MCP 工具页面,会重定向到 MCP 服务器页面,而不再一直加载。
  • 开启 SSRF 防护时,Azure AI Content Safety 测试连接现在会在连接时拒绝名称解析到私有地址的主机,从而关闭 DNS 重绑定窗口;MCP 服务器的 spec_url 获取也是如此。无法解析的主机会报告为不可达(200 且 ok: false),而不再是 400(见 API 变化)。
  • 通知投递的错误信息不再显示被拦截主机解析到的内部地址。

AISIX Enterprise:

  • 唯一所属组织已被删除(例如因组织合并)的成员,会看到一个说明其不属于任何组织的页面以及登出按钮,而不再是环境加载错误。记住了已删除组织的浏览器会被引导到组织选择页面。
  • 修改由 Chart 管理的 Secret 值(主密钥、退役密钥、SMTP 或计费密钥、外部数据库密码)后,helm upgrade 现在会滚动更新 cp-api 和 dp-manager 的 Pod。
  • 离线安装包的 run.sh 只加载当前安装包的镜像,而不再加载 images/ 中残留的每个版本(见升级说明)。
  • 离线安装包的数据库密码可以包含任意字符,包括 @ % : / ? # + = ' 和空格。它不再被写入 cp-api 和 dp-manager 的数据库 URL,因此包含 URL 保留字符的密码不再导致它们无法连接。你仍然只需设置 POSTGRES_PASSWORD,现有 .env 文件无需修改。在 .env 中,包含空格、#、$ 或引号的密码需要加引号。
  • 未设置组织语言时,读取公共配置不再在每次请求时记录错误。

AISIX Cloud:

  • 不属于任何组织的用户会进入创建组织表单,并有登出按钮,而不再是环境加载错误。
  • 在组织解析完成之前,预算横幅不再在标签页首次加载时发送一个以 400 MISSING_ORG 失败的请求。
  • GET /data_export 和 POST /data_import 以标准的 {"error": {...}} 信封返回 404。此前返回的 404 没有响应体。

API 变化​

以下 Cloud Admin API 变化会破坏现有调用方。

  • format: date-time 查询参数会在处理程序之前校验。 这涵盖 GET /environments/{env_id}/usage_events、/usage_events/export、/usage_metrics、/usage_summary 和 GET /usage_analysis 上的 from / to,以及 AISIX Enterprise 上 GET /data_export 的 audit_since / usage_since。状态码和错误码仍为 400 INVALID_REQUEST,但信息文本有变化。用逗号书写小数秒(2026-10-01T00:00:00,5Z)现在会被拒绝,请使用 .。带空的 audit_since= 或 usage_since= 的 GET /data_export 现在返回 400,而不再使用默认时间窗口;请改为省略该参数。
  • GET /environments/{env_id}/usage_summary 和 /usage_metrics 的含义变化。 from 向下取整、to 向上取整到完整的 UTC 小时,因此不在整点上的时间窗口会覆盖两端的不完整小时。一个请求只在其首次尝试所在的小时计一次,成功则计在成功尝试所在的小时,因此按日分桶之和等于总数。latency_p50_ms / latency_p99_ms 是误差在 5% 以内的近似值。success_count 不再计入 ensemble 的 panel 成员,且不超过 request_count。estimated_request_count 统计估算的尝试,因此每个被估算的 ensemble 成员和 judge 各计一次。
  • 用量事件上 model_id 对模型组的含义变化。 对于 1.7.0 网关,GET /environments/{env_id}/usage_events?model_id=<模型组 ID> 不再返回该模型组派发前的失败或其响应缓存命中,它们的 model_id 现在为空。请改为按 requested_model 并设置 requested_model_exact=true 进行筛选。
  • 模型的创建和更新会拒绝把不提供 chat 的服务提供方的模型作为 chat 目标。 不提供 Chat Completions 的服务提供方(Jina、RunwayML、TypeSafe)上的直接模型,不能再被添加为 ensemble 成员或 judge,或语义路由的路由、默认或失败时目标;在这些位置被引用的模型也不能被移到此类服务提供方凭证上。两者都返回 400 INVALID_REQUEST。升级前保存的引用可以原样重新提交。
  • 限流策略会拒绝不指向任何资源的 ID。 POST /environments/{env_id}/rate_limits 现在会检查 scope_ref 以及每个 team、member、api_key 和 model 条件取值:API Key 和模型必须存在于该环境中,团队和成员必须存在于该组织中(member 取 GET /members 返回的成员关系 ID,而不是账号的 user_id)。未知 ID、或来自其他组织或环境的 ID,会返回 400 INVALID_REQUEST 并写出字段;此前它会被保存且永远不会匹配。PATCH /environments/{env_id}/rate_limits/{rate_limit_id} 只在此类 ID 新加入 conditions 时才拒绝;已保存的 ID(例如已删除模型的 ID)仍可保存。升级前保存的策略不会被修改。
  • Amazon Bedrock 服务提供方凭证的密钥按认证模式校验。 POST /provider_keys 和 PATCH /provider_keys/{provider_key_id} 现在会对以下 Bedrock 密钥返回 400:带有其他模式字段的(例如与访问密钥并存的 api_key)、session_token 或角色字段为空的,或者设置了 external_id / role_session_name 却没有 role_arn 的;此前它们会被保存。以纯字符串提交的目录 amazon-bedrock 凭证,在创建或轮换时也按同样方式检查。请移除多余或为空的字段。access_key_id / secret_access_key 的必填要求现在只适用于 auth_type: access_key(默认值)。
  • Azure AI Content Safety 测试连接把无法解析的主机报告为不可达。 开启 SSRF 防护时(这是 AISIX Cloud 的默认设置),对于无法解析的端点主机,POST /environments/{env_id}/guardrails/test-connection 返回 200 和 {"ok": false, "message": "Could not reach the Azure AI Content Safety endpoint."},而不再是 400 INVALID_ENDPOINT(「could not resolve the endpoint host」)。依据 400 分支处理的调用方必须改为读取 ok。

升级说明​

从早于 1.7.0 的版本升级时,均需遵循本节说明,包括跳过 1.7.0 升级到更新版本的情况。

  • 按新的 OTLP Span 形态更新追踪查询和看板(见行为变化),并更新 Datadog 中针对 Anthropic 形态流量、基于 gen_ai.usage.input_tokens 的查询。
  • 把 SLS 索引和 Datadog facet 迁移到结构化内容字段。 在 SLS 上,为 input_messages、system_instructions、tool_definitions 和 output_messages 创建字段索引,并把已保存的查询从 prompt / response 上迁走;在 Datadog 上,把 facet 和监控从 gen_ai.prompt / gen_ai.completion 迁到 gen_ai.*.messages。
  • 在导出器上重新配置请求头采集。 如果你的网关设置了 observability.usage_event.request_headers,请在升级后把同样的请求头列入每个导出器的 request_headers。1.7.0 的 aisix Chart 不再携带该值。
  • 从新的用量事件字段读取缓存写入拆分。 来自 1.7.0 网关的用量事件在 GET /environments/{env_id}/usage_events 和用量导出中携带 cache_creation_5m_tokens 和 cache_creation_1h_tokens。在 CSV 导出中,它们是最后两列,因此按位置读取列的解析器仍可正常工作,但期望固定列数的解析器必须允许这两列。
  • 控制台跟随浏览器语言。 升级后没有任何组织设置了语言,因此浏览器偏好英文或中文的用户会看到该语言的控制台,并收到该语言的验证、重置密码和 SSO 邮件,而不是部署默认语言。如需为所有人固定一种语言,请在设置 → 语言中设置组织语言。
  • 升级后,概览和用量页面会显示为零,并提示「正在回填历史数据」,直到新的用量索引构建完成、现有用量汇总完毕。在用量表较大时这可能需要一段时间,期间流量仍会被正常记录。
  • 更新护栏日志查询和告警。 在护栏日志行上,row=、member= 和 name= 变为 guardrail_name=,Bedrock 护栏日志行的 guardrail_id= 变为 bedrock_guardrail_id=。
  • 更新基于已重命名失败分类的告警。 针对 Bedrock 护栏配置错误、基于 bedrock_5xx 的告警和查询要改为 bedrock_config_error;针对服务提供方转换拒绝的请求、基于 invalid_config 的告警和查询要改为 invalid_request_error。
  • 错误信息现在携带上游的文本。 如果你的网关所服务的调用方不应看到服务提供方账号的细节,请注意:来自 Amazon Bedrock、Azure OpenAI 和 Vertex AI 的错误,以及来自所有服务提供方的 5xx 错误,现在包含服务提供方自己的信息,其中可能写出账号 ID、ARN、部署或项目名称。
  • 带长上下文分档的目录定价模型,在超过阈值时费用更高。 首次价格同步后,此类模型超过某档阈值的请求会按该档计费,因此预算消耗更快。组织自己的价格不受影响。
  • Claude 的 1 小时缓存写入费用更高。 升级后,Anthropic、Amazon Bedrock 或 Google Vertex AI 提供的 Claude 模型上有效期为 1 小时的缓存写入,按输入费率的 2 倍计费,而不再按缓存写入费率(约为输入的 1.25 倍)计费,因此覆盖它们的预算消耗更快。只影响升级后记录的事件,历史数据不会重新计算。
  • 把内部媒体主机列入 outbound.ssrf_protection.allowed_hosts。 发往 Bedrock、Vertex AI 上 Claude 的聊天媒体 URL,以及发往 Anthropic 或 Gemini 的 http:// URL,现在由网关下载,网关会拒绝非公网地址。如果调用方发送的媒体 URL 由内部主机提供,请把这些主机列入 aisix Chart 的 config.outbound.ssrf_protection.allowed_hosts,或设置 outbound.ssrf_protection.enabled: false。被 fake-IP 或透明代理解析到 198.18.0.0/15 的公网域名也会被拒绝;请列出这些主机或关闭检查。设置了 proxy.request_body_limit_bytes 时,下载的媒体会计入其中,因此此前因媒体被丢弃而通过的请求现在可能得到 413。
  • Bedrock 和 Realtime 流量现在经过网关的代理。 在设置了 HTTP_PROXY、HTTPS_PROXY 或 ALL_PROXY 的网关上,Bedrock 运行时、Bedrock 安全护栏、STS 和 /v1/realtime 的上游连接现在会使用该代理。如需保持直连,例如连接 Bedrock VPC 端点,请把主机加入 NO_PROXY。Realtime 不能使用 SOCKS 代理:如果为其上游配置了 SOCKS 代理,Realtime 会话会一直失败,直到该主机被排除或改用 HTTP 代理。
  • 按最长的 Realtime 会话设置网关的终止宽限期。 排空中的网关现在会等待打开的 /v1/realtime 会话关闭。
  • 经路由模型组的 Responses 对话可能在不同网关版本之间失败。 在滚动升级或网关回滚期间,经路由模型组的 /v1/responses 后续轮次,如果延续的是在 1.7.0 网关上开始的对话、却落到较旧的网关上,就会失败。OpenAI 会以 400(string too long)拒绝,其他上游可能返回 404。开启新对话即可恢复。
  • 用控制台生成的 Helm 命令安装的网关固定了 image.tag。 helm upgrade --reuse-values 会保留该 tag,因此新的 Chart 仍会运行旧的网关。升级网关 Chart 时请清除它(例如 --set image.tag=)。
  • 对于无法解析的主机,Azure AI Content Safety 测试连接返回 200 且 ok: false,而不再是 400 INVALID_ENDPOINT。请更新依据 400 分支处理的自动化脚本。

AISIX Enterprise:

  • 从四个已移除的出向开关迁移到 outbound.ssrf_protection。 为加固而把 outbound.notify_allow_private_urls、outbound.playground_allow_private_ips、outbound.mcp_spec_allow_private_urls 或 outbound.guardrail_test_connection_allow_insecure 设为 false 的安装,现在会允许私有地址,除非设置 api.outbound.ssrfProtection.enabled=true(或 AISIX_CLOUD_SSRF_PROTECTION_ENABLED=true)。这包括从 Chart 1.5.0 以 helm upgrade --reuse-values 沿用下来的 Chart 发布,其 api.playgroundAllowPrivateIPs 和 api.notifyAllowPrivateURLs 默认为 false。如果此前只放开了部分地址,请把具体主机列入 allowed_hosts。
  • 离线安装包:旧的镜像压缩包会被删除。 升级后首次成功运行 ./run.sh 时,会删除 images/ 中旧的镜像压缩包(启动失败时会保留),你自己放在那里的镜像压缩包也不再自动加载。
  • 自行设置的数据库 URL 必须携带经 URL 编码的密码。 如果你通过 Chart 的 extraEnvVars 设置了数据库 URL(例如 postgres://…:$(PGPASSWORD)@…),这一条适用。控制面的 PostgreSQL 驱动现在按 libpq 的方式解析连接 URL:用户名和密码在第一个 @ 处结束(此前是最后一个),无效的百分号编码会报错,查询参数中的 + 不再被视为空格。此前可用的、包含 @、% 或其他保留字符的密码,可能在升级后导致 cp-api 和 dp-manager 无法连接。请不要在数据库 URL 中放密码:Chart 已经在 cp-api 和 dp-manager 中把 PGPASSWORD 设为数据库密码,URL 不带密码时驱动会原样读取它。或者,在 URL 中对密码进行 URL 编码。Chart 的默认配置不会把密码放进 URL,不受影响。

在 1.7.0 控制面仍连接着早于 1.7.0 的网关期间,以下说明适用:

  • 0.12.0 至 1.3.x 的网关会拒绝本版本投影的新资源类型。 它们会在 aisix_config_rejected_resources{kind=…} 中计数,并在升级之前一直把 aisix_config_last_reload_successful 保持为 0。从 1.4.0 起,网关只会在 aisix_config_unknown_kind_resources 中计数。两种情况下控制面都不会显示任何信息。升级网关即可消除。
  • 只要组织的任意环境中注册有 1.6.x 或更早版本的网关,标签预算就会被以 422 DP_INCOMPATIBLE 拒绝;只要该环境中有这样的网关,tag: 限流策略也会被拒绝。这些网关加载带 tags 的 API Key、团队和成员时会忽略该字段(控制台会显示部分兼容提示),因此它们的用量不带标签。
  • 较旧的网关会忽略导出器的 request_headers / upstream_response_headers;保存时会返回 field_ignored 警告。
  • 决策端点需要 1.7.0 网关。较旧的网关不上报 service_tier,因此其请求按基础费率计价,也不上报 requested_model_id。
  • 只要密钥所允许的某个环境中有 1.6.x 或更早版本的网关,auth_type 为 api_key 或 default_chain、或带有角色字段的 Bedrock 服务提供方凭证就会被以 422 DP_INCOMPATIBLE 拒绝;使用 kind: api_key / default_chain,或在 static 上使用 session_token 或角色字段的 Bedrock 安全护栏也是如此。
  • Bedrock 或 Vertex AI 上 Claude 模型的 auto_prompt_caching 可以不经检查保存,但 1.6.x 及更早版本的网关在升级之前不会在这些模型上注入标记。
  • 1.6.x 及更早版本的网关不上报 1 小时缓存写入拆分,因此在升级之前,其 1 小时写入按缓存写入费率计费。
  • 1.5.0 至 1.6.x 的网关只在 Chat Completions、Completions、/v1/messages、/v1/responses 和透传路由事件上记录 total_tokens;在升级之前,其 Embeddings、Rerank、音频、图像、Realtime 和批次事件的 total_tokens 保持为 null。早于 1.5.0 的网关从不记录该字段。

已知问题​

  • 标签限流和标签预算可能漏掉之后加入或回滚的网关。 兼容性检查只看保存策略或预算时已注册的网关。之后注册的 1.6.x 网关、或回滚到 1.6.x 的网关,不会执行 tag: 限流,其用量也不会计入标签预算。开发版构建和心跳已过期的网关也不会被检查。控制面的被拒绝资源报告会显示这样的网关。

1.6.0​

发布日期: 2026 年 10 月 12 日

On-Premises 控制面现在可以发送邮件。SMTP 中继负责投递邀请、找回密码链接和管理员签发的登录链接,组织也可以通过自己的 SAML 身份提供方让成员登录。控制台登录移入 cp-api,cp-api 现在以静态页面提供控制台,因此控制面不再运行单独的 UI 组件。语义路由可以用 TypeSafe 的 jev 决策模型而不是向量相似度来选择路由。Prometheus 指标可以在 ID 旁携带可读的 API Key、团队、成员、模型服务提供方凭证和策略名称,用量事件也可以记录你选定的请求头。流式响应在结束时按其结束时的状态计入请求指标。预算改为增量计算,审计日志会在可配置的保留期之后被清理。删除环境现在会从网关撤回其配置。透传路由会校验其目标和查询参数,对整条流执行并发限制,并在输出护栏无法评估响应时失败即拦截。

行为变化​

  • 流式响应在流结束时按其结束时的状态计入请求指标。 这涵盖 /v1/chat/completions、/v1/messages 和 /v1/responses 流、转录和翻译事件流、/v1/audio/speech 以及流式 /a2a 调用。完整送达的流记为 200,调用方中途离开的记为 499,上游中断或流内错误记为 502,读取超时记为 504,流内的 4xx 保留其状态码。此前这类流在响应开始时就被计为 200 成功。受影响的指标族有 aisix_requests_total、aisix_request_duration_seconds、aisix_proxy_requests_total、aisix_proxy_failed_requests_total、aisix_proxy_request_duration_seconds、aisix_llm_requests_total 和 aisix_llm_request_duration_seconds。对于流式流量,成功率会降到实际发生的水平,耗时直方图衡量整条流,因此其分位数会大幅上升。首 Token 时间仍由 TTFT 指标记录。一批长流出现时,rate() 信号会滞后约一条流的时长,Chart 中基于 aisix_llm_requests_total 的 KEDA 示例也是如此。在响应头发出之前离开的调用方仍只计入 aisix_proxy_client_cancelled_requests_total。aisix_request_e2e_latency_seconds 和 aisix_request_ttft_seconds 现在携带该流真实的 status_class,而不再是固定的 200。

  • 访问日志的 error_kind 和用量事件的 error_class 共用一套词表。 非流式访问日志行,以及不带尝试记录的失败请求的最终用量事件,其以下取值发生变化:upstream_error → upstream_status、transport_error → transport、upstream_decode_error → upstream_decode、upstream_in_band_error → upstream_in_band、config_error → config、invalid_request_error → invalid_config(无效的上游配置),以及 authentication_error → invalid_credentials。逐次尝试的事件和流式日志行此前就已使用新名称。客户端收到的错误响应中的 error.type 不变。流式透传日志行现在会携带 error_kind,此前该字段为空。

  • 设置了 on_embedding_failure: fail 的语义路由在向量化失败时以自己的错误码应答。 此前它应答 503 和 type: provider_unavailable("no bridge registered for provider"),指向一个并不存在的配置错误。现在它仍应答 503,但改为 type: api_error、code: semantic_routing_failed,消息为 semantic router '<model>' could not pick a route (<reason>),其中原因为 embedding_timeout、embedding_upstream 或 embedding_unavailable。针对这种情况匹配 error.type == "provider_unavailable" 的客户端必须改为匹配 error.code == "semantic_routing_failed"。访问日志和用量事件的 error_kind / error_class 为 semantic_decision_failed。新增的 jev 分类器在 on_failure: fail 时以同样的方式应答,原因为 classifier_*。

  • 网关拒绝会在用量事件中携带其原因。 网关自行拒绝的请求,现在会把访问日志中的文本记录到最终用量事件的 error_message 以及 OTLP 的 aisix.error_message 中。这涵盖未知或被禁止的模型、IP 限制、限流或预算拒绝、护栏拦截、语义决策失败以及请求过大。文本可能引用请求或上游应答内容的错误会让 error_message 留空。/v1/chat/completions、/v1/responses、/v1/completions、音频路由和 /v1/realtime 上输出侧和结束会话的护栏拒绝现在还会携带 error_class: content_filter,此前它们只有 guardrail_blocked: true。在 200 响应头之后被拒绝的流式回答保留状态码 200,并带有 error_class: content_filter。在调用方离开前一刻被拒绝的透传路由流不再记为 499 client_disconnected。/a2a 和 /mcp 的护栏拦截和额度拒绝也会携带 error_class 和消息。在这些 /a2a 和 /mcp 拒绝上,以及 /v1/responses、/v1/completions 和音频路由上缓冲模式的输出护栏拒绝上,访问日志行现在携带 error_kind 和 error,1.5.0 中这两者为空。对于每一种网关拒绝,它们现在都等于用量事件的 error_class 和 error_message。

  • 护栏不再扫描工具调用 ID。 护栏此前会连同每个工具调用的名称和参数一起读取它的 ID,把消息文本发送给审核服务或自定义脚本的护栏也会收到它。工具调用的 id、call_id、tool_use_id 和 tool_call_id 取值现在在所有接口和透传路由上都会被排除,因此护栏不再因为只出现在 ID 内部的文本而拦截。在透传的 Responses 请求体上,条目句柄、approval_request_id 和推理的 encrypted_content 也会被排除,因此该路由扫描的文本与 /v1/responses 相同。函数名称和参数仍照常扫描。不透明请求体的透传扫描仍会读取每个解码后的字符串。

  • Vertex AI Gemini 模型上的函数调用会拒绝它无法承载的内容。 此前靠把工具扁平化为文本而成功的请求,现在应答 400 invalid_request_error。这涵盖旧式的 functions / function_call 字段、不是函数工具的工具、不支持的 tool_choice、不对应任何调用的工具结果,以及不是 JSON 的调用参数。Bedrock 同样以 400 拒绝 functions / function_call,此前 Converse 会丢弃它们。来自 Vertex Gemini 模型的工具调用 ID 更长,因为其中携带 Gemini 的思考签名,必须原样回传。网关在把对话发送给其他任何上游之前会去掉该后缀。

  • 代理监听器应答的每个请求现在都会写一行访问日志。 认证拒绝(401,以及 JWT 作用域的 403)会新增日志行,扫描器探测也包括在内。未路由的路径(404)、已知路径上的错误方法(405,仍带 Allow)、GET /v1/models、A2A Agent Card 获取以及 OAuth 受保护资源文档同样会新增日志行。面向互联网的网关日志量会明显增加;请在日志管道中过滤,或关闭访问日志。这些日志行从不包含所出示的凭证。/livez 和 /readyz 仍然不写日志。

  • observability.access_log: false 现在会关闭访问日志。 此前该键会被解析但被忽略。设为 false 时,无论 log_level 或 RUST_LOG 如何设置,都不会写任何访问日志行;其他所有日志行不受影响。默认值仍为 true。

  • 没有 observability: 配置块的网关配置文件以 info 级别记录日志。 此前这样的网关会退回为只记录错误,既不输出启动日志,也没有访问日志。现在它采用文档所述的默认值。设置了 RUST_LOG 时仍以它为准;如需保持此前的静默,请设置 observability.log_level: error。

  • 护栏的 timeout_ms 现在约束整次调用。 这适用于阿里云文本审核、阿里云 AI 护栏、Lakera、OpenAI moderation、Presidio,以及 Azure Prompt Shield 和文本审核。该截止时间覆盖发送、读取响应体(包括错误响应体)以及解码。发出响应头后响应体停滞的服务提供方,现在会以超时失败并遵循 fail_open / output_fail_open,此前请求会一直挂起。只按响应头延迟调整过的 timeout_ms 可能需要调大。

  • 推理内容可以跨越 Anthropic Messages 与 Chat 之间的桥接。 在 /v1/messages 上由 OpenAI 兼容推理上游提供服务的 Anthropic 客户端,现在会在回答之前看到一个 thinking 块(流式时为 thinking 事件),其 signature: ""。它重放的思考内容会以 reasoning_content 到达上游,因此 DeepSeek 一类的上游不再拒绝使用工具的后续轮次。请求发往 Anthropic 自己的 API 之前,未签名的 thinking 块会被移除,因此故障转移到或切换到 Claude 的会话不再收到签名无效的 400。由开启扩展思考的 Anthropic 提供服务的 OpenAI 客户端现在会收到 reasoning_content,由 Anthropic 提供服务的 /v1/responses 会返回一个 reasoning 条目。经 /v1/messages 访问的 Bedrock 或 Vertex AI 上的 Claude 也会给出其思考内容,不带签名。拒绝未知消息字段的 OpenAI 兼容上游,会在重放的助手轮次上看到 reasoning_content。

  • 透传路由有若干现有路由可以观察到的变化。 它们会拒绝不安全的路径和冲突的查询参数,中继重定向,对事件流应用 timeout_ms,在整条流期间占用并发名额,并改变护栏的扫描方式。参见升级说明中的透传路由一节。

  • 使用 Redis 限流后端时,并发租约从 Redis 中消失的透传事件流会被结束。 调用方的流在 200 响应头之后停止,该请求以状态 429、error_class rate_limit_lease_lost 记录。

  • 预算在花费到达时计入,且从不重新归属。 花费归属于网关上报它时生效的绑定关系,在请求发生后数秒内完成。把 Key 重新绑定到另一个团队或成员、把模型指向另一个模型服务提供方凭证、删除 Key、成员、团队或环境,以及清理旧的用量,都不再改变已计入的花费;只有之后的请求会遵循新的绑定关系。此前这些操作会按当前绑定关系重新计算花费。新建的预算,或作用范围或周期发生变化的预算,从其当前周期内已记录的花费开始计算。

  • 控制台的预算告警覆盖 team_member 预算。 任一成员越过按成员限额的阈值时即触发,横幅会说明该百分比是相对于按成员限额而言的。此前这类预算只有在限额为零时才会触发告警。

  • 审计日志和通知投递记录只保留有限的时间。 审计日志会在 audit.retention_days 之后被删除,这是一项新增的部署配置(在 Compose 和离线安装包中为 AISIX_CLOUD_AUDIT_RETENTION_DAYS,在 Chart 中为 api.audit.retentionDays)。默认值为 730 天,0 表示永久保留,该配置不在控制台或 Admin API 中提供。通知投递记录会在 90 天后被删除,因此投递日志显示最近 90 天的记录。

  • 删除环境会从网关撤回其配置。 此前其配置键会被遗留下来。仍在 watch 已删除环境的网关现在会失去该配置,而不再继续按旧配置提供服务。升级后 dp-manager 首次启动时还会移除此前删除的环境所遗留的配置,此后每日一次的清理会保持其干净。

  • On-Premises 部署不再提供自助注册、创建组织或计费。 注册需要邀请链接中的 Token;控制台以外的客户端必须以 invitationToken 发送它。创建组织会应答 403 ORG_CREATION_DISABLED。计费页面和 billing 权限随之消失。现有用户和组织会被保留。

  • On-Premises 默认允许出向调用访问私有地址。 这涵盖 Playground 上游、通知渠道、MCP 规范 URL 和护栏测试连接。outbound.playground_allow_private_ips、outbound.notify_allow_private_urls、outbound.mcp_spec_allow_private_urls 和 outbound.guardrail_test_connection_allow_insecure 在未设置时现在跟随部署模式:On-Premises 上允许,Hybrid Cloud 上拒绝。将它们设为 false 即可拒绝。

  • 控制台登录在 cp-api 中运行,所有人都需要重新登录一次。 账号和密码会被保留,但 1.5.x 的会话不会。secrets.betterAuthSecret 不再使用;设置了它的 1.5.0 values 文件仍然可以安装。可信来源移到 api.trustedOrigins(cp-api 上的 AISIX_TRUSTED_ORIGINS)。按 1.5.0 安装说明写在 ui.extraEnvVars 中的 AISIX_TRUSTED_ORIGINS 条目会被沿用。

  • cp-api 提供控制台;UI 组件已移除。 不再有 aisix-cp-ui 镜像、ui Deployment 或 Node 进程。执行 helm upgrade 时 ui Deployment 会被移除。<release>-ui Service(连同已设置的 NodePort)保留,并改为指向 cp-api,因此指向它的代理仍可正常工作。除 defaultLocale、ui.service 和 extraEnvVars 之外的 ui.* 取值会被忽略,包括 ui.extraVolumes 和 ui.extraVolumeMounts。控制台不再连接 PostgreSQL。离线安装包的 run.sh 会移除旧的 ui 容器。Chart 不再从 ui.extraEnvVars 读取 AISIX_DASHBOARD_LOCALE,请改为设置 ui.defaultLocale。Compose 和离线安装包在未设置 AISIX_CLOUD_DEFAULT_LOCALE 时仍会使用 AISIX_DASHBOARD_LOCALE。路径中带有 ID 的页面 URL 现在把它放在查询参数中(/environments/<page>?env=<id>、/teams/detail?team=<id>、/mcp-servers/tools?server=<id>、/invitations?token=<token>)。旧链接,包括已经发出的邀请邮件中的链接,会以 302 重定向。

  • cp-api、dp-manager 和控制台从 Chart 渲染的配置文件中读取设置。 1.5.0 安装中通过环境变量设置的每一项配置都仍以原名生效。环境变量会覆盖配置文件,cp-api、dp-manager 和控制台会在启动时记录每一处覆盖。密钥仍然放在由 Secret 注入的环境变量中。helm upgrade 会保留 1.5.0 的 extraEnvVars 覆盖项。dp-manager 的可选配置文件现在使用嵌套键。

  • On-Premises 控制台显示「AISIX Enterprise」。 在 On-Premises 上,产品内文字、页面标题、邮件、离线安装包和 Chart 的 NOTES 都把产品称为「AISIX Enterprise」,在 Hybrid Cloud 上则称为「AISIX Cloud」。

  • 组织恢复只能加载到全新安装的控制面上。 POST /api/data_import 现在需要 owner 的控制台会话而不是管理员 Token,并且实例中只能有其引导组织和管理员。其他情况一律返回 409 INSTANCE_NOT_FRESH。完整导出包会替换引导组织和管理员。脱敏导出包不加载任何密码,因此恢复的账号要等管理员启用后才能登录,每个恢复的 API Key 也必须先轮换才能通过认证。导出不变。

  • 发布版本的控制面会提供自己的网关镜像。 未设置 data_plane.image 时,cp-api 建议使用 docker.io/api7/aisix:<its version>,而不再是 ghcr.io/api7/aisix:dev。已配置的镜像仍然优先。

  • 自定义 API Key 值只需在其环境内唯一。 此前复用另一个环境中已使用的值会被以 409 拒绝。

  • 模型价格目录的「Updated」列显示最近一次价格变化的时间,而不是最近一次同步的时间。

新功能​

  • On-Premises 的 SMTP 邮件。 cp-api 可以通过 SMTP 中继发送邮件(smtp.host、port、from、取值为 starttls、smtps 或 none 的 tls、username,以及来自 Secret 的密码)。邀请会通过邮件发送,控制台会显示中继是接受了、拒绝了还是无法连接。待处理的邀请可以重新发送,这会签发一个新链接。「Forgot password」会发送一个有效期一小时的重置链接。邀请邮件按邀请人限量(smtp.invitation_limit_per_hour,默认 50)。邮件使用部署语言(i18n.default_locale)。auth.trusted_proxies 让登录限流能够看到代理背后的客户端地址。

  • 基于 SAML 2.0 的组织单点登录。 owner 可以在设置页中通过粘贴或上传身份提供方的元数据,把组织连接到该身份提供方。选项包括带默认角色的即时成员资格、基于断言属性的有序角色映射规则,以及对除 owner 以外所有成员的强制启用。组织启用 SSO 后,On-Premises 登录页会显示「Sign in with SSO」按钮。首次 SSO 登录按邮箱匹配已有账号,之后的登录按 IdP 的 NameID 匹配。在 Hybrid Cloud 上,只有属于该组织已验证域名的邮箱才会按邮箱匹配,其他人需要先关联账号。临时 NameID 和加密断言会被拒绝。

  • 开箱即有首位管理员。 没有任何用户的全新安装会创建组织 Default,并根据 bootstrap.admin_email 及其密码创建一个 owner,在首次登录时强制修改密码。Chart 默认把邮箱设为 admin@example.com,并把生成的密码写入一个 Secret。离线安装包在首次运行时写入并打印两者。升级的安装已经有用户,不受影响。

  • 管理员签发的登录链接(On-Premises)。 管理员可以签发一个一次性、有效期 72 小时的链接,让成员自行设置密码。这可以为创建时没有密码的成员开通登录,或重置密码。配置了 SMTP 时该链接会通过邮件发送。成员列表会报告每个成员的登录方式(sign_in_methods:password、sso 或无)。控制台结合组织的 SSO 状态来解读它们:「Can sign in (Password / SSO)」、「Signs in with SSO」、强制 SSO 下的「Password · SSO required」,或「Cannot sign in」。已停用的成员不显示登录状态或操作,也不能为其签发链接(400 INVALID_REQUEST)。在角色变更、移除,或 SCIM 停用或删除时,尚未使用的链接会失效,并且只有在持有者是活跃成员时才能兑换。

  • 为外部 PostgreSQL 提供私有 CA。 Chart 的 externalDatabase.sslRootCert.existingSecret(以及 .key,默认 ca.crt)会把一个 CA 挂载到 cp-api 和 dp-manager 中。它们在每个数据库连接上都使用该 CA,因此对由私有 CA 签发的托管数据库,externalDatabase.sslmode: verify-ca 或 verify-full 可以正常工作。不使用 Chart 时,请设置 database.ssl_root_cert(AISIX_CLOUD_DATABASE_SSL_ROOT_CERT / AISIX_DPMGR_DATABASE_SSL_ROOT_CERT)。提供 CA 之后,sslmode: require 也会验证它。使用内置数据库时该配置会被忽略。

  • 删除组织。 owner 可以在设置页中删除组织。它会立即消失,其数据在后台删除;在删除完成之前,其 slug 仍被占用。既不属于任何组织、也没有密码的账号会随之一并删除。On-Premises 部署中唯一的组织不能被删除。

  • 语义路由的 jev 分类器。 语义模型可以携带一个 classifier 配置块(type: jev、一个 typesafe 模型服务提供方凭证、model、min_confidence、timeout_ms、on_failure)。此时每条路由都需要一段描述,并且不接受样例或阈值。低于 min_confidence 的选择会交给默认模型。控制台提供决策后端选择器。只要环境中注册了早于 1.6.0 的网关,保存分类器路由就会返回 422 DP_INCOMPATIBLE。所有语义路由的访问日志行现在都携带 semantic_route、semantic_score 和 semantic_fallback。

  • 指标上的可读名称标签。 observability.metrics.labels 可以在每个携带 api_key_id 或 team_id 的指标族上选择 api_key_name 和 team_name,在部署计数器上选择 provider_key_name,在 aisix_ratelimit_rejections_total 上选择 policy_name。user_name 现在会跟随成员的重命名。上述新增位置默认都不开启,因此现有抓取不受影响。provider_key_name 和 user_name 本来就是 aisix_llm_* 和 aisix_proxy_* 请求计数器与耗时直方图上的默认标签。重命名 Key、团队或成员会让旧名称下的 Gauge 序列退休。

  • 用量事件中的请求头。 observability.usage_event.request_headers 列出每个用量事件都要记录到 request_headers 中的请求头,例如共享 Key 上的子用户或部门请求头。SLS、Datadog 和对象存储会携带该映射,OTLP 则为每个请求头携带一个 http.request.header.<name> 属性。凭证类请求头会在启动时被拒绝。这些取值不作他用。

  • 用量事件中由网关发起的向量化调用。 网关为语义路由、语义护栏和语义缓存未命中而发起的向量化调用,会以 gateway_embedding_calls 列在该请求的用量事件中,最多 64 个。事件会说明有多少个被丢弃,以及上游是否报告了用量。日志详情中会显示它们。该请求自身的模型、Token 数和成本不变。

  • 精确的美元价格。 模型价格以每百万 Token 的美元价格存储,最多保留 10 位小数,因此不足一美分的缓存单价也能保留下来。缓存、写入或推理单价为 null 表示「使用提示或补全单价」,0 表示免费。以整数美分表示的字段仍为较早的客户端保留。

  • 将多个 On-Premises 组织合并为一个。 参见升级说明。

改进​

  • 模型价格列表在服务端分页和搜索。 定价页面的各个分区独立分页,搜索覆盖所有页。最低成本路由徽标只获取它们需要的价格。
  • 没有 models.dev 时,在线安装会按内置的价格目录快照为请求计价,在其价格目录仍为空期间如此。
  • 网关失败日志会说明原因。 失败的远程护栏调用会记录 http_status、完整的 error 链、error_kind 和 elapsed_ms。custom 护栏的 aisix.embed、语义护栏、语义路由和语义缓存的向量化失败也会记录其原因。这些日志都不会复述上游响应的文本,因为其中可能引用提示词。
  • 序列类配置可以通过 AISIX_* 环境变量以逗号分隔的列表设置。 包括 observability.heap_profiling.auto_dump.thresholds、cache.redis.nodes、cache.redis.sentinels、ratelimit.redis.nodes 和 ratelimit.redis.sentinels。此前设置其中任何一项都会让网关在启动时停止。
  • 控制台。
    • 未知的环境 ID 在每个环境页面上都显示「Environment not found」。此前会显示另一个环境的数据,或一个看起来处于空闲状态的概览页。
    • 浏览器标签页标题带有环境名称。
    • 删除确认会点明资源及其所在环境。
    • 中文控制台中的错误信息已翻译。
    • 所有日期统一使用 YYYY-MM-DD 格式。
    • 审计记录以邮箱标识操作者。
    • 护栏作用范围显示为「Whole environment」。
    • 空闲的概览页显示「no traffic」,加载失败的卡片会如实说明,而不再显示零。
    • 入门教程跟随侧边栏所显示的环境。
    • 有节点注册后,数据面页面首先显示节点列表,并用一句话解释部分兼容。
    • 只要选中了其他任一权限,自定义角色表单就会保持选中 environments 读取权限。
    • 跳转链接可以直接跳到页面内容。
  • 大表会更频繁地执行 VACUUM,并且在已完成迁移的数据库上,cp-api 重启不再获取表锁。
  • cp-api 在其结构迁移完成后即开始提供服务。 大表上的索引构建在后台继续进行,进度写入日志,数据库的 statement_timeout 也不再中止它们。预算花费、保留期清理和用量清理会在它们所依赖的索引建好后恢复。迁移步骤对每个表锁最多等待 5 秒并重试,同时记录阻塞它的会话,而不再让该表上的所有流量排队等待。两个未使用的索引被删除,用量清理一次只在一个副本上运行。离线安装包的 run.sh 会等待较长的迁移完成,而不再报告启动失败,随后再启动 dp-manager。升级期间它会报告数据库迁移和 PostgreSQL 崩溃恢复的进度,而不再静默等待,并且只有在 cp-api 健康后才启动 dp-manager。
  • 用量表的 request_id 索引改为单列索引,比它所替代的复合索引小约 23%。它在升级后于后台构建,在此之前由旧索引提供查询。
  • 后台清理在批次之间暂停,暂停时长约等于每个批次所花的时间(10 毫秒到 5 秒),因此大量积压不再拖慢控制台。

修复​

  • reasoning_effort 在拒绝 effort 参数的 Claude 模型上可以正常工作。 Haiku 4.5、Sonnet 4.5 及更早的 Claude 模型此前会对 /v1/chat/completions 上的 reasoning_effort 和 /v1/responses 上的 reasoning.effort 应答 400。在这些模型上,网关现在改为发送扩展思考预算:minimal 和 low 为 1024 个 Token,medium 为 2048,high 为 4096,xhigh 为 8192,max 为 16384。不带 max_tokens 的请求会得到该预算再加 4096。调用方的 max_tokens 会被保留,并把预算限制在它之下;预算为 1024 或更低时思考保持关闭。这涵盖 Anthropic、Vertex AI 和 Bedrock,以及 /v1/messages 和 /v1/messages/count_tokens 上运维人员配置的推理档位映射。调用方自己的 thinking 或 output_config.effort 仍然优先。Opus 4.5、Claude 4.6 及更新版本以及非 Claude 模型名称不受影响,none 仍会关闭思考。3.7 之前的 Claude 模型仍然拒绝它。

  • 在只接受控制台会话的路由上使用管理员 Token 会得到 401 CONSOLE_SESSION_REQUIRED,而不再是看起来像 Token 已损坏的 INVALID_TOKEN。

  • 中文控制台会翻译角色。 成员、邀请和团队的角色徽标此前显示原始值 owner、admin 和 member;英文控制台现在会将其首字母大写。在角色页面上,内置角色名称、角色描述和权限描述此前以英文显示。自定义角色的名称和描述保持原样。

  • 被 SCIM 停用的成员在所有地方都失去访问权限。 此前他们仍可以重命名组织、修改其设置,并在组织列表中看到它。API Key 不能再绑定到已停用的成员,SCIM 禁用的 Key 在其所有者处于停用状态时也不能再被重新启用(400 INVALID_REQUEST)。已停用的成员不能再兑换邀请(403 MEMBER_DEACTIVATED)。

  • 网关无法向另一个环境的 API Key 预算计费,即便它上报了该 Key 的 ID。这类事件中的该 ID 会被清除,携带外部 Key 的历史记录不计入 API Key、团队、成员和按成员预算的花费。

  • Playground 只列出支持 Chat 的模型。

  • 工具在 Vertex AI Gemini 模型上可以正常工作。 发布方为 Gemini 的 vertex 模型此前会丢弃 tools 和 tool_choice,把工具结果作为用户文本发送,并丢失历史中助手的工具调用,因此工具请求得到的是一段文字回答。现在函数调用在 /v1/chat/completions、/v1/messages 和 /v1/responses 上双向可用,无论是否流式。

  • Claude 的工具调用能到达流式 OpenAI 协议客户端。 来自 Claude(经 Anthropic 或 Vertex AI)的流式回答此前以 finish_reason: tool_calls 结束,却不含任何工具调用。现在它会携带 delta.tool_calls。/v1/responses 流会发出 function_call 条目,发往 Vertex AI 上 Claude 的 /v1/messages 流会保留其 tool_use 块。

  • Google AI Studio 向量化模型应答 200。 针对 provider: google 模型的 /v1/embeddings 此前每次调用都返回 502 upstream_decode_error,因为 Gemini 会省略第一项的 index。

  • 来自 Gemini 的流式并行工具调用保持彼此独立。 Gemini 以及其他省略工具调用 index 的 OpenAI 兼容上游,此前在 /v1/chat/completions、/v1/messages 和 /v1/responses 上会把并行调用合并成一个。流式 chat-completions 增量现在总是携带 index。

  • 控制台会话失效时,任何页面都会把用户带到登录页。 过期、被吊销或已登出的会话此前会让 /select-org 停在加载错误上,其他页面则停在页内的 401 上;控制台现在会打开登录页,并在登录后回到原页面。

  • 离线安装包中的 ./run.sh stop 最多给 PostgreSQL 2 分钟时间完成干净关闭。 在大量写入之后,PostgreSQL 此前可能在 10 秒时被强制终止,下次启动会在其恢复期间失败。

  • /v1/realtime 和 files/batches 上的未知模型或禁止模型拒绝显示为 model "x" not found / API key is not allowed to use model "x",而不再把这句话包裹两次。转录、翻译和 files/batches 的拒绝会在用量事件中记录所请求的模型。

  • 向量化 Token 数缺失或不完整的响应会被保留,并标记为「usage unavailable」,而不再失败。

  • 自带查询参数的透传 target_url 能正确拼接。 运维人员的参数会被保留,调用方的参数追加在后,并且目标 URL 带有查询参数时 API 版本检测也能正常工作。

  • 透传响应以未解码的形式中继。 应用输出护栏时,网关会向上游请求 identity 编码。上游的非 2xx 响应会绕过输出护栏。

  • 透传路由上的流式输出护栏对每个来源通道分别判定。 它们现在会扫描拒绝回复和旧式的 function_call.arguments,并跳过媒体和推理内容。window 模式不再恰好在达到上限时触发。

  • 在每个配置了 concurrency 的接口上,Redis 并发租约会在长请求期间续期,因此存活时间超过租约 TTL 的请求不再放进额外的请求。

  • 类型化 /v1/responses 上的输出护栏也会扫描拒绝回复以及终止事件和聚合事件,PII 脱敏也覆盖它们。max_buffer_bytes 现在也会统计携带内容但没有增量的事件,因此没有增量的流现在也可能达到上限。

API 变化​

以下 Cloud Admin API 变化会破坏现有调用方。

  • POST /data_import 不再接受管理员 Token 或匿名调用,并且只能加载到全新安装的控制面上。 管理员 Token 现在会得到 401 CONSOLE_SESSION_REQUIRED。该调用需要 owner 已登录的控制台会话,实例中只要有引导组织和管理员以外的任何内容,就会应答 409 INSTANCE_NOT_FRESH。响应不再携带 owner_user_id,warnings 始终为空;证书颁发机构的处理结果请读取 ca。恢复自动化必须以控制台会话的身份针对全新安装运行。
  • API Key 的创建和更新会拒绝被 SCIM 停用的成员。 把 Key 绑定到这样的成员(user_id),或重新启用(disabled: false)所有者已停用的 Key,现在会应答 400 INVALID_REQUEST。此前两者都会成功。
  • 预算 state 不再跟随绑定关系的变化。 GET /budgets 和 GET /budgets/{budget_id} 报告的是到达时计入的花费。重新绑定 Key、把模型重新指向另一个模型服务提供方凭证,或删除 Key、成员、团队或环境,都不再降低或转移已计入的花费。依赖这些重新计算的自动化必须自行处理。
  • GET /model_pricing 和 PUT /model_pricing 响应中的 *_cents_per_1m 现在是精确价格的取整视图。 cache_read_cents_per_1m、cache_write_cents_per_1m 或 reasoning_cents_per_1m 中的 0 不再意味着「没有单独的单价」:它也可能是免费单价,或被向下取整的不足一美分的单价。请读取 *_usd_per_1m 字段,其中 null 表示没有单独的单价,0 表示免费。只写美分字段并写入 0 的 PUT 仍按此前的方式存储为「没有单独的单价」。
  • GET /roles 会省略部署未提供的资源上的权限,持有这些权限的自定义角色也不例外。On-Premises 上是 billing,Hybrid Cloud 上是 data_export。POST 和 PATCH /roles 仍接受这些权限,因此把自己写入的角色与 GET /roles 返回的结果进行比较的自动化会发现它们缺失。
  • 仅限 Hybrid Cloud:POST /members 应答 404。 请改用邀请或 SCIM。
  • 仅限 Hybrid Cloud:GET /data_export 应答 404。 组织导出仅在 On-Premises 上可用。

升级说明​

从早于 1.6.0 的版本升级时,均需遵循本节说明,包括跳过 1.6.0 升级到更新版本的情况。

  • 拥有多个组织的 On-Premises 控制面必须进行合并。 1.5.x 及更早版本允许任何人创建组织;On-Premises 现在只服务一个组织。完成合并之前,每个控制台会话都会被以 403 ORG_CONSOLIDATION_REQUIRED 拒绝,而登录、管理员 Token 和网关流量照常工作。任一组织的 owner 以密码登录后,从自己拥有的组织中选择一个保留。其他所有组织及其全部数据会被永久删除,其网关证书会被吊销,只属于这些组织的成员保留账号但不再拥有成员资格。如果需要这些数据,请先备份数据库。单组织安装不受影响。
  • On-Premises 注册改为仅限邀请,创建组织会被拒绝。 没有账号的人需要邀请,为被邀请人注册的、控制台以外的客户端必须以 invitationToken 发送邀请的 Token。
  • On-Premises 向私有地址发起的出向调用变为允许。 除非 outbound.* 设置为 false,Playground 上游、通知渠道、MCP 规范 URL 和护栏测试连接都可以访问私有和内部地址。从 Chart 1.5.0 执行 helm upgrade --reuse-values 会保留此前为 playgroundAllowPrivateIPs 和 notifyAllowPrivateURLs 显式设置的 false。如需继续拒绝,请将这些值设为 false。
  • 升级后每个控制台用户都需要重新登录一次。 secrets.betterAuthSecret 不再使用。请把额外的可信来源移到 api.trustedOrigins。
  • Chart 的 ui 组件已移除。 除 defaultLocale、ui.service 和 extraEnvVars 之外的 ui.* 取值会被忽略,包括 ui.extraVolumes。<release>-ui Service 保留并指向 cp-api,旧的控制台 URL 会以 302 重定向。通过 ui.extraVolumes 和 NODE_EXTRA_CA_CERTS 挂载到控制台上的私有数据库 CA 不再生效。请改为通过 externalDatabase.sslRootCert 把该 CA 提供给 cp-api 和 dp-manager。
  • Helm 4 会拒绝通过 extraEnvVars 覆盖由 Chart 管理的名称。 Chart 会在你的条目之前渲染它自己的条目,服务端应用(server-side apply)会拒绝重复项。请把这类设置移到 values.yaml 中。
  • 早于 audit.retention_days(默认 730)的审计日志会在 cp-api 启动后的首次运行中被删除。 如需保留更久,请在升级前把 audit.retention_days 调高,或设为 0。
  • 仍在为升级前已删除的环境提供服务的网关会失去该配置,时机为 dp-manager 首次启动时。
  • 升级后,每个预算都会按其周期内的用量重新计算一次。 在用量表较大时,这次一次性的重新初始化可能让预算的定时计算暂停数分钟。
  • 控制面滚动升级期间,仍运行 1.5.x 的副本可能返回错误,涉及组织设置和 SCIM 重命名。在这些副本上创建的团队、成员和环境没有名称文档,因此它们的指标名称标签会显示为 unknown 或 API Key 的内联名称,直到它们下次发生变更。在 1.6.0 新增列之后,它们还可能在每条池化连接上短暂应答一次 500(cached plan must not change result type)。两个版本同时运行期间,1.6.0 副本会记录预算聚合的序列化失败(could not serialize access … 40001 和 "budget spend is not advancing"),直到 1.5.x 副本全部下线。在此期间 1.5.x 副本会继续更新预算,之后的预算数字是正确的。1.6.0 完成后台索引构建后,会删除 1.5.x 预算聚合器所依赖的一个索引,因此在那之后仍在运行的 1.5.x 副本会让预算聚合变慢并加重数据库负载。请尽快完成滚动发布,不要让 1.5.x 副本与 1.6.0 同时运行。
  • 用量表较大时,cp-api 会在启动后于后台构建索引。 控制台立即可用。预算花费和用量清理会在构建结束后恢复,每 5000 万行用量大约需要 15 分钟。构建会增加数据库 IO,因此请把升级安排在业务低峰期。在开始下一次升级之前,请等待日志行 background index build: every index is in place 出现。
  • 复查基于请求指标族、针对流式流量构建的看板和告警。 成功率会下降,耗时分位数会上升到整条流的时长,一批长流出现时 rate() 会滞后。
  • 匹配 error_kind 或 error_class 取值的日志和事件管道必须接受行为变化中列出的新名称。输出侧和结束会话的护栏拒绝现在携带 error_class: content_filter,1.5.0 中该字段为空。在 200 响应头之后被拒绝的流式回答保留状态码 200,并携带 content_filter。
  • 复查那些匹配工具调用 ID 内部文本的护栏规则。 阿里云文本审核、阿里云 AI 护栏、Bedrock、Lakera、OpenAI moderation、Presidio、Azure Prompt Shield、Azure 文本审核、semantic 和 custom 护栏不再接收工具调用 ID,因此只会匹配到 ID 内部文本的规则将不再触发。函数名称和参数仍会发送。在 Chat Completions、Messages 和 Responses 上,keyword 和 pii 护栏此前就不读取工具调用 ID,不受影响。
  • 发往 Vertex AI Gemini 模型、此前能成功的工具请求,现在可能返回 400 invalid_request_error。 此前工具和工具历史会被扁平化为文本或被丢弃,请求返回 200。现在网关会拒绝旧式的 functions / function_call 字段、不是函数工具的工具、不支持的 tool_choice、不对应任何调用的工具结果,以及不是 JSON 的调用参数。Bedrock 同样拒绝 functions / function_call,此前它会丢弃它们。请把客户端迁移到 tools / tool_choice。来自 Vertex Gemini 模型的工具调用 ID 更长,必须原样回传。
  • 如需保留访问日志,请移除遗留的 observability.access_log: false。 此前它会被忽略,现在会关闭访问日志。
  • 0.12.0 到 1.3.x 的网关会把新增的 teams 和 users 配置类型报告为被拒绝,体现在 aisix_config_rejected_resources 中,并在升级之前一直把 aisix_config_last_reload_successful 保持为 0。配置加载不受影响。1.4.0 起的网关会把它们计入 aisix_config_unknown_kind_resources,不会让重新加载失败。
  • 透传路由:
    • 路径穿越片段,或与 target_url 自带查询参数中某个键冲突的调用方查询键,会在网关处被以 400 拒绝。这包括编码后的变体,以及编码后的 & 或 ;。
    • 上游的 3xx 响应会中继给调用方,而不再被跟随。凭证从不会被带到 Location。
    • 在事件流上,timeout_ms 现在约束等待第一个字节的时间,以及之后每一段没有字节的间隔。未设置时回退到部署的 upstream.stream_timeout_ms,再回退到 upstream.timeout_ms(默认 100 分钟);只有把两者都设为 0 才取消限制。1.5.0 在透传事件流收到响应头之后不应用任何超时。
    • 透传事件流会一直占用其并发名额,直到流结束或客户端取消。Key 或团队的 concurrency 现在能真正限制并发的透传流。
    • 除非设置了 output_fail_open,输出护栏会以 422 unscannable_body 失败即拦截。这适用于仍处于压缩状态的成功响应,以及它们无法评估的流或响应体:无法证明原始流的连续性、最后一帧未结束、JSON 嵌套过深或过宽,或未知的类型化缓冲结构。
    • 输入护栏只扫描可解析的原始 JSON 请求体中解码后的 JSON 字符串值,因此匹配 JSON 键或结构的 keyword 规则将不再匹配。格式错误的 JSON、超过 256 KiB 的字符串,或嵌套过深的请求体会失败即拦截,除非设置了 fail_open。

1.5.0​

发布日期: 2026 年 9 月 29 日

模型组现在适用于所有单次请求接口——Completions、Embeddings、重排、图像生成与编辑、音频和视频提交——并具备 Chat 已有的故障转移、重试、逐次尝试用量记录以及 least_latency / least_busy 负载均衡。OIDC 服务提供方可以用共享的 HMAC 密钥验证入站 JWT。Responses 到 Chat 的桥接现在会生成完整的 Response 对象、response.failed 事件以及重放的推理内容,这些正是 Codex CLI 等 Agent 客户端所期望的;/v1/chat/completions 也开始接受 developer 消息。控制面按上游报告的原样记录 Token 用量,包括上游自己给出的总数,并按该上游的计数方式为推理内容计价。流式输出护栏按生成内容计算缓冲区大小,在 /v1/messages 上扣住所有具备拦截能力的护栏链,并在 window 模式下遵循该配置行自己的缓冲设置。每个模型服务请求现在都会留下一条用量记录,响应头发出后才失败的流会以失败的状态码记录,而不再是 200。网关会发布内存指标并自行采集堆 profile,且在等待上游期间持有大请求体所占的内存减少约三分之一。

行为变化​

  • 响应头 200 发出后才失败的流,现在以失败的状态码记录。 流中途的上游错误、传输错误、解码错误或超时、上游的带内错误事件,以及 Responses 桥接的空流失败,会被记录为 502、504 或上游自己的 4xx(例如 Anthropic 带内的 rate_limit_error 记为 429),并填入 error_class 和 error_message。调用方中途离开时,在所有流式接口上都记为 499。此前这些记录都是 200,错误字段为空。日志页的状态列、控制台的成功率和延迟分位数(只统计 2xx)、访问日志以及 aisix_usage_events_emitted_total 的 status 标签都会随之变化。成本、预算和限流不受影响。/v1/audio/speech 现在在音频结束时写入用量事件,因此其延迟覆盖整个流。

  • 每个模型服务请求现在都会留下一条用量记录。 Cohere 重排(它上报的是搜索单元而非 Token 数)、模型服务提供方在 Completions、Embeddings、图像生成和视频提交上缺少对应能力时网关自己返回的 501,以及网关无法读回结果的 MCP 工具调用(502),此前都不会写入用量事件。现在它们会以零 Token 记录出现在日志中。轮询视频任务和下载视频内容仍是仅有的不写记录的调用。

  • 单次请求接口上每一次失败的上游尝试都有自己的用量记录。 在 Completions、Embeddings、重排、图像生成与编辑、三个音频接口、视频提交以及 /v1/messages/count_tokens 上,每一次失败的尝试——无论是故障转移还是对同一目标的重试——现在都会写入一条零 Token、不计费的记录,带上它的 attempt_kind 和错误,与 Chat 已有的行为一致。这同样适用于直连模型:重试预算重放了 5xx 的直连模型,现在每次尝试都会留下一条记录。所有尝试都失败时,最后一次尝试的记录就是该请求的最终记录。

  • 用量事件的 occurred_at 精确到毫秒(2026-09-24T12:42:25.123Z),控制面、SLS、Datadog 和对象存储都是如此。OTLP 把它作为 span 的结束时间携带,而不是字符串。只接受 …:SSZ 的解析器必须能接受小数秒。Admin API 和控制台仍然把 occurred_at 显示到秒。

  • 日志列表及其导出改为按 occurred_at、再按 ID 排序,而不再按插入顺序。环境中有多个网关时,较晚的请求不会再排在较早的请求之下。

  • 经 Vertex AI 记录的 Gemini 用量现在就是 Gemini 报告的用量。 这适用于经 Vertex AI 的思考型调用(无论是否流式),前提是 Gemini 报告的总数等于提示、补全和思考内容三者之和。此时用量记录中的 completion_tokens 不含思考内容,reasoning_tokens 为思考内容,并新增 total_tokens。没有这样的总数时,记录仍把思考内容计入 completion_tokens。SLS 和对象存储导出携带同样的原始取值,因此对导出数据的 completion_tokens 求和时,这些记录不再包含思考内容。成本、限流、预算、Prometheus Token 指标、访问日志、OTLP/Datadog 的 gen_ai.usage.output_tokens 以及客户端收到的用量均不变。

  • 推理内容按上游自己的计数方式计价。 当上游给出的总数表明推理内容是在补全之外单独计数的(prompt + completion + reasoning == total)时,全部 completion_tokens 按补全单价计费,全部 reasoning_tokens 按推理单价计费。其他所有记录,包括没有总数的记录,仍沿用此前的公式。对于在 completion_tokens 之外上报推理内容的 OpenAI 兼容上游,这会为此前公式漏计的补全 Token 计费。/v1/messages 和 /v1/completions 现在与 /v1/chat/completions 一样记录推理 Token,因此如果模型设置了单独的推理单价,这两个接口上的推理内容也会按该单价计费。

  • 推理 Token 超过补全 Token、或缓存命中的提示 Token 超过提示 Token 的用量记录,现在会被存储。 此前控制面会丢弃这类记录,同时把整个批次应答为已接受,于是该请求从日志中消失,也从未被计费。现在它会按上报的原样存储这些计数。

  • 流式输出护栏的 max_buffer_bytes 按生成内容计算。 流因输出护栏而被扣住期间,该上限在所有路由上统计助手文本、推理内容和工具调用参数,从不统计 SSE 封装。JSON 封装同样不计入,只有透传路由中继网关无法解析的请求体时例外,此时整个 data: 载荷都计入。纯文本的 Chat 流触发位置与此前完全相同。推理内容或工具调用参数较多的 Chat 流,现在会在合计内容达到上限(默认 256 KiB)时触发,此前推理内容不被计入。在原生 /v1/messages 和 /v1/responses、Responses 桥接以及透传路由上,此前统计的是线上字节,现在该上限会更晚触发。每个被扣住的流还有一个以原始字节计、等于 max_buffer_bytes 128 倍的上限,几乎不含内容的帧组成的流可能达到它;越过该上限同样是缓冲区超限事件,按 on_buffer_exceeded 处理。

  • 在具备拦截能力的输出护栏下,流式 /v1/messages 响应在扫描完成后才下发。 window 模式的输出护栏——Azure 和阿里云文本审核、custom 以及 aliyun_ai_guardrail——此前会让流式 /v1/messages 响应逐 Token 通过,因此拦截只能在内容已经发出后追加一条错误,custom 脚本看到的文本也是空的。现在响应会被扣住,扫描通过后整体放行,因此调用方收到第一个字节的时间会推迟。只监控的护栏链仍然实时流式输出。

  • 在整条流被扣住的场景下,window 模式护栏遵循自己的缓冲设置。 在 /v1/responses 上(原生和桥接均是),window 护栏链此前以固定的 256 KiB 上限扣住,并且总是失败即拦截;在 /v1/messages 上它此前根本不会被扣住,见上一条。现在这两个接口上被扣住的 window 护栏链都使用该配置行的 max_buffer_bytes 和 on_buffer_exceeded;有多个 window 配置行时取最小的上限,并且除非每一行都设置为失败放行,否则流会失败即拦截。含有任何 buffer_full 配置行的护栏链不受影响。在全部为 window 的护栏链下,/v1/chat/completions 上流式工具调用参数现在也受同一个合并后上限约束,此前扫描会在固定的 256 KiB 处停止。

  • /v1/messages 和 /v1/responses 现在遵循 on_buffer_exceeded: fail_open。 此前这两个接口不论该设置如何都会失败即拦截。现在已扣住的内容会不经扫描放行,与 Chat 一致,并且请求会记录 guardrail_bypassed_reason: output_buffer_exceeded。

  • keyword 和 pii 护栏对每个值分别判定。 在 /v1/chat/completions、/v1/completions、/v1/messages、/v1/messages/count_tokens、/v1/responses 和 MCP tools/call 上,此前它们对每个请求扫描一整段拼接后的文本,而脱敏却按值分别进行,因此拦截规则、监控模式下的 would_mask 和实际执行的脱敏可能给出不一致的结果。现在每条消息、每个内容块、每个工具调用参数、调用方发送的每个工具结果,以及 MCP tools/call 结果和 structuredContent 中的每个值都会被单独判定,工具载荷中的对象键和 JSON 数字也各自算作一个值。锚定整个值的规则(^…$)现在会触发拦截。只在跨越两个值时才能匹配的规则——跨两条消息、同一条 Chat 消息的两个文本块、键和它的值、工具名称和它的参数——将不再匹配。匹配对象键或数字的 keyword 或 pii 规则现在会触发拦截。请复查那些依赖跨值匹配的规则。透传路由仍把提取出的文本作为一整段扫描。在 /v1/responses 上,请求中重放的条目——mcp_call 的参数和输出、mcp_approval_response.reason 以及数组形式的 function_call_output.output——现在不仅会被扫描,还会被脱敏。在响应侧,只有 mcp_call 的 arguments 会被扫描和脱敏,托管工具的 output 不会。

  • 透传路由上的护栏读取的内容与类型化接口一致。 此前经透传路由中继的 Anthropic Messages 流不会被扫描,工具调用参数(双向)、系统提示词以及调用方发送的工具结果也不会被读取。现在这些都会被读取,因此此前未经扫描就通过的请求和响应现在可能被拦截。推理和思考内容与类型化接口一样不被扫描。

  • 无法改写内容的路由上的 pii 脱敏规则命中现在会被记录。 在透传路由、/a2a、任务类接口、/v1/realtime 和 /v1/videos 上,脱敏命中此前会静默放行。内容仍然原样通过,但该记录现在会带有一条执行命中,动作为新增的 mask_unsupported;监控模式下的命中则为 would_mask_unsupported,而不再是 would_mask。

  • 被扣留上限拒绝或放行的流现在会说明原因。 失败即拦截的触发现在会记录一条执行命中,动作为新增的 blocked_buffer_exceeded,并指明当时生效的是哪一行的上限。失败放行的触发现在会记录 guardrail_bypassed_reason: output_buffer_exceeded,并计入 aisix_guardrail_bypasses_total。

  • 按护栏拆分的阶段序列只统计护栏实际运行过的阶段。 此前仅作用于输入的护栏会在每个请求上记录一个接近零的 aisix_guardrail_latency_seconds{phase="output"} 样本,仅作用于输出的护栏则记录对应的输入样本。对于单阶段护栏,这些序列将不再出现。hook_point: both 的配置行不受影响。

  • 首 Token 时间指标新增 side 标签。 aisix_request_ttft_seconds 和 aisix_llm_time_to_first_token_seconds 原有的观测保留为 side="upstream",并新增 side="downstream":从网关收到请求到客户端收到第一个帧,包括输入护栏、重试和输出扣留。不按 side 过滤的查询现在会混合两者,其 _count 也会翻倍;加上 side!="downstream" 即可保持原有含义,滚动升级期间它也能匹配 1.4.0 网关的序列。side 总是会输出,且不会被 observability.metrics.labels 移除。

  • aisix_request_e2e_latency_seconds 也新增 side 标签,但默认含义相反。 它原有的观测,即客户端感受到的整个请求耗时,变为 side="downstream"。新增的 side="upstream" 表示产生该响应的那次尝试中上游所花的时间,与该尝试的 upstream_latency_ms 是同一个数值:每个请求最多一个,缓存命中、到达上游之前就失败的请求、/a2a 以及集成模型则没有。不按 side 过滤的查询现在会混合两者。加上 side!="upstream" 即可保持原有含义,它也能匹配 1.4.0 网关的序列;这与 TTFT 的过滤条件正好相反。side 总是会输出,且不会被 observability.metrics.labels 移除。

  • 阿里云配额限流和阿里云侧超时现在会被单独归类。 阿里云以 HTTP 200 加响应体中的 Code 588 / Code 581 报告这两种情况;两种阿里云护栏现在把它们报告为 aliyun_throttled 和 aliyun_timeout,而不再是 aliyun_5xx,体现在 guardrail_bypassed_reason 和 aisix_guardrail_bypasses_total{reason} 中。

  • 对象存储导出器在首次尝试即被存储服务明确拒绝时,会直接丢弃该批次。 当 S3、Google Cloud Storage 或 Azure Blob 以不可重试的 4xx 应答一次上传时,该批次会被立即丢弃,计入 aisix_otlp_fanout_drops_total{reason="permanent_error"},记录一次日志,并立即体现在导出器的健康状态中。401、403 和 404 此前就会被立即丢弃;其他 4xx 此前会在完整的 5 分钟预算内反复重试,其后的记录则不断排队,最终以 queue_full 被丢弃。408、429、5xx 以及 S3 的 RequestTimeout 和 OperationAborted 仍会重试。Datadog 导出器现在会重试 408,而不再丢弃。

  • 接收端持续失败的导出器,从第一次失败的尝试起就显示为失败。 此前,对正在限流、超时、返回 5xx 或不可达的接收端进行重试的导出器,会一直报告自己健康,直到某个批次在重试预算耗尽时被丢弃。现在每一次失败的尝试都会上报其最近的错误,因此控制台会立即显示它处于失败状态,并在下一次成功投递后恢复。失败批次数仍然只统计被丢弃的批次。既未投递也未丢弃过任何批次的导出器,现在显示为「no batches delivered yet」,而不再是「delivery healthy — 0 batches shipped」。

  • 流式护栏拒绝现在带有 error.code。 在 /v1/messages 和 count_tokens 上,护栏拒绝保留 error.type: invalid_request_error,并新增 error.code(策略拦截为 content_filter,失败即拦截的配置行为 guardrail_unavailable)。/v1/chat/completions 上的流式拒绝帧现在携带与缓冲模式下 422 相同的错误码。在中继 Anthropic 流的透传路由上,拒绝帧现在采用 Anthropic 的格式,因此其 error.type 从 content_filter 变为 invalid_request_error;请改为读取 error.code。

  • 所配置 URL 中的用户信息(user:pass@host)会被接受并按原样使用。 它既不会被校验,也不会被脱敏。控制面现在在模型服务提供方凭证的 api_base 和 apis.<name>.base,以及环境的 mcp_resource_url 上接受它,并按原样存储和返回。网关现在在 Azure OpenAI 和 Vertex AI 的 api_base、Azure AD 的 authority_host、OIDC 的 issuer 和 jwks_uri、MCP OAuth 的 resource_url(按配置原样发布在受保护资源元数据端点上),以及 managed.cp_base_url / managed.cp_etcd_endpoint 上接受它;此前这些位置都会拒绝它。回环地址的 http:// OTLP 和对象存储导出器端点也可以携带它:OTLP 会把它作为 Basic 认证发送,对象存储服务则会忽略它并自行签名请求。只要环境中注册的某个网关早于 1.5.0,这样的导出器端点就会被以 422 DP_INCOMPATIBLE 拒绝。日志、错误和调试输出会按原样显示所配置的 URL,包括其中的用户信息;凭证类查询参数仍会被脱敏。

  • 访问日志在响应体结束时写出。 它现在排在该请求的 provider call completed 日志之后。如果慢速客户端仍在读取非流式响应时关闭宽限期已经耗尽,该请求的日志会丢失,这与流式请求此前的情况相同。对于由网关代理的视频,GET /v1/videos/{id}/content 现在在转发结束时才结束 duration_ms。

  • 从日志页和审计页下载的文件使用查看者所在的时区。 控制台会请求浏览器所在的时区,因此在首尔下载的日志或审计导出文件,会显示 2026-09-12T13:03:01+09:00,而此前显示的是 2026-09-12T04:03:01Z。按 %Y-%m-%dT%H:%M:%SZ 解析这些文件的脚本需要改用能识别时区偏移的解析器。Admin API 用量事件导出的调用方如果不传新增的 timezone 参数,仍然得到 UTC。

  • 任何网关都无法加载的护栏配置现在会被以 400 拒绝。 pii / presidio 的 action、default_action、operator 或 language 为空字符串,pii 或 presidio 的 max_buffer_bytes 为 0,任一阿里云护栏的 max_buffer_bytes 为负数,以及 pii 自定义模式名称超过 64 个字符——此前这些配置可以保存,随后被每个网关丢弃,导致该护栏什么都不检查。pii 或 presidio 上的负数此前就会被拒绝,阿里云护栏上的 0 仍表示使用默认值。省略某个字段仍表示使用其默认值。

  • 新建的预算在其花费首次被计算之前显示「no spend data yet」,而不再是 $0.00 (0%)。这一状态在预算创建后,以及升级后到第一次聚合之前,持续一个聚合周期,约 5 秒。

  • 从控制台保存护栏时,会保留表单中未显示的配置。 此前控制台只发送表单渲染出来的字段,而 API 会整体替换 config,因此通过 API 设置的取值会在第一次从控制台保存时被重置为默认值。现在从控制台保存的 custom 或 Azure 文本审核的 window 模式配置行,以及任意模式下的任一阿里云护栏配置行,会显式写入 max_buffer_bytes 和 on_buffer_exceeded,阿里云的 window 配置行还会写入 window_size / window_overlap_size,除非有修改,否则都取网关的默认值。

  • MCP 护栏拒绝在日志中显示为「tool error」。 网关以带内方式报告该拒绝,即 HTTP 200 上一个 isError: true 的 JSON-RPC 结果;日志中的徽标和概览页的最近尝试卡片现在显示「tool error」,并把 HTTP 状态码移到记录详情中。存储和导出的 status_code 不变。

  • Playground 不再在未设置时发送 temperature,向 OpenAI 和 Azure OpenAI 推理模型发送 max_completion_tokens 而不是 max_tokens,并应用模型服务提供方凭证的 request.param_renames。

新功能​

  • 共享密钥(HMAC)JWT 验证。 OIDC 服务提供方可以携带 hmac_secret 来代替 JWKS。设置了它即选择 HMAC 验证:HS256、HS384 和 HS512 Token 会按原样以该密钥的 UTF-8 字节进行验证,不会发起任何获取请求,issuer 和 audiences 也变为可选。iss 与某个服务提供方的 issuer 匹配的 Token 只由该服务提供方验证;否则会按名称顺序依次尝试所有已启用且未设置 issuer 的共享密钥服务提供方。密钥至少为 32 字节,在 Admin API 中只写(读取时返回 hmac_secret_set),静态加密存储,并且从不出现在审计事件或数据导出中。JWKS 服务提供方不受影响。只要环境中有任何已注册网关早于 1.5.0,控制面就会以 422 DP_INCOMPATIBLE 拒绝保存携带密钥的服务提供方,因为更早的网关会改用 issuer 发布的密钥来验证该服务提供方。

  • 模型组适用于所有单次请求接口。 /v1/completions、/v1/embeddings、/v1/rerank、/v1/images/generations、/v1/images/edits、/v1/audio/transcriptions、/v1/audio/translations、/v1/audio/speech 和视频提交此前对模型组返回 400。现在它们会按与 Chat 相同的策略顺序、健康过滤、重试预算和故障转移遍历模型组的目标。用量记录归属于实际服务该请求的目标,部署和回退指标以及访问日志中的路由摘要都会被填写,least_latency 和 least_busy 模型组也会在这些接口上跨目标均衡负载。每个目标都必须支持其所在的接口。/v1/realtime 和任务类接口按设计仍拒绝模型组。

  • /v1/chat/completions 支持 developer 消息。 OpenAI 推理模型以及 Pi 等客户端会发送带有 role: "developer" 的请求,此前这类请求会被以 400 拒绝。现在对 OpenAI 原样保留;对不接受该角色的 OpenAI 兼容模型服务提供方,以 system 发送;在 Anthropic、Gemini 和 Bedrock 上映射到原生的指令位置。护栏把它们当作系统消息处理:input_messages: latest_turn 不包含它们,all 包含它们。

  • 用量记录保存上游报告的 total_tokens。 每条用量记录按原样保存上游报告的总数,未报告或报告为 0 时为 null。用量日志 API 以及 JSON 和 CSV 导出会返回它,日志详情中显示为「Total tokens (reported by upstream)」。usage_summary 会对它求和,没有该值的记录改用计算得出的总数。/usage 页面的合计现在累加每条记录自己的总数。

  • 区分策略拦截和失败即拦截。 用量记录新增 guardrail_blocked_fail_closed,当护栏因为无法评估内容(例如其服务提供方宕机,或流超出了缓冲区)而非策略命中而拒绝时为 true。护栏拦截标签页新增拦截类型过滤器,每一行显示 Policy / Fail-closed 徽标,列表和导出也接受同样的过滤条件。升级前记录的行读取为 false。

  • 按指定时区导出时间戳。 日志导出(GET /environments/{env_id}/usage_events/export)接受可选的 IANA timezone,并以该时区及其偏移显示所有时间戳。控制台下载的日志和审计文件使用查看者所在的时区。

  • Google Cloud Storage 导出器支持 endpoint:即上传所用的 Cloud Storage XML API 基础 URL,例如私有端点。上传使用 XML API,因此该端点必须提供 XML API。控制台的导出器表单现在为 GCS 和 Azure Blob 提供端点字段。只要环境中有任何已注册网关早于 1.5.0,控制面就会以 422 DP_INCOMPATIBLE 拒绝保存携带端点的 GCS 导出器,因为更早的网关会忽略它并上传到 Google 的公共主机。

  • 网关内存诊断。 Prometheus 监听器现在会发布内存分配器的字节统计(aisix_allocator_bytes)、cgroup 内存上限(aisix_memory_limit_bytes)、标准的 process_* 指标、按运行时的任务数 Gauge,以及进程内各存储的条目数和字节数 Gauge(aisix_component_entries、aisix_component_bytes)——其中包括排队中的用量事件和导出器批次、各类缓存、输出护栏扣留的内容以及处理中的请求体。堆采样默认开启。新增的监听器 observability.debug(默认 127.0.0.1:9091,默认开启)在 GET /debug/pprof/heap 上提供堆 profile。它默认监听回环地址;配置非回环地址也会被接受,但会输出一条告警。启用 observability.heap_profiling.auto_dump(默认开启,阈值为内存上限的 80% 和 90%,目录为 /var/lib/aisix/heap,每台主机保留 5 个文件)后,网关会在内存越过每个阈值时自行写出一份 profile,因此即使发生内存不足被杀,磁盘上也会留有一份。这两个配置块都在网关的配置文件中设置。分配器指标、堆采样和堆 profile 需要官方镜像所用的基于 GNU C 库的 Linux 构建,进程指标仅在 Linux 上发布。实测采样开销在多次运行间的正常波动范围内。

  • 访问日志记录消息体大小。 proxy request completed 日志新增 request_body_bytes,即从客户端读取的字节数,以及 response_body_bytes,即发送给客户端的字节数,包括 SSE 封装和保活帧。无法得到最终值时对应字段会被省略:请求体未读到结尾时(例如 Content-Length 检查返回的 413)省略 request_body_bytes,未写出响应头时省略 response_body_bytes;/v1/realtime 上两者都不出现。

  • 被拒绝的用量事件会被计数。 当控制面接受一个用量批次、但拒绝其中部分事件时,网关会输出一条告警日志,并把它们计入新增的 aisix_usage_events_rejected_total 计数器。此前这类事件会无声无息地消失。

  • 控制台提供更多护栏设置。 Lakera、Presidio(包括按实体设置的动作和分数阈值)、OpenAI Moderation(按类别的阈值)以及两种阿里云护栏,现在会展示网关读取的全部配置字段,window 模式的护栏也会显示其流缓冲设置。

  • 入门教程包含部署网关。 教程现在在创建环境与添加模型服务提供方凭证之间新增一步「Deploy your data plane」,在有网关完成注册后即算完成。

改进​

  • Responses 到 Chat 的桥接行为符合 Agent 客户端的预期。 它发出的每个 Response 都携带 Responses API 定义的完整字段集。中途失败的流会在已有的 error 事件之后以 response.failed 结束:护栏中止时为 invalid_prompt,上下文长度、配额、速率限制和过载则使用上游自己的错误码(context_length_exceeded、insufficient_quota、rate_limit_exceeded、server_is_overloaded 或 slow_down),因此 Codex CLI 不会再把这样的轮次当作连接中断而重试五次。首个事件就是失败的流会以 response.created 和 response.in_progress 开头,这是 OpenAI SDK 的要求。不含任何内容的上游流现在会以可重试的 upstream_error 失败,而不再以空输出完成;在结束之后才断开的连接会正常完成。重放的 reasoning 条目会以 reasoning_content 发送给上游,因此这类请求会发送更多输入 Token。助手消息及其后的工具调用会作为一条消息发送给上游,namespace 工具(Codex 的 multi_agent_v1)会以 <namespace>__<tool> 的形式提供给模型。

  • 发往 OpenAI 和 Azure OpenAI 推理模型的 max_tokens 会以 max_completion_tokens 发送,在 Chat、/v1/messages 桥接和 Responses 桥接上均是如此,因此这些请求不会再被上游以 400 拒绝。模型服务提供方凭证的 request.param_renames 仍具有最终决定权。

  • 透传路由会为重排和 DashScope 原生调用计量。 经透传路由中继的 Cohere 风格重排请求体或 DashScope 原生信封,其非流式 JSON 响应现在会记录上游的 Token 数和调用方的模型,此前记录的是零 Token 且没有模型。流式响应的计量方式不变,这些记录仍然不产生费用。

  • 自定义护栏脚本在 Chat、Responses 和 Messages 上可以读取 ctx.model。 在这些接口上,输入钩子的 ctx.model 此前始终为空,因此以模型为键的策略从不生效。现在它是调用方所指定的模型。

  • 所有上游事件流都由同一个符合规范的解析器读取。 以单独回车符分帧的流在所有路由上都能被正确分帧、重新打时间戳、扫描和计费,以字节顺序标记开头的流会保留其第一个事件,把一个 JSON-RPC 事件拆成多行 data: 的 A2A Agent 会被正常中继而不再中断流。模型服务提供方的流中单个帧未结束就增长超过 16 MiB 时,现在会失败,而不再无限增长。

  • 流式集成模型只报告一次用量,放在一个最终的用量块中,而不再在每个携带用量的评审帧上重复报告整个评审组的用量。仅当客户端请求了 stream_options.include_usage 时才会发送该块。

  • 删除或禁用导出器会停止其投递流水线,并将其从网关上报的导出器健康状态中移除。重新启用会启动一条全新的流水线。

  • routing target attempt failed 告警日志在所有日志级别下都携带 request_id,包括 log_level: warn。

  • 控制台更易阅读。 文字采用更易读的字号层级和更高的对比度,每个页面的页头都是一句话,细节收在折叠的「How it works」说明中。

  • 部分故障期间,/usage 页面会显示部分数据。 数据加载失败的环境会被标记为「Data unavailable」并在横幅中列出,其他环境仍正常显示。

  • 预算会报告其花费最近一次被计算的时间(state.aggregated_at),/budgets 页面上的数据新鲜度说明也以该时间为准。

  • 导出组织数据的速度不再随共享配置存储的规模变慢。 此前在大型部署上,即使是很小的组织,GET /data_export 也要花几分钟;导出内容不变。

  • 控制面会压缩其配置存储的历史。 dp-manager 每 5 分钟从控制面 PostgreSQL 数据库中的配置存储里删除已被取代的修订版本,以及比最新 1000 个修订版本更早的删除记录。在 1.4.0 中没有任何机制清理它们,因此该表只增不减。间隔和保留数量都是固定的。0.12.0 及以后的网关在 watch 读到已被压缩的历史时会重新读取配置。

  • 控制面只输出结构化 JSON 日志。 cp-api 和 dp-manager 此前会在 JSON 日志中混入带颜色的纯文本行。一次性的启动迁移和回填现在各写一行 JSON:成功的汇总为 INFO,数量作为字段;运维人员仍需修复的配置行,以及迁移重新使之生效的护栏,保持为 WARN。数据库错误是 error 级别的 JSON 记录,超过 200 毫秒的查询以 slow sql 记为 warn。「record not found」查询不再记录日志,API 已经应答的约束冲突以 debug 级别记录。panic 和第三方库的输出也都是 JSON 记录。

修复​

  • 修复了依赖先前配置的配置(例如护栏和紧接着创建的护栏挂载)偶尔以错误顺序到达网关、导致网关跳过该挂载的问题。
  • 修复了 Cohere 模型服务提供方凭证在以裸主机作为 api_base 时,Chat 和 Embeddings 请求发往错误 URL,以及在使用 /compatibility/v1 基础地址时重排请求发往错误 URL 的问题。
  • 修复了已存储裸主机地址的 Jina 模型服务提供方凭证在 Embeddings 上返回 404 的问题;一次性迁移会把它们改为带版本号的基础地址并重新发布。
  • 修复了响应体为空或错误消息为空白的上游错误以空的 error.message 返回给调用方的问题;现在会显示例如 upstream returned 404 Not Found。
  • 修复了在响应或流式块中省略 model 的 OpenAI 兼容上游以 upstream_decode_error 失败的问题。
  • 修复了用量记录缺少 applied_guardrails 的问题。/v1/completions、/v1/embeddings、/v1/rerank、图像、音频、视频、count_tokens、透传路由和任务类接口上的错误记录和护栏拒绝记录缺少该字段;/v1/responses、透传路由、/v1/realtime 和任务类接口上的成功记录也缺少该字段。
  • 修复了监控模式的输出护栏漏掉流式响应前 256 KiB 之后出现的匹配的问题。
  • 修复了 /v1/messages/count_tokens 在请求发生重试或故障转移时只记录成功那次尝试的问题。
  • 修复了启用网关磁盘快照缓存时,重启前刚删除的资源在重启后重新出现的问题。
  • 修复了共用同一张网关证书的多个副本互相覆盖被拒绝资源报告的问题;现在只有当每个拒绝该资源的副本都仍在使用先前的取值时,才会出现 stale_serving_since。
  • 修复了 Google Cloud Storage 导出器忽略 endpoint 的问题。
  • 修复了在由资源文件配置的网关中,两类未设置 api_base 的模型服务提供方凭证返回 400 的问题:anthropic 凭证在 /v1/messages 和 count_tokens 上失败;provider 为空的旧式 adapter: openai 凭证在自行构建上游 URL 的路由(音频、图像编辑、任务类接口、Realtime 和 /v1/responses)上失败。
  • 修复了输出 keyword 和 pii 护栏对流式原生 /v1/responses 回复中的原始推理文本进行脱敏或拦截的问题,这类回复来自 gpt-oss 等以 response.content_part.done 结束推理内容的上游。生成的推理内容不在输出护栏的范围内,这与非流式路径一直以来的行为一致。
  • 修复了创建、重命名或删除环境后,控制台的环境切换器在下一次导航前一直显示旧状态的问题。
  • 修复了中文控制台中护栏 endpoint 的帮助信息显示为英文的问题。
  • 修复了网关在等待上游应答期间持有请求体约三份拷贝(某些路由上更多)的问题,该问题可能在并发的大型 base64 图像请求下导致网关内存耗尽。现在请求在等待期间最多持有两份请求体,集成模型每多一个处理中的成员再加一份。
  • 修复了 content 为文本块数组的 Chat 消息中,redacted_entity_counts 把每个实体计数两次的问题。
  • 修复了网关在配置 watch 因压缩以外的原因被取消后静默停止应用配置变更、而 /status/config 仍报告已连接的问题。现在它会重新读取配置并重新开始 watch。经过一段健康期之后的重连也会重新从 1 秒的等待开始,而不再沿用先前失败累积下来的最长 60 秒的延迟。
  • 修复了经 Vertex AI Gemini 的流式 /v1/chat/completions 在第一个内容块上发送全零 usage 对象的问题;现在用量只出现在最后一个块上。
  • 修复了导出器投递错误在网关日志和控制台的导出器健康状态中暴露导出器上所配置密钥的问题:API Key、请求头凭证和对象存储密钥现在显示为 ***。接收端自己的错误文本其余部分保持不变。
  • 修复了所有网关都会丢弃的导出器端点仍可被保存的问题——大写的 scheme(例如 HTTPS://),以及紧跟在回环 http:// 主机之后的空端口、查询参数或片段;现在它们会被以 400 拒绝。

API 变化​

以下 Cloud Admin API 变化会破坏现有调用方。

  • 护栏的创建和更新会拒绝任何网关都无法加载的取值(POST / PATCH /environments/{env_id}/guardrails…):pii / presidio 上为空字符串的 action、default_action、operator 或 language,pii 或 presidio 上为 0 的 max_buffer_bytes,任一阿里云护栏上为负数的 max_buffer_bytes,以及超过 64 个字符的 pii 自定义模式名称,现在会应答 400。此前它们会被存储。
  • 导出器的创建和更新会拒绝两种 endpoint 写法,针对 otlp_http 和 object_store:大写 scheme(HTTPS://),以及紧跟在回环 http:// 主机之后的空端口、查询参数或片段。现在它们会应答 400。

升级说明​

从早于 1.5.0 的版本升级时,均需遵循本节说明,包括跳过 1.5.0 升级到更新版本的情况。

  • 控制面和网关都运行 1.5.0 后,报告的成本可能上升。 有三类流量的计费比 1.4.0 更完整。在 completion_tokens 之外单独计算推理内容的 OpenAI 兼容上游此前被少计费,因为 1.4.0 会从补全中减去推理部分;现在其补全 Token 会全额计费。推理 Token 超过补全 Token、或缓存命中的提示 Token 超过提示 Token 的请求,此前被 1.4.0 丢弃、从未计费;现在它们会被存储并计费。/v1/messages 和 /v1/completions 上的推理内容现在按模型的推理单价计费,与 /v1/chat/completions 此前的行为一致。在 Gemini 报告了总数的情况下,经 Vertex AI 的 Gemini 思考型记录的计数会变化——completion_tokens 不再包含思考内容,思考内容计入 reasoning_tokens,SLS 和对象存储导出中也是如此——但成本不变。
  • 在首 Token 时间的查询和告警中加上 side!="downstream"。 否则,针对 aisix_request_ttft_seconds 或 aisix_llm_time_to_first_token_seconds 的查询会把新增的网关侧观测混入上游观测,其 _count 也会翻倍。滚动升级期间,side!="downstream" 同样能匹配 1.4.0 网关。
  • 在端到端延迟的查询和告警中加上 side!="upstream"。 否则,针对 aisix_request_e2e_latency_seconds 的查询会把新增的上游观测混入客户端感受到的延迟。这与 TTFT 指标的过滤条件正好相反,它同样能在滚动升级期间匹配 1.4.0 网关。
  • 对于响应头发出后才失败的流式流量,成功率、延迟分位数和状态码分布会发生变化。 这些请求现在记为 502、504、上游的 4xx 或 499,而不再是 200,体现在日志、控制台的成功率和延迟分位数,以及 aisix_usage_events_emitted_total 的 status 标签中。
  • SLS、Datadog 或对象存储导出中 occurred_at 的解析器必须能接受小数秒。 只接受 …:SSZ 的解析器会拒绝新的取值。
  • 复查那些依赖跨两条消息、同一条 Chat 消息的两个文本块、键和值或工具名称和参数进行匹配的 keyword 和 pii 规则。 这类规则将不再匹配,而锚定整个值的规则,以及匹配工具载荷中对象键或数字的规则,现在会触发拦截。
  • 透传路由上的护栏现在可能拦截此前未经扫描就通过的流量,因为它们会读取工具调用、系统提示词、调用方发送的工具结果以及 Anthropic 流。
  • 推理内容或工具调用参数较多的流,会更早在 /v1/chat/completions 上触发 max_buffer_bytes,因为该上限现在会统计它们。如果这类流现在会触发 on_buffer_exceeded,请提高扣住它们的护栏的上限。
  • 根据 guardrail_enforced_hits[].action 或 guardrail_monitor_hits[].action 分支处理的消费方会看到新的取值:blocked_buffer_exceeded、mask_unsupported 和 would_mask_unsupported。
  • 读取经透传路由中继、来自 Anthropic 上游的流式护栏拒绝的客户端,应根据 error.code 而不是 error.type 进行分支处理。
  • 1.4.0 和 1.5.0 网关共用一个 Redis 响应缓存期间,1.4.0 网关会把 1.5.0 写入的部分条目视为未命中,直到这些条目过期。这些条目的用量中带有上游报告的总数,或被折叠进补全的 Gemini 思考内容。响应和计费不受影响。
  • 写在 Redis URL 中的密码(redis://user:pass@host)现在会出现在网关的 Redis 连接告警和降级告警中。 这些告警按原样显示所配置的 URL,而 1.4.0 只输出 host:port。任何所配置 URL 中的用户信息现在都会按原样出现在网关日志和错误中。对于单节点和集群 Redis,请把凭证移到单独的 username 和 password 字段;Sentinel 的认证信息仍然写在 sentinel URL 中。
  • 解析从控制台下载的日志或审计文件的脚本必须能接受数字形式的 UTC 偏移,例如 +09:00。省略 timezone 的 Admin API 用量事件导出调用方仍然收到 UTC。
  • dp-manager 首次在 1.5.0 上启动约 5 分钟后,会一次性压缩从未压缩过的配置存储的全部历史。 该过程运行期间,配置写入会变慢,变更到达网关也会更久。该过程中重启 dp-manager 会从中断处继续。之后的压缩规模很小。
  • 升级后,每个网关都会监听 127.0.0.1:9091、对堆分配进行采样,并在内存接近上限时把堆 profile 写入 /var/lib/aisix/heap。 无需修改任何配置。如需关闭,可以设置 observability.debug.enabled: false(释放该端口)或 observability.heap_profiling.auto_dump.enabled: false(不写 profile 文件)。端口已被占用时只会记录日志,不会阻止网关启动。在公开的 Helm Chart 中,/var/lib/aisix 是一个 emptyDir,因此这些 profile(每台主机最多 5 个)会占用节点的临时存储。

已知问题​

  • 在 google(AI Studio)模型服务提供方凭证上,思考型 Gemini 模型的思考 Token 会被少计。 网关对这类凭证调用 Gemini 的 OpenAI 兼容接口,该接口只在 total_tokens 中体现思考 Token。它们不会被计为推理内容,因此报告的成本、基于 Token 的限流和预算都会少计这部分。
  • 如果在一次压缩过程中 PostgreSQL 停顿数秒,dp-manager 会重启。 当某个压缩批次错过其 5 秒超时、随后又提交失败时(例如 PostgreSQL 故障切换或长时间的锁等待期间),dp-manager 会退出。它会重启,并从中断处继续压缩。

1.4.0​

发布日期: 2026 年 9 月 22 日

网关现在会重发控制面未能应答的用量批次,因此控制面故障只会延迟用量数据,而不再丢失它们。启动时连不上 Redis 的网关不再让监听端口一直关闭;etcd 的连接始终无法完成时,网关也不再卡在启动阶段——它会正常启动,有快照缓存就按快照缓存提供服务,并在后台持续重试。网关不认识的资源类型现在被视为向前兼容,而不再算作一次失败的重新加载。日志写出、配置下发、Prometheus 抓取和上游 DNS 解析都不再与请求处理争抢资源。控制台只生成最基础的网关部署模板,更高级的网关配置改为由文档说明。离线安装包现在会透传 CORS 允许列表,Origin 允许列表也接受浏览器实际发送的写法。

行为变化​

  • 启动时限流 Redis 不可用,不再导致网关无法启动。 此前,配置了 ratelimit.backend: redis 的网关在该 Redis 只接收或丢弃数据包而不应答时(容器停止、主机宕机、网络分区),完全不会绑定任何监听端口,几分钟后进程退出;在此期间它不响应任何请求,/livez 和 /metrics 也不例外。现在网关会绑定监听端口并开始服务,按副本计数,并输出一条 WARN 日志,点明后端、Redis 的主机和端口,以及本次连接所花掉的预算;日志永远不会输出所配置的 URL,因为其中带有密码。该降级状态每 5 分钟重述一次。后台任务会在 Redis 恢复应答后立即接入共享后端。这是临时降级,网关不会永久切换到 memory 后端;降级期间不执行集群级限流。

  • 启动时缓存 Redis 不可用,同样不再导致网关无法启动。 网关会绑定监听端口,并在 Redis 恢复应答之前把每条 backend: redis 缓存策略都当作未命中处理,告警、5 分钟重述和后台接入的机制完全相同。是否支持向量检索只在服务端真正应答探测时才判定,因此不会有任何东西被贸然启用:探测尚未通过时,语义策略只记录一次日志并退化为仅精确匹配,期间每个请求既不触发向量化调用,也不产生 Redis 往返。原本希望缓存 Redis 不可达时启动失败的运维人员,将不再得到该行为。

  • etcd.dial_timeout_ms 现在默认为 5000 毫秒,此前该连接过程完全没有上限。 只有设置了 etcd.user 的部署受影响,因为没有凭据时该连接不产生任何 I/O。该取值约束单次连接尝试,整次连接按每个已配置端点各获得一份,即 dial_timeout_ms × max(1, 端点数)。超时到期会被报告为 etcd 不可达,并走既有路径:输出警告、绑定监听端口、按快照缓存提供服务、后台重试。该快照缓存是在连接之后才读取的,因此无上限的连接过程也让这个专为控制面故障而存在的机制一直没被用上。写 dial_timeout_ms: 0 可保持此前无上限的行为。request_timeout_ms 未作改动,仍然默认无上限。

  • Redis 缓存故障期间,每次中断只报告一次,而不再每个请求报告一次。 cache lookup failed、cache write failed、cache backfill write failed 及其两个语义缓存对应项,会把一次中断中的首次失败记为 WARN,其余记为 DEBUG,并在下一次成功后重新置位,因此后续再次中断仍会被报告。aisix_redis_failures_total{operation} 未作改动,仍然统计每一次失败的操作。

  • Redis 明确应答并拒绝连接配置的情况,现在与「连不上」区分开,并且不再导致启动失败。 凭据被拒绝、服务端返回 NOAUTH 或 DENIED、服务端没有所配置的 database,此前一律按「连不上」上报,于是告警把一台毫秒级就已应答的服务端归咎于网络。现在这类失败以自己的名义走降级路径:启动告警带 reason=refused 和驱动返回的错误,每 5 分钟的重述也带同一个词,因此一个过滤条件就能同时找到两者;真正连不上时仍然是 reason=unreachable。网关随后以降级方式提供服务——限流器按副本计数,缓存一律未命中——并持续尝试重新接入。因此在 Redis 一侧修好凭据后,网关无需重启即可采用它。错误信息的具体程度取决于驱动:被拒绝的 database 会带上服务端自己的原文,而被拒绝的凭据只会得到一条固定的认证失败信息。

  • 仍会导致启动失败的,是网关在任何网络交互之前就拒绝的配置。 驱动无法解析的 Redis url 和无法读取的 TLS 材料,对限流器和缓存都是如此;该配置块自身的校验同样如此:所选模式缺少 url、nodes、sentinels 或 master_name,以及 timeout_secs: 0。这样配置写错时仍会在启动阶段立即暴露。

  • 共享 Redis 的 username、password 和 database 字段现在在所有模式下都生效。 作为默认模式的 single 此前会解析这三个字段、然后直接丢弃:通过 password 提供的凭据从未进入握手,因此网关在启动时记录 connected,之后在整个进程生命周期内每一次 Redis 操作都失败。这些显式字段现在还会覆盖内嵌在 url 中的凭据——否则通过环境变量注入的取值会被 URL 里遗留的旧凭据压过,失去意义。凭据按「一对」处理,设置其中任意一半都会同时替换两半。database 在 single 和 sentinel 模式下生效;Redis Cluster 只有 DB 0。两处同时配置了凭据时,启动阶段会有一条 WARN 日志点明这一情况。

  • 无法识别的资源类型不再被读作一次失败的重新加载。 网关读到 kind 不在其构建版本认识范围内的文档时,现在上报 aisix_config_last_reload_successful 1 和 state: "synced",此前上报的是 0 和 "degraded"。该配置行在 GET /status/config 上从 rejected[] 移到新增的 unknown_kinds[],指标上从 aisix_config_rejected_resources 移到新增的 aisix_config_unknown_kind_resources{kind};两组序列互不重叠。真正的拒绝——类型错误、缺少必填字段、未知枚举取值、没有任何 oneOf 匹配——仍会翻转该 Gauge,并由保留的最后一次失败记录点名。未知类型的配置行还有自己独立的保留额度,因此大量此类配置行不会再把真正被拒绝的记录挤出 /status/config 和心跳。不需要修改任何配置。此前把 aisix_config_rejected_resources 跨所有 kind 求和、用来表示「有东西加载不了」的告警,现在不再包含未知资源类型。

  • 部署网关页面上的 Metric labels 编辑器已移除。 控制台现在只生成最基础的网关部署模板:mTLS 证书包、AISIX_CONFIG_PATH、dp-manager 端点和代理端口。observability.metrics.labels 仍然是受支持的网关启动配置项,只是改为按文档配置,而不再通过控制台表单配置。该面板没有任何服务端状态,因此已按此前生成的片段运行的网关不受影响。

  • 发送失败的用量批次现在会被重发,而不是丢弃。 面向 1.4.0 控制面时,网关会以相同的批次 ID 原样重发同一批次,直到该批次被接受,或直到批次中最早的事件已超过 30 分钟。连续 8 次收到响应的失败之后,网关也会放弃。因此控制面故障只会延迟用量数据,而不再丢失它们,用量可能在控制台上晚几分钟出现。后续批次的投递会排在正在重发的批次之后。aisix_usage_event_drops_total 新增两个 reason 取值:send_failed(未经重发即放弃)和 retry_budget_exhausted。面向不声明批次去重能力的控制面时行为不变,该批次仍按此前的方式被丢弃。

  • 日志消费方卡住时,代价是丢日志行,而不是网关整体卡住。 日志事件进入一个容量为 32768 的有界队列,由专用线程消费。容器运行时停止读取网关的 stderr 时——一次日志轮转就足以造成这种情况——新的事件会被丢弃并计入 aisix_log_lines_dropped_total,待写出端恢复后输出一条汇总 WARN。此前请求工作线程会阻塞在 write 上,整个网关随之卡住,/livez 也不例外。队列未写满时不会有任何丢失。

  • 遥测导出器可以扛过更长的中断,并遵循 Retry-After。 暂时失败的导出器会把一个批次保留最多 5 分钟,退避区间从 200 毫秒增长到 30 秒上限;此前它在约 3 秒内尝试 4 次后即放弃。这覆盖 OTLP、Datadog、SLS 和对象存储。429 或 503 响应上的 Retry-After 两种写法都会被遵循,上限同为 30 秒。每个 Sink 背后的队列容量从 1024 提升到 8192。队列写满时会丢弃最新的一条记录并计为 queue_full,此前这类记录会在更上游以 retries_exhausted 丢失。全量采集的导出器持有自己的记录,因此长时间中断会占用更多内存。永久性错误仍然在第一次尝试后即丢弃。

  • 中断期间不再有请求为探测 Redis 是否恢复付出代价。 Redis 熔断器打开后,30 秒窗口到期时改由后台探测任务验证恢复情况,而不再让下一个业务请求充当探测者。响应缓存和共享限流计数器共用这个熔断器。恢复速度不变,只是不再由调用方买单。由于 PING 的说服力不如此前探测所用的真实命令,一台能应答 PING、但该子系统自身的操作仍然超时的服务端会让熔断器关闭;此时熔断器后面的命令会各付一次超时预算,直到第一次失败重新打开它。

  • GET /metrics 改为分块响应。 指标文本按 256 KiB 分块流式输出,不再在内存中整体构造;文本内容本身不变,分块边界总是落在完整的序列之间。在高基数场景下,一次抓取带来的内存峰值从数百 MB 降到几 MB。这带来两个后果:渲染在第一个分块之后失败时,响应体会以一个错误结束,而不是返回 500,因此被截断的抓取不会被当作完整数据摄入;读取方停止读取却不关闭连接时,它会在有限等待后失去自己这次抓取,而不再阻塞之后的每一次抓取。两次重叠的抓取不再共用同一次渲染,第二次会等待一次渲染并得到属于自己的当前指标文本。

  • 上游主机名现在通过一个短生命周期的共享缓存解析。 请求路径上的每个出向客户端都经由同一个进程级缓存解析:对同一名称的并发查询会合并为一次,成功结果复用 30 秒,失败结果复用 1 秒,缓存最多保存 1024 个名称。因此上游地址发生变化时,网关最多会在 30 秒内仍然连向旧地址。Bedrock 和 /v1/realtime 的连接自建传输层,不在覆盖范围内。模型服务提供方凭证的 resolve_addresses 固定地址仍然在其之上生效,且从不经过该缓存。

  • 无法读取吊销列表时,控制面返回 503 而不是 401。 网关调用的每个 /dp 路由现在都区分两种情况:吊销列表读取失败返回 503 MTLS_UNAVAILABLE,网关会重试;证书本身不被接受返回 401。涉及的路由包括心跳、证书轮换、额度检查和用量上报。两种情况都不会放行。此前,最常见的这类控制面瞬时故障会以最终拒绝的形式到达网关。

  • Origin 允许列表现在接受浏览器实际发送的写法。 AISIX_CLOUD_CORS_ALLOWED_ORIGINS 和 AISIX_TRUSTED_ORIGINS 现在接受十六进制形式的 IPv4 映射地址(例如 https://[::ffff:c0a8:1]),这正是 Origin 头携带的形式。Helm Chart 现在接受显式写出零段的规范地址(例如 https://[1::1:0]),而不再拒绝安装。Chart 还会在渲染阶段拒绝那些此前能渲染通过、随后导致 cp-api 反复崩溃重启的非法 IPv6 条目,并拒绝带有多个前导分隔符的通配符后缀——后者 cp-api 一直都是拒绝的。cp-api 此前接受的条目,现在没有任何一项会被拒绝。

新功能​

  • 用量上报按批次幂等。 网关为每个用量批次生成一个 ID,通过 X-Aisix-Usage-Batch-Id 发送;dp-manager 在插入这些记录的同一个事务中登记该 ID,因此已提交的批次会得到与首次投递完全相同的响应,并且不会重复写入任何内容。每个 /dp/telemetry 响应都携带 X-Aisix-Usage-Batch-Dedup: 1,网关据此判断重发是安全的;该能力逐响应判定、从不缓存,因此 dp-manager 副本版本混杂和回滚都是安全的。控制面永远无法存储的批次会返回 422,网关立即丢弃而不重发。登记记录至少保留 24 小时,并由既有的清理守护任务回收。

  • 离线安装包可以配置 CORS。 打包的 docker-compose.yaml 现在会透传 AISIX_CLOUD_CORS_ALLOWED_ORIGINS,.env.example 中以注释形式提供该项,README 中也在 AISIX_TRUSTED_ORIGINS 旁作了说明。此前,控制台与 cp-api 不同源的部署只能手工修改 compose 文件,而下一次解包又会覆盖它。源码树中的 compose 环境也获得了同样的配置项,外加通知、MCP 规范的开关和 CA 引导覆盖项。

  • 新增网关指标。 新增 aisix_config_unknown_kind_resources{kind}、aisix_config_apply_duration_seconds{trigger}、aisix_config_apply_batch_events{trigger} 和 aisix_log_lines_dropped_total。trigger 标签取 watch 表示一批合并后的 watch 事件,取 full 表示一次全量同步。四者都已登记到指标标签目录中,因此 observability.metrics.labels 可以对它们做选择,trigger 是新增的标签变量。

改进​

  • 后台计算不再与请求处理争抢资源:配置下发、Prometheus 指标渲染和快照回收都运行在降低了优先级的线程上,而请求工作线程、/livez 与 /readyz 监听器以及日志写出线程保持原有优先级。
  • 配置摘要改为在被读取时计算,而不是每次下发都计算。在约 70000 个资源的配置上,一次下发的 CPU 开销从 0.165 核秒降到 0.0275 核秒,摘要逐字节一致,apply_seq 和 applied_at 也保持文档所述的规则。
  • 按调用方的额度判定缓存改为常数时间淘汰,而不再在每次未命中时扫描全部 10000 个条目。
  • 代理与用量发送器之间的队列容量从 1024 提升到 16384,可以吸收此前会以 sink_full 丢弃事件的数秒级控制面停顿。定时刷新现在会从就绪队列补齐,而不再在仍有积压时发送一个偏小的批次。
  • 环境级额度汇总改由新增的部分覆盖索引应答,不再扫描其他环境的计费用量。该索引在启动时于既有的迁移锁下并发创建,中断的创建过程会被修复。
  • 用量上报解析一个批次的定价时改为两次查询,而不是每个模型一次、每次未命中再加一次:一个包含 100 个模型、其中 50 个未命中的批次,现在只需两次读取,此前需要 150 次。
  • 公开的 aisix-cp Chart 的配置项表格现在覆盖全部 117 个配置项,包括安装时必须提供的那 4 个。PostgreSQL 密码仍为占位值时的渲染期提示改为 openssl rand -hex 24,因为 base64 字符(+、/、=)会破坏内嵌该密码的 postgres:// DSN。

修复​

  • 大量网关同时申请证书时,cp-api 不再耗尽连接池。POST /api/environments/{env_id}/gateway_certificates 此前会在持有一条池化连接的同时再取最多三条,因此 16 个网关副本的一次滚动发布就可能把连接池卡住,直到调用方放弃。现在证书、其凭据身份和审计记录会一起提交或一起回滚,因此回滚掉的签发不会再留下一条调用方从未拿到私钥的、仍然有效的 mTLS 凭据。
  • DELETE /api/environments/{env_id} 现在会原子地吊销证书并删除环境。此前中途失败可能导致证书已被吊销、而环境仍然存在,从而把一整批网关踢出一个仍在正常工作的环境。
  • 读取已注册网关列表时发生的瞬时数据库故障,不再让一次资源保存变成 500 且什么都没存下。网关列表读不出来时不再对任何操作设限,与 1.3.0 之前一致;网关列表可以读出时,兼容性闸门自身的判定(422 DP_INCOMPATIBLE)没有变化。
  • 在 dp-manager 从未运行过的控制面上,GET /api/data_export 现在返回 409 DATA_EXPORT_UNAVAILABLE 并点名需要启动 dp-manager,而不再返回带有原始 SQL 错误的 500。
  • 数据导出和导入的审计记录,现在对失败的以及下载中途被放弃的尝试也会写入,记录中的 outcome 取 completed、failed 或 client_disconnected;导出还会记录在响应写出端统计的 bytes_delivered。此前,取走了组织部分数据后消失的客户端不会留下任何记录。
  • dp-manager 不再因为一个长生命周期的 watch 而无限停留在 gRPC 优雅关闭状态;排空过程被限制在既有的 5 秒关闭预算内,启动失败时也会取消并回收它已创建的工作任务。
  • cp-api 和 dp-manager 不再以 Gin 的 debug 模式运行:每次启动 187 行、逐条点名内部处理函数的路由清单,已从生产日志中消失。GIN_MODE=debug 仍然可以打开该清单。
  • 控制台不再在启动时对从未配置过的 Google 和 GitHub OAuth 提供方输出告警;只配置了 client id 的提供方也不再以空 secret 注册。
  • 在额度聚合任务执行期间删除额度,不再产生来自聚合任务或告警通知器的告警日志。
  • 用量事件的四个有长度上限的字段中出现超长取值时,现在在上报时被截断,并按批次输出一条告警,而不再让整个批次失败、连带影响其中所有其他计费记录。这四个字段是 cache_status、inbound_protocol、operation 和 guardrail_bypassed_reason。

API 变化​

以下 Cloud Admin API 变化会破坏现有调用方。

  • 在 dp-manager 从未启动过的控制面上,GET /data_export 应答 409 DATA_EXPORT_UNAVAILABLE,此前应答 500 EXPORT_FAILED。

升级说明​

从早于 1.4.0 的版本升级至本版本或后续版本时,均需遵循本节说明,包括跳过 1.4.0 的升级。

  • 在环境内所有网关都升级到 1.4.0 之前,不要把新增的指标族写进 observability.metrics.labels。 网关在启动时会拒绝该配置中无法识别的指标族,因此一段写有 aisix_config_unknown_kind_resources、aisix_config_apply_duration_seconds、aisix_config_apply_batch_events 或 aisix_log_lines_dropped_total 的配置,会让 1.3.0 的网关无法启动。
  • 基于 aisix_config_rejected_resources 的告警现在不再包含未知资源类型。 如需保留此前「有东西加载不了」的更宽口径,请把 aisix_config_unknown_kind_resources 一并纳入。
  • 升级后 cp-api 首次启动会在 dpmgr_usage_events 上创建第二个部分索引,在既有的迁移锁下并发创建。用量表较大时,启动会一次性多做一些工作,此后还会持续付出该索引的存储和写入维护开销。
  • 带凭据的 etcd,如果其连接过程本来就需要超过 5 秒,现在必须显式设置 etcd.dial_timeout_ms。 该字段现在默认为 5000 毫秒,此前该过程没有上限;写 0 可恢复原有行为。没有配置 etcd.user 的部署不受影响,因为其连接过程不产生任何 I/O。
  • 升级前请移除或修正遗留的 redis.password(或 redis.username)字段。 在 1.4.0 之前,single 模式下这两个字段完全不生效,因此在可用的 URL 凭据旁遗留了旧取值的部署,升级后会改用字段中的取值。此时共享后端会以 reason=refused 降级,而此前该字段是被忽略的。
  • 指向需要认证、但未配置任何凭据的 Redis 时,启动阶段会出现该 WARN 日志,这是预期结果。 这类部署本来就每一次 Redis 操作都失败。现在它会在启动时报告 reason=refused 并以降级方式提供服务,而不再是先记录 connected、再逐请求失败。
  • 用量重发需要控制面和网关都是 1.4.0。 1.4.0 的网关面向更早版本的控制面时,发送失败的批次仍按此前的方式丢弃;没有任何配置项可以开启或关闭该能力。

1.3.0​

发布日期: 2026 年 9 月 18 日

模型、MCP Server 和定价现在按资源 ID 被引用,而不再依赖它们当前使用的名称,因此重命名其中任何一个都不会再改写所有指向它的文档。结构化输出现在在 Anthropic、Gemini 和 Bedrock 上游上均可用;Responses 到 Chat 的桥接会按调用方的请求和预期返回推理内容、图片、工具参数和用量。调用方中途放弃的请求现在会记入用量日志;流式请求改为在流结束时写一条访问日志,而不是在流开始时写。网关和控制面镜像除 linux/amd64 外还发布 linux/arm64,控制面 Helm Chart 允许 OpenShift 自行分配 UID。模型服务提供方凭证可以为通过私有链路访问的端点指定固定地址;一个网关可以提供多个各带独立 TLS 的代理监听器;一个组织的全部配置可以导出为单个文件并加载到另一套部署上。

行为变化​

  • 调用方中途放弃的请求现在会记录一条用量数据。 此前,客户端在响应头写出前断开连接时,只会留下一条访问日志,用量日志中没有任何记录,所有计量端点均如此。现在这类请求会记录一条终态事件:状态码 499、error_class = "client_disconnected"、Token 数为零、费用为零;此外,此前已失败的每次尝试各记录一条事件。正在进行中的那次尝试会被记录下来,因此 499 记录可以说明请求当时已选定哪个目标。流式响应在传输过程中被放弃,或在首字节之前被断开,都会以各自的消息记录同样的数据。/mcp、/a2a、透传命名空间、/v1/realtime 的升级前阶段,以及文件、批处理和微调相关接口,会记录一条模型字段为空、并带有各自归属信息的数据。上传被放弃时同样会记录一条。

    这些记录此前并不存在,因此环境的请求数会上升、成功率会下降——控制面的这两项指标都由用量事件推导得出。延迟分位数不受影响,它们本来就只统计成功的记录。花费也不受影响:这些记录的费用为零。

  • 网关的磁盘配置缓存现在改为显式开启。 新增的 managed.snapshot_cache_enabled 在托管模式和自建 etcd 模式下均默认为 false;仅配置 snapshot_cache_path 不再启用持久化:只配置路径时,网关完全不会写快照文件。关闭时,网关会跳过缓存读取、编码、全量状态拷贝和后台写入。内存中保留最后一份可用配置并继续服务的行为不变。不启用缓存时重启会发生什么,参见升级说明。

  • 流式请求改为在流结束时写访问日志。 此前有六类接口在响应头生成时就立刻写日志,往往提前数分钟:被放弃的流会写一条 200 的访问日志,同时另有一条 499 的用量事件;正常完成的流所写的日志既没有 Token 计数,也没有模型服务提供方的响应 ID。现在该日志与请求的终态用量事件一同写出,因此两者在状态码、错误类别和错误消息上必然一致;流式请求的日志也会包含 Token 计数、provider_request_id、upstream_model 和 provider_key_id。三种结束方式下,每个请求都只写一条日志。

  • 每条访问日志新增 duration_ms,表示请求从到达网关到最后一个字节发出所占用的时间。latency_ms 含义不变,仍表示调用方的等待时间,流式请求为首 Token 时间;因此两者在流式请求上相差整个流的时长,在非流式请求上相等。日志还新增 upstream_model 和 provider_key_id,表示实际选中的目标,而 model 表示调用方请求的入口。

  • 缓存命中现在会上报缓存信息,并且不会再上报未实际分发到的目标。 日志新增 cache_status,命中时还会带 cache_hit_layer。路由型或语义型模型组命中缓存时,provider、provider_key_id 和 upstream_model——以及由它们构造的 Prometheus 标签——现在会上报 unknown 或不上报,而不再上报策略恰好排在首位的那个候选。因此,按模型服务提供方统计请求的面板不会再把模型组的缓存命中计到并未提供服务的提供方上,而按凭证标签过滤日志页时这些记录会被排除。直连模型的缓存命中行为不变;命中时的用量事件现在会在 provider_model_version 中记录生成被缓存内容的模型。缓存命中的费用本来就为零。

  • 上游未返回用量时,非流式 /v1/chat/completions 现在会返回网关自己的估算值,而不是零。 用量记录中本来就保存了该估算值,因此调用方无法把读到的数据与控制台的计费对上。按计数项处理:上游返回的计数保持原值,为零的计数用估算值填充,与被填充的零并列的总数会重新计算。缓存命中同样这样返回。计费结果不变;流式 /v1/chat/completions 仍然转发上游自己的用量帧。

  • 协议转换后没有工具留存时,tool_choice 会被丢弃。 OpenAI 兼容上游和 Anthropic 上游都会拒绝只有 tool_choice 而没有 tools 的请求,因此提交空工具列表的调用方——Agent 类 CLI 在上下文压缩调用时就是这个形状——会收到上游返回的 400。现在三个转换器都只在转换后的工具列表非空时才带上 tool_choice,包括强制调用工具的取值,并按普通的无工具请求处理。直接向 OpenAI 形状上游的 /v1/chat/completions 提交这一组合的调用方,仍按原样转发。

  • /v1/responses 上的输入护栏现在会读取重放的工具调用的名称和参数。 该 API 把模型轮次表示为不带 role 的类型化条目,因此此前扫描会把 Agent 的整个工具循环当作用户文本,并完全丢弃 function_call 条目——在 /v1/chat/completions 上会命中的拦截规则(该接口一直会扫描同样的重放调用),只要把内容移入这个接口的工具调用就可以绕过。如果拦截规则的匹配模式会出现在重放的工具调用参数中,运维人员会看到此前放行的请求开始被拒绝。这是在补上该缺口,不是回归。

  • 两类护栏不再扫描 /v1/responses 上重放的工具结果。 semantic 和 azure_content_safety_text_moderation 在默认 text_source 下只读取 user 角色的消息。此前 function_call_output 被错误地标记为 user 消息,因此它们恰好会扫描到;现在它被正确地识别为工具结果,因此不再扫描——这与 role: "tool" 消息一直不在它们于 /v1/chat/completions 上的读取范围内是一致的。这是两个接口行为对齐,但对配置未变的既有规则来说是覆盖范围的缩小:把 text_source 设为读取全部消息的取值即可继续扫描工具结果。

  • URL 改写规则现在也会在按 Host 匹配的透传分发之前执行。 改写是所有路由族在入口阶段的操作,因此不带 hosts 列表的既有规则,现在也会改写按 Host 分发的请求。为规则添加 hosts 可以把作用范围收回。

  • Bedrock、对象存储遥测导出器和 Realtime 连接现在遵循所配置的 upstream 连接参数。 Bedrock 和对象存储的连接池现在按 upstream.pool_idle_timeout_secs(默认 30 秒)回收空闲连接,而不再固定为 90 秒;这正是在会提前回收空闲连接的负载均衡器后面,调低该参数能够生效的原因。护栏访问 Bedrock 时使用 upstream.connect_timeout_ms(默认 5 秒),而不再使用 SDK 内置的 3.1 秒;/v1/realtime 的升级请求卡住时,也会在该预算内失败,而不再等待内核的 SYN 重试耗尽。Realtime 会话无法建立上游连接时,现在还会向请求指标贡献一个 status="502" 的样本,此前这种情况只出现在日志中、不计入任何指标。

  • 出向请求会带上构建版本号。 此前无论运行哪个版本,上游请求都携带 aisix/0.1;现在默认 User-Agent 为 aisix/<build version>,与 aisix --version 和 Server 响应头取自同一来源。基于旧字符串配置的上游允许列表需要更新。

  • 无法识别的 AISIX_* 环境变量不再导致启动失败。 此前加载器会把所有此类变量都当作配置覆盖项,而根配置会拒绝未知字段,因此命名空间中只要有一个名为 aisix-* 的 Kubernetes Service,就会让同命名空间内所有网关 Pod 反复崩溃重启。现在只有首段能对应到顶层配置项的变量才会被保留,其余会被丢弃,并输出一条点名该变量的 WARN 日志。真实配置段下拼错的键名仍然会像此前一样导致启动失败。直接运行二进制时,AISIX_CONFIG 现在可以生效。

  • 不带 scheme 的控制面地址会被接受,格式错误的地址会导致启动失败。 managed.cp_base_url 在加载时会统一归一化,因此 dpm.example.com:7944 会被读作 https://dpm.example.com:7944。此前这样的取值可以连上 etcd,但随后会以 429 budget_exceeded 拒绝所有被代理的请求,而控制台仍显示网关健康。managed.cp_etcd_endpoint 保持相反的约定,现在会剥离 scheme 从而容忍带 scheme 的取值,此前这种取值会拼成无法连接的地址。两种形状都不符合的取值现在会导致启动失败,并点名对应的变量。控制面对自己的同类配置(AISIX_CLOUD_DPMGR_BASE_URL、AISIX_DPMGR_BASE_URL)应用完全相同的规则,因此不带 scheme 的取值现在会带着 scheme 出现在控制台的安装指令和 dp-manager 的服务端证书中。

  • 删除被限流策略指定为作用对象的模型会被拒绝,返回 409 MODEL_IN_USE。 此前删除会成功,并在 PostgreSQL 和 etcd 中都留下一条悬空的策略,按一个解析不到任何资源的 ID 统计请求。请先删除或改指该策略。仅携带 model 或 model_name 条件的条件型策略不构成阻塞——该条件只是不再匹配。

  • 缓存策略的 model: 作用域现在可以在重命名后保持有效,但删除后不再恢复。 该选择器按所选模型的资源 ID 生效。删除该模型后,策略将永久不再覆盖任何请求:之后创建的同名模型是另一个资源。在重新保存之前,策略仍会列出且处于启用状态,但不匹配任何请求;重新保存会按当前使用该名称的资源重新解析选择器。

  • MCP Server 重命名现在会带上环境的匿名访问上限配置。 此前该上限会保留旧名称、不再匹配,从而在没有任何提示的情况下关闭匿名访问。删除 MCP Server 现在也会改写并重新投影引用它的配置行;运维人员观察到的结果是没有变化——引用仍然可见且不生效——但这些配置行会在删除时被写入,而此前删除完全不会触及它们。

  • 控制面 Helm Chart 不再固定 UID。 三个组件的 podSecurityContext 中都移除了 runAsUser、runAsGroup 和 fsGroup;runAsNonRoot: true 和 RuntimeDefault seccomp 配置保留。在会自行分配 UID 的集群上(例如 OpenShift 的 restricted-v2 SCC),Pod 以该命名空间分配的 UID 运行;在其他环境中以镜像自带用户运行,该 UID 与 Chart 此前固定的值相同。镜像的 USER 也因此改为数字形式(cp-api 和 dp-manager 为 10001,控制台为 1001,网关为 10001):Chart 不再提供 runAsUser 后,kubelet 无法确认以名称指定的用户是否为 root,会拒绝启动这类容器。

  • PUT /model_pricing 更新时现在会写入所有费率列。 此前更新路径漏掉了 duration_cents_per_1m_seconds,因此从第二次保存起,按音频时长计价的模型会一直保留第一次写入的费率,而控制台显示的是修改后的值,遥测链路则按已存储的值计费。该端点的审计事件存在同样的问题:修改四项费率中的任意一项,记录下的 before 和 after 都逐字节相同。

  • 删除包含环境内部相互引用的环境现在可以成功。 此前,只要路由型模型组的目标、Ensemble 的评审模型、语义路由的模型、缓存策略的向量化模型或透传路由的匿名 API Key 位于待删除的环境内,DELETE /api/environments/{id} 就会返回 500 并报出外键错误,该环境只能手工逐项解除引用后才能删除。

  • 由 Go 列表渲染出的 CHECK 约束在该列表变化后会重建自身,升级后的数据库和新建数据库都是如此。此前,升级后的数据库可能保留一条会拒绝合法 kind=custom 护栏的约束,表现为 500。同一套判定的另一面:运维人员手工删除的约束不会再被下次启动重新加回。

  • AISIX_TRUSTED_ORIGINS 的取值现在按 cp-api 对自身允许列表所用的 Origin 语法校验。 无法匹配浏览器 Origin 头的取值——*、通配符形式、大写的 scheme 或主机名、结尾的点或斜杠、显式写出的默认端口——会被丢弃并在服务端日志中记录错误,而不再被信任,来自该来源的登录会被拒绝。部署自身的 Origin 及其 loopback 形式仍然受信任。

新功能​

  • Anthropic、Gemini 和 Bedrock 上游支持结构化输出。 此前,/v1/chat/completions 调用方要求返回 JSON 时(以及 /v1/responses 调用方通过 text.format 要求时),这三类上游都会返回普通文本,因为它们的协议都没有顶层的 response_format。现在每类上游都会收到其自身 API 定义的形状:Claude 4.5 及更新版本使用 output_config.format,Gemini 使用 generationConfig.responseJsonSchema(2.x 及更新版本)或 responseSchema(1.x,并做旧方言的转换),Bedrock 在 Messages 路径使用 output_config.format、在 Converse 路径使用 outputConfig.textFormat。其余情况——较早的 Claude 系列、Anthropic 兼容的第三方、支持工具调用的 Converse 厂商——会把 Schema 挂在一个合成的强制工具上,并把回复转换回普通的 JSON 内容。Schema 会被收窄到各提供方文档所支持的关键字子集,每个被移除的约束都会折叠进对应属性的描述中,并以 additionalProperties: false 封闭,而 required 完全保留调用方的原始写法。调用方自己的工具和显式指定的 tool_choice 始终优先于合成工具。工具路径的上游请求以非流式发出,再以伪流式返回结果,因此这类请求会付出本来不会有的首字节延迟。

  • Responses 到 Chat 的桥接达到与原生路径一致的能力。 该桥接用于服务模型没有原生 Responses 端点的 /v1/responses 调用方。现在它会把模型的推理内容作为 reasoning 输出条目返回,并带上对应的流式事件序列;转发 input_image、input_file 和 input_audio 部分而不再丢弃;把 text.format 转换为 response_format;转发 parallel_tool_calls;转换 custom(自由形式)工具,使模型能够调用它;把各种 tool_choice 形式归一化为与提供方无关的形状;并把 function_call_output 序列化为 JSON,而不再向模型发送空字符串。经桥接的自由形式工具调用会作为携带自由形式 input 的 custom_tool_call 条目返回,并通过其专用的事件对流式输出;重放这类调用时也会正确回传上游,因此多轮对话可以正常工作。经桥接的调用方读到的用量现在与实际记录的用量一致。在 Anthropic 转换器上,parallel_tool_calls: false 会被改写为 tool_choice.disable_parallel_tool_use,而不再被平铺到一个会拒绝未知字段的请求体上。

  • 护栏可以只读取最新一轮对话。 所有护栏类型新增 input_messages 配置项(all,默认值;或 latest_turn)。IDE 和 Agent 客户端每次调用都会重放整段对话,因此一条命中过某条消息的规则会在该会话的后续请求中持续拒绝,即使新的提示词本身没有问题。latest_turn 只读取最后一条 assistant 消息之后的消息(不含 system 消息)——即本轮的 user 消息和回应它们的工具结果——因此结尾处的 assistant 预填内容仍属于当前轮次。该配置只作用于输入钩子;hook_point: output 与 latest_turn 同时配置会被拒绝,而不是被接受后忽略。在 latest_turn 下,脱敏类护栏会完整保留调用方发送的对话历史。控制台的护栏表单提供“输入扫描范围”选择器,并在列表中显示对应标记。

  • 重命名不再破坏指向模型、MCP Server 或定价的引用。 控制面投影的每一处引用,现在都会在一直携带的展示名称之外带上被引用资源的 ID,网关在每个请求中都按 ID 到实时的资源表中解析。覆盖范围包括:调用方 API Key 的模型允许列表,路由型模型组的目标,Ensemble 的候选模型和评审模型,语义路由的向量化模型、默认模型、各条路由和失败兜底目标,缓存策略的作用域及其相似度向量化模型,语义护栏的向量化模型,MCP 工具的授权与拒绝项,按 MCP Server 的限流策略,以及环境的 MCP 匿名访问上限。重命名资源会在下一个请求生效,不需要修改引用它的文档,也不会在配置中产生改写扇出。运维人员已有的配置都不需要调整;名称仍然写在 ID 旁边,因此早于本版本的网关仍按原有方式读取这些引用。

  • 定价改为独立的配置文档。 模型的按 Token 价格现在取自共享的定价文档——依次为环境自身的覆盖项、部署级的目录、模型自带的 cost 字段——而不再内联保存价格。调整价格现在只需写入定价本身,而不必改写所有按该价格计费的模型;向量化模型也第一次带上了网关可以解析的价格。该目录发布在一个新的部署级 etcd 前缀下,网关可读但不可写。

  • 模型服务提供方凭证可以为其端点指定固定地址。 通过私有链路访问的上游往往没有 DNS 记录,而其后的厂商仍然会对不携带自身主机名的请求返回 404——并且 Host 不是可转发的请求头。模型服务提供方凭证新增可选字段 resolve_addresses,接受一组有序的 IPv4 或 IPv6 字面量地址,并在连接凭证 api_base 所指主机名时使用这些地址。只有连接目标发生变化:Host 请求头、HTTP/2 的 :authority、TLS 的服务器名称和证书校验都仍使用该主机名,scheme 和端口仍取自 base URL。地址按书写顺序依次尝试,与解析器返回的结果一样,因此当私有链路在每个可用区各终结于一个地址时,其中一个不可用仍然可达。该字段的作用范围是 api_base 的主机,因此从同一主机提供第二种协议的 apis 条目也被覆盖,而指向其他主机的条目按正常方式解析。省略该字段即按此前方式通过 DNS 解析,null 会清除已有配置。所有通过该凭证分发请求的接口都遵循该字段;Bedrock 和 /v1/realtime 不遵循,因为它们自行构建传输层,同样也不遵循该凭证的 tls 配置。网关通过正向代理访问上游时该字段无效,因为主机名会交给代理、由代理自行解析。控制台在端点 URL 旁提供“端点地址”字段。

  • 直连模型的 effort_mapping 支持保留键。 此前该映射只回答一个问题——“调用方要求 X,就发送 Y”——对运维人员实际遇到的两种情况没有表达方式。现在空字符串键匹配完全没有设置推理档位的请求(字段缺失、为 null 或为空),并为其补上一个档位;* 键匹配其他所有没有独立条目的已有取值;而 null 值表示从出向请求中移除该档位,从而使用提供方自己的默认值。在 Anthropic 的 messages 和 Token 计数端点上只读取 output_config.effort:对本映射而言 thinking 块不算推理档位设置,因此只发送 thinking 而不设置推理档位的客户端会命中空字符串条目。通过 thinking.type: disabled 关闭推理的请求永远不会被赋予档位。控制台把规则两侧都渲染为选择器,因为保留键和移除操作都无法手工键入。

  • 可自定义 Webhook 请求体、请求头,并记录响应内容。 此前 Webhook 通知渠道只能发送一种固定的载荷形状和一个固定的请求头,因此期望其他格式的接收方根本无法接入;投递被拒绝时也只记录 webhook returned 400。现在渠道可以配置可选的 Go text/template 请求体(可使用告警事件变量、单行的 message 变量和 json 函数,保存时即渲染并校验),以及最多 16 个额外请求头,其取值与渠道 URL 一样是只写的。投递失败时会记录目标返回的状态码和响应体,并从其中脱敏掉渠道自身的 URL 和请求头取值;列表中保留前 8192 字节,新增的单条投递查询端点返回完整内容。测试按钮会展示实际发送的请求体和收到的响应。

  • 组织数据的导出与导入。 GET /api/data_export 会把一个组织拥有的全部数据——环境、模型、凭证、各类策略、团队、成员、网关读取的投影配置,以及一段时间窗口内的审计记录——以单个 gzip 压缩的 SQL 文件流式导出;POST /api/data_import 则在一个事务内把它应用到另一套同版本控制面的部署上。默认行为是备份:凭证仍以该部署自身的主密钥加密保存,未脱敏的文件还会额外携带证书颁发机构,从而使恢复后仍保留原有网关,该模式需要 owner 角色。redact=true 则生成支持包:所有凭证被替换为已知的合成值,所有账号使用一个公开的固定口令登录,因此不应接触真实密钥的人员也可以复现该配置。恢复到已经签发过证书的部署时,会保留该部署自身的颁发机构并在响应中说明。控制台提供导出卡片。

  • URL 改写规则可以按入站 Host 限定作用范围。 新增可选的 hosts 列表,把规则限定到指定的主机——大小写不敏感的精确名称,或单段通配符,端口忽略。Host 和路径都必须匹配,且只应用第一条匹配的规则。

  • /mcp 访问日志会说明请求内容。 所有 MCP 操作都通过同一个 POST 传输,因此握手、工具调用和被 ACL 清空的 tools/list 此前在日志中完全一样。现在日志会带上 mcp_method,tools/call 时带 mcp_tool,tools/list 时带 tools_total 和 tools_returned。上游返回了工具但 tools/list 结果为空时,会输出一条 WARN,点明是两种配置错误中的哪一种。

  • MCP 匿名访问允许列表,以及所有 API Key 和策略,都可以按资源 ID 指定 MCP Server,这正是上面的重命名保持有效在网关侧得以成立的原因。

  • 控制面提供可选的 Prometheus 指标,使用独立的监听地址,未设置 AISIX_CLOUD_METRICS_LISTEN 时不启用(Helm Chart 中为 api.metrics.enabled,同时会渲染指标 Service 和可选的 ServiceMonitor)。这些指标以 aisix_cp_ 为前缀,上报写入量和配置扇出的基数,因此一套 Prometheus 可以同时覆盖两个平面。

  • 多个代理监听器,各带独立的 TLS。 此前 proxy.addr 加 proxy.tls 描述的是唯一的那个监听器,因此配置证书会让这个唯一端口变成仅 HTTPS,而同时还需要明文 HTTP 的部署没有任何办法实现。新增的 proxy.listeners 配置块接受代理监听器的完整集合,每一项包含一个地址和各自可选的 TLS,因此一个网关可以同时提供 HTTPS 和明文 HTTP。所有监听器共用一个路由表和一份应用状态,TLS 与 ALPN 协商按监听器各自进行,每个监听器都像此前唯一的那个监听器一样参与优雅关闭和连接排空。listeners 缺失或为空时,proxy.addr 和 proxy.tls 仍是单监听器的简写形式且行为不变;listeners 已设置时,proxy.addr 不会被绑定,网关会输出一条 INFO 日志说明这一点,而 proxy.tls 与非空的 listeners 并存属于配置错误,而不是一个不作用于任何监听器的证书。重复的地址会在启动时被拒绝,并点名两个条目,因为否则 SO_REUSEPORT 会让两个条目共同绑定同一端口,在部分连接上按 TLS 应答、在其他连接上按明文应答。仅使用环境变量的部署可以通过 AISIX_PROXY__LISTENERS 以单个 JSON 数组配置整个集合。aisix Chart 1.3.0 提供对应的 listeners 配置项,每个端口一项,各自带有独立的容器端口、Service 端口、可选的 NodePort 和可选的 TLS Secret。

  • 网关和控制面镜像发布 linux/arm64。 流水线发布的每个 tag——dev、sha-*、发布候选版本和正式版本——现在都是同时包含 linux/amd64 和 linux/arm64 的 manifest list,网关和 aisix-cp-api、aisix-cp-dpm、aisix-cp-ui 都是如此。每个架构都在其自身的 runner 上原生构建并做冒烟测试,两个架构都就绪后才发布 tag。离线安装包按架构分别构建并在文件名中体现(aisix-self-hosted-offline-<version>-linux-{amd64,arm64}.tar.gz);run.sh 会拒绝为其他架构构建的安装包,而不是加载无法执行的镜像。不带架构后缀的文件名仍然提供 amd64 安装包。

  • cp-api 可以为部署在其他 Origin 上的控制台提供服务。 AISIX_CLOUD_CORS_ALLOWED_ORIGINS(Helm Chart 中为 api.corsAllowedOrigins)列出允许跨源调用 /api/* 的浏览器 Origin。默认为空,此时完全不写 CORS 响应头,这也是私有化部署的控制面所需要的行为:它从同一个 Origin 提供 API 和控制台,因此不存在跨源请求。配置后,它允许跨源调用 /api/*,包括 /api/auth/* 下的 Better Auth 路由,并按具体取值而不是 * 回显 Origin;控制台代理不在范围内。Chart 会在渲染时校验取值,cp-api 也会在启动时再次校验。此版本的 Docker Compose 软件包不会将 .env 中的环境变量传递给 cp-api;需要跨源访问时,请使用 Helm chart。Chart 与镜像对浏览器规范化的 IPv4 映射 IPv6 Origin 存在差异,因此请使用 DNS 主机名或 IPv4 地址,而不要使用这种形式。

  • 控制台的 Deployment 可以挂载私有数据库 CA。 ui.extraVolumes 和 ui.extraVolumeMounts 接受 ConfigMap 或 Secret,并通过 ui.extraEnvVars 把 NODE_EXTRA_CA_CERTS 指向它,因此基于数据库的认证可以信任私有 PostgreSQL 证书链。

改进​

  • 批量修改配置不再与请求处理路径争抢资源。 watch 事件现在按时间窗口合并,而不再按恰好积压的数量合并,窗口大小会根据上一次应用的开销自适应调整;配置应用移出异步 I/O 工作线程,因此无关的连接不再排在它后面等待;配置摘要从检查点续算,而不再重新哈希所有配置行;资源索引在多个快照之间共享字符串;被替换的配置由一个共享的后台线程回收,而不再由恰好持有最后一个引用的请求线程同步回收。在 7 万行配置的场景下,仅最后一项就把请求线程的析构开销从 7 到 8 ms 的 p99 降到 1 微秒以内。1507 行的突发写入现在只需 12 次全量配置遍历,此前为 131 次。

    代价是单次孤立的配置写入会延后一个静默周期才可见:以本地 etcd 实测,从写入到 applied_revision 变化的中位耗时从 21 ms 变为 42 ms。这不需要调整任何配置,被服务的配置内容也没有任何变化。

  • 高基数指标抓取的开销大幅降低。 指标记录器改为按序列存储并使用无锁样本缓冲,按指标类型缓存转义后的标签和排序后的序列目录,按上一次渲染结果预分配输出缓冲,并在阻塞型工作线程上渲染,重叠的抓取共享同一次渲染。在 53260 条序列、723 MB 输出的场景下,预热后的渲染 CPU 耗时从约 6.8 秒降到 0.57 秒,空闲维护开销从 1.11 秒降到 0.011 秒。指标名称、类型、默认标签、直方图分桶边界和滚动分位数均保持不变。标签取值中包含原始反斜杠、引号或换行符时,现在会被正确转义,不会再把不同的序列混为一条。

  • 限流判定和 JWT 认证不再扫描无关的配置行。 限流策略候选项按其所需条件建立索引,JWT 与 API Key 的绑定按 API Key 表的 generation 建立索引,两者都由其所读取的表触发失效,而不再由任何配置写入触发。

  • 控制面 outbox 的投递速度提升。 事务改为在进程内直达内嵌的 Kine,而不再经过其自身的 gRPC 监听地址;最多四个互不相关的键可以并发投递,同一个键的顺序仍然保持;水位线读取不再列出整个资源范围;较大的 etcd Range 和 Watch 响应在编码时不再使用临时缓冲;遥测刷写改为每条语句最多持久化 100 个事件,此前为 1 个(内嵌的 Kine 同时升级到 v0.16.3,修正了资源类型名称中包含下划线时的前缀读取)。预算检查不再扫描零费用的用量记录,为此在启动迁移之后并发创建了一个新增的部分索引;配置写入时的网关兼容性查询改为复用同一个事务,而不再从可能已经耗尽的连接池中再取一条连接。

  • 控制台采用 API7 Console 的颜色 Token。 所有背景、文字、边框、状态和操作的颜色都改为 Console 的取值,卡片边缘改用阴影表现。仅涉及视觉:字体、间距、控件尺寸和布局均未改变。

修复​

  • 被反复剔除的路由目标可能导致请求工作线程长时间阻塞。 60 秒日志限流窗口过期后的第一次剔除会在持有读锁的同时获取同一分片的写锁,因此请求既不会走到上游超时,故障期间被阻塞的工作线程还会不断累积。

  • 有效密钥正在拉取时,并发的 JWT 请求可能失败。 此前刷新间隔在结果产生之前就被记录,因此缓存为空时的调用方会被拒绝,而使用刚轮换密钥的请求可能错过已在进行的刷新。现在按 JWKS URL 或 issuer 合并拉取请求,并在刷新期间或上游故障期间继续使用已过期的信任材料。

  • 修复了一个连接池死锁,它可能在并发访问下使环境的模型列表和成员列表卡住。

  • 网关可能在关闭时挂住。 此前,未配置 etcd 请求超时时,一直得不到响应的初始配置读取或 watch 创建不会被关闭信号取消。

  • GET /api/config/public 和控制台的安装指令会带上 scheme。 参见行为变化中关于控制面地址的说明;此前从控制台复制的不带 scheme 的取值,会产生一个拒绝所有被代理请求的网关。

  • 网关可以读取共享的定价目录。 etcd 授权拦截器此前把每张网关证书的作用范围限定在其所属环境的前缀内,因此新增的部署级前缀会返回 PermissionDenied——网关可以容忍,但每次启动都会告警。现在 /aisix/global/ 下的读取被授权,写入仍不被授权,网关也仍然无法访问其他环境的键空间。

  • 语义路由可能被投影成错误的向量化失败兜底目标。 通过 API 无法触发,API 会从三个方面拒绝这种形状;现在投影会拒绝该文档并说明原因,而不再填入恰好位于该位置的模型。

  • 控制台的脱敏开关不再在角色信息加载期间显示为选中状态,此前这会让没有动过该开关的 owner 静默下载到未脱敏的备份。快速切换页面时,上一个页面的迟到响应也不会再覆盖当前 URL 所对应页面的内容。

API 变化​

以下 Cloud Admin API 变化会破坏现有调用方。

  • 模型的创建和更新会拒绝映射到 "" 的 effort_mapping 条目(POST / PATCH /environments/{env_id}/models…),返回 400;该取值的最小长度从 0 提高到 1。
  • DELETE /environments/{env_id}/models/{model_id} 应答 409 MODEL_IN_USE,条件是某个 scope: model 的限流策略指定了该模型。此前该调用会成功。
  • 缓存策略的 applies_to: "model:<name>" 绑定到模型的 ID。 重命名的模型会保留该策略,删除的模型会让该策略不再覆盖任何内容,即使之后再次创建同名模型也是如此。重新保存该策略即可重新解析。
  • 精确指定某个已注册 Server 的 MCP 工具授权项、拒绝项、按 Server 的限流和匿名访问上限会绑定到该 Server,并在重命名后按新名称读回。带 * 的条目,或未指定任何已注册 Server 的条目,仍按名称匹配。
  • effort_mapping 的键 "" 和 * 是保留键。 1.2.0 把它们作为普通键存储。现在 "" 匹配未设置推理档位的请求,* 匹配没有自己条目的任意取值;只要环境中注册了早于 1.3.0 的网关,保存其中任一键都会应答 422 DP_INCOMPATIBLE。

升级说明​

从早于 1.3.0 的版本升级至本版本或后续版本时,均需遵循本节说明,包括跳过 1.3.0 的升级。

  • 请先升级控制面,再升级网关。 这是唯一受支持的顺序。
  • 如果依赖跨重启的磁盘恢复能力,请设置 managed.snapshot_cache_enabled: true。 该配置项是新增的,默认为 false;仅配置 snapshot_cache_path 不再启用持久化——只配置路径时,1.3.0 完全不会写快照文件。因此,dp-manager 不可达时重启的网关会输出 waiting for the first configuration before binding the proxy listener,并且在控制面恢复可达之前完全不提供服务;1.2.0 会从磁盘恢复并继续提供服务(snapshot restored from on-disk cache)。处理方式是设置 managed.snapshot_cache_enabled: true,Helm Chart 或容器部署可使用 AISIX_MANAGED__SNAPSHOT_CACHE_ENABLED=true;路径保持默认值 /var/lib/aisix/config_cache.json。内存中保留最后一份可用配置并继续服务的行为不变。
  • 环境的请求数会上升、成功率会下降,这是预期结果。 调用方放弃的请求现在会记录用量数据,此前不记录。这些记录的 Token 数和费用均为零,可按 error_class = "client_disconnected" 过滤,也不改变任何花费。延迟分位数不受影响。
  • 请把日志处理改为读取流结束时的那条访问日志。 流式请求只写一条日志,写在流结束时,携带最终状态码和 Token 计数;此前写在响应头生成时,携带 200 且没有计数。所有日志还会新增 duration_ms(与 latency_ms 并列),非流式 /v1/chat/completions 的日志新增 cache_status。
  • 请检查为网关或控制面配置的各个地址是否带 scheme。 不是 http 或 https URL 的取值现在会导致启动失败,而不再在运行期才出问题:网关的 managed.cp_base_url 和 managed.cp_etcd_endpoint,cp-api 的 AISIX_CLOUD_DPMGR_BASE_URL,以及 dp-manager 的 AISIX_DPMGR_BASE_URL。不带 scheme 的 host:port 现在会被接受并读作 https://;已有的小写 http:// 或 https:// 取值不受影响。
  • 如果此前依赖固定的 UID,请重新配置。 控制面 Helm Chart 不再为任何组件设置 runAsUser、runAsGroup 或 fsGroup。按 UID 匹配的 PodSecurityPolicy 或 Gatekeeper 规则,以及已预先 chown 的外部挂载卷,需要通过 values 重新设置这三个键。内置的 PostgreSQL 子 Chart 保留自己的 UID,在 OpenShift 上需要单独关闭——--set postgresql.primary.podSecurityContext.enabled=false --set postgresql.primary.containerSecurityContext.enabled=false。
  • 请下载与自身架构匹配的离线安装包。 安装包现在按架构分别构建,文件名为 aisix-self-hosted-offline-<version>-linux-{amd64,arm64}.tar.gz;run.sh 会拒绝为其他架构构建的安装包。不带架构后缀的文件名仍然提供 amd64 安装包。
  • 升级窗口期间,早于 1.3.0 的网关会上报一条被拒绝的定价配置,这是预期结果。 只要还有早于 1.3.0 的网关处于已注册状态,1.3.0 控制面对 Model Pricing 覆盖项的投影(已有的覆盖项在升级时重新投影,新的覆盖项在保存时投影)就会使该网关上报 aisix_config_rejected_resources{kind="pricing"} 1 和 aisix_config_last_reload_successful 0。流量、就绪状态和后续的配置更新都不受影响,控制面的「被拒绝的资源」视图也仍然为空,因为对该网关而言这是一个未知的资源类型。网关升级到 1.3.0 后,这两条序列会立即恢复。请在升级控制面后尽快升级网关,并在此窗口期间不要对早于 1.3.0 的网关的 aisix_config_last_reload_successful 配置告警。
  • 请重新保存所有带音频时长费率的组织定价覆盖项。 第一次保存之后的任何一次保存所设置的 duration_cents_per_1m_seconds 都被丢弃了,因此已存储的值是最早写入的那个。重新保存该定价即可写入当前费率。
  • 请重新保存 applies_to 所选模型已被删除并重新创建过的缓存策略。 该选择器现在在保存时解析为资源 ID,而重新创建的模型是另一个资源。
  • 请修正或清除携带 {"": null} 或映射到 "" 的条目的 effort_mapping。 这两种形状现在都返回 400。已存储此类配置的模型仍然可以正常服务,但其编辑表单会把该规则显示为不完整,并且重新提交未改动映射的 PATCH 会被拒绝。这两种形状此前都无法通过控制台配置出来。
  • 请更新所有基于网关出向 User-Agent 做匹配的配置。 它现在上报 aisix/<build version>,而不再是固定的 aisix/0.1。
  • 如果使用 Bedrock、对象存储遥测导出或 /v1/realtime,请检查 upstream.pool_idle_timeout_secs 和 upstream.connect_timeout_ms。 这三条链路现在遵循所配置的取值(默认分别为 30 秒和 5 秒),此前它们使用的是 90 秒、3.1 秒,或完全不设超时。

1.2.0​

发布日期: 2026 年 9 月 8 日

本版本明确了最低支持版本,并加强了网关配置兼容性校验:控制面会在保存前拒绝已注册网关无法加载的配置。网关优化了配置变更处理,避免每次 watch 事件都产生与完整配置规模成正比的开销,解决批量修改配置导致请求处理阻塞的问题。此外,运维人员可以按指标选择标签集合;OpenAI 上游返回的原始缓存写入计数也会完整保留在网关响应、用量日志及其导出结果中。

行为变化​

  • Token 用量恰好达到窗口上限时,网关现在会拒绝新请求。 此前,当已提交的 Token 计数恰好达到上限时,tpm 和 tpd 仍会额外放行一个请求,只有超过上限后才会拒绝。内存和共享 Redis 两种后端现在使用相同的上限判断规则,切换后端不会改变实际限流行为。此变更适用于所有 Token 窗口,包括由策略派生的窗口和 API Key 级窗口。窗口上限显式配置为 0 时,现在会拒绝所有请求,与上限为 0 的请求计数窗口(例如 rpm)保持一致。请求计数采用预扣方式,此前已能准确执行上限,因此行为不变。

  • 控制面现在会拒绝保存已注册网关无法加载的配置。 控制面会根据目标环境中各已注册网关版本的配置读取规则,校验每份投影文档;只要某个受支持版本无法加载该文档,就返回 422 DP_INCOMPATIBLE。此前,写入会成功,响应中仅包含一条 row_rejected 告警,此时资源可能已在部分网关上停止生效。error.message 会完整说明网关版本、受影响的网关及配置中存在问题的部分;error.dp_compat 则以结构化字段提供相同信息。row_rejected 告警码已移除。新增的 below_floor 告警用于报告低于控制面最低支持版本的网关;控制面不对这些旧版本网关执行兼容性校验。

    网关停止上报后,其注册信息仍会保留 5 分钟。因此,集群升级后的一段时间内,拒绝信息仍可能列出集群中已不再运行的旧版本。这是预期的保守校验行为:旧注册信息过期前,控制面仍会将其纳入检查。拒绝信息包含 last_heartbeat_age_seconds,可在过期注册信息被清理后重试。

  • 数据库记录的上一次控制面版本低于 0.12.0 时,控制面会拒绝启动。 控制面 API 服务(cp-api)会在启动迁移时记录自身版本。如果数据库中记录的版本低于最低支持版本,服务会停止启动,并提示已记录的版本及处理方式。离线安装包的 run.sh 也会在启动任何容器前拒绝此类升级。请先升级到受支持的版本,或在完成备份后设置 AISIX_ALLOW_UNSUPPORTED_UPGRADE=1。API 服务和安装脚本均支持该环境变量,Helm Chart 中可通过 api.extraEnvVars 设置。全新安装不受此限制;上一次使用该数据库的控制面版本尚未引入版本记录机制时,也不受此限制。

  • 显式为空的 ignore_statuses 列表现在会被保留。 此前,创建或修改模型时提交的空列表会被接受,但随后会被替换为 [408, 429],并以该默认值存储、返回和投影。这导致后台健康探测仍会忽略 408 和 429,未按用户配置将其视为失败,且没有提示输入已被覆盖。现在,空列表在存储、GET 返回结果和网关配置中均保持为空列表。省略该字段的行为不变,仍使用默认值 [408, 429]。本版本之前保存的模型会保留已被替换的默认值,需显式设置为空列表后重新保存。

  • 使用非 Anthropic 上游时,系统提示词中的 Anthropic 计费归属行会被移除。 Anthropic 原生客户端会在系统提示词开头添加一行 x-anthropic-billing-header;在某些部署中,该行的部分内容会随请求变化,导致其他模型服务提供方收到的提示词前缀每轮都不同,无法命中提示词缓存。对于 POST /v1/messages 和 POST /v1/messages/count_tokens,如果解析出的目标并非目录中的第一方 anthropic 提供方,网关会在构建上游请求前移除该行:对于数组形式的 system,移除计费归属块;对于字符串形式的 system,移除第一行。提示词其余部分(包括 cache_control 标记)逐字节保留,messages 不会被修改。判断依据是目录中的厂商 ID:指向区域性或经代理的 Anthropic 端点的第一方凭据会保留该行;OpenAI Chat 桥接、第三方 Anthropic 兼容透传,以及 Bedrock、Vertex、Azure 平台适配均会移除该行。此变更无需调整配置,未发送该行的调用方不受影响。

新功能​

  • 按指标选择标签。 新增 observability.metrics.labels 配置块,用于声明每个指标族的完整标签列表;也可通过环境变量 AISIX_OBSERVABILITY__METRICS__LABELS 以 JSON 对象形式配置。未配置的指标族保留原有默认标签,因此升级后无需调整现有指标配置。标签选择在观测值累加前生效,移除 counter 或 histogram 的标签会聚合对应的观测值,不会丢弃观测数据;gauge 会保留用于标识序列的必需标签。未知的指标名称、不支持的标签变量或重复标签会导致启动失败,配置变更需重启后生效。首 Token 时间和请求延迟指标现在支持在原生和桥接请求路径上添加模型服务提供方凭证及调用方归属标签,这些标签默认不启用。

  • 控制台的网关安装页面支持选择指标标签。 运维人员可以添加受支持的标签、移除默认标签或恢复默认配置。Docker、Compose、Helm 和 systemd 安装指令都会通过启动环境变量包含完整的标签配置。这是网关进程级设置,不新增资源字段,也不改变资源投影。

  • 完整保留 OpenAI 上游返回的原始缓存写入计数。 cache_write_tokens 现在会保留在网关响应的 usage.prompt_tokens_details.cache_write_tokens 中,并传递至用量事件、Admin API 的用量日志列表与导出结果,以及控制台的日志详情。此功能覆盖原生 OpenAI 请求、各协议桥接、旧版非流式 Completions 及可识别的透传用量。显式返回的 0 与字段缺失保持区分,上游未提供该字段时不会补值。该字段保存原始计数,与 Anthropic 可累加的 cache_creation_tokens 分开存储,不改变 Token 总数,也不影响计费。历史用量记录中的该字段不会补填。

改进​

  • 批量修改配置不再阻塞网关请求处理。 此前,每次配置写入成功后,网关都会深拷贝完整快照,重新解析所有存储文档并进行规范化序列化,以重新计算两个哈希值,随后递增全局版本号。所有派生缓存均使用该版本号判断是否失效,因此每次写入的处理开销都与完整配置规模成正比。各工作线程收到下一个请求时,还会同步重建完整的护栏索引:为每个启用的挂载创建运行时和 HTTP 客户端,并分别重新加载 CA 存储。如果构建期间快照发生变化,构建会反复重试,且没有重试次数上限。该线程上的 /livez 请求也需等待这些操作完成。

    派生缓存现在根据其读取的表判断是否失效。每个已配置的护栏仅构建一个实例,并在各挂载间共享;只要对应配置行未变化,索引重建时就会复用该实例。并发触发的索引构建会合并执行,原有的重试循环已移除。快照克隆改为结构共享,每个条目版本的摘要仅计算一次,排队的配置事件在同一个写时复制周期内批量应用。聚合式 /mcp 端点也会按配置行缓存各 MCP Server 的工具集,无需在每次调用时重新遍历所有已注册的 OpenAPI 文档。

    配置、协议结构和上报值保持不变:config_hash 和 source_hash 逐字节一致,请求所应用的护栏及被拒绝配置行的上报行为均不变。新增 info 级别日志 guardrail index rebuilt,记录各类配置行数及构建、复用的实例数量。

  • 修复三个指标族未输出的问题。 aisix_redis_failures_total、aisix_otlp_fanout_failures_total 和 aisix_otlp_fanout_drops_total 此前虽已定义输出方法,但未被调用,因此查询结果始终为空。这些指标用于观察采用失败放行策略的子系统是否发生降级。Redis 失败现在按限流存储、响应缓存和语义缓存分别计数,并通过包含子系统信息的操作标签(如 ratelimit_acquire、cache_get、semantic_lookup)区分来源,便于在共用 Redis 时识别发生降级的子系统。OTLP 扇出会统计每次失败的导出尝试,包括重试;丢弃记录按 queue_full、worker_stopped、retries_exhausted 和 permanent_error 分类计数。批次被丢弃时,按批次中的记录条数计入。

  • 控制台页面在数据加载失败时会显示明确的错误提示。 此前,列表数据为 null 同时表示“仍在加载”和“加载失败”,导致错误卡片下方持续显示加载动画,部分页面甚至没有错误提示。现在,列表页会在加载成功或失败后结束加载状态。此变更覆盖团队及团队详情、预算、A2A Agent、管理员 Token、MCP Server、模型服务提供方凭据、定价、审计、通知渠道及投递记录,以及三个用量列表;也覆盖环境内的模型、API Key、限流策略、缓存策略、Claim 映射、OIDC 提供方、透传路由、可观测性、日志和 MCP 策略页面。组织设置卡片及团队 MCP 授权卡片采用相同处理方式。设置页和通知页在组织列表加载失败时会显示标准提示条。刷新或重试时,页面会重新进入加载状态,避免在请求进行期间持续显示上一次失败的提示。

修复​

  • Redis 不可达时,不再让每一个用到它的请求挂起。 当 ratelimit.backend 为 redis,或某条缓存策略使用 Redis 后端时,运行期出故障的 Redis 此前会让这些请求等上数分钟,而不是降级;aisix_redis_failures_total 会记下这次失败,却没有任何请求结果随之而来。现在每一次 Redis 往返和连接尝试都由各 redis: 块下新增的 timeout_secs 约束,默认 5 秒。在这个预算之内,既有的失败即放行路径会接管:限流回落到进程本地计数器,缓存则记为未命中。一次失败之后,该子系统会短路 30 秒,因此中断期间大约每 30 秒只有一个探测请求会付出完整预算。熔断器按子系统共享:缓存的精确连接和向量连接算作一个,限流器是另一个。Redis 恢复之后,网关最多在 30 秒内察觉,在此之前限流按副本各自计数、缓存记为未命中;上游环节耗时超过 30 秒的请求,仍可能在缓存写入时再付出一份预算。之后共享计数会自动恢复,既不需要重启,也不需要改配置。

  • 控制面无法提交的写入,不再返回 2xx。 每请求的事务此前是在处理函数的响应已经发出之后才提交的。读取状态行后就断开的调用方会取消上下文,随后提交失败、插入被回滚,而这个调用方手里却留着一个 201,对应的记录已经不存在。现在写操作的响应会一直挂起到提交成功为止:一个事务没能保住的 2xx 会被丢弃,改为以标准错误信封返回 500,记录照旧回滚。只有 2xx 会被扣住,409、400 或 499 与此前完全一样地送达。保持连接的调用方感受不到任何差别。

  • 多行 data: 流式帧现在会正确返回调用方使用的模型别名。 事件流格式允许单个帧的负载分布在多行 data: 中,并以换行符连接。此前,模型 ID 改写逻辑只读取第一行,导致这类帧无法解析为 JSON,进而被原样转发,调用方收到的是上游模型 ID,而非请求中使用的模型别名。受影响的帧包括 /v1/messages 的 message_start 帧和 /v1/responses 的快照帧。现在,网关会读取拼接后的完整负载,改写模型 ID,并将各行写回原位置,保留原有分帧结构和换行格式。

  • 控制台不再无限重试失败的 Token 签发。 此前,控制台未记录签发失败状态。当认证服务不可达时,预算提示条的轮询会使每个打开的标签页每 30 秒启动一轮新的签发,每轮尝试 3 次。现在,签发失败后会保存错误,并进入指数退避窗口:初始为 30 秒,逐次翻倍,最长为 5 分钟。窗口内的请求直接返回已保存的错误,不再发起签发尝试。下一次签发成功或退出登录时会重置退避状态。若刷新失败时旧 Token 仍有效,则继续使用旧 Token,与此前行为一致。

  • 路由模型的审计记录不再包含未设置字段的 null 值。 此前,路由模型未设置 hash_on 和 fallback_on_statuses 时,审计事件会将其记录为 JSON null,但 API 既不接受也不返回该值。现在,未设置时会省略这些字段,与网关配置文档保持一致。历史记录不会被改写。

API 变化​

以下 Cloud Admin API 变化会破坏现有调用方。

  • 到达网关的写操作可能应答 422 DP_INCOMPATIBLE。 这涉及 32 个会投影配置的创建、更新、轮换、清除、批准和 PUT 操作。已注册网关无法加载的保存会被拒绝,而不再以带 row_rejected 告警的方式成功。请在每个这类写操作上处理 422。
  • warnings[].code 不再返回 row_rejected(该结果改为 422),并且可能返回 below_floor。根据 row_rejected 分支处理的自动化必须修改。
  • CompatibilityWarning.min_dp_version 和 affected_dp_count 的含义发生变化。 min_dp_version 现在是能读取该字段的最低受支持网关版本(对于 below_floor,为最低受支持网关版本);affected_dp_count 统计该告警适用的网关数量。
  • background_model_check.ignore_statuses: [] 按 [] 存储和返回;此前它会被存储为 [408, 429]。

升级说明​

从早于 1.2.0 的版本升级至本版本或后续版本时,均需遵循本节说明,包括跳过 1.2.0 的升级。

  • 如果当前版本低于 0.12.0,请先升级到 0.12.0 或更高的受支持版本,再升级到本版本。数据库记录的上一次控制面版本低于 0.12.0 时,控制面 API 服务和离线安装包均会拒绝升级。完成备份后,可设置 AISIX_ALLOW_UNSUPPORTED_UPGRADE=1 绕过该限制;Helm Chart 中可通过 api.extraEnvVars 设置。本控制面支持 0.12.0 及更新版本的网关。
  • 请更新依赖 row_rejected 告警码进行分支处理的自动化程序。此前返回该告警的情况,现在改为返回 422 DP_INCOMPATIBLE,所有向网关投影配置的写操作都可能返回此错误。同一告警枚举新增 below_floor,用于报告低于最低支持版本的网关。
  • 对于本版本之前曾将 background_model_check.ignore_statuses 显式设为空列表的模型,请将该字段重新设置为 [] 后保存。旧版本实际存储的是默认值 [408, 429];仅升级不会修正该值,原样保存默认值也不会恢复空列表配置。

1.1.0​

发布日期: 2026 年 9 月 7 日

这个版本加固了控制面到网关之间的这条路径。网关现在只有在拿到可服务的配置之后才打开代理端口,能够自行从 etcd 中断、etcd Token 过期或 watch 始终未被确认中恢复,并且可以加载此前会超出内部消息大小上限的配置集。A2A Agent 补齐了调用方请求头转发契约;On-Premises 控制面 Chart 支持固定 NodePort,也不再等待一个已经被告知不使用的内置数据库。

行为变化​

  • 网关只有在应用过一次配置之后,才绑定代理监听器。 在 etcd 模式下,冷启动的实例会保持代理端口关闭,直到第一次配置读取成功;此前它会立即接受连接,并因为还不知道任何 API Key 而对每个请求返回 401 invalid_api_key。把"端口可连接"当作"该实例已就绪"的编排系统,不会再把流量路由到一个无内容可服务的实例上。这没有配置开关,也无法关闭;启动顺序现在就是如此。这段等待只会发生在从未应用过配置的实例上。文件模式会立即通过这道闸门;重启后发现磁盘快照缓存的实例同样如此——它会恢复快照并在远不到一秒内完成绑定,即使此时配置源不可达,因此已经运行过的 Pod 在控制面故障期间也能直接恢复服务。只有没有快照缓存的首次启动会等待,而在控制面可达时,这段等待在真实配置规模下是数十毫秒量级。由于 /livez 和 /readyz 由代理监听器提供,在这个窗口内针对它们的探针会收到连接被拒绝而不是响应;指标监听器上的 /status/ready 和 /status/config 全程可用。使用 Helm 的用户请在升级镜像的同时采用 1.1.0 Chart:Chart 的启动预算已经相应放宽。

  • etcd.dial_timeout_ms 和 etcd.request_timeout_ms 现在开始生效。 此前的版本会解析这两个键,但没有任何代码读取它们,所以无论配置文件里写了什么,每个部署实际上都没有 etcd 超时。两个键都是可选的,不设置即表示无上限,不存在隐式的 5000。request_timeout_ms 约束每一次单请求单响应的 etcd 调用——启动时以及每次 watch 重连时的配置范围读取、创建 watch,以及 Admin API 的读取——不会约束已建立的 watch 流。dial_timeout_ms 约束整个拨号过程,包括 TLS 握手和认证交换。从上一版本自带示例复制而来的配置文件已经带着这两个键的 5000 取值,升级前请先检查,详见升级说明。

  • 配置了 etcd 凭据的网关,在 etcd 启动时不可达的情况下不再退出。 此前设置 etcd.user 和 etcd.password_env 会让不可达的 etcd 成为致命错误:进程会在大约 20 到 25 秒后退出,此时还没有任何重试或监听器。这样的实例现在与未认证的实例行为一致——它会启动、保持代理监听器关闭、按已有的退避策略重试,并在配置到达后立即绑定。etcd 主动拒绝的凭据——用户名或密码错误、用户缺少所需权限,或者向未开启认证的集群发送了凭据——仍然是致命错误,并且现在会在 etcd 的第一次应答上就中止启动,而不是走完一整轮固定的重试阶梯。此前依赖进程退出来判断"etcd 挂了"的做法,应改为读取 /status/ready。

新功能​

  • A2A Agent 可以把入站的调用方请求头转发到上游。 A2A Agent 新增 forward_client_headers 列表,用于点名网关转发给该 Agent 的调用方请求头,写法是最多含一个 * 的 glob 模式,匹配不区分大小写。它作用于 /a2a/<name> 上提供的每一个 JSON-RPC 方法——message/send、message/stream 以及所有任务操作——也作用于 /a2a/<name>/.well-known/agent-card.json 上的 Agent Card 获取。至此,这份转发契约在四个代理面上全部补齐:模型服务提供方凭证、透传路由、MCP Server 和 A2A Agent。默认为空且不转发任何内容,因此现有 Agent 的行为不会改变。

    点名该 Agent auth_type 所填充的凭据槽位——bearer 对应 authorization,api_key 对应 x-api-key——会把调用方自己的凭据替换网关的凭据交给 Agent,而不是同时给出两份;这让原本就按最终用户身份做鉴权的内部 Agent 可以继续这样做。凭据槽位以及 traceparent 和 tracestate 只有在模式精确写出名称时才会转发,* 或 x-* 这类宽泛 glob 永远不会把它们扫进来。转发后会破坏这次交互的请求头,无论模式多宽泛都会被拒绝:host、逐跳请求头、x-aisix-* 命名空间、描述由网关重新序列化的请求体的那些请求头,以及 a2a-version——后者是网关自己对 protocol_version 所固定版本的声明。

    转发 cookie 之前有一个限制值得了解。网关会终结入站的 HTTP/2,并且不做 cookie 重组,因此如果 HTTP/2 调用方的客户端把 cookie 拆成多个请求头字段(这是 HPACK 的一种压缩手段,并非每个客户端都会这么做),只有其中第一个会被转发。A2A Agent、MCP Server 和模型服务提供方凭证都是如此;透传路由则会转发每一个取值。

    该配置可以在控制台的 A2A Agent 创建与编辑表单的"高级"区域中设置,也可以通过 Admin API 设置。如果在保存非空列表时,作用范围内仍有网关运行着不支持该字段的版本,保存会返回一条兼容性告警;这些网关在升级前不会转发任何内容,方向上是失败即拒绝。

改进​

  • 网关可以加载大于 4 MiB 的配置集。 网关会在单次 etcd 范围响应中读取自己的整个前缀,而 4 MiB 的 gRPC 解码上限意味着规模超过该值的环境永远无法加载——触及这条上限的是环境中资源的数量,而不是某个资源本身很大。它也不会自愈:运行中的实例会静默地不再看到配置变更,重启或新调度的实例则根本不会应用任何配置。配置读取路径和 Admin 读取面上的这条上限都已解除。低于旧上限的部署不受影响。

  • 控制面不再限制它写往网关的单个资源的大小。 控制面自身写入路径上的两条消息大小上限——outbox 客户端 2 MiB 的发送上限和内嵌存储 4 MiB 的接收上限——会让某个过大的投影资源在每一轮轮询中都被拒绝,且永远如此。由于按键隔离,队列中其余部分仍在正常排空,所以外部看到的现象是:某一个资源的配置始终没有到达网关,而保存它的人得不到任何提示。这两条上限都不是为这条路径选择的,现已移除。触及其中任何一条都需要异常大的投影值,例如一个授权了数千个模型的 API Key。

  • 等待配置源的网关现在会明确说明。 在第一次配置读取尚未完成期间,网关会在等待开始时记录日志,并每十秒重复一条告警。此前,一个能接受 TCP 连接却不作应答的端点,会让进程既没有端口、也没有任何日志。

  • On-Premises 控制面 Chart 支持为 API 和控制台服务指定固定 NodePort。 api.service.nodePort 和 ui.service.nodePort 加入了已有的 dpm.service.nodePort,各自只在对应 Service 类型为 NodePort 且已设置取值时才渲染;两者默认都为空,因此没有设置它们的安装保持动态分配。这让运维方可以在安装前就把 api.publicBaseURL 设为一个已知的地址。通过 NodePort 访问 API 和控制台走的是明文 HTTP:控制台的 NodePort 并不是一个独立入口,而是一个同源代理的上游,该代理会把 /api/* 路由到 API;除非部署在受信任的私有网络中,否则应由该代理终结 TLS。

修复​

  • etcd 认证 Token 过期或失效后,不再需要重启网关。 etcd 客户端只在连接建立时认证一次、之后不再认证,因此当 Token 在连接空闲期间到期(配置稳定的网关正处于这种状态),或因 etcd 认证存储发生变更而失效时,后续所有调用都会被拒绝,直到进程重启为止。网关现在会丢弃该连接、重新认证并把这次调用重试一次,配置读取路径和 Admin 读取面上都是如此。etcd 确实拒绝的凭据仍会按原样上报,不会被循环重试。

  • 网关在一次更新后不久被停止时,不再丢失最后一份配置快照。 快照缓存的写入此前是分离派发的,没有任何环节等待它完成,因此在应用变更后不久被停止的实例可能在写入尚未完成时就退出,重启后失去最后一份已知良好快照。现在关闭时会排空进行中的写入,上限为五秒。快照写入也按应用顺序提交:较旧修订版本的写入不会再覆盖较新的,因此在一连串更新之后重启的网关,不会回到一份它早已越过的快照上。优雅排空流程、排空窗口和 preStop 行为均保持不变。

  • 始终未被确认的配置 watch 现在能够被发现。 如果 etcd 能应答范围读取、却始终不确认 watch,网关会永远停留在自己的第一份快照上,对之后的每一次变更都视而不见,而 /status/config 仍然报告连接正常。设置了 request_timeout_ms 时,未被确认的 watch 创建会被中止,并按已有的退避策略重试。

  • MCP 访问控制的重投影现在覆盖每一条受影响的记录。 升级时刷新 MCP 访问控制的重投影,其分页方式可能跳过部分记录,让这些记录保留着已被淘汰的投影,兼容性告警也因此一直存在。现在它会显式遍历每一个 API Key 和每一条 MCP 策略。升级控制面时,每个现有 API Key 和每条 MCP 策略会多出一次投影写入。API、配置和资源形状都没有变化,也不需要运维方做任何操作。

  • 配置了外部数据库时,On-Premises 控制面 Chart 不再等待内置的 PostgreSQL。 设置 postgresql.builtin=false 会关闭内置的 PostgreSQL 服务,但 API 和数据面管理器仍会运行一个由 postgresql.image.* 构建的 PostgreSQL 就绪 init 容器,因此在私有网络中,即使外部数据库健康,拉不到 PostgreSQL 镜像也可能阻塞启动。该就绪 init 容器现在只在 postgresql.builtin=true 时渲染。内置部署不受影响,仍然是默认方式。使用外部数据库的运维方需要自行确保它在控制面启动前已经就绪。

API 变化​

本版本没有会破坏现有调用方的 Cloud Admin API 变化。

升级说明​

从任何早于 1.1.0 的版本升级时,本节说明都适用,包括那些途中越过 1.1.0 直接升到更新版本的升级。

  • 升级前请检查你的 etcd: 配置块。etcd.dial_timeout_ms 和 etcd.request_timeout_ms 在本版本中首次生效,而上一版本在 config.example.yaml 和 config.managed.yaml 中把这两个键都写成了生效的 5000。因此从其中任一文件复制而来的配置文件,会在配置范围读取上获得一个真实生效的 5 秒上限。如果某个部署的配置集无法在该上限内完成加载,这次读取会失败并重试;而由于网关现在只有在成功应用配置之后才绑定代理监听器,它将无法开始提供服务。除非你确实希望缓慢的 etcd 快速失败,否则请移除 request_timeout_ms;如果保留,请按你自己的配置集规模来设定取值,而不是沿用示例中原有的数字。dial_timeout_ms: 5000 没有可比的风险。现在两个键在自带示例中都处于未启用状态,不设置即表示无上限。
  • 如果你的控制面 Helm values 文件中已经写了 api.service.nodePort 或 ui.service.nodePort,升级前请检查它们。这两个键在本版本之前是被忽略的,现在会被渲染,因此升级 Chart 可能改变一个原本由 Kubernetes 动态分配的端口。想保持动态分配,请删除该键。

1.0.0​

发布日期: 2026 年 9 月 4 日

这个版本让安全护栏的行为在需要调优的地方变得可见、可配置。语义护栏会报告实际测得的相似度,控制台可以在规则挂到生产流量之前对已保存的规则做测试,失败后放行的决定也会在整个网关中得到一致记录。本次发布还为模型路由、MCP 服务器、透传路由和 Realtime 统一了调用方请求头转发契约,完善了不同模型服务提供方协议之间的推理控制,并让路由与配置失败更容易诊断。

行为变化​

  • 模型冷却现在需要显式开启。 直接模型没有 cooldown 配置块,或配置块中省略 enabled 时,请求失败后不再进入冷却。需要保留此前行为的,请设置 cooldown.enabled: true;开启后,默认超时时间与触发条件不变。此前依赖隐式冷却的现有模型会受到这一破坏性行为变化的影响。

  • 安全护栏不再把 Files API 当成一个不透明的整体扫描。 /v1/files 下的上传请求体、上传响应和文件下载现在不做输入或输出护栏评估。此前的整文件扫描既不能逐条评估 JSONL 记录,也无法把掩码后的内容写回 multipart 请求体,还会用替换字符解码二进制文件。/v1/batches 和 /v1/fine_tuning/jobs 的请求信封仍受护栏保护;本版本不包含逐条文件记录筛查。

  • 网关无法扫描的请求体现在遵循实际管辖该方向的护栏策略。 只有至少一条作用域内的护栏会读取这个方向、并且对它采用失败即拒绝时,网关才拒绝不可读内容。不会读取这个方向的护栏不会导致拒绝;所有相关护栏都采用失败后放行时,请求会继续,并记录 unscannable_body。fail_open 现在同样适用于 keyword 和 pii 护栏,而不只适用于远程护栏。已缓冲的流式输出在无法恢复出任何可扫描内容时仍然失败即拒绝,因为放行就意味着释放从未经过护栏评估的字节。

  • 无法解码的音频转写与翻译响应现在遵循输出失败策略。 输出护栏采用失败即拒绝时,这类纯文本转写返回 422 content_filter,错误码为 guardrail_unavailable;采用失败后放行时,原始字节会被转发,并记录这次绕过。能够解码的转写内容仍会接受扫描。

  • 不支持的流式请求会在到达模型服务提供方之前失败。 对 /v1/completions 或 /v1/images/generations 发送 stream: true 现在返回 400 invalid_request_error。这两个端点不转发流式响应;此前请求会被发往上游,可能在重试预算内重复产生可计费工作,最终返回与解码有关的 502。

  • 安全护栏现在按推理内容的提供者确定作用域。 调用方重放的推理内容属于输入,会在 Chat Completions、Responses 和 Anthropic Messages 上接受扫描;模型生成的推理内容不属于输出扫描范围。Anthropic 已签名的 thinking 块会接受拦截动作检查,但不会被掩码动作改写,因为客户端重放时必须保持这些已签名字节不变。

  • 流式错误事件现在采用各端点的原生信封。 /v1/messages 流中的护栏错误使用 Anthropic 的 invalid_request_error 类型;/v1/responses 发出扁平的 Responses API 错误事件,code、message、param 和 sequence_number 位于顶层。HTTP 错误信封不变。

  • 新发布的镜像只使用不可变的完整版本标签。 稳定版本发布 :X.Y.Z、:latest 和 :sha-*;候选版本发布完整 RC 标签与 SHA 标签。此后不再创建新的 :X.Y 和 :X 缩写标签。注册表中已经存在的缩写标签会保留,但本版本及后续版本都不会再推进它们。

新功能​

  • 语义护栏在部署前后都可以测量。 编辑表单新增试运行面板,可以为探测文本生成向量嵌入,并展示拒绝或允许分数、配置阈值、最接近的样例以及最终判定。经过语义护栏评估的请求会在用量事件中新增 guardrail_scores,通过的请求也会记录。日志会显示分数、阈值、方向、最接近样例的索引和向量嵌入模型;用量 API 与 CSV 导出携带同一份记录。持久化用量数据只保存样例索引,不保存样例或被筛查的文本。

  • 调用方请求头转发现在覆盖模型服务提供方凭证、MCP Server、透传路由和 Realtime。 MCP Server 与透传路由新增 forward_client_headers;模型服务提供方凭证已有的配置现在也作用于 Realtime 和所有经过协议翻译的模型服务提供方路径。在 MCP 与标准模型端点上,它是一份允许列表;在透传路由上,它恢复一条原本会被路由剥离的请求头。由于该字段可能传递调用方凭据与链路上下文,包括 AWS SigV4 请求身份头在内的凭据槽位,以及 traceparent / tracestate,都必须精确写出名称,不能由 glob 选中。被精确转发的凭据会替换网关或 default_headers 原本放入该槽位的凭据,不会追加第二个值。Amazon Bedrock 是例外:其签名器拥有 authorization 和 SigV4 请求头,签名前会丢弃调用方提供的这些值。

  • 直接模型可以为上游规范化推理力度。 新增的 effort_mapping 对象会在最终直接目标选定后,执行一次区分大小写的精确字符串映射。没有列出的值或缺失值原样透传;映射不会补充调用方没有提供的值,映射结果也不会再次进入映射。它覆盖 Chat Completions、Responses、Anthropic Messages 与 Token 计数请求,包括原生及跨模型服务提供方路径、流式请求、Bedrock 两种调用方式,以及由路由、语义或 Ensemble 模型选出的直接目标。该配置只允许用于直接模型,并可在控制台编辑。

改进​

  • 语义护栏要求使用为其向量嵌入模型选定的阈值。 非空的 deny_examples 必须同时配置 deny_threshold,非空的 allow_examples 必须同时配置 allow_threshold;没有样例的方向不要求阈值。此前省略阈值的现有数据会填入 0.75,保持原有执行效果。控制台测试面板与每次请求的分数可用于测量并调整替代值。

  • 所有受保护的代理面都能看到失败后放行结果。 成功和失败的用量事件都会携带 guardrail_bypassed_reason,包括在任何单条护栏运行之前发生的绕过。aisix_guardrail_bypasses_total 指标新增 reason="unscannable_body";aisix_guardrail_blocks_total 也会计入在某条可计时护栏运行前发生的失败即拒绝。A2A、原本不产生用量的 rerank,以及不支持能力的路径,会在需要保留护栏归因时发出零 Token 用量事件。

  • 护栏配置失败现在会作为配置状态上报。 能反序列化、但运行时无法构建的记录会出现在 /status/config、拒绝指标和托管心跳状态中,修复后自动消失。PII、Presidio、关键词和语义护栏配置中,原本可能导致整条护栏被丢弃的 JSON null 现在会被拒绝。升级迁移只会用安全默认值修复已存储的 null 与缺失值,再校验完整投影记录;其他格式错误的记录保持不变。

  • 缓冲式输出护栏覆盖完整 SSE 帧。 Messages 与 Responses 路径现在可以处理 CRLF 分帧、多行 data: 载荷、缺失的最终终止符,以及流式请求返回的非 SSE JSON 响应。无法在保持结构的前提下掩码的内容会被移除或拒绝,而不会未经读取就释放;可以掩码的多行帧会保留完整载荷。

  • 推理控制可以跨协议翻译。 Anthropic 的 output_config.effort 和自适应/禁用 thinking 会映射到相应的 OpenAI reasoning_effort;OpenAI 的 effort 值会映射到 Anthropic 当前使用的 output_config.effort 形式。Anthropic 的结构化输出声明也会转换成带严格 JSON schema 的 OpenAI response_format,而不再被丢弃。

  • 路由和指标会展示网关实际完成的更多工作。 因冷却或后台健康检查而被移除的路由目标会产生一条限频告警,写明目标与原因;失败尝试告警在 Chat Completions、Messages、Token 计数和 Responses 之间保持一致。原生与翻译后的 Responses 流现在都会报告两组 TTFT 指标;Ensemble 请求在配额、用量事件和 Token 指标中使用同一份用量估算。

  • 控制台会保留资源引用,不再要求运营方重新输入。 已有资源字段使用可搜索选择器;允许合法新值的字段继续提供可编辑建议;过期引用仍然可见,不会因一次无关编辑而被静默清空。在日志中,手工输入的请求模型筛选仍然是大小写不敏感的子串搜索;从已知模型中选择则会在数据流与 CSV 导出中执行大小写敏感的精确匹配。

修复​

  • Rerank 与 Realtime 的响应模型名保持一致。 Jina 形状的 /v1/rerank 响应以及 Realtime 的 session.created / session.updated 事件现在报告调用方寻址的网关模型名,而不是模型服务提供方的模型 ID。把完整 Realtime session 对象发回 session.update 时,模型名会再次转换为上游 ID,同时不会改动单独配置的转写模型。

  • 模型服务提供方不支持的能力不再消耗重试预算。 缺失的 completions、embeddings 或图像生成能力会被明确分类,并直接返回已有的 501,不再重试一次不会随尝试变化的 adapter 能力。

  • 通配符模型引用会在失效或扩大访问范围之前得到校验。 当模型被精确名称引用,或重命名会把 API Key 的单模型授权静默扩成命名空间授权时,不允许把该模型重命名成通配符别名。语义护栏不能新选择通配符别名作为 embedding 模型。缓存策略可以选择由通配符别名服务的具体模型名,但不能选择通配符模式本身。已有引用只在其值发生变化时重新校验。

API 变化​

以下 Cloud Admin API 变化会破坏现有调用方。前四项会以 400 拒绝此前被接受的请求。

  • PATCH /environments/{env_id}/models/{model_id} 在精确名称引用或 API Key 授权会被破坏时,拒绝把模型重命名为通配符别名。
  • 护栏的创建和更新:语义样例列表要求配套的阈值,语义向量化模型不能新引用通配符别名,受影响的语义、PII、Presidio 和关键词配置字段拒绝 JSON null。PATCH 上完整替换的 config 必须包含其样例列表所要求的每个阈值。
  • 缓存策略的创建和更新:model:<name> 选择器不能是通配符模式。已有取值只在发生变更时重新校验。
  • 模型服务提供方凭证的创建和更新:request.forward_client_headers 和 request.default_headers 拒绝会破坏传输的名称和 x-aisix-* 名称,并应用精确匹配和冲突规则。再次保存完整的请求覆盖配置块之前,请先移除这类条目。

还有一处变化改变了未作修改的调用的含义:

  • 除非 cooldown.enabled 为 true,否则冷却处于关闭状态。 创建或更新时不带 cooldown 配置块、或不带 enabled 的直连模型,此前会在默认触发状态码上进入冷却;现在它会保持在轮转中。设置 cooldown.enabled: true 可保持此前的行为。

升级说明​

从任何早于 1.0.0 的版本升级时,本节说明都适用,包括那些途中越过 1.0.0 直接升到更新版本的升级。

  • 冷却改为显式开启属于破坏性行为变化。升级前,请为每个需要保留 1.0.0 之前隐式冷却行为的直接模型设置 cooldown.enabled: true。
  • 本版本中 /v1/files 不在安全护栏覆盖范围内。不要依赖上传或下载的整文件关键词、PII 或远程护栏判定。
  • 检查每条护栏的 hook 与失败策略。AISIX 无法扫描、且由相关失败即拒绝护栏管辖的请求体仍会被拒绝;没有相关失败即拒绝护栏时则可能继续。特别是 fail_open: true 现在会对 keyword 和 pii 护栏生效,可能新放行 AISIX 无法扫描的请求或响应。
  • 客户端重放的推理内容现在可能被输入护栏拦截。模型生成的推理内容不再由输出护栏评估,掩码动作也不会改写 Anthropic 已签名的 thinking 块。
  • 当音频转写或翻译响应字节无法解码、且输出护栏采用失败即拒绝时,客户端需要处理 422 content_filter。采用失败后放行时,原始字节现在可能在未经内容评估的情况下被转发。
  • 对 /v1/completions 或 /v1/images/generations 发送 stream: true 现在不会联系模型服务提供方,而是返回 400 invalid_request_error,不再最终返回与解码有关的 502。请更新状态码处理和重试策略。
  • 请更新自定义流解析器以适配原生护栏错误信封:Messages 流使用 Anthropic 的 invalid_request_error,Responses 流把 code、message、param 和 sequence_number 放在顶层。
  • 升级前检查包含 JSON null 的已有护栏。上一版本跳过、且能够安全修复的记录在迁移后可能开始执行;只缺少语义阈值的记录会保持已有的 0.75 行为。
  • 创建或完整替换语义护栏配置的 API 客户端,必须为每个非空样例列表提供对应阈值。即使 OpenAPI 形状没有结构性破坏,阈值与 null 校验仍属于 Cloud Admin API 的语义破坏性变化。
  • 检查重命名模型或写入模型引用的自动化。当精确引用会被破坏或 API Key 授权会扩大时,不允许把模型重命名成通配符别名;语义护栏不能新使用通配符别名作为向量嵌入模型;缓存策略可以写由别名服务的具体模型,但不能写通配符模式本身。
  • 检查 Realtime 使用的模型服务提供方凭证 forward_client_headers 模式:1.0.0 开始在该代理面上执行这份配置。凭据槽位与 traceparent / tracestate 必须精确写名,宽泛 glob 不会选中它们。再次保存完整覆盖配置前,请删除被拒绝的传输头、x-stainless-*、anthropic-version 或 x-aisix-* 条目。在 Bedrock 兼容端点上,转发的调用方值现在会在 x-api-key、api-key、x-goog-api-key、proxy-authorization 和 cookie 槽位中覆盖 default_headers。Bedrock 签名器仍然拥有 authorization 与 AWS SigV4 请求头,并丢弃调用方提供的值。
  • 原本期望新发布的 :X.Y 或 :X 镜像别名继续推进的自动化,需要改用完整版本或 :latest。
  • 如果告警基于 aisix_guardrail_bypasses_total,请考虑新增的 reason="unscannable_body" 序列,以及现在被纳入总数的其他事件。

0.13.0​

发布日期: 2026 年 9 月 1 日

这个版本围绕两件事:把流量区分开,以及按上游自己的方式访问它。模型服务提供方凭证现在可以声明该端点原生提供哪些 API 面、每一个面在哪个地址上,因此一份凭证就能同时访问一个上游的 OpenAI 兼容路径和 Anthropic 兼容路径,不必再建第二份凭证和第二个模型。每条用量记录现在都写明了这次请求要网关做的是什么,图像生成和视频提交在导出器和日志里不再和文本对话混成同一股 OpenAI 流量。被网关限流的调用方,也终于能从响应里读到上限是多少、什么时候可以再来。此外,凡是会返回模型名的端点,响应里现在报的都是调用方寻址时用的网关模型名,而不再是其中一部分端点报服务提供方自己的 ID。

行为变化​

  • 升级后,现有的 DeepSeek 模型服务提供方凭证会直达 DeepSeek 自己的路由,而不再被翻译。 AISIX 现在内置了一份经过实测的声明,写明 DeepSeek 原生提供 /v1/responses 和 Anthropic 兼容的 /anthropic/v1/messages,并在升级时一次性应用到符合条件的凭证上:自身没有任何声明、使用 deepseek 提供方、且 api_base 仍指向 https://api.deepseek.com。这些凭证的 apis_source 会标记为 catalog。对流量的影响是:Responses API 请求会被转发到 DeepSeek 自己的 /v1/responses 而不再翻译成 chat completions,推理输出项因此得以保留;Anthropic 协议的请求会走到 Anthropic 兼容路径,提示缓存断点和思考块因此得以保留。你自己声明过的凭证不会被改动。
  • 客户端从响应里读到的 model 字段,现在是它请求时用的网关模型名。 涉及 /v1/messages、/v1/responses、/v1/completions、/v1/embeddings(流式与非流式同样适用)以及 /v1/videos 的轮询。这几条路径此前返回的是服务提供方自己的模型 ID——一个别名为 gpt4o-mini 的模型会回来 gpt-4o-mini-2024-07-18,而 /v1/chat/completions 早就返回别名了。透传路由不受影响,仍然原样转发服务提供方的响应。
  • 网关自己产生的限流拒绝现在带响应头。 网关拒绝一个请求时,429 会描述拒绝它的那一条上限:x-ratelimit-limit、x-ratelimit-remaining、x-ratelimit-reset、x-ratelimit-scope 和 Retry-After。x-ratelimit-reset 与 Retry-After 都是以秒为单位的相对值。并发维度的拒绝此前完全没有重试提示,现在也有了。这些响应头只在网关自己拒绝时添加;上游返回的 429 仍按上游原样透传。成功响应上原有的 x-ratelimit-limit-requests / -tokens / -concurrent 这组按维度命名的响应头保持不变。
  • 键已经消失的 Prometheus gauge 不再继续上报最后一个值。 aisix_budget_limit_usd / _spent_usd / _remaining_usd / _reset_seconds / _details_present 以及 aisix_ratelimit_remaining_{requests,tokens} 只在请求路径上被写入,因此删掉一个 API Key 会把它的时间序列冻结在最后读到的值上——一条针对预算耗尽的告警,会为一个已经不存在的凭证持续触发。这类序列现在会退休为 NaN,Prometheus 将其视为"没有值"而不是零。比较这些 gauge 的告警不会再匹配到已删除的 Key。如果你的仪表盘面板直接读原始值,Key 删除之后看到的会是一段空缺,而不是一条水平线。

新功能​

  • 模型服务提供方凭证可以声明原生 API 面。 同一个上游账号常常在同一个主机的不同路径上提供多种协议,共用一份凭证——DeepSeek、智谱和 Kimi 都同时提供 OpenAI 兼容路径和 Anthropic 兼容路径。api_base 只能指出其中一个,于是其余请求一律被翻译,丢掉目标协议携带而标准 chat 形状没有的东西。凭证现在支持一个 apis 块,写明每个面以及它所在的 base URL:

    {
    "apis": {
    "responses": {},
    "messages": { "base": "https://api.deepseek.com/anthropic" }
    }
    }

    两个面的判定规则不同,因为它们各自的依据不同。messages 是附加的:adapter 本来就是 anthropic 的凭证,无论这个块怎么写都继续原生提供 /v1/messages,在这里列出它是为了给 adapter 是别的值的凭证补上这条路由。responses 是权威的:一旦这个块存在,/v1/responses 只有被列出才会原生提供——运营方正是用"不列出"来表达"这个端点没有 Responses 路由",从而让请求被翻译成 chat completions,而不是打到上游收一个 404。完全没有这个块时,两者都回退到此前的推断方式:/v1/messages 依据提供方 ID 或 anthropic adapter,/v1/responses 仅依据提供方 ID。这个块没有涉及的面——embeddings、音频、图像、视频、files、batches、微调、rerank——一律照旧使用 api_base。把它设为 {} 表示该端点除自身 adapter 的面之外不提供任何其他面,设为 null 则清除声明。可在控制台的 Provider Keys 页面配置,也可通过 Cloud Admin API 的 POST 与 PATCH /provider_keys 配置。

  • 用量记录写明了请求要网关做的是什么。 每条用量记录现在都带 operation 字段,取值由请求命中的路由决定、绝不取自调用方文本:chat、completions、messages、count_tokens、responses、embeddings、rerank、realtime、image_generation、image_edit、transcription、translation、speech、video_generation、files、batches、batch_completion、fine_tuning、mcp、a2a、passthrough。inbound_protocol 对每一条 OpenAI 形状的路由都报同一个 openai,因此此前要区分文本对话、图像生成和视频提交,只能对捕获到的 prompt 做正则——而 metadata_only 的导出器根本没有 prompt,零 Token 的视频提交更是无从判断。这个字段会进入你自己的导出器(OTLP、Datadog、SLS),也会进入控制台:Logs 页可以按它筛选,并为每个请求标注——对话类端点(chat、messages、responses、completions)作为常见情形不做标注;GET /usage_events 与 GET /usage_events/export 新增 operation 查询参数,返回的每一项也带这个字段。

改进​

  • 用量记录与预算指标现在写出成员名字,不只是 ID。 aisix_usage_events_emitted_total、aisix_usage_event_drops_total 和五个 aisix_budget_* gauge 现在都在 user_id 旁边带上 user_name,与 aisix_proxy_requests_total 及 aisix_llm_* 系列保持一致。一条用量记录告警或一块预算看板,不必再去 Prometheus 之外查表才能说出它讲的是谁。

修复​

  • aisix_budget_remaining_usd 现在真的会发出来了。 网关只有在控制面的预算决定里写明剩余金额时才能发出这个 gauge,而那份决定从来没带过它——所以指标参考文档里描述的这条时间序列,在 0.12.0 及更早的任何部署里都不存在,基于它做的看板面板或告警匹配不到任何东西。它现在会与 aisix_budget_limit_usd、aisix_budget_spent_usd 一同出现,标签相同、出现时机也相同。只需升级控制面即可,网关不用改、也不用配置。
  • 因来源被拒的登录错误提示不再误述服务端信任的来源,也不再指错要重启的组件。 它此前说服务端只信任它被配置的那一个地址;实际上它同时信任该地址的 localhost/127.0.0.1 对应形式,以及 AISIX_TRUSTED_ORIGINS 中列出的每一个来源,提示现在给出了后一种解法。它此前还让运营方去重启 cp-api,而拒绝这次登录的检查其实运行在控制台里。
  • Helm Chart 的安装后提示不再给出一个它让你执行的 port-forward 并不服务的地址,那段提示里同样存在的、关于可信来源的不准确说法也一并修正。

API 变化​

本版本没有会破坏现有调用方的 Cloud Admin API 变化。

升级说明​

从任何早于 0.13.0 的版本升级时,本节说明都适用,包括那些途中越过 0.13.0 直接升到更新版本的升级。

  • 控制面会在升级后的第一次启动时,一次性把内置的 API 面声明应用到「行为变化」中描述的那些凭证上。这个动作是尽力而为且幂等的:某次启动没能完成,下一次启动会重试;已经带有声明的凭证永远不会被改动。如果某个端点你不希望被原生访问,自己给它写上 apis。
  • 如果你对 aisix_budget_* 或 aisix_ratelimit_remaining_* 配了告警,升级前请对照上面的 gauge 退休变化检查一遍表达式。
  • 仍运行 0.13.0 之前版本的网关不会记录 operation,因为这个取值是由网关根据匹配到的路由推导的。只要机群中还有这样的网关,按 operation 过滤——无论是在 Logs 中、在 GET /usage_events 上,还是在导出中——都会把它的流量排除在结果之外。这些请求照常被代理和记录,只是 operation 过滤看不到它们。升级该网关后,此后的流量即可正常过滤;已经记录下来、没有 operation 的行仍然在过滤范围之外。

0.12.0​

发布日期: 2026 年 8 月 30 日

这个版本让两份契约开始名副其实。Cloud Admin API 现在覆盖控制台能做的全部操作,每个版本发布一份不可变的文档,并且对它所声明的内容做校验。安全护栏则只在你挂载它的地方生效——"没有挂载就等于处处生效"这条规则,已经从网关、控制台和升级回填三处一并移除,而现有护栏实际拦截的范围不受影响。除此之外,Token 计数改为按调用方自己的协议上报,Gemini 模型的思考 Token 终于被计入,用量记录会指出凭证背后的那个人,还有几处删除操作可能留下悬空引用的路径被堵上了。

行为变化​

  • 安全护栏的作用域现在就是它的挂载关系;没有任何挂载的护栏不筛查任何流量。 此前一条没有挂载记录的护栏会以最低优先级作用于整个环境。以"没有记录"作为判据正是危险所在,因为收窄作用域恰恰是通过删除环境级挂载来表达的:一条只作用于某个模型的护栏,会在该模型被删除的那一刻,悄无声息地扩大到环境里的每一个请求。升级不会改变你现有护栏实际拦截的范围——控制面会在升级过程中,把原来隐含的环境级作用域写成一条显式的环境级挂载,且发生在网关不再认可隐含作用域之前;同时它还会把此前某次启动错误放大到环境级的护栏,恢复成你配置的窄作用域。从此之后有变化的是:新建的护栏在你挂载之前不作用于任何流量。声明一条没有挂载的护栏仍然不算错误:它的作用对象可能只是被删掉了。控制台中这类护栏现在显示为 Not attached——"没有挂载到任何对象,因此不筛查任何流量",此前显示的是 Global/"作用于所有模型";网关也会为每条已启用但没有挂载的护栏打一条 WARN。与此相关:在控制台打开一条窄作用域护栏、只改了个无关的地方就点 Save,不会再写出一条环境级挂载——编辑器现在把"没有挂载"表示成一个独立状态,而不是默认回退到环境级。
  • 控制台一直在调用的二十一条控制面路由现在进入了 Admin API 契约,并且会对请求做校验。 这些路由此前用 Admin Token 就能访问,只是没有公开的 schema;现在它们出现在 API 参考中。把一条在线路由纳入契约同时也为它打开了请求校验,因此请求体中携带了 schema 未声明的字段时会返回 400,而不再是被接受后忽略——POST /teams 带一个多余字段,在上个版本返回 201,现在返回 400 additional properties not allowed。如果你有程序在调用用量数据流、用量导出、用量汇总或请求级指标、团队与团队成员、模型价格覆盖、邀请、成员移除或通知投递日志,请确认它只发送已文档化的字段。完整路由清单见「API 变化」。
  • 响应中的 Token 计数现在按调用方自己的协议口径上报。 两种协议只在一件事上有分歧:提示缓存的计数是包含在输入计数之内,还是与之并列。OpenAI 协议下 prompt_tokens 是包含缓存命中在内的完整输入;Anthropic 协议下输入计数不含缓存,cache_creation_input_tokens / cache_read_input_tokens 与之并列。网关此前会把上游报什么形状就原样透传,因此当客户端用的协议与上游的协议不一致时,它拿到的是另一种口径的账:用 OpenAI 协议访问 Anthropic 上游的客户端会看到 prompt_tokens: 40 与 total_tokens: 2104 并存——既对不上账,缓存命中也无处体现。同一个请求现在上报 2088 与 2104,命中部分出现在 prompt_tokens_details.cached_tokens 中。在发生口径转换的情况下,total_tokens 会由投影后的输入与输出计数重新算出,而不是照抄一个按另一种口径算出来的总数;不需要转换时,仍然原样透传上游给出的总数。流式、非流式与 /v1/responses 均已覆盖。记录下来的用量事件不变,因此计费与历史费用不受影响——变的只是回给调用方的计数。
  • OpenAI 协议的响应现在可能带上缓存写入计数。 prompt_tokens_details.cache_creation_tokens(/v1/responses 上是 input_tokens_details 下的同名字段)表示本轮被上游写入缓存的 prompt Token 数。它不是 OpenAI 的字段——OpenAI 没有"缓存写入"这个概念——但如果没有它,Anthropic 或 Bedrock 的一次缓存写入就表现为 prompt_tokens 无缘无故变大、调用方无法据此估价,而写入的单价是高于普通输入的。该字段仅在非零时发出,因此严格拒绝未知字段的客户端需要检查一下。
  • Gemini 模型的思考 Token 现在会被计入,并计费。 Gemini 会上报 thoughtsTokenCount,而网关此前在任何地方都没有解析它——因此思考模型的 completion_tokens 记录值少了思考部分,reasoning_tokens 在所有协议下都读作 0。现在两者都会被携带,reasoning_tokens 表示 completion_tokens 中的那一部分,是否包含则依据上游自己上报的总数来判定,因此在 Gemini 已经把思考计入自己的候选 Token 数的情况下不会被重复计算。费用按推理单价(未设置推理单价时按补全单价)对 reasoning_tokens 计费。如果你在使用会思考的 Gemini 模型,记录的补全 Token 数与费用会上升——上升到与 Google 本来就在向你收取、而网关此前没有记录的那部分一致。与上面那条协议转换不同,这一条确实会改变用量记录。
  • /v1/messages/count_tokens 现在会发出用量记录。 这个路由在任何结果下都不发用量事件,因此一个被入站护栏拒绝的请求,虽然被正确拒绝了,却无法在日志中找到——包括 Guardrail blocks 视图。它仍然不计费:无论是正常返回还是被拒绝,prompt_tokens 与 completion_tokens 都是零。"不计费"和"不记录"此前被当成了同一件事,其实是两件。
  • 会留下悬空引用的删除操作,现在会被拒绝、被修复,或者如实告知。 删除一个被语义护栏用作 embedding 模型的模型会返回 409,而重命名该模型会改写这条护栏,而不是把它变成孤儿。此前的代价很高,因为护栏默认失败即拒绝:在上个版本中这个删除会成功,而该护栏作用域内的每一个请求随后都会收到 422 semantic_embed_unresolved。删除一个被声明映射解析到的 API Key 同样返回 409,与 passthrough 路由的匿名 Key 已有的保护方式一致——悬空的映射虽然是失败即拒绝,但代价并非为零:匹配会取优先级最高的规则且不再向下回落,因此一条坏掉的规则会遮蔽一条本来仍然有效的低优先级规则。删除团队、移除成员现在都会清掉它们留在调用方 Key 上的归属,并把变更同步到网关。 这两列此前是被数据库外键置空的,而外键动作不产生投影事件,于是网关继续读着一份指向已不存在团队的文档——一条挂在被删团队上的限流会一直拦着那些 Key,而控制台上没有任何东西能解释那些 429。删除 MCP Server 也不再顺手删掉引用它的按 Key 限流:此前它会删掉限流却保留工具授权,于是"用同名重新创建"这条被支持的路径会恢复权限、却静默丢掉限流上限。删除 OIDC Provider 仍然会成功——它的两处引用持有的都是名称,重命名本身就是删除加重建,悬空是常态且失败即拒绝、可自愈——但响应现在会报告还有多少个 API Key 和声明映射仍在引用它。

新功能​

  • Cloud Admin API 按版本发布。 每个发布 tag 现在都会发布一份由该 tag 自身源码生成的、不可变的 OpenAPI 文档,API 参考会为每个已发布版本提供一个页面,并自动生成相邻版本之间的变更记录。你可以直接查阅自己这套部署所暴露的 API,并与要升级到的版本进行对比,而不必再去对照一份跟随开发分支变化的文档。
  • 用量记录与日志会归因到组织成员,而不只是凭证。 用量记录此前只写明请求是从哪个 API Key 进来的,却从不写明背后是谁,因此"查这个成员最近 24 小时的错误"意味着枚举他名下的每一个 Key 再手工合并结果——而一个既用 API Key 又用 OIDC 的成员,还会被拆成两个身份,没有任何一个筛选条件能把它们并起来。用量记录现在携带成员信息,日志页也可以按成员筛选。这个归因是在请求被处理时打的快照:重新绑定或删除一个 Key,不会改写它已经产生的历史记录。
  • 日志可以按精确的状态码筛选。 此前只提供按状态码族筛选,因此没有办法只查 429 而不把其他所有 4xx 一起带出来。现在支持精确状态码,也支持 500-599 这样的区间。
  • aisix_usage_events_emitted_total 与 aisix_usage_event_drops_total 带上了成员与精确状态码。 两个计数器都新增了 user_id 标签和一个保存原始响应码的 status 标签,因此"这个成员有多少请求被限流了"和"这个成员有没有丢过用量记录"现在可以直接从指标回答。原有的 status_code 族标签保持不变,基于它的告警不受影响——但如果某个仪表盘在聚合这两个计数器时没有显式写出标签,它会看到新增的维度。

改进​

  • 用量页面在加载过程中不再报零。 在第一个响应返回之前,/usage 会在两张写着"最近 30 天没有用量"的表格下面渲染出 $0.00、0 个请求和 0 个 Token,几秒之后再把它们全部替换成真实数字。在网络较慢时,运营方会被明确告知自己的网关没有任何流量。现在它显示 — 并配一行 Loading…,与概览页保持一致。
  • 离线安装脚本会报告所安装的版本,以及真正对外暴露的端口。 离线部署此前没有办法在安装结束时确认自己刚装的是哪个版本;而当端口来自环境变量而不是默认值时,结束时打印的横幅仍然显示默认端口——于是一套监听在某个端口上的部署,却告诉运营方去打开另一个端口。
  • 参考文档现在写明了自定义 PII 规则中替换文本的行为。 $1 不会被当作捕获组引用展开;而当正则里有捕获组时,只替换第 1 个捕获组而不是整个匹配——所以对 ACCT-([0-9]{4})-([0-9]{4}) 用 replacement: "ACCT-$1-****",得到的是 ACCT-ACCT-$1-****-5678:看上去像脱敏了,其实原文还在里面。控制台现在会在替换文本里含 $ 时给出提示。

修复​

  • 两个控制面副本同时启动不会再互相搞崩。 Schema 迁移全程都是"先检查再动作"——先探查系统目录,再执行创建或修改——而 PostgreSQL 并不会为此串行化,因此高可用部署可能在启动时让某个 Pod 以多种不同的错误码失败。启动期的 schema 操作现在会串行执行;对着全新数据库同时启动八个副本,现在八个全部起来,此前这一档大约八次里会失败七次。
  • 升级回填不会再把只作用于某个模型的护栏重新放大。 那个为"挂载关系出现之前就已存在"的护栏补一条环境级挂载的回填任务,会在每一次控制面启动时运行,并且用"没有环境级挂载"来判定目标——这个判据是在挂载表刚建立、所有护栏都还没有任何挂载时写下的,那时它只可能意味着"早于挂载机制"。而自从把护栏收窄到某个模型会删除它的环境级挂载之后,每一次重启都会悄悄把它重新放大回整个环境。
  • 删除护栏现在会把它的挂载关系从网关撤回;升级还会清理掉此前删除留下的残留。 挂载记录此前是被数据库级联删除的,而级联不会产生投影事件,因此那些挂载文档会一直留在网关侧,每个数据面在每次重建索引时都会打一条"引用了不存在的护栏"的日志,且永不停止。升级会把这些残留撤回,那条日志会自行消失,无需人工处理。

API 变化​

以下 Cloud Admin API 变化会破坏现有调用方。

  • 进入契约的二十一条路由会校验其请求。 携带 schema 未声明字段的请求体会被以 400 拒绝,而不再被忽略;例如,带有多余字段的 POST /teams 此前返回 201,现在返回 400。这涵盖用量明细、其导出、用量汇总和请求级指标、团队和团队成员、模型价格覆盖、邀请、成员移除以及通知投递日志。
  • DELETE /environments/{env_id}/api_keys/{api_key_id} 应答 409 KEY_IN_USE,条件是有声明映射解析到该 Key。此前它会成功。
  • DELETE /environments/{env_id}/models/{model_id} 应答 409,条件是有语义护栏把该模型用作其向量化模型。此前它会成功。

升级说明​

从任何早于 0.12.0 的版本升级时,本节说明都适用,包括那些途中越过 0.12.0 直接升到更新版本的升级。

  • 安全护栏无需任何操作。 这次作用域变更不会改变你现有护栏实际拦截的范围:升级会把原来隐含的环境级作用域写成一条显式的环境级挂载,并把此前某次启动错误放大到环境级的护栏恢复成你配置的窄作用域;它还会撤回此前删除操作遗留下来的挂载记录,因此网关那条"引用了不存在的护栏"的日志会自行停止。升级之后新建的护栏,则只作用于你为它挂载的对象。
  • 如果你直接调用控制面 API,请检查这二十一条新纳入契约的路由。 对它们的请求现在会按公开的 schema 校验,因此此前被接受并忽略的未文档化字段,现在会返回 400。
  • 会思考的 Gemini 模型上,记录的费用会上升。 它们的思考 Token 此前完全没有被计入,现在会出现在 completion_tokens 与 reasoning_tokens 中并参与计费。按此前偏低的数字标定的预算和费用告警需要重新评估。其他模型和服务商不受影响。
  • 检查聚合 aisix_usage_events_emitted_total 或 aisix_usage_event_drops_total 的仪表盘。 这两个计数器新增了 user_id 与 status 标签,会改变未显式指定标签的 sum by (...) 的基数。status_code 族标签保持不变。

0.11.0​

发布日期: 2026 年 8 月 28 日

这个版本的主题是安全护栏。筛查新增两种类型——一种按语义而非模式判断,另一种运行你自己写的脚本——同时整个子系统变得可追责:护栏拒绝一个请求时,现在会说清是你的策略命中了,还是这条规则根本没跑起来;每一次强制命中也都会进入日志和用量记录。与此同时,网关滚动更新时不再丢弃流量,Anthropic 协议上的提示缓存用量得到正确计费与度量,还有几处可能让运营方悄无声息丢失数据、或者执行了一次什么都没做的"升级"的路径被堵上了。

行为变化​

  • 入站安全护栏现在会在每一个到达模型服务提供方的请求上运行。 此前只有当请求携带网关已经提取出的文本时,护栏链才会被调用,因此不带文本的请求——没有参数的 MCP 工具调用、没有 prompt 的语音转写、没有 prompt 的图片编辑、对空字符串做 embedding——都会绕过筛查直达上游,而 /v1/messages/count_tokens 与 /a2a/:agent 则从未被筛查过。按路由变化的是提供给护栏链的文本,而不是护栏链是否被调用。如果你依赖某条护栏把守数据外发,那么在这个版本之前,它并没有覆盖上述路径。 另外,当挂有护栏时,Anthropic 解析器无法读懂的请求体现在会被拒绝,而不再转发给上游。
  • 护栏拒绝现在会记录在它所产生的用量事件上。 控制台日志页 Guardrail blocks 视图筛选所依据的那个标记,此前只有十四个可能拒绝请求的接口中的两个会设置,因此在调用方正被拒绝的同时,那个视图可能显示为空——读起来就像网关完全没有记录任何护栏活动。现在所有接口都会设置它。
  • 无法运行的护栏不再声称你的内容被拦截。 当一条筛查规则失败时——上游不可达、脚本返回了不是裁决的东西、超时——这次拒绝现在会如实上报:调用方收到 422,其中 "code": "guardrail_unavailable",消息指出是哪条护栏以及失败原因(request rejected: guardrail 'x' could not evaluate it (...)),而不再是真正命中时才该出现的 request blocked by content policy。网关会打一条 WARN 日志,aisix_guardrail_latency_seconds 上的 error_type 也会标明原因。HTTP 状态码与 error.type 保持不变,因此基于它们的告警仍然会把两种情况都计入。这适用于所有类型的护栏、所有接口。aisix_guardrail_blocks_total 一如既往地把两者合并计数——它不带任何标签,因此无法区分二者,而且它只在 chat completions 这条路径上记录。要统计策略拦截,请使用 aisix_guardrail_latency_seconds_count{result="blocked", error_type="none"}; 同一序列上 error_type != "none" 的部分就是规则失败。不要只按 error_type 筛选——这个直方图记录的是每一次护栏执行,其中包含被放行的请求。
  • 安全护栏默认改为失败即拒绝(fail closed)。 两个平面上 fail_open 现在都默认为 false:无法连通其服务的规则会拒绝请求,而不是让它未经筛查地通过。需要保持旧行为的,在该护栏上设置 fail_open: true。脚本故障同样遵循这个默认值。
  • 超出服务商长度上限的内容改为分块,而不再截断。 超限的请求体此前会被截断后只筛查一部分,这在一个"本该看到全部内容"的控制上是个静默的漏洞。现在它会被分块并完整筛查——每一个分块都会被提交,且不设分块数量上限,因为一旦给分块数设预算,超出的部分就成了从后门溜走的未筛查内容。
  • mandatory 开关已移除。 它与 fail_open 表达的是同一件事。请从存量配置中删除;"不允许被绕过"的护栏就是 fail_open: false 的护栏。
  • 已移除的 /passthrough/* 隧道现在返回普通的 404。 0.10.0 用显式 passthrough 路由取代了隐式隧道,并保留了一个版本的 410 Gone 迁移指引。那个版本已经发布,因此未被任何路由认领的 /passthrough/* 路径现在走路由器的常规未命中路径,这个命名空间完全交由你用显式路由认领。随之移除的还有对应的 WARN 日志和 provider="unresolved" 指标序列。
  • /v1/messages 现在会上报 OpenAI 兼容上游的提示缓存命中。 当 OpenAI 兼容上游服务一个 Anthropic 协议请求时,命中缓存的前缀不再被计入 input_tokens:客户端收到的 input_tokens 是未缓存部分,cache_read_input_tokens 是命中部分;用量记录则不做这个转换,它沿用 OpenAI 的形状:prompt_tokens 仍是整个 prompt,cached_prompt_tokens 是其中命中缓存的那一部分,而不是需要再加上去的另一笔——正因如此,日志、用量 API、CSV 导出与计费才能把缓存部分按缓存读取的价格计费。流式响应在收尾的 message_delta 中上报。该计数器仅在非零时发出。此前整个 prompt 都按未缓存价格计费。
  • 十二个指标族新增 upstream_protocol 标签。 它标明实际服务该请求的协议——跨协议转换此前会让这一点不可见。聚合类查询不受影响;精确匹配标签的仪表盘、告警和记录规则需要更新。
  • 已停止的网关会显示为离线。 节点存活现在由控制面判定,而不再在浏览器里计算,DpNode 上新增 status 字段(healthy / warning / offline),依据心跳时间推导。已停止的实例不会再一直显示为健康直到刷新页面,数据面列表也会自行更新。
  • 环境没有 MCP 策略时,GET /environments/{env_id}/mcp_policy 返回 200 且策略为 null,不再返回 404。该接口的 404 现在只表示环境不存在。
  • 通知通道的 URL 不会再因为回写而被销毁。 读取响应会对 URL 打码,因为 webhook 的路径本身就是凭证。此前那个打码值会被当作写入值接受,因此任何"读取-修改-写回"都会静默地把真实 webhook 替换掉并返回 200。现在原样回显的打码值是空操作,指向不同主机的打码值会被拒绝,创建通道时使用打码 URL 也会被拒绝。投递错误不再回显远端响应体——它可能包含该 URL。

新功能​

  • 语义安全护栏。 筛查规则现在可以按语义而非模式判断:给出允许和拒绝的示例语句,它会用你指定的 embedding 模型为每条消息打分,两侧可分别设置阈值。它逐条筛查消息,可以只看用户消息,也可以看整段对话。
  • 自定义脚本安全护栏。 对于内置类型无法表达的策略,可以自己写检查逻辑:网关在沙箱中运行你的脚本,超时时间由你设置,密钥按名称注册而不是内联写入。钩子返回 {action: "none"}(或 "allow")表示放行,{action: "block", reason, reason_code} 表示拒绝,{action: "mask", segments} 表示改写。这四个就是全部词汇——返回其他任何东西都属于脚本故障,并会被如实上报。
  • PII 规则可以只作用于捕获组,并指定替换内容。 自定义规则可以只脱敏匹配中真正敏感的那一部分,并指定替换用的字符串,而不是用固定的记号遮盖整个匹配。
  • 强制生效的护栏命中会进入日志和用量记录。 每个 LLM 接口现在都会记录是哪条护栏作用于该请求,因此被拦截或被脱敏的调用事后可以归因,而不再只表现为一次拒绝。日志页会区分策略拦截与失败即拒绝导致的中断。
  • validate 会报出能加载但跑不起来的护栏。 配置能解析、却构建不出规则的行——非法的正则表达式、无法识别的检测器或动作取值、编译不通过的 kind: custom 脚本——此前只会打一条 WARN 日志后被移出护栏链,它所描述的筛查就这样悄无声息地不存在了。现在这类问题会在校验时暴露,而不是等到第一个请求。该检查在进程内构建配置、不发起任何网络请求,因此它不会告诉你某个服务是否可达;它还会完全跳过 kind: semantic 的行,这类行所指定的 embedding 模型不在检查范围内。
  • 网关开始排空时会退役 HTTP/2 连接。 收到 SIGTERM 后,网关在排空窗口开启时向 HTTP/2 下游发送 GOAWAY,客户端因此会停止在该连接上发送并改连他处,而不是与关闭过程赛跑。HTTP/1.1 此前已经收到 Connection: close。正在排空的网关同时会对健康探针保持存活,因此编排系统不会在排空中途把它杀掉。
  • POST /v1/images/edits。 multipart 图片编辑现在是一个有类型的接口,与代理的其余部分共享同样的认证、安全护栏和用量计量。
  • 提示缓存 Token 计数器与指标上的 upstream_protocol。 缓存读取与缓存写入现在各有自己的 Prometheus 计数器,因此"输入中有多少来自缓存"可以直接从指标回答,而不必再去聚合用量导出。
  • 网关的 trace id 会随每个请求存储,并可通过 trace_ui_url_template 中的 {trace_id} 插值成追踪查看器的链接,因此一条日志可以直接跳到它对应的链路。

改进​

  • 现在可以在控制台里重命名环境、编辑 embedding 模型。
  • 所有列表底部都支持直接跳转到指定页码,而不再只能逐页翻。
  • 邀请现在是新用户真正可以接受的东西:链接会先展示所属组织再让人加入,加入是一个显式动作而不是打开页面的副作用,并且邀请与被邀请的邮箱绑定。
  • 护栏配置的"读取-修改-写回"可以正常往返。描述已存密钥的那些字段原样回显时会被接受、被篡改时会被拒绝,因此脚本和基础设施即代码不必再手工剔除它们。编辑 Bedrock 护栏也不再索要 API 从不返回的 AWS 密钥。
  • 数据卷已存在而 .env 缺失时,离线安装包会拒绝启动并说明将会丢失什么,而不是重新生成密钥然后陷入崩溃循环。
  • AISIX_CLOUD_NOTIFY_ALLOW_PRIVATE_URLS、AISIX_CLOUD_MCP_SPEC_ALLOW_PRIVATE_URLS、AISIX_CLOUD_ALLOW_FRESH_BOOTSTRAP 与 AISIX_CLOUD_PRICESYNC_URL 现在可以在离线安装包的 .env 中设置;此前它们写在文档里却无法生效。
  • 用量按 UTC 自然日分桶,不受会话所在时区影响;请求总数为精确值而非抽样;估算得出的用量会被标注为估算值。
  • 日常使用控制台不会再耗尽自身的认证额度。受限流的 Token 刷新现在显示为"稍后重试",而不是"你已登出"——此前已登录的用户会被要求重新登录,另有几处流程也把一次失败的会话读取当成了会话丢失。
  • Overview、Logs、Budgets 与 Observability 页面在数据尚未加载完成时,不再渲染不完整或有误导性的数字。
  • 文档所述的 On-Premises 升级流程现在真的会更新版本。AISIX_VERSION 归安装包所有,每次启动时按包内容对齐;此前它固定在 .env 里,因此照着文档操作会让旧镜像继续运行,还报告成功。需要固定版本请改用镜像变量。降级会被拒绝,除非设置 AISIX_ALLOW_DOWNGRADE=1。
  • 控制面启动失败时会指出原因——数据库密码错误、主密钥错误、密钥 id 不匹配、缺少 CA 根——并同时读取 api 与 dpm 两侧的日志,而不再只留下一句"容器不健康"。

修复​

  • /v1/realtime 重新可以对接 OpenAI。 网关此前在每个 realtime 连接上都发送一个 beta 启用请求头;OpenAI 现已转正式版的接口会拒绝它并在客户端发出任何内容之前关闭会话。该请求头现在只在调用方主动要求时才转发,因此遗留客户端仍能得到 beta 形态,其他人则连到正式接口。
  • kind: custom 安全护栏现在可以在控制台里创建。 网关此前没有在能力清单里宣告这个类型,因此控制台把它显示为"不受支持",尽管两个平面都能运行它。
  • 没有配置 api_base 的 OpenAI 模型服务提供方 Key,现在在所有路由上都会回落到厂商默认地址,而不只是部分路由。
  • 对模型服务提供方 Key 的空操作更新——把已存的内容原样发回——现在会成功,而不再返回内部错误。
  • 所有接受 multipart prompt 字段的接口都会拒绝非 UTF-8 内容。
  • 控制台编辑表单中,逐项设置的 PII 处理方式不会再丢失。
  • 在三层 MCP 规则之前写入的 API Key 配置行仍然可以正常加载。已退休的 mcp_access.mode 选择器按普通的未知字段忽略,因此整行不会加载失败,该 Key 的 mcp_access 块其余部分照常读取——一行被拒绝的 API Key 会失去对它全部流量的认证能力,而不只是 MCP 流量。
  • 从未接线的静态 OTLP 导出配置块不再打印虚假的成功日志。

升级说明​

  • 先升级控制面,再升级网关。 这是受支持的顺序。在这个窗口期内,仍停留在 0.10.0 的网关无法运行新增的护栏类型(semantic、custom)、PII 的 replacement 字段,以及新增的 text_source 取值:它无法解析这样的配置行,会把整行丢弃,因此该规则在那里什么也不筛查。控制面仍然会保存这样的配置——它不会拒绝——并在写入响应中返回一个 warnings 数组,指出是哪个字段、从哪个版本起才能读取它,以及你有多少个网关受影响。请务必查看这些警告: 在所有网关升级完成之前,这条规则在尚未升级的网关上并未生效。
  • 重新核对你的安全护栏此前究竟覆盖了什么。 这个版本中有两处修复改变了答案:入站护栏链现在会在此前被跳过的路径上运行,拒绝也会记录在每一个可能拒绝的接口上。如果某条护栏此前看起来一直很安静,那可能是覆盖缺口,而不是流量少。
  • 重新录入升级前已被破坏的通知通道 webhook URL。 如果你曾经通过 API 读取某个通道再把整个对象写回,那么真实的 webhook URL 已经被它的打码形式替换,并且无法找回——它只存在于服务商那边。升级后,处于这种状态的通道会在投递错误中报告出来;请从 Slack(或你使用的服务商)重新取得该 URL 并填回。只通过控制台编辑过的通道不受影响。
  • 更新精确匹配标签的指标查询。 十二个指标族新增了 upstream_protocol。
  • 把 aisix_guardrail_blocks_total 当作策略命中量的查询,同时也在统计规则失败。 这个计数器不带任何标签,从来就没有区分过两者,而且它只在 chat completions 这条路径上记录(aisix_guardrail_bypasses_total 同理)。由于 fail_open 现在默认为 false,服务不可达的护栏会拒绝请求而不是放行,因此此前会计入 bypasses 计数器的失败,现在改为计入 blocks 计数器。要统计整个网关范围内的策略拦截量,请使用 aisix_guardrail_latency_seconds_count{result="blocked", error_type="none"}。

0.10.0​

发布日期: 2026 年 8 月 20 日

这个版本的主题是 Agent 流量。正向代理流量——把 IDE 或编码 Agent 指向网关——现在由一个显式、可审计的路由资源承载,而不再是那条需要猜测"该借用哪个凭证"的隐式隧道。MCP 支持了协议的 2026-07-28 修订版、面向无凭证客户端的匿名访问、OAuth 2.1 发现,以及一条统一的工具授权规则。模型组新增一致性哈希与优先级层级。网关在关闭前会保持一个排空窗口继续接受连接,不再拒绝负载均衡器尚未停止转发的请求;通过 OTLP 导出的链路追踪也形成了真正的层级结构。

行为变化​

  • 隐式的 passthrough 隧道被显式路由取代。 /passthrough/<provider>/<rest> 不再按模型服务提供方的名字自动解析;未被任何路由认领的 /passthrough/* 路径返回 410 Gone(error.code: endpoint_removed),并为每次命中打一条 WARN 日志指出调用方,便于找出尚未迁移的客户端。迁移方式:创建一条 passthrough 路由,path_prefix 设为 /passthrough/<provider>、target_url 设为原先的 API base、provider_key_id 设为它此前借用的那把 Key——客户端 URL 即可逐字节保持不变。有两处行为与旧隧道不同:路由是单次转发,上游 5xx 与传输层重试不再进行;由于路由不解析任何模型,这类流量也不再交叉标记模型冷却。访问权限是调用方 Key 上的显式授权(allowed_routes),没有授权的 Key 访问不到任何路由。
  • MCP 工具访问改为三层求交的一条规则。 环境策略、调用方所属团队的策略、以及 Key 自身的 mcp_access 块,各自携带 allow 与 deny 列表。allow 取交集、deny 取并集,因此任何一层都无法放宽另一层已经收紧的范围;未设置的层不施加任何约束,而三层都没有的调用方没有任何 MCP 访问权限。策略与 Key 上的 mode 均已移除,Key 上的 allowed_tools 也已移除(Key 这一层就是 mcp_access.allow),遗留 Key 的迁移流程一并删除。如果你配置过 MCP 工具策略,升级后请重新核对:最终生效的授权会按上述规则重新计算,可能与旧配置产生的结果不同。 其中两处变化影响最大:团队策略现在是在环境授权基础上进一步收窄,而不再是替换它,因此它无法再授予环境本身不允许的工具;没有 mcp_access 块的 Key 现在会跟随策略层,而不再游离于策略之外。每一层都必须写出 allow,因此一个只打算做减法的层需要把 allow 侧显式写成 ["*"]。
  • 安全护栏拦截 MCP 工具调用时,改为以工具错误的形式作答。 调用在协议层面返回成功,结果上带 isError: true,消息中指出是哪条安全护栏生效——绝不回显命中的内容——而不再返回 JSON-RPC 的 -32600。调用方 Agent 因此看到的是一段可以据此调整的工具输出,而不是一条中断的传输通道。此前依据 error.code == -32600 判断拦截的客户端,需要改读 result.isError。
  • weighted 路由策略与 sticky 开关已移除。 权重现在是每个目标自身的属性,在所有策略下都可用:round_robin 采用平滑加权轮询,因此权重相等或缺省时与此前的声明顺序轮转完全一致,权重不等时则严格保持比例。会话粘性成为独立策略 consistent_hash。通过 AISIX Cloud 管理的部署会自动迁移。声明式配置需要手工更新:weighted 改为 round_robin 并保留权重,weighted 加 sticky 改为 consistent_hash。仍然写着 weighted 的存量配置会加载失败,而不会被悄悄改变含义。迁移到一致性哈希后,会话与目标的对应关系会重新分布一次,因为它构建哈希环的方式不同。
  • 不受支持的 MCP 协议版本改为在 JSON-RPC 信封内被拒绝。 当请求的 MCP-Protocol-Version 请求头指定了该端点不提供的修订版时,返回 400 并附带一个 JSON-RPC 错误,其中列出受支持的版本,而不再返回游离于所有网关信封之外的裸 text/plain 响应。该端点提供 2025-03-26、2025-06-18、2025-11-25 与 2026-07-28;不再宣告 2024-11-05——它只存在于 HTTP+SSE 传输时代。
  • 通过 OTLP 导出的链路追踪现在形成层级结构。 到达上游的模型请求会产生一个 HTTP SERVER 跨度、一个覆盖全部重试与故障转移的逻辑 CLIENT 跨度,以及每次上游尝试各一个子跨度,取代了此前“每个用量事件一个扁平跨度”的形状。没有上游分发的已导出请求链路只有 SERVER 跨度;不采用逐次尝试追踪的协议包含 SERVER 跨度和一个 CLIENT 跨度。任何以“每个请求一个跨度”为前提的用法——跨度数量告警、按名字计数——都会看到结构性跨度出现。承载完整属性集的是尝试跨度,可用 aisix.attempt_index 识别;结构性跨度携带较少的关联属性,其中包括 aisix.request_id,SERVER 跨度的 Kind 为 2。另外,调用方的 traceparent 与 tracestate 不再转发给模型服务提供方;运营方为可信上游显式配置的 default_headers 条目仍然有效。
  • 文本转语音的延迟改为按首字节计。 /v1/audio/speech 现在边接收边转发合成的音频,而不再整体缓冲,因此播放器可以在首批字节到达时就开始播放,上报的延迟也随之从"到最后一个字节"变为"到第一个字节"。这与此处所有其他流式接口已有的口径一致。

新功能​

  • Passthrough 路由。 一条路由把一个网关入口——路径前缀、入站 Host 白名单,或两者兼有——绑定到一个上游目标,因此可以把 IDE 或编码 Agent 指向网关,在不改动客户端的前提下对其流量进行审计。Host 匹配在路由之前进行,因此携带原始 Host 送达的正向代理流量可以认领网关同样在用的路径;路径匹配则作为路由器的兜底,因此一条路由绝不会遮蔽网关自身的 API。调用方可以用网关 Key 认证、把 Key 放在你指定的请求头里(从而让 Authorization 留给上游凭证),或者以受源 CIDR 白名单约束的绑定主体身份匿名访问。上游凭证要么由模型服务提供方 Key 注入,要么在路由删除网关凭证和固定请求头集合后转发调用方凭证。可选的设备注入身份请求头会被记录为该请求的终端用户身份,用于按员工归因。请求信封按请求识别——chat、Responses、completions 或不透明——并据此驱动安全护栏取文、审计留存与 Token 计量;非 LLM 调用的流量不会产生虚假 Token。SSE 响应逐帧转发。参见 Passthrough 路由和面向 IDE AI 流量的正向代理。
  • 模型组的一致性哈希与优先级层级。 strategy: consistent_hash 通过把请求键哈希到目标环上,将每个会话固定到同一个目标:相同的键始终命中同一个目标,权重决定各目标的份额,而某个目标故障时只有它自己的会话迁移到环上的后继目标,其余键的映射全部保持不变。请求键来自你配置的来源链(hash_on:请求头、Cookie、调用方 API Key 或客户端 IP),默认使用路由键请求头并回退到 API Key。此外,每个目标都可以设置 priority:目标据此划分为若干层,数值越大越优先,只有当某一层内所有目标都失败或被健康状态摘除后,下一层才会收到流量——因此备用池可以在活跃池之后静默待命,而首个发现整层已死的请求也能在层内溢出并成功返回。
  • MCP 2026-07-28。 /mcp 与 /mcp/{server} 提供该规范的最终修订版,包含免握手的发现生命周期与无状态传输。已注册的 MCP 服务器可选配置 protocol_version,用于固定网关开启上游会话时使用的修订版——这是访问"不再响应旧握手"的服务器的唯一方式;不配置时网关按此前方式协商,因此既有配置保持不变。两个方向上都是显式选择:网关既不探测也不静默回退,因此版本不匹配会明确失败,而不会悄悄协商到一个你本想排除的版本。
  • MCP 匿名访问。 环境可以允许不携带任何凭证的 MCP 客户端访问指定入口,并以你指定的一把 API Key 的身份运行——该 Key 的工具授权、限流、预算与用量归因全部适用。它受一份必填的源 CIDR 白名单约束,需要列出所开放的入口,且聚合入口 /mcp 需要显式开启。携带凭证的客户端仍按正常流程认证;凭证无效时会被拒绝,而不会被降级为匿名服务。
  • 面向 /mcp 的 OAuth 2.1 资源服务器发现。 配置了规范资源 URL 并启用了身份提供方后,网关会发布受保护资源元数据,并对未认证的 MCP 请求返回指向该元数据的 WWW-Authenticate 质询,使标准 MCP 客户端能够自行发现到哪里获取 Token。Bearer Token 的 audience 必须包含该 URL。
  • 安全护栏可以限定到单个 MCP 服务器,从而只守护某一个已注册的服务器,而不必守护环境内所有 MCP 流量。安全护栏现在还会扫描工具的结构化输出,而不只是文本块。
  • 关闭时的排空窗口。 收到 SIGTERM 后,网关立即将自身标记为未就绪,随后至少在 shutdown.min_drain_secs(默认 30 秒)内继续接受新连接,然后才关闭监听器,使负载均衡器在其自身检测窗口内转发过来的连接仍能被正常服务。窗口期内 HTTP/1.1 响应会带上 Connection: close,让使用连接池的客户端在使用过程中自然退休这些连接。这个窗口是下限而非期限:只有窗口耗尽且没有请求在途时,监听器才会关闭。
  • 现在会采纳 W3C 链路上下文。 合法的入站 traceparent 会让网关产生的 span 成为调用方链路的子节点;格式错误或重复的请求头会被忽略并改用本地根节点,而不会导致请求失败。span id 与 trace id 每个请求只生成一次,因此投递重试会重发完全相同的 id,而不是新的一组。用量事件中携带 trace id 以便关联。
  • 流式音频转写改为实时转发。 /v1/audio/transcriptions 在 stream=true 时现在边接收边转发帧,而不再从完整读取的响应体作答,同时仍会记录该请求的 Token 用量。带拦截或掩码能力的输出安全护栏仍走缓冲路径,因为它必须在任何内容到达调用方之前看到完整的转写文本。
  • Cloud Admin API 支持角色管理。 自定义角色的增删改查、组织角色分配,以及环境级角色绑定,现在都纳入了公开的 API 契约,并具备生成的绑定代码与请求校验。

改进​

  • 发布镜像现在采用基于性能剖析的优化(PGO)构建,内存分配器会在负载回落后通过后台线程把已释放内存归还给操作系统。
  • 严格校验在拒绝"某个模型类型根本不读取的配置"时,现在会指出具体是哪个配置项,而不再只是报告文档校验失败。
  • Passthrough 流量会记录其识别出的信封所携带的全部用量维度。

修复​

  • 流式音频转写此前一直按零 Token 计费。 网关的 SSE 解码器只在遇到一对换行符时才认为事件结束,而模型服务提供方在转写流中使用回车换行分帧,因此携带 Token 计数的终止事件从未被解码,每一次流式转写都记录为零 Token。事件现在在任意两个连续的行终止符处结束。该解码器被所有流式桥接路径共用,因此任何使用回车换行分帧的上游都受此影响,不限于音频。
  • 在分层规则之前写入 MCP 访问配置的调用方 API Key 现在仍能正常加载,而不会被丢弃。
  • deployment 与 fallback 计数器现在会被正确发射;分发前的失败不再计入其中,失败的请求也会归因到已解析出的调用方。
  • Passthrough 流量在链路追踪与被拒请求事件中的归因已修正,基于请求头的认证返回 401 时会指出它期望的请求头。
  • 按 Host 匹配的正向代理路由现在可以认领网关保留的路径前缀,并镜像完整的请求路径。
  • 音频元数据解析不再对普通上传文件输出告警日志。
  • 控制台方面:创建模型时的选择器不再显示为"不支持",Dimensions 字段不再被错误标注为可选,页面路由切换有了加载态,MCP 认证设置也移到了 MCP Access 页面,与其余 MCP 配置放在一起。

升级注意事项​

  • 请先升级控制面,再升级网关。 这是受支持的顺序,中间的混合版本窗口可以持续任意长时间。在窗口期内,仍运行 0.9.x 的网关会停止服务此前使用 weighted 加 sticky 的模型组(迁移后的配置使用了该版本不认识的策略名),也不会应用 MCP 工具策略(其存储形状已变化)。调用方 API Key 在整个窗口期内始终可以正常认证——只是在尚未升级的网关上,它们的 MCP 访问处于关闭状态,直到该网关完成升级。这两种情况都可以在控制台的数据面兼容性视图中看到。
  • 通过 AISIX Cloud 管理的部署,会在升级后控制面首次启动时自动迁移存量的路由配置。声明式配置不会被自动迁移,需要按"行为变化"一节所述手工更新。

0.9.0​

发布日期: 2026 年 8 月 13 日

这个版本让网关明显更快,也让 Agent 流量变得可观测。代理层改为按核独立的 worker 模型,吞吐大约翻倍、p99 延迟减半。缓存学会了匹配“意思相同”的请求,而不再只能匹配“写法相同”的请求。A2A 调用现在会记录它推进了哪个任务、消耗了多少;经过验证的 JWT 也可以代替调用方 API Key,由身份提供方的 claim 决定请求以哪个调用方的身份运行。

这个版本同时完成了 0.4.0 中宣布的 Admin API 弃用:网关自带的 Admin API 现在是只读的,资源改为声明式管理或通过 AISIX Cloud 管理。

行为变化​

  • 网关的 Admin API 不再写入资源。 Admin 监听端口保留全部读取能力——各类资源的列表与详情、模型状态、健康检查、OpenAPI 参考和 Playground——但 /admin/v1/<kind> 上的 POST、PUT、DELETE 现在返回 405 并带 Allow: GET,API Key 轮转路由的两种拼写都返回 404。这完成了 0.4.0 中宣布的弃用。请改用资源文件管理资源(用 aisix validate --resources <file> 校验,用 SIGHUP 重载),或直接写入 etcd;连接 AISIX Cloud 的网关从不暴露该监听端口,不受影响。声明式轮转调用方 Key 的方式是:用同一个资源 id 写入新的 key_hash,写入传播后旧密钥立即失效。发布的 Admin API 参考中已不再包含写操作。参见资源文件。
  • 缓存条目默认按调用方 API Key 隔离。 缓存策略新增 scope 字段,默认值为 api_key,因此一个调用方的应答绝不会被回放给另一个调用方。依赖环境内跨 Key 共享的部署需要显式设置 scope: env。无论选择哪种,缓存键的形状都会发生变化,升级后会出现一次性的全量未命中。参见缓存。
  • 首 Token 时间改为在第一个流式帧处停表,不再区分帧的类型。 此前它会一直等到出现携带生成内容的帧,因此对于“先静默思考再作答”的模型,记录到的是思考结束的时刻——这个数值可能超过该请求自身上报的延迟,也无法与前置网关的口径直接比较。思考所花的时间仍可从上游延迟中看到。按旧口径校准过的监控面板和告警阈值需要重新调整。参见指标与日志。
  • 调用方传入的 request id 现在会被网关采用。 网关默认接受 x-aisix-request-id:该值会原样回传、记入访问日志与用量事件,并转发给上游。id 必须是 1–256 个可见 ASCII 字符;不满足的一律忽略并由网关自行生成,因此格式错误的请求头绝不会导致请求失败。若还想遵循 x-request-id 约定,将其加入 proxy.request_id.accept_headers;把该列表置空则恢复此前行为。由于该 id 现在由调用方控制,它既不唯一也不可信,因此不会被用作任何指标的标签。参见访问日志与请求关联。
  • 某个模型类型运行时根本不读取的配置,现在会被拒绝,而不再是存下来却被忽略。 模型组上的 retries、auto_prompt_caching、cost,Ensemble 上的通用调用参数,以及语义路由上的 auto_prompt_caching 和 cost,在写入时都会被拒绝并返回 400。携带这类字段的资源文件将加载失败,并指出出问题的条目。已经存下这类字段的模型不受影响:网关会剥离该字段并按“部分兼容”上报,而不会让这个模型停止服务。反方向上,语义路由和 Embedding 模型现在接受 timeout、stream_timeout 和 retries,此前这些是被拒绝的。
  • 若干此前被静默接受的配置现在会被拒绝。 创建模型时携带属于其他类型的配置块、把通配符别名用作 Ensemble 成员或裁判模型、用作语义路由的目标或默认模型、用作缓存策略的作用目标,把被引用的模型改名为通配符,以及让缓存策略指向不存在的模型,现在都返回 400。这些操作此前都会被接受,然后被悄悄忽略。
  • 经过通配符模型的流量按通配符自身的名字上报。 指标、限流计数桶和健康状态现在以配置中的通配符条目为准,而不再以各调用方随手写下的别名为准,因此一个模型就是一个身份,不会因写法不同而分裂成多条序列。按调用方别名过滤的监控面板,会看到对应序列在这个版本处中断。
  • 升级注意事项。 控制面把用量表的 request_id 列从 uuid 加宽为 text,以便保存调用方自己的 id。在大表上这会触发整表重写——大约每 1000 万行 6 分钟——重写期间控制面不对外服务。Helm Chart 的启动探针预算已相应放宽到 30 分钟;如果你使用自己维护的编排清单,请在升级前同步调大。

新功能​

  • 代理层改为按核独立的 worker 模型。 每个 worker 拥有各自的运行时、监听套接字和上游连接池,因此一个请求的接收、派发和应答都在同一个线程上完成,不再需要在线程之间来回移交两次。在 4 核上,吞吐随并发度提升 54%–88%,p99 延迟大约减半,每请求的系统调用次数从 11.9 降到 5.0。Linux 上默认开启。两个启动期生效的配置项:proxy.thread_per_core 和 proxy.workers,后者默认取进程可用的并行度并会跟随 cgroup 的 CPU 限制。当每个 worker 分到的客户端连接不足约 4 条时,内核的连接分配会不均,此模式反而慢于共享运行时;这种低并发场景请设置 proxy.thread_per_core: false。
  • 语义缓存。 缓存策略现在可以按语义匹配:未命中精确匹配的请求会被向量化,并从余弦相似度达到设定阈值的最近条目中返回结果。只有纯文本请求会走这条路径——包含图片、音频或工具调用的请求一律走精确匹配。条目可以存放在各网关自身的内存中,也可以设置 backend: redis,借助 Redis 向量检索在多个副本间共享。共享方式要求 Redis 8 及以上版本或加载 search 模块;网关在启动时探测,若不具备该能力,则继续提供精确匹配并在日志中说明,而不会让流量失败。策略也可以在不删除的前提下整体清空。参见语义缓存。
  • JWT Claim 映射。 新增的资源可以把经过验证的 OIDC claim 解析到一个已存在的调用方 API Key,从而无需为每个用户单独发放 Key,就能由身份提供方决定请求以哪个调用方的身份运行。规则按优先级顺序求值,第一条 claim 条件全部成立的规则选定目标 Key,随后请求完整继承该 Key 的模型与工具访问权限、限流和预算。条件支持对嵌套 claim 路径做精确字符串匹配和数组包含匹配。未命中任何规则的 Token 一律拒绝。用量事件会记录 subject、身份提供方和命中的映射——请注意 subject 属于最终用户标识,会随用量事件流向已配置的可观测性导出目标。参见 Claim 映射。
  • A2A 调用现在具备协议级可观测性。 每次调用都会记录操作类型、任务 id、上下文 id 和最终任务状态,并对两套线上词汇做归一,避免同一个指标被拆成两份。流式调用还会额外记录首个事件的到达时间、事件数量,以及流结束时调用方是否仍在接收,因此中途挂断的调用不再被计为成功。由于该协议本身不携带 usage 字段,网关会依据流经的消息文本估算 Token 并标记为估算值;成本保持为零,因为 Agent 的计费方式不是网关能够知晓的。指标按 Agent 和操作类型切分。参见 Agent 网关。
  • 模型服务提供方返回的响应 id 现在会被记录。 它会出现在访问日志中,也会出现在每次上游尝试各输出一条的专门日志行里——后者覆盖了单条访问日志在结构上无法覆盖的两种情况:流式响应,以及重试或故障转移产生的后续尝试。控制台的日志详情面板也会展示该 id,因此排查上游侧问题时无需再手工跨系统关联记录。
  • 限流策略支持 day 窗口,按 UTC 自然日计数。参见限流策略。
  • 控制台的请求日志按网关面拆分。 LLM、MCP 和 A2A 流量各有独立的标签页,且每个标签页只提供真正能用于筛选它的过滤条件,而不再是一个混合列表配一组只对部分流量有效的过滤器。
  • 控制台的下拉选择框支持搜索。 模型、模型服务提供方 Key、调用方 API Key 等可能变长的选择框,现在都可以边输入边筛选,不必在完整列表中滚动查找。
  • 控制台会提示网关的配置兼容性。 当你保存的某个配置并非环境内所有网关都能理解时,控制台会在保存时和数据面视图中给出提示,指明具体字段和引入该字段的版本,而不是让这个配置在旧版本网关上静默失效。

改进​

  • 除按核 worker 模型之外,每请求路径还做了一系列优化:改用 jemalloc 内存分配器并启用链接期优化、为零配置部署跳过不需要的处理环节、为每个 worker 缓存指标句柄、对下行连接设置 TCP_NODELAY、缓存上游端点 URL,以及每个请求只加载一次配置快照。
  • 限流条件中的模型维度,现在会同时匹配调用方寻址的条目和实际派发到的目标,因此以模型组为条件的策略能够覆盖所有寻址到该组的请求。此前只比较派发目标,这类条件永远不会命中。
  • 语义路由在选路时会遵守成员自身的访问规则,遇到调用方无权使用的成员会转向其他目标,而不是直接派发过去。
  • 按模型的限流现在适用于所有模型类型,控制台也在每种类型上提供限流表单。
  • 缓存策略的作用目标会在创建时校验;被策略引用的模型改名后,引用会同步更新。

修复​

  • 已过期的邀请不再继续占用邮箱地址,同一个人可以被重新邀请。仍在有效期内的邀请依然会阻止重复邀请。
  • 创建资源时把布尔字段显式设为 false,现在会真正存为 false。此前数据库列默认值会替换掉零值,导致创建时设为禁用的 OIDC 身份提供方被存成启用,API 也随之回显为启用。
  • Realtime 端点上认证通过之后发生的拒绝,现在会归属到已解析出的调用方,而不再是没有身份信息的记录。
  • 已停止上报心跳的网关不再计入控制台的配置兼容性提示,避免一个已下线的实例让健康的集群看起来处于部分不兼容状态。
  • 从源码构建且未注入版本号的网关会上报一个占位版本号;该占位值现在被视为“版本未知”,而不再被当作某个真实的旧版本,因此这类集群不会再对其实际可能支持的特性长期告警。

0.8.2​

发布日期: 2026 年 8 月 11 日

这是一个面向 A2A 网关的维护版本。网关现在会向上游声明每台 Agent 所固定的协议版本,能找到发布在路径前缀下的 Agent Card,把 Card 上公布的每一个地址都指向自身,并把 message/stream 按事件到达的节奏实时中继,而不再缓冲整个响应体。此外,Agent 与 MCP 服务器的命名规则和凭据约束现在适用于所有配置路径,而不再只有网关自带的 Admin API。

行为变化​

  • 通过资源文件提供的 A2A Agent 与 MCP 服务器定义,现在会按 Admin API 相同的规则校验:名称格式、各 auth_type 所需的凭据,以及基于 OpenAPI 的 MCP 服务器所需的字段。违反其中任何一条的文件不再加载,网关会指出是哪一条目缺少哪个属性,而不是带着一份无法工作的定义启动——名称中含 / 的 Agent 会把自己的 /a2a/<name> 路由劈成两段,auth_type: bearer 却未设置 secret 则等于用空凭据向上游认证。通过控制面配置的部署不受影响,因为这些规则在创建资源时就已生效;由控制面托管的网关只会拒绝出问题的那一条,其余配置继续服务。发布前可用 aisix validate --resources <file> 先行检查。参见 Agent 网关。

修复​

  • 网关现在会在发往某台 Agent 的每个请求中,用 A2A-Version 头声明该 Agent 所固定的协议版本,包括获取 Agent Card 的请求。此前网关从不发送该头,而 A2A 规范要求 Agent 把该头的缺失读作 0.3 版本——因此固定为 1.0 的 Agent 会回 VersionNotSupportedError,配置的 protocol_version 形同虚设。调用方自行提供的版本不会覆盖注册时固定的版本。
  • 发布在路径前缀下的 A2A Agent 现在能被正确发现。此前网关在源站构造 well-known Card URI,丢弃了注册时给出的路径,因此部署在 ingress 路径之后的 Agent、或按路径前缀区分租户的 Agent 平台,都会被请求一个它并不在该位置提供的 Card,而平台兜底返回的 405 会被当作 Agent 自己的应答。
  • 网关返回的 Agent Card 现在会把公布的每一个地址都指向网关自身。此前只重写顶层 url,supportedInterfaces 中仍是上游的真实地址——而 A2A 1.0 客户端正是从那里选取端点,因此可以绕过网关(连同调用方身份认证和按 Agent 的访问控制)直接访问上游 Agent。
  • message/stream 和 tasks/resubscribe 现在会按事件到达的节奏中继 Agent 的事件流。此前这两个方法走单响应路径,会缓冲整个响应体并按单个 JSON 文档解析;而事件流不是合法的 JSON,因此这两个本就用于观察长任务进展的方法都会失败并返回 502,完全无法使用。事件会跨数据块边界重新组装;遇到格式错误的事件会以错误结束流,而不是跳过它,从而避免被截断的任务被读成已完成的任务。

0.8.1​

发布日期: 2026 年 8 月 7 日

这是一个维护版本。它修正了网关判断上游是否使用 Anthropic 协议的依据,使指向自建 Anthropic 端点的模型可通过整个 /v1/messages 端点族提供服务,并原样转发请求体。此外,认证拒绝日志补充了排查问题所需的上下文,MCP 服务器重命名时工具授权会随之迁移,并修复了控制面上若干缺少可用请求格式或可操作错误提示的准入路径。

行为变化​

  • 启用 auto_prompt_caching 现在要求模型的服务提供方密钥采用 Anthropic 协议,即 provider: anthropic,或适配器为 Anthropic 的 BYO 密钥。该设置通过注入 Anthropic cache_control 标记实现;此前,该设置在其他上游上虽然可以保存,却从不生效,也不会提示运维人员提示词缓存并未开启。现在,在其他上游上启用该设置会返回 400。所有模型服务提供方仍可关闭该设置,因此可以清理本版本之前配置的模型;如果无法确定密钥的适配器,系统仍会允许操作,而不会在无法确认的情况下拒绝。参见 Anthropic 提示词缓存。
  • 配置为 provider: byo 且适配器为 Anthropic 的模型,现在可通过 /v1/messages 提供服务并原样转发请求体,不再通过跨模型服务提供方的桥接重新编码。客户端自行设置的 cache_control 标记会原样到达上游;此前,该标记会被丢弃,或在模型启用 auto_prompt_caching 时被改写为模型配置的 TTL。这也会改变适用的上游缓存写入价格:1 小时写入的价格是基础输入价格的 2 倍,5 分钟写入的价格是 1.25 倍。身份认证行为保持不变。

改进​

  • 认证拒绝日志现在包含排查问题所需的请求上下文:通过可信代理配置解析出的调用方地址、HTTP 方法和路径,以及请求 ID。密钥被禁用或已过期时,拒绝日志还会包含该密钥的 ID。返回 401 的请求会在任何处理程序运行前被拒绝,因此不会进入访问日志;拒绝计数指标此前是唯一的记录,但该指标无法说明调用方是谁、拒绝发生在何时或请求了哪条路由。日志级别保持不变:扫描器流量仍使用 debug 级别,默认日志级别的输出与之前完全相同。参见指标与日志。
  • AISIX Cloud Admin API 参考现在正确描述了模型服务提供方请求头和条件限流的计数器语义。此前,参考文档称修改策略的 conditions 会重置当前窗口;实际上,计数器 Key 由策略 ID 和所选 group_by 维度的值构成。因此,只修改 conditions 或 limits 会保留现有 Key 及其计数,而修改分组维度会使请求使用不同的 Key。

修复​

  • /v1/messages/count_tokens 现在依据适配器而不是模型服务提供方标识来判断上游是否使用 Anthropic 协议。指向 Anthropic 协议端点的 provider: byo 模型此前会在该端点上收到 400,但同族的 /v1/messages 可以正常提供服务。
  • MCP 服务器重命名时,工具授权现在会随之迁移。工具名采用 <server>__<tool> 格式,因此每项授权都通过名称引用服务器。按 API Key 配置的限流条目此前已经会随重命名迁移,但访问控制不会;这会在没有任何提示的情况下撤销对整台服务器的访问,使其工具从 tools/list 中消失。调用方 API Key 的 allowed_tools 和 mcp_access,以及环境级和团队级访问策略,现在都会一并重写。匹配名称模式而非某一台特定服务器的通配符(例如单独的 *)保持不变。参见工具访问控制。
  • Amazon Bedrock 和 Google Vertex 的模型服务提供方密钥现在可以仅通过 config 创建。两者的凭证无法放入单个 api_key 字符串,但 Schema 要求提供 api_key,而处理程序又会拒绝非空值,因此此前唯一可接受的请求必须使用文档中从未说明的空字符串。现在,缺少凭证的请求会指出该模型服务提供方实际接受的字段。参见选择模型服务提供方上游。
  • 用 PATCH 提交 "tls": null 现在会清除模型服务提供方密钥的 TLS 设置,与 rate_limit 等其他可选块的行为一致。此前它返回 400,只能用空对象清除。
  • 用量列表及其 CSV 导出现在包含 audio_duration_seconds。按时长计费的转写此前能看到费用,却无法从 API 读回它的计费基数。不含音频的请求会省略该字段。参见音频。
  • 离线包不再让两份安装变成一份。Compose 项目名此前取自解压出的目录名,因此在其他位置解压第二份安装包并运行 run.sh,会接管正在运行的安装,使用第二份安装的配置重建其容器,同时继续挂载原来的数据卷。项目名现在固定为安装包本身;若另一目录中已存在同名栈,启动会被拒绝,并同时显示两个目录路径和可选处理方式。原地升级不受影响;如需启动第二套独立安装,仍可显式指定 COMPOSE_PROJECT_NAME。参见 On-Premises 快速入门。
  • 离线包中的控制台容器现在拥有可写的 Next.js 缓存目录,与 Helm Chart 保持一致。
  • 可信代理 CIDR 与 User-Agent 客户端类型规则现在可以用环境变量设置。proxy.real_ip.trusted_proxies 和 observability.metrics.client_type_rules 此前只能写在配置文件里,用对应的 AISIX_* 变量设置会导致网关无法启动。因此完全依赖环境变量配置的部署——Helm Chart 与控制台给出的 docker run 片段——无法把自己的负载均衡器声明为可信代理,所有请求看起来都来自它。参见指标与日志。
  • 两处准入错误现在会说明如何修正。在策略不是 weighted 的路由组目标上配置 weight 时,错误会指出相关字段和策略,而不再只报告笼统的字段无效;provider 值无法识别时,错误会指出被拒绝的值,并说明目录路由需要控制台会话,而不是 Admin Token。
  • 控制台现在允许一个 API Key 访问多个模型组。此前,选择一个模型组会禁用其他选项,因此一个 API Key 只能引用一个模型组,尽管 API 始终接受包含多个模型组的列表,编辑对话框也从未实施该限制。两个对话框现在共用同一个选择器,这还修复了模型组、合议模型、向量嵌入模型和语义路由在编辑对话框中显示空箭头的问题。

0.8.0​

发布日期: 2026 年 8 月 6 日

此版本让限流足以表达真实的配额策略。单条策略现在可以通过条件树决定自己作用于哪些流量、按这些流量的任意维度拆分计数器、同时约束七种不同的量,并按周期性时间表自动暂停自身——例如工作日的非高峰时段、整个周末或指定的节假日。MCP 网关新增只服务单个 MCP 服务器的端点,并保留其原始工具名,使针对该服务器编写的客户端无需改动即可接入。Token、支出和请求指标现在覆盖所有上报用量的端点,而不再只有 Chat Completions 和 Messages;音频转写按音频时长计费。

行为变化​

  • 网关现在在所有 OpenAI 系列端点上都把 api_base 当作上游根路径。此前 /v1/chat/completions 会逐字把端点追加到所配置的 Base URL 之后,而 /v1/responses、/v1/rerank、/v1/audio/*、/v1/realtime、/v1/files、/v1/batches 和 /v1/fine_tuning/jobs 会在 Base URL 未以 /v1 结尾时插入一段 /v1,因此上游根路径不是 /v1 的密钥能正常处理聊天,其余端点全部返回 404。现在两条路径以同一方式解读 Base URL。带路径但不含版本段的 Base URL 现在会构造 https://proxy.corp/openai-shim/responses,此前构造的是 .../openai-shim/v1/responses;如果你依赖旧的补全行为,请把 /v1 写进 api_base。仅含主机名的 Base URL 仍会补上 /v1,以 /v1 结尾的 Base URL 行为不变,Anthropic 在所有 Base URL 形态下均不变。参见兼容 OpenAI 的模型服务提供方。
  • 两个指标的直方图桶边界发生变化。aisix_request_ttft_seconds 去掉了 50 毫秒以下的两个边界,因为它度量的是上游首 Token 时间,永远不会落在那里;aisix_request_e2e_latency_seconds 新增 420 秒和 600 秒两个边界,使 histogram_quantile() 能在 300 秒之上插值,而不是被钉在 300 秒。依赖旧边界的仪表盘和记录规则需要更新。两套边界现在都可以在 observability.metrics.buckets 下按指标分别配置。参见指标。
  • 首 Token 时间现在计入推理模型的首个推理增量。此前只有普通内容才会打点,因此先推理再作答的模型上报的首 Token 时间晚于调用方实际观察到的时刻。这类模型上报的数值会相应下降。参见指标与日志。
  • GET /v1/models 现在会连同直连模型、语义路由和合议模型一起列出模型组。模型组此前是唯一被过滤掉的虚拟别名,因此把模型组作为对外入口、并将调用方 API Key 限定到该模型组的部署,拿到的是一个空列表。授权没有任何变化,这些名字本来就可以被这些 Key 调用。只有断言精确模型列表的客户端会受影响。参见模型别名。

新功能​

限流​

  • 限流策略现在可以写成条件式,携带一棵条件树而不是单一作用域。条件可以匹配团队、成员、调用方 API Key、模型、模型名和模型服务提供方,通过显式的 and、or 分组组合,最多嵌套三层,支持取反,并可按相等、列表成员或正则表达式匹配字符串。因此同一个资源可以为不同流量承载不同配额,而不是只有一个固定数值。参见限流策略。
  • 条件式策略通过 group_by 拆分自己的计数器,按团队、成员、调用方 API Key、模型或它们的任意组合分桶。此前需要为每个租户各配一条策略,现在单条策略即可实施按租户的配额。
  • 一条策略可以任意组合约束七种量:每秒、每分钟、每小时、每天的请求数,每分钟、每天的 Token 数,以及并发请求数。
  • 匹配模型属性的策略会在具体模型确定处预留配额,对路由或合议模型的父别名而言即按每个目标预留。超限的目标被视为一次失败的尝试并故障转移到下一个,而不是消耗父别名自身的配额。
  • 限流拒绝现在会标明是哪条策略产生的。429 响应体携带该策略的 ID 和名称,aisix_ratelimit_rejections_total 现在统计所有端点上的拒绝,并带有生效层级和策略标签。在多条策略同时生效时,无归因的拒绝无法追溯成因。
  • 策略可以携带周期性的暂停窗口,窗口期内不予执行。每个窗口按星期或按显式日期选择生效日,起止时间是其自身 IANA 时区下的挂钟时间,结束时间早于或等于开始时间即视为跨越午夜,并归属于其起始日。多个窗口取并集,窗口结束后自动恢复执行,且切换不会重置计数器,因此无法通过在同一个限流窗口内暂停再恢复来清掉已消耗的配额。在 AISIX Cloud 中,控制台以限流策略表单上的时间表列表呈现该能力。参见限流策略。

MCP 网关​

  • 新增按服务器划分的端点 /mcp/{server},只服务单个已注册的 MCP 服务器,并以工具的原始名称列出其工具,不带聚合端点所加的 <server>__ 前缀。调用工具时同时接受裸名和带前缀两种写法,而工具访问控制始终在带前缀的形式上判定。因此针对某个服务器自身工具名编写的客户端,经由网关也无需改动即可工作。参见MCP 网关概述。

部署​

  • 新增 proxy.url_rewrites 配置,在网关入口处改写请求路径,按正则表达式匹配并支持在替换字符串中引用捕获组。启动时会校验这些模式,对于不携带配置文件的部署也可以通过环境变量提供。这让 Base URL 无法更改的客户端能够访问不同的网关路径。参见 URL 重写。

计费​

  • 音频模型现在可以按音频时长而不是 Token 计价。转写请求会以音频长度作为计费依据,模型价格按每分钟音频表示。在 AISIX Cloud 中,控制台的模型定价表单接受这类费率。参见音频和模型定价。

改进​

  • 详细请求指标以及 Token 和支出指标现在覆盖所有上报用量的端点,包括 Responses、Embeddings、Rerank、音频、图像和 Realtime。此前它们只覆盖 Chat Completions 和 Messages,因此其他端点上的用量虽然记入用量日志,却在指标中缺失。参见指标。
  • 配置读取现在向前兼容。携带了本网关版本不认识的字段的资源文档会正常加载并生效,未知字段被忽略并上报:配置状态端点的 partially_compatible、一条去重后的告警,以及一个新的 gauge 指标。此前任何未知字段都会导致整条文档被拒绝,这使控制面上每一次纯新增的变更,对尚未升级的网关而言都成了破坏性变更——携带新字段的调用方 API Key 会直接失效。写入路径仍然严格,依旧拒绝未知字段。参见配置状态。
  • 被拒绝的配置更新不再让最后一份可用值丢失。网关会在重新同步和重启之后继续提供此前为该键加载到的值,而不是丢弃该条记录。参见配置传播。
  • 模型服务提供方在已经开始的流中上报的错误,现在会带着其自身的状态码和消息呈现出来,覆盖 OpenAI 系列、Anthropic、Gemini 和 Amazon Bedrock 的流。此前 Anthropic 在流中途送达的 error 事件会被丢弃,被截断的流像正常完成一样关闭,客户端无法区分响应是被切断还是已经结束。这类流现在以一个错误帧结束,且不带完成标记。参见流式响应。
  • 因超出请求体大小限制而被拒绝的请求,现在会通过一个专门的指标上报其请求体读取是如何结束的,从而把客户端断开导致的拒绝与请求体被完整读完的拒绝区分开。参见访问日志与请求关联。
  • 当网关以明文 http 访问需要凭证的 MCP、OpenAPI 或 A2A 上游时,会告警一次,并按服务器和地址去重,使配置失误可见而不至于灌满日志。参见MCP 上游认证。
  • 发往 /v1/realtime 但并非 WebSocket 升级的请求,现在会被记录并以网关自身的错误格式作答;代理中其他位置的路径拒绝也走与其他早期拒绝相同的路径,因此会出现在访问日志和请求计数中。参见Realtime。
  • AISIX Cloud Admin API 参考现在记录了其公开的所有操作和 Schema,并将 Base URL 从固定的相对路径改为可编辑字段。该参考托管在 API7 文档站点,而不是读者的控制面上。因此,混合云或本地部署的读者可以把 Base URL 设置为自己的控制面,使示例使用正确的端点。

修复​

  • 流式转写现在会记录它上报的用量。此类请求此前记录零 Token,因此不产生费用,而同一个转写以非流式方式发起时会正常计费。参见音频。
  • 离线包的快速入门脚本现在打印可用的控制台地址。此前它打印的是容器内部端口,因此按默认安装路径操作时,照着打印出的 URL 访问会失败。参见On-Premises 快速入门。
  • 控制台的模型定价表单现在接受每分钟低于一美分的音频费率,多数模型服务提供方的音频定价都需要这一精度。
  • 控制台中的预算阈值提示不再暗示硬停止可以任意超出其上限。参见预算。

0.7.1​

发布日期: 2026 年 7 月 31 日

此版本让网关可以部署到此前无法接通的网络中。出站连接新增信任配置,因此证书由私有或企业 CA 签发的模型端点、安全护栏或 MCP 上游,无需进程级的变通手段即可访问,既可以在部署级配置,也可以在声明该端点的模型服务提供方密钥上逐个配置。运行在独立主机上、以 IP 地址寻址的数据面,现在可以完成双向 TLS 握手并接入其控制面。被调用方放弃的请求,以及网关在分发前就拒绝的请求,不再从访问日志和指标中消失。

行为变化​

  • 流式响应在传输中途被调用方放弃,现在记为 499 而不是 200。此前用量事件上报的是一次完整的投递,因此中途关闭连接的调用方与把整个流读完的调用方无法区分。按状态码 200 筛选的报表和仪表盘会看到这些请求转移到 499。参见指标与日志。

新功能​

出站 TLS​

  • 新增 upstream.tls 配置,通过 ca_file、client_cert_file、client_key_file 和 verify 设定网关在每一条出站连接上使用的信任配置。它适用于模型端点、所有安全护栏服务、MCP 和 A2A 上游、透传路由、JWKS 与 OIDC 发现,以及 OpenTelemetry 导出。此前私有 CA 之后的上游只会以一个笼统的连接错误失败,唯一的变通手段是进程级的 SSL_CERT_FILE 环境变量,而若干出站路径并不遵循它。参见TLS 与 mTLS。
  • 模型服务提供方密钥可以携带自己的 tls 块,其中包含内联的 ca_cert 和 verify 开关,因此面对多个私有 CA 的部署可以在声明端点的位置声明信任。证书以内联方式而非文件路径提供,因为配置模型服务提供方密钥的人没有办法把文件放到网关主机上。在 AISIX Cloud 中,控制台将其呈现为模型服务提供方密钥表单上的 Endpoint TLS 区块。
  • rediss:// 的缓存或限流后端可以携带字段相同的 tls 块,因为它通常位于你自己的部署内部,由与模型端点不同的 CA 签发。有两处限制被明确记录而不是静默忽略:Amazon Bedrock 支持 ca_file,但不支持客户端证书,也不支持 verify: false;Redis Sentinel 模式支持 verify,但不支持 ca_file。

改进​

  • 在分发前被拒绝的请求现在会出现在访问日志和 aisix_requests_total 中。请求体超过 request_body_limit_bytes 时会正确返回 413,但除此之外不留任何痕迹,这使得"客户端报告了一次网关毫无记录的拒绝"与"请求根本没有到达"无法区分。Content-Length 头冲突返回的 400 存在同样的缺口。这些拒绝发生在认证之前,因此不携带用量事件,也不会出现在 AISIX Cloud 的日志页上。
  • 在响应头之前就被放弃的请求会被记录,而不是凭空消失。此类请求此前同时缺席于访问日志、用量事件和指标,恰好掩盖了运维最想看到的情况:调用方在漫长的首 Token 等待中放弃。新增计数器 aisix_proxy_client_cancelled_requests_total 按端点统计它们。参见访问日志与请求关联。

修复​

  • 位于独立主机、以 IP 地址指向其控制面的数据面,现在可以完成双向 TLS 握手并接入。数据面管理器签发的服务端证书,其 SAN 只来自它的监听地址以及客户端发送的服务器名称,而在容器中这两者都得不到控制面的对外地址:监听器绑定在所有网卡上,因此没有主机名可读,而以 IP 地址发起连接的客户端根本不会发送服务器名称。现在对外公布的地址会传给数据面管理器,由它为该主机签发证书,因此 IP 地址与 DNS 名同样可用。通过 AISIX_CLOUD_DPMGR_BASE_URL 设置,或在 Helm Chart 中使用 api.dpmgrBaseURL。参见On-Premises 部署。

0.7.0​

发布日期: 2026 年 7 月 31 日

此版本让 AISIX 网关能够为 REST API 的 OpenAPI 3.x 文档中所描述的受支持操作生成 MCP 工具,无需另外部署 MCP 服务器。该能力在开源 AISIX 网关和 AISIX Cloud 中均可使用,由网关调用该 API 并注入所配置的凭证。MCP 服务器还新增了限定到单个服务器的按调用方限流。AISIX Cloud 增加了审核流程,可要求服务器在对调用方可见之前先获批准。此外,每个模型现在即使没有配置也会有上游截止时间,用量记录也把上游耗时与调用方实际等待的时间区分开来。

行为变化​

  • 用量事件的延迟字段被重命名以明确其作用范围,并新增一个字段记录调用方侧的等待。latency_ms 改为 upstream_latency_ms,ttft_ms 改为 upstream_ttft_ms,两者仍以单次尝试为范围。upstream_ttft_ms 现在从该次尝试开始处度量,而不是从请求进入处度量,因此可以与它旁边的延迟直接比较。新增的 downstream_latency_ms 以整个请求为范围。在 OpenTelemetry 导出中,span 属性 aisix.ttft_ms 改为 aisix.upstream_ttft_ms,并新增 aisix.downstream_latency_ms,因此任何读取这些名称的仪表盘或告警都需要更新。控制面同时接受新旧两种名称,因此由 AISIX Cloud 托管的网关无需改动。参见指标与日志。
  • 未配置超时的模型不再没有上界。新增部署级的 upstream.timeout_ms,默认 6000000,即 6000 秒,适用于既未设置 timeout 也未设置 stream_timeout 的任何模型。此前这类模型完全没有上游截止时间,因此接受了连接随后不再响应的上游会把请求无限挂住。这个默认值刻意宽松,它是兜底而不是响应性目标。要在部署级恢复此前的行为,设置 upstream.timeout_ms: 0;单个模型可用 timeout: 0 退出。参见配置文件。
  • 模型组上的 timeout 和 stream_timeout 字段此前没有效果,因为成员只会使用自己的取值。它们现在对两者都未设置的成员生效,按成员、模型组、部署默认值的顺序解析。已经携带这些字段的模型组在升级后会开始应用它们。
  • proxy.request_body_limit_bytes 的默认值从 10 MiB 改为 0,即不限制。模型服务提供方能接受的请求大小超过任何固定的网关默认值,因此原本直连模型服务提供方可用的客户端,经由网关反而可能失败。这只在配置文件中缺少该项时生效;文件中显式携带该值的部署保持原值。若要在省略该项的配置上保留限制,设置 request_body_limit_bytes: 10485760。取值 0 此前的含义是"拒绝所有带请求体的请求",现在的含义是"不限制"。

新功能​

MCP 网关​

  • 开源 AISIX 网关和 AISIX Cloud 都支持以普通 REST API 为后端的 MCP 服务器。把服务器类型设为 openapi 并提供 OpenAPI 3.x 文档,网关就会为每个受支持的操作生成一个 MCP 工具,并把每次工具调用作为一次 HTTP 请求发往该 API。网关持有所配置的凭证,将其注入出站调用,且不会暴露给发起调用的 Agent。参见将 REST API 暴露为 MCP 工具。
  • 生成的工具与来自真实 MCP 上游的工具经过相同的网关控制,包括工具访问策略、限流、安全护栏和用量记录。
  • 在 AISIX Cloud 中,运维可以粘贴 OpenAPI 文档、提供一个由控制面抓取一次的 URL,或通过控制台加载本地文件。每个由 OpenAPI 支撑的服务器都有一个工具页,用于查看生成的工具名和对应操作。
  • AISIX Cloud 可以要求 MCP 服务器在发布前经过审核。已提交的服务器在审核者接受之前对调用方不可见,而对已上线服务器提出的变更在等待审核期间不会影响正在运行的服务器。参见MCP 服务器上线前审核。
  • 在两个产品中,API Key 都可以携带按服务器设置的限流,因此在某个 MCP 服务器上循环的 Agent 不会消耗同一个 Key 在另一个服务器上的额度。限制可按秒、分钟、小时或天表示,另有并发数,且只对工具调用计量,因此某个服务器的额度耗尽后客户端仍可连接并列出工具。Key 自身的限流仍会叠加生效。参见限流与预算。

超时​

  • 新增两项网关配置 upstream.timeout_ms 和 upstream.stream_timeout_ms,为请求截止时间和流式分块之间的最大间隔提供部署级默认值。截止时间按模型、模型组、这些默认值的顺序解析,并适用于所有端点而不只是聊天路径。参见配置文件。
  • 模型组在控制面和控制台中暴露 timeout 和 stream_timeout,模型上显式的 0 现在会被保留而不再被归一化掉,因此模型可以退出部署级默认值。

可观测性​

  • 用量记录现在上报调用方所等待的时间,度量点在网关把字节交给客户端处,而不是上游分块到达处。在会脱敏响应的输出安全护栏之下,流会被扣留到整个响应扫描通过为止,只有调用方侧的数值反映这段等待。控制台的延迟分位数使用该数值,且只统计成功的请求。参见指标与日志。
  • 用调用方侧延迟减去上游首 Token 时间,就能分离出上游未计入的那段等待,从而在不关联两套系统的情况下看到网关侧开销。对于发生过重试的请求,这个差值还包含此前的各次尝试及其之间的间隔。

审计日志​

  • 审计日志支持在事件的操作者、动作和目标上做全文搜索,支持绝对时间范围、逐页浏览,以及导出当前结果集。参见日志与审计。

部署​

  • 数据面页面在基于清单的安装方式之外提供了真正的 Helm 安装页签,因此可以用已发布的 aisix Chart 安装数据面,其中该环境的连接配置已经填好。

改进​

  • 空闲的网关保持在服务中。就绪端点此前会在配置监听超过五分钟没有事件时报告网关未就绪,而资源不再变化的环境经常如此。在 Kubernetes 上所有副本会在同一时刻越过该阈值,于是完全健康的服务失去了全部端点。就绪现在只报告网关是否正在退出以及配置是否已应用。配置的新鲜度仍可通过健康端点、配置状态端点和 aisix_config_* 指标观察。参见配置状态。
  • aisix 数据面 Helm Chart 的就绪探针现在使用代理端口上的该就绪端点。
  • 超过所配置请求体大小限制的请求,在所有接受请求体的路由上返回相同的错误结构。此前若干 JSON 端点和两个原始请求体端点返回纯文本拒绝,multipart 上传报告一个笼统的客户端错误,而 MCP 和 Agent 端点返回裸的 400。这些端点上的畸形 JSON 现在同样返回标准结构。参见请求头与错误码。
  • Amazon Bedrock 模型现在遵守其所配置的截止时间和连接超时。AWS SDK 此前会用自己的默认值构建自己的 HTTP 客户端,因此 Bedrock 模型的超时并未生效。
  • MCP 上游连接遵守网关的 upstream 连接配置,包括连接超时、TCP Keepalive 和连接池规格。
  • Prometheus 指标占用的内存不再无界增长,指标序列句柄只解析一次并缓存,而不是每个请求都查找一遍。
  • 发布的网关二进制保留符号表,因此针对已发布镜像抓取的性能剖析记录无需特殊构建即可解读。
  • 概览页在其 Top 模型列表中显示完整模型名,不再截断。

修复​

  • 成功的那次尝试所记录的延迟以该次尝试为范围。发生故障转移的请求此前上报的是获胜尝试从请求进入处度量的延迟,因此包含此前所有尝试及重试之间的间隔,使一次成功的故障转移看起来像上游很慢。
  • 重命名 MCP 服务器时会带走其按服务器设置的限流,删除该服务器时也会一并删除。此前这些限制留在旧名字下并静默失效。
  • 审核者编辑 MCP 服务器时会发布它,而不是把它下线。
  • 网关原生支持但公共模型目录未收录的模型服务提供方现在可以重新配置,此前它们在校验阶段被拒绝。
  • 按地域的模型服务提供方 Base URL 与目录中的提供方标识匹配,因此地域相关的默认值可以正确解析,不再落空。
  • 客户端在请求中途断开时不再丢失审计记录。控制面会干净回滚、把断开记录一次,并返回一致的响应体。

0.6.0​

发布日期: 2026 年 7 月 29 日

此版本让调用方可以使用自有身份提供方签发的 JWT 认证,而不必使用网关 API Key。它还把按 Key 维护的 MCP 工具白名单,替换为由环境、团队和 Key 逐层解析的访问策略。此外,重试预算移到模型上,上游请求获得请求上下文变量和客户端请求头白名单,视频生成新增两个模型服务提供方。

行为变化​

  • 重试现在默认开启。此前未设置 routing.retries 的模型组完全不会重试。预算现在按模型、模型组、以及新增的部署级 upstream.retries 默认值 2 的顺序解析,因此从未配置过重试的部署在升级后会开始重试。每次重试都会重新发送完整请求体,并叠加在模型服务提供方自身边缘所做的任何重试之上。要保持此前的行为,在网关配置文件中设置 upstream.retries: 0。参见代理错误与重试。

新功能​

认证​

  • 调用方可以使用 OIDC 提供方签发的 JWT 认证,而不必使用网关 API Key。新增的 oidc_providers 资源按环境保存信任条目,固定 issuer、其接受的 audience 以及 JWKS 位置,网关在请求继续之前校验每一项声明。参见JWT 认证。
  • API Key 通过提供方与 subject 组成的一对与外部身份绑定,因此经 JWT 认证的调用方携带该 Key 的预算、限流、模型访问权限和用量归属。subject 只会针对该 Key 上指定的信任提供方解析,因此第二个受信 issuer 无法声明属于另一个提供方的 subject。
  • JWT 认证作用在网关唯一的认证点上,因此所有代理面都接受它,包括聊天、messages、responses、embeddings、rerank、音频、图像、视频生成、files、batches、fine-tuning、MCP 与 Agent 端点、realtime WebSocket 连接以及透传。
  • 校验默认拒绝:只接受非对称签名算法,必须有过期和 audience 声明,issuer 必须匹配一条已启用的信任条目,运维还可以额外要求 scope 或固定任意嵌套声明。

MCP 访问控制​

  • MCP 工具访问现在由分层策略治理,而不是在每个 Key 上维护白名单。环境默认策略适用于所有调用方,团队策略对该团队成员的 Key 取而代之,Key 再进一步收窄结果。参见MCP 访问策略。
  • 策略可以不授予任何工具、授予指定的一组工具,或授予全部工具。授予全部工具涵盖当前和未来的工具,是一个显式选择而不是默认值。
  • 各层的拒绝模式始终做减法,因此环境级的拒绝会穿透团队策略,并且对本版本之前创建的 Key 同样生效。
  • Key 只能收窄它所继承的权限,永远不能放宽。仍在使用此前 allowed_tools 字段的 Key 行为完全不变,因此升级不会静默授予访问权限。

视频生成​

  • 视频生成端点新增两个模型服务提供方:Runway(runwayml,覆盖 Gen 系列和由 Runway 托管的 Veo)以及 OpenAI Sora(openai)。
  • 内容路由现在使用两种方式交付成品视频。对于返回签名下载 URL 的模型服务提供方,内容路由仍返回 302 重定向,文件会直接从服务提供方存储传输到客户端。OpenAI 要求使用其凭证下载文件,因此网关会使用配置的模型服务提供方密钥获取文件并流式返回,不会将完整文件保存在内存中,也不会向调用方暴露服务提供方凭证。
  • 对于 OpenAI Sora,progress 现在会返回真实完成百分比。不提供百分比的模型服务提供方仍会在任务完成前返回 0,完成后返回 100。
  • OpenAI 是唯一具有内置默认 Base URL 的视频模型服务提供方。其他四个服务提供方仍要求在密钥上配置 api_base。

上游请求头​

  • 模型服务提供方密钥上的默认请求头取值可以引用请求上下文,例如 "x-tenant-id": "${request.api_key.team_id}",网关按请求渲染它们。内部模型服务因此可以把流量归属到发起调用的团队或 Key,而不必为每个租户单独配置一份模型服务提供方凭证。变量词汇表是封闭的且不含任何机密,变量未能全部解析的请求头会被丢弃,而不是以空值发出。参见上游请求头。
  • 模型服务提供方密钥可以通过一份精确名称或单通配符模式的白名单,把指定的入站客户端请求头转发到上游。它默认为空,且即使在通配符之下也会拒绝来自客户端的认证、传输和网关内部请求头。这让调用方可以在标准端点上传递模型服务提供方特有的请求头或传播 trace 上下文,而不必退化到透传。
  • 视频生成以及 files、batches、fine-tuning 端点此前完全不应用默认请求头,现在每个请求都会携带解析后的集合。

重试​

  • 重试预算现在是模型级配置,作用于所有端点而不只是聊天路径。它按模型、模型组、部署级默认值的顺序解析,并可在控制台中按模型配置。参见代理错误与重试。

连接管理​

  • 网关可以限定已接受的客户端连接在请求之间的最长空闲时间,也可以在尚未产生输出的流式响应上发送心跳注释,使前置代理不会把首 Token 较慢的模型当作已放弃的连接。进行中的请求或流永远不会被中断。参见配置文件。

改进​

  • 日志页支持跨请求的模型、Key、错误消息和标识符做全文搜索,可将当前结果集导出为 CSV 或 JSON,并在时间戳列中与时间一同显示日期。
  • 模型页可按模型名、上游模型或模型 ID 筛选。
  • 模型 ID 字段会提示所选模型服务提供方目录中的模型,同时仍为自由文本,因此目录未收录或刚刚发布的模型仍可手动输入。
  • API Key 和模型服务提供方密钥页面改用紧凑表格,配统一搜索、类型筛选和服务端分页,替换此前的卡片布局。
  • 控制台侧边栏显示控制面构建版本,运维无需登录终端即可确认某个环境运行的是哪个发布版本。
  • aisix-cp Helm Chart 为控制面 API 和数据面管理器新增启动探针,因此首次启动较慢或升级时耗时较长的 Schema 迁移不再被存活探针中断。

修复​

  • 输入安全护栏现在扫描消息文本内容与其结构化内容块的并集。这两者在协议上是相互独立的字段,而模型服务提供方桥接层在存在结构化块时会转发它们,因此此前一个文本无害、载荷藏在块中的请求可以通过所有输入安全护栏,而模型仍然收到该载荷。
  • 失败请求的访问日志行现在会说明失败原因,同时携带可用于筛选或告警的稳定错误类别以及底层原因。此前上游错误、域名解析失败、被回收的连接和未获应答的连接尝试都产生完全相同的日志行。参见访问日志与请求关联。

0.5.0​

发布日期: 2026 年 7 月 24 日

此版本新增统一视频生成端点、向外部系统发送通知的预算阈值告警,以及 Anthropic 模型的自动提示词缓存;同时修复重试、超时、限流和用量核算未覆盖所有请求路径的多个问题。

新功能​

视频生成​

  • 新增视频生成端点,通过 /v1/videos 接受文生视频任务、轮询状态并返回成品视频,遵循 OpenAI 视频 API 的三阶段形态。当前映射的模型服务提供方包括 Alibaba Cloud Model Studio、Zhipu AI CogVideoX 和 Volcengine Ark Seedance。
  • 视频请求现在会经过与聊天流量相同的网关控制:模型别名、调用方 API Key 访问检查、客户端 IP 白名单、模型级限流和提示词输入安全护栏扫描。此前,视频流量只能通过透传到达模型服务提供方,不会应用这些模型级控制。
  • 网关不存储任务状态。返回的视频 ID 携带路由信息,因此状态和下载调用可由任意网关实例处理。
  • 视频提交以零 Token 记录在用量日志中。此版本尚未应用按时长计费,因此视频流量不会消耗预算。

安全护栏​

  • 新增 Alibaba Cloud AI Guardrails 类型,调用 MultiModalGuard 服务并执行其建议判定。当服务返回脱敏内容时,网关会将脱敏文本写回请求,而不是直接拒绝。
  • 网关记录 aisix_guardrail_latency_seconds,这是按每次执行统计的延迟直方图,可将安全护栏开销与上游模型延迟区分开。参见指标。
  • Alibaba 安全护栏服务的响应会保留其上游请求 ID,网关会将该 ID 与自身请求 ID 关联,便于跨系统排查。

预算和告警​

  • 预算阈值告警会在支出达到预算配置百分比时通知外部系统。通知渠道支持通用 Webhook 和 Slack。
  • 控制台预算页面现在可以在同一位置管理所有作用域的预算,预算也已纳入 AISIX Cloud Admin API 契约。

提示词缓存​

  • 模型可以启用自动提示词缓存,由网关向符合条件的请求插入 Anthropic 缓存断点。调用方无需修改客户端代码即可获得提示词缓存折扣,也可以在控制台中按模型配置此选项。

用量上报​

  • 当上游未返回用量块时,网关现在会在本地估算 Token 数,而不再记录为零。估算记录会在用量上报和控制台日志页面标记,因此可与模型服务提供方报告的用量区分。
  • aisix_llm_tokens_by_client_total 指标新增 model 标签,并开始为 Responses 端点记录。
  • 内置客户端类型检测覆盖更多编程 Agent,运维人员也可为网关无法识别的客户端添加 User-Agent 映射规则。

部署​

  • 新增 aisix export 命令,可从正在运行的 etcd 存储导出 resources.yaml,作为现有部署切换到独立模式时的初始配置。
  • 对于使用声明式配置且不希望暴露写入 API 的部署,可通过 admin.enabled 设置禁用 Admin 监听器。
  • 状态监听器会报告每个模型的运行时健康状况,无需发送模型请求即可检查上游可达性。
  • 网关会在心跳中报告已应用配置的哈希值,控制面公共规范会公开网关节点和被拒绝资源,从而确认哪些网关已经应用配置变更。参见配置传播。

改进​

  • 模型服务提供方密钥的上游凭证现在可以原地轮换,无需重新创建密钥或重新关联使用它的模型。
  • 控制台模型服务提供方选择器支持搜索,并使用正确的显示名称列出服务提供方。
  • 控制台日志页面会显示完整上游错误消息,不再截断;上游筛选器也不再提供不属于上游的模型组。
  • 日志查询窗口会遵循组织的用量保留设置,不再使用固定范围。
  • 控制面会报告请求被拒绝的原因,而不是返回通用失败。
  • Admin API 写入路径已弃用,推荐使用声明式配置。此版本中它仍可使用。请改为在 resources.yaml 文件中声明动态资源,或通过 AISIX Cloud Admin API 管理它们。

修复​

  • retries 设置现在适用于流式聊天请求;此前独立的流式代码路径不会重试。
  • 对 Azure 模型,stream_timeout 现在按文档限制分块间隔,不再限制整个响应,因此耗时较长但健康的流不会被提前截断。
  • 连接失败会报告底层传输原因,而不是通用上游错误;连接层也开始应用显式限制,不再依赖库默认值。
  • 调用方提供的 cache_control 标记在 OpenAI 到 Anthropic 的桥接过程中会保留,因此使用 OpenAI 客户端访问 Anthropic 模型时仍能获得提示词缓存折扣。
  • 合议成员和评审模型子调用会在后端未报告用量时进行估算,避免合议请求少报 Token。
  • 透传隧道会执行请求正文中指定模型的限流。
  • 组分发会应用每个路由目标自身的模型限流和客户端 IP 白名单,而不再只检查组入口。
  • 每次尝试的错误消息不再截断到 256 个字符,使上游故障在日志中保持可读。
  • 将凭证交换为短期 Token 的服务提供方,其已签发 Token 缓存会按完整凭证建立键,因此密钥轮换会立即生效,无需等待旧 Token 过期。
  • 控制台 Pod 会挂载可写缓存目录,修复 Helm 部署中图片请求可能无限挂起的问题。
  • Playground 只接受控制台会话,个人访问 Token 无法再通过它消耗模型服务提供方配额。

0.4.0​

发布日期: 2026 年 7 月 16 日

此版本引入基于角色的访问控制、自定义角色和环境范围内的管理权限,增加基于状态码的路由故障转移,并通过延迟直方图和更丰富的失败诊断扩展可观测性。

新功能​

访问控制​

  • 组织可以定义自定义角色,按资源类型授予细粒度 read 和 write 权限,替代固定的所有者、管理员和成员划分。
  • 环境范围内的访问权限允许成员管理单个环境,而不授予组织范围内的权限。
  • SCIM 组到角色映射会根据身份服务提供方的组成员身份自动分配角色。
  • 控制面对每个 Admin API 请求执行这些权限检查。

路由​

  • fallback_on_statuses 可将选定的上游 HTTP 状态码纳入重试和故障转移,使 408、409 等服务提供方特定的临时状态码尝试其余目标,而不是直接返回调用方。

可观测性​

  • 分桶的首 Token 时间和端到端延迟直方图支持为服务级目标计算 p90、p99 等延迟分位数。详见指标。
  • 网关会在 Chat、Messages 和 Responses 端点的失败请求中采集请求体,并通过保留结构的截断限制大型载荷。
  • 新的 /status/config 端点会报告已加载的可观测性配置,网关也会发出配置指标。

部署​

  • 独立模式可以从 resources.yaml 加载资源,使网关无需控制面或 etcd 即可运行。

改进​

  • AISIX Cloud Admin API 现在暴露缓存策略、可观测性导出器和限流。
  • 控制台可以为定价目录中没有的模型设置价格覆盖项,使其用量仍能计费。
  • API Key 和限流列表支持分页与搜索。
  • 安全护栏配置错误现在会记录服务提供方的错误响应体,便于排查问题。
  • 阿里云内容安全护栏表单会显示 output_fail_open 选项。

修复​

  • 监控模式的输出安全护栏不再延迟或关闭流式响应。
  • aisix_deployment_state 指标现在根据目标的服务状态派生。
  • SCIM POST /Users 会返回持久化后的身份,而不是回显身份服务提供方的载荷。

0.3.1​

发布日期: 2026 年 7 月 9 日

此维护版本增加 SCIM 目录同步,并改进可观测性、核算、On-Premises Playground 访问和控制面可靠性。

新功能​

  • SCIM 2.0 目录同步可以通过新的 /scim/v2 端点,从 Okta、Microsoft Entra ID 等任意 SCIM 2.0 身份服务提供方自动预配和取消预配组织成员。

改进​

  • 网关构建现在会在 Server 响应头、aisix --version 输出和控制台显示的数据面版本中报告发布版本,不再报告静态构建版本。
  • 按客户端统计的 Token 指标现在包含计入缓存的 total 序列。当前指标目录请参见指标。
  • 健康状态变化时会发出部署冷却指标。
  • 安全护栏管理 API 现已加入 AISIX Cloud Admin API 契约。

修复​

  • 每个代理响应现在都包含 x-aisix-request-id 响应头,用于关联日志和用量事件。
  • Anthropic 提示词缓存 Token 现在会计入原生 /v1/messages 和 /v1/responses 端点的 Token 限流。
  • 单个格式错误的遥测事件不再阻止同一用量批次中的其它事件投递。
  • 启用 AISIX_PLAYGROUND_ALLOW_PRIVATE_IPS 后,On-Premises 控制台 Playground 可以访问私有或内部 LLM 端点。
  • 登录现在接受部署自身的 Origin 和对应的回环 Origin,并为限流或不受信任 Origin 的尝试返回更明确的消息。
  • 成员列表分页不再在视图加载后很快跳回第一页。
  • 控制面重启不再产生无害的重复约束错误日志。

0.3.0​

发布日期: 2026 年 7 月 9 日

此版本引入 MCP 网关和 Agent 网关,扩展代理 API 与安全护栏目录,并增加基于指标的路由。

新功能​

MCP 网关​

  • 新的聚合 /mcp 端点使用一个 AISIX 调用方 API Key 代理多个上游 MCP 服务器。
  • 上游 MCP 服务器成为一等资源,支持在控制面和控制台中注册、完整 CRUD、启用或禁用以及配置上游超时。
  • 工具访问控制将每个调用方 API Key 限定到指定 MCP 工具。
  • 上游认证支持 API Key 和 OAuth 2.0 客户端凭证。
  • MCP 工具调用与模型流量使用相同的限流、预算以及输入和输出安全护栏,同时发出用量事件和访问日志。

Agent 网关​

  • 新的 Agent 网关代理由控制面和控制台管理、作用域为组织的 A2A Agent。
  • allowed_agents 字段将每个调用方 API Key 限定到指定 Agent。

API​

安全护栏​

路由​

  • 多目标模型支持最低成本、最低延迟和最低负载目标选择。
  • 条件路由可按标签或元数据选择目标,通配符别名可路由 provider/* 等模型名称。
  • 粘性加权路由支持 A/B 测试和灰度发布。

流量控制与 API Key​

  • 调用方 API Key 生命周期控制可以设置过期时间、禁用 Key,或通过单次操作完成轮换。
  • 集群限流可以使用共享 Redis 存储,并在现有每分钟(rpm)和每天(rpd)限制之外增加每秒(rps)和每小时(rph)请求限制。

可观测性​

  • 请求和响应内容采集现在覆盖 Embeddings、Rerank、Images 和 Audio。

控制台​

  • 可以在控制台中管理 MCP 服务器,并在限流、预算和安全护栏视图中配置 MCP 治理。
  • 可以按组织配置用量日志保留时间。

改进​

  • 容器镜像以非 root 用户运行,并通过 CAP_NET_BIND_SERVICE 文件能力绑定端口 80 和 443。
  • 控制台提供统一、可筛选的模型视图,并在创建模型时使用单一模型类型选择器。
  • 路由目标可通过拖动重新排序,最低成本目标会显示每个目标的成本标记。
  • 成员和团队列表支持分页。

修复​

  • 缓存和限流 Key 按环境划分作用域,共享 Redis 存储不会混合不同环境的状态。
  • 透传端点现在会为成功和失败请求发出用量事件,并归因到调用方 API Key。