GPTMap

openai-node v7.20.0 更新解读:环境变量 vault 凭据、外部存储管理与 safety cases 检索

openai-node v7.20.0 一版带六个 PR:vault 凭据新增 environment_variable 类型(沙箱只拿占位符、出站代理 443/8443 替换密钥)、admin 外部存储配置管理面、safety cases 检索端点与 warning/deactivation 两个新 webhook 事件、三个来电事件的 SIP 媒体安全字段,外加遗留 GET 请求选项修复。逐项对应 PR 与 tag 源码拆解。

TL;DR
openai-node v7.20.0(2026-09-19 发布,2026-09-20 核对)四件事:① vault 凭据新增 environment_variable——沙箱只拿占位符,出站代理在 443/8443 对允许的 HTTPS 目标替换真实密钥;② client.admin.organization.externalStorage 管理客户自管外部存储(AWS/Azure,status 三态);③ client.safety.cases.retrieve(GET /v1/safety/cases/{id})配 safety.warning_issued / safety.deactivation_issued 新事件,payload 携带 case ID;④ 三个来电事件新增可选 sip_media_security。另修遗留 GET 请求选项(#2771)。
openai-node v7.20.0(2026-09-19)是 JavaScript/TypeScript 官方 SDK 的一个功能批次:vault 凭据体系新增 environment_variable 类型(占位符注入、出站代理替换密钥)、admin 命名空间新增客户自管外部存储配置资源(AWS/Azure)、safety 命名空间新增 cases 检索端点并配合两个新 webhook 事件(safety.warning_issued / safety.deactivation_issued)、三个来电事件数据新增可选 sip_media_security 字段,并修复遗留 GET 调用中请求选项被误序列化为查询参数的问题。

openai-node 在 2026-09-19 发布 v7.20.0:一个版本带进六个 PR——五个 API 功能加一个修复。功能集中在三条此前已有雏形的线上:Agents API 的 vaults 凭据体系补上第三种 auth 类型、admin 命名空间补上外部存储配置管理面、safety 家族从 alert 延伸出 case 检索端点和两个配套 webhook 事件;外加一个来电事件的 SIP 媒体安全字段和一个影响面不小的遗留 GET 调用修复。本文逐项对应 PR 与类型源码拆解(全部基于 2026-09-20 当日经 GitHub API 重抓的 release notes、PR diff 与 v7.20.0 tag 源文件核对),示例代码取自 tag 内官方文档字符串与类型定义。

截至 2026-09-20 经 GitHub releases 核对,openai-python 最新版仍为 v3.16.2(2026-09-18 发布),本批六项改动尚未出现在 python 侧的 release notes 中。

1. 版本速览

PR类型内容主要源文件
#2768featvault 凭据新增 environment_variable 类型与 networking 配置beta/agents/vaults/credentials.ts
#2773featadmin 外部存储配置管理(AWS/Azure)admin/organization/external-storage.ts
#2774featsafety cases 检索端点safety/cases.ts、safety/safety.ts
#2772featsafety.warning_issued / safety.deactivation_issued 两个 webhook 事件webhooks/webhooks.ts
#2770feat三个来电事件 data 新增可选 sip_media_security 字段webhooks/webhooks.ts
#2771fix遗留 GET 调用的请求选项保留57 个源文件(见第 6 节)

2. vault 凭据第三种类型:environment_variable(#2768)

Agents API 的 vault 凭据此前只有两种 auth 类型:mcp_oauth(OAuth 凭据,带自动刷新元数据)与 static_bearer(静态 Bearer 令牌)。#2768 把 CredentialAuth 联合扩为三值,新增 environment_variable,官方定位是"仅用于 OpenAI 托管环境的 HTTP 凭据"。它的工作方式与另外两种有本质区别:

  1. 创建凭据时把真实密钥(secret_value)存进 vault;
  2. 沙箱代码拿到的环境变量不是密钥,而是占位符(占位符通过 secret_name 指定的变量名注入);
  3. 代码照常把该变量放进出站请求;
  4. 出站代理对允许的 HTTPS 目标(端口 443 与 8443)把占位符替换为真实密钥。

官方文档字符串对边界的表述很明确:真实密钥不返回到凭据资源里、沙箱代码不可读取、也不能用于本地计算——文档字符串点名"签名请求"这类用法不行,因为那需要拿到明文密钥。

const credential = await client.beta.agents.vaults.credentials.create('vault_id', {
  name: 'service-api-key',
  auth: {
    type: 'environment_variable',
    secret_name: 'SERVICE_API_KEY',
    secret_value: process.env.SERVICE_API_KEY ?? '',
    networking: { type: 'limited', allowed_hosts: ['api.example.com'] },
  },
});
// credential.object === 'vault.credential'

networking:代理替换目的地的两层约束

environment_variable 类型必须带 networking 字段,二选一:

取值语义附加条件
unrestricted对环境网络策略允许的目的地都可替换要求 environment.network.access 为 restricted 且显式配置 allowed_domains
limited只对列出的主机替换allowed_hosts 为 1-16 个去重主机名或 IPv4 地址(小写、不含 scheme/路径/端口/通配符;不支持 IPv6)

文档字符串同时强调:networking 描述的是"代理可以替换这个密钥的目的地",它并不给环境授予网络访问权——环境自身的网络策略仍然独立生效,两层约束同时满足才走得通。

其余约束(均出自 tag 内类型文档字符串):凭据 name 去除首尾空白后须为 1-256 个 UTF-8 字节;secret_name 限 ASCII 字母、数字、下划线且以字母或下划线开头(如 SERVICE_API_KEY),CODEX_ 前缀与代理/证书托管变量名为保留名;secret_value 只写、必须非空、不得含回车/换行/NUL 字节;update 语义是轮换(CredentialAuthRotateParam),environment_variable 同样在支持之列。资源仍挂在 client.beta.agents.vaults.credentials 下,create / retrieve / update / list(cursor 分页)/ delete 五个操作与 OpenAI-Beta: agents=v1 请求头不变。

3. 外部存储配置管理:client.admin.organization.externalStorage(#2773)

#2773 在 admin 命名空间下新增外部存储配置资源,create 的官方文档字符串只有一句:Register one customer-managed external storage configuration(登记一条客户自管的外部存储配置)。五个操作对应五条端点:

  • create — POST /organization/external_storage
  • retrieve — GET /organization/external_storage/{id}
  • list — GET /organization/external_storage(cursor 分页,参数 after / order(asc、desc)/ project_id)
  • delete — DELETE /organization/external_storage/{id}
  • validate — POST /organization/external_storage/{id}/validate

配置对象(object 恒为 organization.external_storage)包含 id、created_at、geography、project_id、provider 与 status 三态枚举:pending / validated / unhealthy。provider 支持 AWS 与 Azure 两种:

字段AWSAzure
创建时必填bucket、role_arnaccount_name、container、resource_group、subscription_id、tenant_id
资源返回另有 account_id、external_id、region另有 region

SDK 文档字符串只给了 create 的定位一句话;这一资源与具体产品形态的绑定关系,官方未在 SDK 内说明,截至 2026-09-20 本站也未在可加载来源核实到更多信息,此处不做推断。鉴权层面该资源走 admin API key(adminAPIKeyAuth),与 admin 命名空间其他资源一致。

// 官方 JSDoc 示例(external-storage.ts 内)
const externalStorageConfiguration =
  await client.admin.organization.externalStorage.create({
    project_id: 'proj_123',
    provider: {
      bucket: 'bucket',
      role_arn: 'role_arn',
      type: 'aws',
    },
  });

4. safety cases:检索端点与两个新 webhook 事件(#2774 / #2772)

2026-09-03 的 SDK 批次里,safety 家族落地的是 alerts:GET /v1/safety/alerts/{id} 加上 safety.alert.created / safety.org_alert.created 事件。本批 #2774 在 client.safety 下并列新增 cases 子资源:

const safetyCase = await client.safety.cases.retrieve('case_id');
// GET /v1/safety/cases/{id}
// safetyCase.object === 'safety.case'
// safetyCase.notice.type === 'warning' | 'deactivation'
// safetyCase.reason === string | null

返回的 SafetyCase 对象字段:id、created_at、entity_identifier、notice(含 type 二值 warning / deactivation)、object 恒为 safety.case、reason(可空字符串)。

#2772 配套新增两个 webhook 事件,官方文档字符串原文:

  • safety.warning_issued — Sent when a warning is issued for a safety identifier in your organization.(组织内某 safety 标识符被发出警告时发送)
  • safety.deactivation_issued — Sent when a deactivation is issued for a safety identifier in your organization.(组织内某 safety 标识符被发出停用处理时发送)

两个事件的 payload.data 结构相同,只有一个 id 字段,文档字符串明确写出它的用途:The safety case ID to pass to GET /v1/safety/cases/{id}——事件与检索端点之间这条跳转路径是官方原文写死的。事件名(warning_issued / deactivation_issued)与 case 的 notice.type 二值在命名上对应。

消费侧用既有的 unwrap(本批未改其签名):

const event = await client.webhooks.unwrap(
  req.body,              // 原始 payload 字符串
  req.headers,           // 请求头(webhook-signature / webhook-timestamp / webhook-id)
  process.env.OPENAI_WEBHOOK_SECRET, // 省略时用 client.webhookSecret
);
if (
  event.type === 'safety.warning_issued' ||
  event.type === 'safety.deactivation_issued'
) {
  const safetyCase = await client.safety.cases.retrieve(event.data.id);
}

一个类型层面的精确事实:两个新事件加进了 UnwrapWebhookEvent(unwrap 返回的事件联合,v7.20.0 tag 实测共 21 类),但 WebhookCreateParams / WebhookUpdateParams 里 event_types 字段的静态订阅联合在本批之后仍是原 18 值——SDK 类型层尚未把两个新事件列为创建端点时的可订阅项(截至 2026-09-20 对 tag 源文件核对)。实际可订阅列表以 client.webhooks.event_types.list() 返回为准(该端点返回 string 数组,无静态枚举约束)。

5. 来电事件的 SIP 媒体安全字段(#2770)

#2770 给三个来电类 webhook 事件的 data 各新增一个可选字段 sip_media_security:

  • live.call.incoming(LiveCallIncomingWebhookEvent)
  • live.transport.incoming(LiveTransportIncomingWebhookEvent)
  • realtime.call.incoming(RealtimeCallIncomingWebhookEvent)

取值类型是开放联合:'rtp' | 'srtp' | (string & {})。官方字段描述全文:SIP leg 在 SDP 协商中选定的媒体保护方式——srtp 表示 SRTP,rtp 表示未加密 RTP;未知时省略;该字段不描述 SIP 信令的安全,也不确认媒体已经开始流动;客户端应把未识别值当未知处理。两点注意:live.transport.incoming 事件本身此前已存在,本批只是加字段;字段可选,消费代码不能假设它必然出现。

6. 修复:遗留 GET 调用的请求选项保留(#2771)

release notes 里唯一的 fix:Preserve request options in legacy GET calls。背景是 SDK 内一批 list 型 GET 方法的第一参数在历史上同时承担"查询参数"与"请求选项"两种角色;本批为这些方法增加了重载与运行时归一化(normalizeRequestOptionsForQuery):第一参数里出现的传输选项——headers、maxRetries、timeout、signal、idempotencyKey——被识别为请求选项,不再被序列化进 URL 查询字符串。

改动面:57 个非测试源文件,覆盖 admin/organization 全系 21 个资源(api keys、audit logs、certificates、groups、invites、projects 系、roles、spend alerts、users 等)以及 batches、beta/agents 全家、beta/assistants、beta/threads、chat/completions、containers、conversations、evals、files、fine-tuning、images、responses、skills、vector-stores、videos、webhooks。

运行时行为随之收紧,两种传参会直接抛 TypeError:

  • 查询参数与请求选项混在一个对象里传 — Query parameters and request options must be passed as separate arguments.
  • 在查询位置传传输覆盖(method、path、body 等) — Pass transport overrides in the explicit request options argument.

正确写法是各归其位:

// 第一参数只放查询参数,第二参数放请求选项
const page = await client.admin.organization.externalStorage.list(
  { project_id: 'proj_123' },
  { timeout: 30_000, maxRetries: 2 },
);

如果既有代码把 timeout / signal 之类传在第一参数里且一直"没生效",这次升级后行为会改变(选项开始真正生效);如果依赖了被误序列化进查询串的旧行为,需要自查。

7. 常见错误与排查

  • 沙箱里拿到的是占位符不是密钥:environment_variable 类型设计如此。检查三处——出站目标是否 HTTPS、端口是否 443/8443、networking 配置与环境网络策略是否都放行该目标;本地计算场景(如签名)官方明确不支持。
  • secret_name 设置失败:检查命名规则——ASCII 字母/数字/下划线、以字母或下划线开头、不得使用 CODEX_ 前缀与代理/证书托管保留名。
  • 创建 webhook 端点时事件列表里没有 safety.warning_issued:SDK 静态联合尚未收录(见第 4 节),以 client.webhooks.event_types.list() 返回为准;unwrap 侧的类型已经支持。
  • 升级后 list 调用抛 TypeError:查询参数与请求选项分开放(见第 6 节的两个错误信息)。
  • external storage 配置一直 pending:validate 端点用于发起校验;status 枚举 pending / validated / unhealthy,校验失败后的具体排查手段 SDK 内没有更多说明。

8. 下一步

关键要点

  • environment_variable vault 凭据(#2768):CredentialAuth 联合从 mcp_oauth + static_bearer 两值扩为三值,新增 environment_variable——HTTP 凭据仅用于 OpenAI 托管环境:沙箱代码拿到的环境变量是占位符,出站代理对允许的 HTTPS 目标(端口 443 与 8443)把占位符替换为真实密钥;真实密钥不返回、沙箱代码不可读取、不能用于本地计算(如签名请求)
  • networking 与约束(#2768):CredentialNetworking 二选一——unrestricted(要求 environment.network.access 为 restricted 且显式配 allowed_domains)或 limited(1-16 个去重主机名/IPv4,小写、不带 scheme/path/端口/通配符,不支持 IPv6);secret_name 命名限 ASCII 字母/数字/下划线且以字母或下划线开头,CODEX_ 前缀与代理/证书托管变量名为保留名;secret_value 只写、非空、不得含 CR/LF/NUL;rotate 同步支持该类型
  • 外部存储配置管理(#2773):client.admin.organization.externalStorage 提供 create(POST /organization/external_storage,登记一条客户自管外部存储配置)/ retrieve / list(cursor 分页)/ delete / validate(POST .../{id}/validate);配置对象含 geography、project_id、status(pending/validated/unhealthy);provider 支持 AWS(bucket + role_arn)与 Azure(account_name/container/resource_group/subscription_id/tenant_id),鉴权为 admin API key
  • safety cases 与新事件(#2774 / #2772):client.safety.cases.retrieve 对应 GET /v1/safety/cases/{id},返回 safety.case 对象(entity_identifier、reason 可空、notice.type 为 warning 或 deactivation);新 webhook 事件 safety.warning_issued 与 safety.deactivation_issued(官方文档字符串:组织内某 safety 标识符被发出警告/停用处理时发送)的 payload.data.id 即要传给该端点的 case ID;client.safety 下 alerts 与 cases 两个子资源并存
  • SIP 媒体安全字段(#2770):live.call.incoming、live.transport.incoming、realtime.call.incoming 三个事件的 data 各新增可选 sip_media_security——取值 rtp / srtp 或其他未识别字符串(开放联合);官方描述:SIP leg 在 SDP 协商中选定的媒体保护,未知时省略;不描述 SIP 信令安全、也不确认媒体已流动,客户端应把未识别值当未知处理(live.transport.incoming 事件本身此前已存在,非本批新增)
  • 遗留 GET 修复(#2771):为遗留 list 型 GET 方法增加重载与运行时归一化——第一参数里混入的传输选项(headers/maxRetries/timeout/signal/idempotencyKey)被识别为请求选项而非序列化进 URL 查询;查询参数与请求选项混传抛 TypeError(Query parameters and request options must be passed as separate arguments.);改动覆盖 57 个源文件(admin/organization 21 个 + batches、beta/agents、chat/completions、containers、evals、responses、videos 等)

常见问题

static_bearer 是给 MCP 服务器用的静态 Bearer 令牌凭据;environment_variable 是仅用于 OpenAI 托管环境的 HTTP 凭据。核心差异在密钥的可见性:environment_variable 的沙箱代码拿到的环境变量只是占位符,不是真实密钥——代码照常把占位符放进出站请求,由出站代理对允许的 HTTPS 目标(端口 443 与 8443)把占位符替换成真实密钥。真实密钥不出现在凭据资源里、沙箱代码读不到,也不能用于本地计算(官方原文明确点名签名请求这类用途不行)。

官方参考

相关文章

订阅 GPTMap Weekly

每周一封邮件,精选 OpenAI 重要更新、深度解读与最佳实践。无广告,可随时退订。

提交后将在新标签页打开 Buttondown 完成订阅确认。

GPTMap Editorial发布于 2026-09-20 14 分钟阅读
测试环境(EEAT)
最后测试时间:2026-09-20
使用模型:gpt-5.6