Skip to content

Latest commit

 

History

History
2813 lines (2217 loc) · 248 KB

protocol.md

File metadata and controls

2813 lines (2217 loc) · 248 KB

Google AI Studio 私有协议

本文定义 AIStudio2API 使用的 Google AI Studio 私有协议、认证状态、WAA 运行时、JSON+protobuf 数组、增量事件、工具与媒体链。模型方法、限制和能力由账户的实时 ListModels 返回,公开 API 将原始结构投影为规范事件和兼容响应。

1. 协议范围、入口与公共头

用途 入口 格式
页面 origin https://aistudio.google.com HTTPS
MakerSuite RPC https://alkalimakersuite-pa.clients6.google.com/$rpc/google.internal.alkali.applications.makersuite.v1.MakerSuiteService/<METHOD> application/json+protobuf
WAA RPC https://waa-pa.clients6.google.com/$rpc/google.internal.waa.v1.Waa/<METHOD> application/json+protobuf
BotGuard interpreter https://www.google.com/js/bg/<INTERPRETER_HASH>.js JavaScript
Drive discovery https://clients6.google.com/discovery/v1/apis/drive/v3/rest?pp=0&fields=…&key=<API_KEY>&%24unique=gc953 JSON
Drive 上传 https://content.googleapis.com/upload/drive/v3/files?uploadType=multipart&key=<API_KEY> multipart/related
Drive resumable 上传 https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&fields=id 分块 HTTPS body
Drive 下载 https://www.googleapis.com/drive/v3/files/<FILE_ID>?alt=media HTTPS body

MakerSuite 请求使用以下公共头:

Header 来源
content-type 固定为 application/json+protobuf
user-agent 账户固定指纹的 Firefox UA
x-user-agent 官网 gRPC-Web 标识
x-goog-api-key AI Studio 首页或当前官网请求动态值
x-goog-authuser 当前账户官网请求
x-aistudio-visit-id 首页初始化或当前官网请求
x-aistudio-g1-tier GetAiStudioBenefitTier 返回值映射为 TIER0、TIER1 或 TIER2
x-goog-ext-519733851-bin 当前官网请求动态值;SpiderMonkey WAA 后端由 GetLoggingContext 编码
authorization 三段 SAPISID 签名
cookie 当前账户对目标 RPC 可见的 Cookie
origin、referer https://aistudio.google.com
accept-language 账户 locale

请求头 x-goog-api-key 是 AI Studio 页面使用的动态公共值,与用户创建的 Google Cloud API key 不同;免费网页链仍依赖 Cookie、SAPISID 签名和 WAA proof。

受 WAA 保护的 GenerateContent 由服务进程以 Firefox 152 网络形状经账户固定出口发送;其他 MakerSuite 与 Drive 请求使用同账户固定出口的 Go HTTP transport。WAA_BACKEND=camoufox 时受保护请求通过账户固定指纹 Camoufox 页面发送,保留原生 Firefox TLS、HTTP/2、请求头、Cookie 与页面指纹。

JSON+protobuf 使用数组表示 protobuf message。数组索引从 0 开始,protobuf field 从 1 开始,因此 field N 对应索引 N-1。Google 响应允许省略空槽并形成 [,value];解码器先把省略槽规范化为 null,再从完整 JSON 根值中提取 repeated message。HTTPS chunk 仅提供字节序列,业务事件起止由数组结构确定。

协议核心使用以下 MakerSuite RPC:

RPC 用途
ListModels 读取模型、方法、限制、默认参数与能力选项
CountTokens 权威输入 token 计数
GenerateContent 文本、思考、函数、Google 工具、图片、语音与音乐
GenerateAccessToken 获取 Drive bearer token
GetAppFolder 读取对话附件所在的应用文件夹 ID
GenerateTitle 生成 API 试用页的对话标题

GenerateTitle 正文为 ["<提示词>","<回答>","<WAA_PROOF>"],没有回答时回答位为 null,响应为 ["<标题>"]。

AI Studio 页面初始化还包含以下控制面 RPC:

RPC 用途
GetLoggingContext 页面日志上下文与条款同意状态
AcceptTerms 同意 AI Studio 条款
GetUserPreferences 用户偏好与欢迎状态
UpdateUserPreferences 更新欢迎状态等用户偏好
ListPromos 页面活动信息
GetAiStudioBenefitTier 账户权益枚举与 tier 请求头
ListRecentApplets 最近 Applet
ListPrompts 提示词目录
GetUserRestrictions 账户限制
ListIncidentsHistory 服务事件记录;页面打开期间从启动时的那次请求起每 10 分钟请求一次

管理进程启动时加载账户并准备公共头。POST /api/control/start 刷新实时模型目录、预热 WAA Worker并启用数据面,业务能力随后按需调用对应 RPC。

本文中的数据面指处理公开 API 请求、可通过 Stop/Start 启停的生成服务。

2. SAPISID、Chrome DBSC、Cookie 与账户状态

SAPISID 授权

authorization 由三个 Cookie 分别签名:

令牌标签 Cookie
SAPISIDHASH SAPISID
SAPISID1PHASH __Secure-1PAPISID
SAPISID3PHASH __Secure-3PAPISID

三段使用相同的 Unix 秒级时间戳:

source = "<TIMESTAMP> <COOKIE_VALUE> https://aistudio.google.com"
digest = lowercase_hex(SHA1(source))
token = "<LABEL> <TIMESTAMP>_<DIGEST>"
authorization = token_1 + " " + token_2 + " " + token_3

MakerSuite 响应的 Set-Cookie 在响应头到达时与账户最新 storage-state.json 串行合并并原子写回。签名、Cookie 选择和过期判断均以请求时重新读取的账户状态为准。

Windows Chrome DBSC 导入

Windows Chrome 导入从 Profile 恢复 OAuth 与 Device Bound Session Credentials:

Chrome Local State + Profile Preferences + Web Data/token_service
  -> Gaia ID、v20 refresh token 密文、wrapped binding key(可为空)
  -> 解开 App-Bound v20 主密钥
  -> AES-256-GCM 解密 refresh token
  -> 有 binding key:OAuthMultilogin sentinel 请求取得 DBSC challenge
     -> NCrypt 设备密钥签发 ES256 assertion
     -> X25519/HPKE 解密服务端 Cookie
  -> 没有 binding key:MultiBearer 头的 OAuthMultilogin 直接返回明文 Cookie
  -> 保存 Playwright storage state 结构与续签材料

Chrome 运行期间以排他锁打开 Web Data,程序把 Web Data 与 Web Data-wal 复制到临时目录后只读打开,读取后删除副本。Local State.os_crypt.app_bound_encrypted_key 使用 Base64 编码并带 APPB 前缀。程序把内嵌 ABE helper 加载到独立、隐藏的 Chrome 进程中,取得 32 字节主密钥;临时进程树由 Windows Job Object 管理。token_service.encrypted_token 使用 v20 || nonce[12] || ciphertext+tag,以该主密钥执行 AES-GCM 解密。

设备绑定的账号 OAuthMultilogin 使用 MultiOAuth 头,token_service.binding_key 为空的账号使用 MultiBearer <refresh token>:<Gaia ID> 头,一次请求返回明文 Cookie。MultiOAuth 第一次 assertion 为 DBSC_CHALLENGE_IF_REQUIRED,响应提供 challenge;第二次 assertion 的 JWT header 使用 ES256 与 DEVICE_BOUND_SESSION_CREDENTIALS_ASSERTION。payload 绑定 Google OAuth client、challenge、设备公钥 issuer 和临时 HPKE 公钥。Cookie 密文使用 X25519、HKDF-SHA256 与 AES-128-GCM 解密。

OAuthMultilogin 以该 Profile 的 Chrome 身份发出,请求头与 Chrome GaiaAuthFetcher 相同:HTTP/2 下依次为 content-length、authorization、content-type、sec-fetch-site: none、sec-fetch-mode: no-cors、sec-fetch-dest: empty、user-agent、accept-encoding: gzip, deflate, br, zstd、accept-language 与 priority: u=4, i。user-agent 的主版本取 User Data 的 Last Version;accept-language 取 Profile Preferences 的 intl.accept_languages,没有该项时取 intl.selected_languages,按 Chromium 的规则在带地区的语言后补主语言并依次加 q=0.9 到 q=0.1。导入与续签都读取账户导入来源的 User Data 目录中当前的 Chrome 版本与该 Profile 的语言设置,来源没有记录目录时读取稳定版 Chrome 的默认目录。

Chrome 导入状态在 storage-state.json 的 aistudio2api 扩展中保存来源(浏览器、User Data 目录、Profile 与邮箱)、Gaia ID、refresh token 与 wrapped binding key。登录页跳转、签名 Cookie 失效、HTTP 401 与协议 Code 16 进入同一认证恢复流程,覆盖 Worker 预热、按需启动、普通 RPC、受保护 RPC 与 Live 建连。服务优先在同一账户出口续签 Cookie;保存的 OAuth 材料被拒绝时,从当前 Chrome 匹配原账户邮箱与 Gaia ID,更新来源材料。没有 aistudio2api 扩展的账户在本机 Chrome 登录着同一邮箱时,从 Chrome 导入该邮箱的材料并写入扩展,此后按 Chrome 导入账户续签。有效 Cookie 提交后使动态头失效、关闭该账户 WAA runtime,并重放一次。恢复失败后,服务以账户的指纹、出口与保存的 Cookie 打开 AI Studio 新对话页:被转到 Google 登录页时账户标为 auth_required,管理事件同步发布账户状态,后续调度使用其他合格账户;页面正常打开时账户状态不变,只有该次请求失败或换号。

认证恢复等待同账户的正常请求结束;并发失效复用一次提交结果。替换登录材料推进认证代际,旧请求的认证结果按代际和请求顺序写回;生成正常结束后确认认证有效。HTTP 403、协议 Code 7 与 Drive unauthorized_client 保留模型权限或 Drive 授权含义。隔离 Camoufox 登录和外部 storage state 在本机 Chrome 没有同一邮箱时只使用各自的登录材料。

storage-state.json 保留 Playwright 根字段和未知扩展字段,已定义形状如下。wrapped_binding_key 是 Go []byte 的 Base64 JSON 字符串。

{
  "cookies": [
    {
      "name": "<NAME>",
      "value": "<VALUE>",
      "domain": ".example.com",
      "path": "/",
      "expires": -1,
      "httpOnly": true,
      "secure": true,
      "sameSite": "Lax",
      "partitionKey": "<OPTIONAL>"
    }
  ],
  "origins": [
    {
      "origin": "https://example.com",
      "localStorage": [{"name": "<NAME>", "value": "<VALUE>"}]
    }
  ],
  "aistudio2api": {
    "source": {"browser": "chrome", "profile": "<PROFILE>", "email": "<EMAIL>"},
    "oauth": {
      "gaia_id": "<GAIA_ID>",
      "refresh_token": "<REFRESH_TOKEN>",
      "wrapped_binding_key": "<BASE64>"
    }
  }
}

Cookie 的 name、value、domain、path、expires、httpOnly、secure、sameSite 与可选 partitionKey 原样持久化;sameSite 接受空值、Lax、Strict 或 None。origin 必须包含 scheme 与 host。请求 Cookie 过滤过期项与不匹配的 Secure/domain/path 条目,按 path 长度降序、同长度按持久化顺序发送;普通 HTTP 响应的 Set-Cookie 按 name、domain、path 替换或删除未分区项,替换项留在原位置,新项排在末尾,同名分区项独立保留。浏览器恢复时按持久化顺序逐个写入 Cookie,partitionKey 映射到 BiDi storageKey.sourceOrigin,空值使用默认分区;浏览器导出的 Cookie 中,恢复时写入的项保持写入顺序,之后出现的项排在其后。

账户持久状态

文件 内容
auth/<Google 邮箱>/account.json 邮箱、enabled、proxy、locale、timezone、auth_user
auth/<Google 邮箱>/storage-state.json Cookie、localStorage 和可选 Chrome 续签材料
auth/<Google 邮箱>/camoufox-fingerprint.json 账户固定的 navigator、屏幕、字体、WebGL、语言、地区和时区配置
auth/<Google 邮箱>/runtime-state.json 账户权益、实测模型资格、冷却与 Drive/视频资源绑定
auth/<Google 邮箱>/pairing-renewal.json 远程配对上传签发的续签凭据 SHA-256 与最近一次配对续签时间
auth/<Google 邮箱>/camoufox-cache/ 该账户 Camoufox 的 HTTP 磁盘缓存与 Firefox 启动缓存,运行中的 WAA Worker 独占
auth/.leases/<Google 邮箱>.lock 同一账户目录的跨进程占用锁
auth/.leases/<Google 邮箱>.runtime.lock 每次 runtime-state.json 读取、合并与写回的短事务锁
[用户缓存]/AIStudio2API/runtime-leases/<Google 邮箱>.lock 当前电脑上该邮箱的 WAA Worker 占用锁

Google 邮箱的小写形式同时作为账户目录、管理页面标识和日志来源。新账户的 locale 与 timezone 读取当前电脑设置,管理页面使用浏览器语言和 IANA 时区;CLI 使用操作系统语言和时区。初始化、WAA、MakerSuite、OAuth 续签和 Drive 使用账户固定代理。locale 同时设置 navigator language、Accept-Language 与地区,timezone 设置浏览器时区;重新登录和 WAA runtime 复用同一账户指纹。同一电脑上的多个进程按邮箱共享 WAA runtime lease,调度器只会为未被占用的邮箱创建 Worker。

runtime-state.json 根字段为 cooldowns、resources、model_access、benefit_tier、catalog_fingerprint。cooldown value 为 {until,reason?};model access value 为 {state,checked_at,reason?};resource value 为 {kind?,name?,mime?,size?,purpose?,created_at,video?:{model,seconds,size,file?},alias?,sha256?,video_duration?,used_at?,display_name?}:alias 为上传时指定的公开文件 ID,sha256 为内容的 SHA-256 摘要(Base64),video_duration 为视频时长(纳秒),used_at 为内联附件最近被请求引用的时间,display_name 为内联附件在请求中给出的文件名。

每次运行状态事务先取得 auth/.leases/<账户>.runtime.lock,每 25ms 尝试一次,等待上限为 2 秒;携带调用方 context(Go 取消上下文)的事务在调用方取消或 deadline 更早到达时立即结束。取得锁后重新读取当前磁盘值,只合并目标字段,以临时文件原子替换 runtime-state.json,再同步内存状态与资源归属。锁等待失败、读取失败、写回失败和 unlock 失败均返回原始错误链。

调度器按实时模型方法、capability、AccessModes 和账户权益选择候选,优先使用已经成功调用目标 scope(模型资格与冷却的状态记录范围)的预热账户,再按目标模型最近一次真实首事件耗时排序。常驻 Worker 优先覆盖可调用模型更多的账户。预热数量低于上限时提升待机账户,预热账户均忙时等待并发槽位。同账号 WAA proof 串行生成,已准备的 MakerSuite HTTP 请求并发执行;首个活动请求获取 .leases/<邮箱>.lock,最后一个释放。Drive file、视频任务与结果 file 始终使用创建账户。

账户权益

GetAiStudioBenefitTier 请求为 [],响应 field 1 的枚举映射如下。[]、[null] 和 [0] 均表示 Free;响应存在后续字段时,权益仍由 field 1 决定。

值 权益 RPC Header
0 Free 无
1 Pro X-AIStudio-G1-Tier: TIER1
2 Ultra X-AIStudio-G1-Tier: TIER2
3 Plus X-AIStudio-G1-Tier: TIER0

官网为 GenerateContent、CountTokens、Interaction、Code Assistant 与 StreamExtractVideoFrames 注入该 header。模型 field 83 描述访问方式:1 为付费 API key,3 为 Pro/Ultra 订阅,4 为 Ultra 订阅。公开模型目录合并全部账户的实时 ListModels 记录;账户调度使用 AccessModes、BenefitTier 与成功调用历史选择具体账户。

条款同意

GetLoggingContext 请求为 []。响应 field 6 存在且为否、field 7 存在时,官网要求账户同意条款:功能开关开启且 field 10 为空或 0 时进入 /onboarding 条款表单,否则弹出条款对话框。两处提交的 AcceptTerms 请求如下,成功响应为 []:

字段 值
1 "users/me"
3 日志上下文 field 7,为 0 时省略
4、5 邮件订阅,未勾选时省略
6 1
7 日志上下文 field 15,为 0 时省略
9 条款对话框为 1,onboarding 表单为 5

服务在每个账户本进程的首次目录同步前读取 GetLoggingContext,需要同意时按 field 10 选择 field 9,以不订阅邮件发送 AcceptTerms;成功后本进程内不再读取,失败时本次目录同步失败,下次同步重新读取。

地区或账户不受支持

官网启动时 GetLoggingContext 返回 HTTP 403、错误体 [7,"Region not supported."] 或 [7,"Account not supported."] 时,页面跳转到 https://aistudio.google.com/docs/available-regions。

服务对任一 RPC 的这两种错误报告 AI Studio 不支持当前出口地区或账户,错误文字附上游原文、该跳转页与处理方法(为该账户或全局代理换用支持地区的出口):

  • 目录同步失败时账户状态显示该原因,已有目录的账户同样显示
  • SpiderMonkey Worker 启动时读取 GetLoggingContext 得到该错误即失败
  • Camoufox Worker 订阅页面导航事件,页面开始导航到 available-regions 页后,后续页面操作立即以该原因失败

3. WAA challenge、官方 VM 与 fresh proof

受保护请求使用以下链路:

Waa/Create
  -> decode challenge
  -> load interpreter by current hash
  -> initialize official VM lifecycle
  -> SHA-256(binding prompt) as lowercase hex
  -> snapshot({TYb:{content:<DIGEST>}})
  -> write fresh proof into request
  -> send protected MakerSuite RPC

WAA_BACKEND=camoufox 时官方 VM 运行在账户固定指纹的 Camoufox 页面,受保护请求由页面 XMLHttpRequest 发送;最后一轮是带文本的 user 轮次的 GenerateContent 由页面应用在输入框写入该轮文本并点击 Run 时发出(与页面上一轮的对话相同时点击 Rerun),proof 由页面应用以服务给出的 binding 摘要生成,发送时正文换成服务编码的请求正文;WAA_BACKEND=spidermonkey 时 VM 运行在服务进程内的 SpiderMonkey 与 Firefox 形状宿主中,受保护请求由 Go HTTP 以 Firefox 152 网络形状发送。

Waa/Create 请求是 JSON+protobuf 数组。Worker 启动时只带 request key,VM 刷新时追加当前 interpreter hash 与上一 VM 的无绑定 snapshot:

["lmnUSbltwc5ULv48iKLX"]
["lmnUSbltwc5ULv48iKLX", "<INTERPRETER_HASH>", "<PREVIOUS_SNAPSHOT>"]

响应外层索引 1 是 Base64 challenge,解码后每个字节加 97,得到 message ID、interpreter、program、全局函数名与 client experiments 状态。interpreter 按 hash 缓存,摘要为 SHA-256 的 Base64URL 无 padding 编码;program 属于当前 Create 生命周期,proof 绑定当前 prompt 摘要与 VM 内部状态,每个请求生成新的 proof。

snapshot 的底层输入是四槽数组,首槽承载 binding:

[{content: sha256(bindingPrompt)}, undefined, undefined, undefined]

返回值是 ! 开头的 proof。GenerateContent、CreateInteractionStream、CreateInteraction 与 GetInteractionStream 写入 field 5,Build 代理写入 field 3,Build 写代码助手 CodeAssistantOffline 写入 field 2,Bidi 的每个客户端 wire 写入 field 6;原请求的其他槽位保持不变。GenerateContent 按 contents 和 parts 原顺序以单个空格连接。

Waa/Ping 请求和成功响应:

["lmnUSbltwc5ULv48iKLX", "<BOTGUARD_RESPONSE>"]
[]

field 1 是 request_key,field 2 是 botguard_response。正确 proof、损坏 proof、省略 field 2、错误 request key 与无账户认证均可返回 HTTP 200 和 []。Ping 成功表示 WAA RPC、API consumer identity 与字段类型可达;Worker VM、snapshot proof、binding、账户会话、模型资格和 GenerateContent 接受状态由实际受保护业务 RPC 判定。

生成服务启动时按配置的常驻数与启动并发数预热账户 WAA Worker。一个账户 Worker 为该账户的所有普通生成模型提供 proof,业务模型切换直接复用当前 Worker;同一账户的 snapshot 串行执行。

4. ListModels、CountTokens 与 GenerateContent 请求

ListModels

请求正文:

[]

响应根形状为 [[<MODEL_ROW>, ...]]。模型列表位于 field 1,后续根字段不改变模型目录。模型行字段:

JSON 索引 protobuf field 内容
0 1 models/<MODEL_ID>
2 3 版本
3 4 显示名称
4 5 描述
5 6 输入 token 上限
6 7 输出 token 上限
7 8 支持的方法
8 9 默认 temperature
9 10 默认 topP
10 11 默认 topK
22 23 模型阶段码:1 UNSTABLE_EXPERIMENTAL、2 EXPERIMENTAL、3 PREVIEW、4 STABLE、5 LEGACY、6 DEPRECATED、7 RETIRED
56 57 模型别名
64 65 主能力码
66 67 TTS voice 列表
70 71 视频配置
71 72 thinking 默认配置
74 75 次能力码
75 76 图片宽高比码
76 77 图片输出分辨率码
77 78 Paid 标记,值 2 时显示 Paid
78 79 Interaction 配置:索引 2 为后台任务,索引 3 类型 1 为 agent、2 为模型
81 82 官网新建对话时默认开启的设置与工具的能力码
82 83 模型访问方式

能力码映射:

码 能力 码 能力
1 chat model 9 code execution
10 function declarations 12 Google Search
13 URL Context 20 video route
21 image route 25 thinking
26 live route 35 thinking budget
37 speech route 43 media resolution
47 aspect ratio 49 output resolution
52 thinking level 53 music route
54 image search 58 Google Maps
59 private Interaction route 85 TTS 分段说话人
69 Agentic 视频理解
46 Live 实时翻译 48 Build 写代码助手可选

未知能力码按原值保留为 capability_code_<N> 或 secondary_capability_code_<N>。

公开模型对象为已知主能力码增加以下语义键:

码 capability 键 码 capability 键
1 chat_model 9 code_execution
10 function_declarations 12 google_search
13 browse 20 video_route
21 image_route 25 thinking
26 live_route 35 thinking_budget
37 speech_route 43 media_resolution
47 aspect_ratio 49 output_resolution
52 thinking_level 53 music_route
54 image_search 58 google_maps
59 thinking_summaries 74 transcription_word_timestamps
69 agentic_video
76 transcription_language_codes 77 transcription_output
80 transcription_speaker_labels 81 transcription_custom_vocabulary
84 transcription_smart 85 speech_metadata
46 speech_translation 48 code_assistant

每个主能力码都保留为 capability_code_<N>,同时为上表中的已知码增加语义键;次能力码保留为 secondary_capability_code_<N>;field 82 中默认开启的码保留为 default_capability_code_<N>;有 field 79 的模型带 interactions_api,其中经后台任务生成的模型另带 interaction_task。

图片与视频选项使用枚举码:

类型 码值映射
图片/视频宽高比 1=1:1、2=9:16、3=16:9、4=3:4、5=4:3、6=3:2、7=2:3、8=5:4、9=4:5、10=21:9、11=9:21、12=1:4、13=4:1、14=1:8、15=8:1
图片分辨率 1=1K、2=2K、3=4K、4=512
视频时长 1=5s、2=6s、3=7s、4=8s、5=4s
视频分辨率 1=720p、2=1080p、3=4k、4=368p、5=360p

视频模型 field 71 的宽高比、时长和分辨率分别位于子索引 4、5、9;子索引 7 含 3 而子索引 9 为空时,分辨率为官网默认的 720p、1080p、4k。子索引 7 含 4 时模型接受起始帧与尾帧,含 5 时接受参考图,公开为 video_inputs 的 frames 与 reference_images。TTS field 67 是 repeated voice row,每行索引 0 为 voice name。thinking field 72 的默认 level 位于子索引 5。

field 57 alias 可以是 ["models/<ALIAS>"],也可以是 repeated row;row 形状时取每行索引 0 并移除 models/ 前缀。公开 capability_options 的键全集为 aliases、voices、image_aspect_ratios、image_output_resolutions、video_aspect_ratios、video_durations_seconds、video_output_resolutions、video_inputs、video_duration_range、video_frame_rates 和 video_tasks;没有值的键省略。Omni 的 field 71 子索引 10 为时长滑块的下限、上限、步长与默认值,公开为 video_duration_range 的 min=、max=、step=、default= 四项;子索引 11 为帧率,1 公开为 24fps;field 85 为视频任务,1–5 公开为 text_to_video、image_to_video、reference_to_video、edit、extend。各键的取值保持上游目录的顺序,多个账户的目录合并时按首次出现的顺序去重;API 试用页以 video_output_resolutions 的第一项为 Omni 的默认分辨率。

CountTokens

纯文本且无 system:

["models/<MODEL_ID>", [<CONTENT>, ...]]

含 system、inline data、外部媒体或 Drive file:

["models/<MODEL_ID>", null, ["models/<MODEL_ID>", [<CONTENT>, ...], null, null, null, <SYSTEM>]]

请求形状选择:

条件 根结构 GenerateContent 子消息位置
纯文本 contents [model, contents] —
system instruction [model, null, generate] $[2][5]
function / Google tools [model, null, generate] $[2][6]
media resolution [model, null, generate] $[2][3][17]
inline data、external media、Drive、function call/result、code result [model, null, generate] $[2][1]

响应为 [totalTokens, system, [content, ...], [tool, ...], null, [[modality, tokenCount], ...]]。system 与每个 content 为 [[partTokens...], roleTokens],没有系统指令时 system 为 [];每个 tool 为 [[functionDeclarationTokens...]],不含函数声明的工具为 []。请求中的系统指令带 user 角色,上游把它的角色 token 计入 totalTokens 与 TEXT 模态;Gemini API 的系统指令没有角色,服务从这两处减去系统指令的角色 token 数。

计数请求的分辨率为请求级分辨率,未设置时取全部媒体 Part 共同指定的分辨率。Part 分辨率各不相同且 Build 通道启用时经 Build 通道 ProxyUnaryCall 发送 POST /v1beta/models/<MODEL_ID>:countTokens,请求体为 {"generateContentRequest":{model,contents,systemInstruction?,tools?,generationConfig?:{mediaResolution}}},响应为 {totalTokens,systemInstructionsTokens,contentTokens,toolTokens?,promptTokensDetails};Playground 目录没有、Build 目录列出 countTokens 的模型同样经 Build 计数。

包含 system 与函数声明的完整计数请求:

[
  "models/gemini-3.6-flash",
  null,
  [
    "models/gemini-3.6-flash",
    [
      [
        [[null, "调用 ping 检查服务"]],
        "user"
      ]
    ],
    null,
    null,
    null,
    [
      [[null, "你是诊断助手"]],
      "user"
    ],
    [
      [null, [["ping", "检查服务"]]]
    ]
  ]
]

响应为单元素数组:

[<INPUT_TOKEN_COUNT>]

索引 0 是权威输入 token 数。其他槽按不透明协议字段保留。

Content、Part 与 system

Content 形状:

[[<PART>, ...], "user|model"]

带 finish reason 的模型完成帧可以使用 [null,"model"],该帧只提供终止状态与 usage。

客户端 tool result 使用 user role。Part 字段:

JSON 索引 protobuf field 内容
1 2 文本
2 3 inline data [mime, base64]
5 6 Drive file [fileId]
6 7 外部媒体 [mime, url]
7 8 executable code [languageCode, code]
8 9 code execution result [outcomeCode, output]
10 11 function call [name, Struct, callId?]
11 12 function result [name, Struct, callId?]
12 13 thought boolean
14 15 thought signature
15 16 视频静态处理元数据 [startOffset?, endOffset?, fps?];offset 为 [seconds,nanos?]
17 18 上传附件 [mime, 上传路径, 文件名, 字节数],字节数为十进制字符串;用于 Build 写代码助手,见 Build 通道 第 8 节
22 23 transcription metadata [text, speaker?, timestamp spans?]
25 26 服务端媒体处理调用 [13, name?, Struct?, callId?]
26 27 服务端媒体处理结果 [13, name?, Struct?, callId?]
39 40 视频处理模式:1 STATIC、2 AGENTIC

field 26 与 27 是服务端工具调用与结果 [toolType?, name?, Struct?, callId?],toolType 为 MCP=1(Gemini API 名 CUSTOM)、Google Search=2、URL Context=3、Google Maps=8、媒体处理=13;MCP 结果的 toolType 为空。外部媒体 [mime, url, null, null, null, displayName?] 的第 6 项为附件文件名。

system instruction 每个文本分段一个 Part:

[[[null, "<SYSTEM_TEXT_1>"], [null, "<SYSTEM_TEXT_2>"]], "user"]

GenerateContent

根消息字段:

JSON 索引 protobuf field 内容
0 1 models/<MODEL_ID>
1 2 contents
2 3 safety settings
3 4 generation config
4 5 fresh WAA proof
5 6 system instruction
6 7 tools
10 11 固定值 1,自动续写模型省略
11 12 历史中最后一个模型轮的 turnToken
13 14 tool config [[<[lat,lng]?>, <languageCode?>, <TIMEZONE>], null, <includeServerSideToolInvocations?>]
14 15 用户 Cloud API key,免费网页链保持 null
16 17 自动续写轮的续写 token

safety settings:

[
  [null, null, 7, 5],
  [null, null, 8, 5],
  [null, null, 9, 5],
  [null, null, 10, 5]
]

每项为 [null, null, 类别, 阈值],编号与 Gemini API 枚举相同:类别 HARM_CATEGORY_HARASSMENT=7、HATE_SPEECH=8、SEXUALLY_EXPLICIT=9、DANGEROUS_CONTENT=10、CIVIC_INTEGRITY=11;阈值 BLOCK_LOW_AND_ABOVE=1、BLOCK_MEDIUM_AND_ABOVE=2、BLOCK_ONLY_HIGH=3、BLOCK_NONE=4、OFF=5。Playground 没有 HARM_CATEGORY_JAILBREAK 的编号,含该类别的请求经 Build 通道发送。非图片模型默认发送上面 7–10 四类 OFF,Gemini 协议请求中的类别按名称覆盖或追加;图片模型只发送请求中的类别,没有时为 null。上游对 HARM_CATEGORY_UNSPECIFIED(0)与 DEROGATORY 至 DANGEROUS(1–6)返回 400,这些类别与 HARM_CATEGORY_IMAGE_* 不发送;其他未知名称在发送前返回 400 并列出可用类别,未知阈值同样在发送前返回 400。

generation config 字段:

JSON 索引 protobuf field 内容
1 2 stop sequences
3 4 max output tokens
4 5 temperature
5 6 topP
6 7 topK
7 8 response MIME type
8 9 response schema
13 14 固定值 1
45 46 自动续写模型为 1
14 15 response modalities:TEXT=1、IMAGE=2、AUDIO=3
15 16 speech config
16 17 thinking config [1, budget?, null, level]
17 18 media resolution:LOW=1、MEDIUM=2、HIGH=3、ULTRA_HIGH=4
18 19 seed
26 27 image config [aspectRatio?, imageSize?]
31 32 transcription config

生成参数校验:

参数 默认来源 有效值
max output ListModels field 7,自动续写模型为 inputTokenLimit 1..model.outputTokenLimit,自动续写模型为 1..model.inputTokenLimit
temperature ListModels field 9 0..2
topP ListModels field 10 0..1
topK ListModels field 11 非负整数
thinking level ListModels field 72 Low=1、Medium=2、High=3、Minimal=4
thinking budget 请求值 模型能力码包含 thinking budget
  • max output 大于模型上限时按上限发送

reasoning_effort / thinkingLevel / Anthropic output_config.effort 接受 none、minimal、low、medium、high、xhigh、max,xhigh 与 max 按 high 处理,THINKING_LEVEL_UNSPECIFIED 视为未设置。none 在只支持 thinking budget 的模型使用预算 0,支持 thinking level 的模型使用最低可用 level。模型只有 thinking level 能力时,显式 budget 按 0、1024、8192 以内与更大预算分别退化为 minimal、low、medium、high;没有 thinking level 能力的模型忽略其余 effort,两类能力都缺少时同时忽略 budget。

生成与计数请求的模型名可以带思考后缀 <模型 ID>(<值>),例如 gemini-4-argon(low)、gemini-2.5-pro(16384)。值不区分大小写:none、minimal、low、medium、high、xhigh、max 作为思考强度,非负整数作为思考预算,auto 与 -1 使用模型默认思考设置;后缀覆盖请求体中的思考强度与预算,去掉后缀的模型 ID 用于调度、请求日志与用量统计。其他值返回 400。

能力码 48 的模型在目录中另有 <模型 ID>-build 条目,经 Build 写代码助手生成,思考后缀写在 -build 之后,例如 gemini-3.8-flash-build(low);条目定义、请求与流格式见 Build 通道 第 8 节。

模型名等于 MODEL_MAPPING 中的别名(可带 models/ 前缀)时,生成、计数、embedding、Live、视频与转录请求先换成映射的模型名,再解析思考后缀,映射目标可以带后缀,例如 fast:gemini-4-argon(low);别名本身带后缀时以该后缀替换目标自带的后缀,例如 fast(high) 按 gemini-4-argon(high) 处理。同一别名写了多次时以第一项为准,映射只替换一次。/v1/models 与 /v1beta/models 在目录之后列出目标在目录中的别名,字段取自目标模型;与目录 ID 同名的别名替换该条目。

response modalities:

wire 指发送给上游的原始数组字段。

输出 wire 默认路由
text [1] chat
image [2] image route
image + text [2,1] 显式组合请求
audio [3] speech / music route

AUDIO 采用独立输出模态,与其他模态同时请求时按模型能力取交集。JSON Schema type code 为 string=1、number=2、integer=3、boolean=4、array=5、object=6;schema 支持 format、description、nullable、enum、items、properties、required 和 field 23 propertyOrdering。

以下最小组合请求包含 system、文本、函数声明、generation config、WAA proof 与账户时区。连续空槽保持在同行,字段含义查上表:

[
  "models/gemini-3.6-flash",
  [
    [
      [[null, "调用 ping 检查服务"]],
      "user"
    ]
  ],
  [
    [null, null, 7, 5],
    [null, null, 8, 5],
    [null, null, 9, 5],
    [null, null, 10, 5]
  ],
  [null, null, null, 512, 0.2, 0.95, 40, null, null, null, null, null, null, 1],
  "!WAA_PROOF",
  [
    [[null, "你是诊断助手"]],
    "user"
  ],
  [
    [null, [["ping", "检查服务"]]]
  ],
  null,
  null,
  null,
  1,
  null,
  null,
  [[null, null, "Asia/Taipei"]]
]

5. 增量流、思考、usage、来源与错误

GenerateContent 返回持续增长的 JSON+protobuf 根数组,根索引 0 是 repeated frames。帧结构:

路径 内容
$[0][frame][0] candidates
$[0][frame][0][0][0] candidate content
$[0][frame][0][0][1] finish reason code
$[0][frame][0][0][6] citations
$[0][frame][0][0][7] grounding metadata
$[0][frame][2] usage
$[0][frame][7] turnToken
$[0][frame][3] 且 frame 0 为空 interaction metadata

传输正文是一个 JSON 根值,网络 chunk 提供字节;解码器在 $[0] 中每出现一个完整 repeated frame 时立即消费该 frame。每个内容帧包含一个 candidate,candidate content 为 [[parts...], "model"]。完成帧可以同时携带最后一组 Part、usage、turnToken 和 finish reason,根数组解析完成后结束读取。出错时根索引 1 为流尾 google.rpc 状态 [code, message, details],code 不为 0 时按 Build 通道 的流尾状态表换算 HTTP 状态,以该上游错误结束回复。turnToken 为 v1_ 加 Base64 protobuf,field 2 为该响应的 responseId,同一响应的各帧相同;服务以该 responseId 作为 Gemini 输出的 responseId。

从 $[0] 提取出的文本帧:

[
  [
    [
      [
        [[null, "42"]],
        "model"
      ]
    ]
  ]
]

随后到达的完成帧包含 finish=1、usage 和 turnToken:

[
  [[null, 1]],
  null,
  [27, 1, 28, null, null, null, null, 0, null, 0],
  null,
  null,
  null,
  null,
  "v1_TURN_TOKEN"
]

高频路径速查:

结构 JSONPath 内容
GenerateContent $[0] model
GenerateContent $[1] contents
GenerateContent $[3] generation config
GenerateContent $[4] WAA proof
GenerateContent $[5] system instruction
GenerateContent $[6] tools
GenerateContent $[13][0][2] timezone
response root $[0][frame] repeated frame
candidate content $[0][frame][0][0][0] [[parts], "model"]
candidate finish $[0][frame][0][0][1] finish reason code
candidate finish message $[0][frame][0][0][3] finish message
Part text ...parts[part][1] text
Part inline data ...parts[part][2] [mime, base64]
Part function call ...parts[part][10] [name, Struct, callId?]
Part thought ...parts[part][12] boolean
Part signature ...parts[part][14] signature
frame usage $[0][frame][2] usage array
frame turnToken $[0][frame][7] turnToken

Part 文本带 part[12]=1 时属于 reasoning summary,普通文本属于可见正文;带 part[12]=1 的内联图片是图片模型思考过程中的草图,不作为输出媒体返回,最终图片以普通 Part 另行返回;part[14] 是 thought signature。签名可以附在文本、函数调用或独立空 Part 上,下一轮必须原样回传:

公开协议 签名输入 签名输出
OpenAI Chat assistant tool call 的 extra_content.google.thought_signature tool call 的同名扩展字段
OpenAI Responses reasoning.encrypted_content 紧邻后续 function_call include 含 reasoning.encrypted_content 时为 reasoning item 的 encrypted_content
Anthropic thinking 或 redacted_thinking block 的 signature thinking block 的 signature
Gemini 数据 Part 或独立 Part 的 thoughtSignature Part 的 thoughtSignature

OpenAI Chat 的 assistant tool call 未带 extra_content 时,服务按调用 ID、函数名和参数补回本进程最近签发的签名;查不到时写入 skip_thought_signature_validator。

Playground 通道的历史模型轮与官网同形:服务在进程内按 API key 与对话摘要保存最近 1000 次生成的模型轮,内容为上游按帧给出的思考 Part、正文 Part、函数调用与只带签名的空文本 Part([null,"",…,<signature>]),以及最后一帧的 turnToken。客户端回传的模型轮与保存的回复在正文(忽略空白)、函数调用名称与参数上相同、且之前的对话相同时,发往上游前换成保存的 Part,函数调用沿用客户端的 ID,历史中最后一个模型轮的 turnToken 写入根消息 field 12。带内联媒体的回复与以模型轮结尾的请求不保存;STRIP_THOUGHT_SIGNATURES 打开时不补回。

Anthropic redacted thinking block 以 data 承载同一份不透明状态;适配器在输入与输出两侧保留该值。流式响应不输出文本之后到达的签名。

reasoning summary 是服务端返回的摘要文本。thought signature 作为下一轮请求的协议状态字段原样回传。

协议核心按网络顺序输出 text、reasoning、tool_call、executable_code、code_execution_result、grounding、citation、media、thought_signature、usage、finish 和 error。

Grounding 与引用

grounding metadata 字段:

JSON 索引 内容
0 search entry point [renderedContent?, sdkBlob?]
1 grounding chunks
2 grounding supports
3 retrieval metadata,动态分数位于子索引 1
4 web search queries
5 第二个 repeated web search query 槽
6 Maps widget context token

索引 4、5 按槽位与元素顺序合并并去重。

oneof 表示同组字段中最多选择一种值。

grounding chunk 的 oneof 索引 0/1/2 分别为 web、retrieved context、maps;内部字段依次为 URI、title、text、place ID。support 为 [segment, chunkIndices, confidenceScores],segment 为 [partIndex,startIndex,endIndex,text]。candidate citations 的 entries 位于 metadata 索引 0,每项 URL 在索引 2、title 在索引 3。

包含 web chunk、maps chunk、正文 support、检索分数和查询词的 raw metadata:

[
  ["<div>Search results</div>", "SDK_BLOB"],
  [
    [["https://example.com/gemini", "Gemini Guide", "Protocol overview"]],
    [null, null, ["https://maps.google.com/?cid=1", "Google Taipei", "", "ChIJ_demo"]]
  ],
  [
    [[0, 0, 12, "Gemini Guide"], [0], [0.98]]
  ],
  [null, 0.91],
  ["Gemini AI Studio protocol"],
  null,
  "MAPS_WIDGET_CONTEXT_TOKEN"
]

Code Execution 的 language code 为 0=LANGUAGE_UNSPECIFIED、1=PYTHON。执行结果 outcome code 为 0=OUTCOME_UNSPECIFIED、1=OUTCOME_OK、2=OUTCOME_FAILED、3=OUTCOME_DEADLINE_EXCEEDED。

Usage

完成帧 usage:

数组索引 语义 规范字段
0 input tokens input_tokens
1 visible output tokens output_tokens
2 total tokens total_tokens
3 输入中命中上游隐式缓存的 tokens cached_tokens
7 tool tokens tool_tokens
9 thought tokens reasoning_tokens

完整 usage 按上游原值返回;请求带系统指令时,上游把系统指令 user 角色的 1 个 token 计入 input、total 与 TEXT 输入模态,Gemini API 不计,服务从这三处减去。上游每帧都带累计 usage,服务把它写入该帧的事件。完成帧省略 visible output tokens 时,服务按上游 total 与其余分类字段恢复该值。完整 usage 缺失时,内置 Gemini SentencePiece tokenizer 在本地统计可观测输入、工具声明、reasoning summary 和实际输出。

OpenAI 与 Anthropic 的输入统计为 input + tool,输出统计为 visible output + reasoning。Gemini 分别投影 promptTokenCount、candidatesTokenCount、thoughtsTokenCount 与 totalTokenCount。缓存命中数在 Chat 中为 prompt_tokens_details.cached_tokens,在 Responses 中为 input_tokens_details.cached_tokens,两者都包含在输入统计内;Anthropic 的 cache_read_input_tokens 为缓存命中数,input_tokens 为输入统计减去缓存命中数,cache_creation_input_tokens 为 0;Gemini 在命中时输出 cachedContentTokenCount。Build 通道的缓存命中数来自 usageMetadata.cachedContentTokenCount。思考用量在 Chat 中为 completion_tokens_details.reasoning_tokens,在 Responses 中为 output_tokens_details.reasoning_tokens,在 Anthropic 中为 output_tokens_details.thinking_tokens。Chat 的 prompt_tokens_details 与 completion_tokens_details 另含 audio_tokens(上游音频模态细分之和)与值为 0 的 accepted_prediction_tokens、rejected_prediction_tokens。Gemini usageMetadata 省略值为 0 的计数;Build 通道上游给出 billedToolCalls、toolCallStats、modelInvocationTokenCounts、rawPromptTokenCount 与 nonGroundingModelInvocationTokenCounts 时原样输出,Playground 通道的 usage 没有这些字段。隐藏思考用量来自上游 usage field 9;本地 fallback 统计服务端返回的 reasoning summary。

Anthropic 流式 message_start 在首个上游帧带输入用量时写入该用量,否则写入本地输入估算:收到请求时取下文本与工具 JSON,在后台用内嵌 Gemma 3 分词模型计数,与等待上游首个事件同时进行,1 KB 以上文本的计数按内容缓存;最终 message_delta 使用完成 usage 覆盖为权威输入与输出统计。

携带 stop sequence 的 GenerateContent 与 CreateInteractionStream 请求并行执行同账户 CountTokens。正文匹配实际序列时,协议核心关闭生成流,使用 CountTokens 的输入总数以及已输出的正文、reasoning 和工具统计构造最终 usage;计数失败时仍返回 stop_sequence 终态并省略 usage。

自动续写

ListModels 能力码 91(目录能力 output_continuation)的模型由官网分轮生成超过 32768 token 的输出,输出长度上限为该模型的 inputTokenLimit:

  1. 请求的 generation config field 46 为 1,根 field 11 省略;max output 大于 32768 时首轮发送 32768
  2. 候选 field 9(JSON 索引 8)给出续写 token。完成帧以 max_tokens 结束且同一帧带 token、本轮上限小于请求的输出总量,或以终止原因 22 结束时,本轮不形成终态
  3. 下一轮复制原请求,根消息 field 17 写入最近的 token,max output 为 min(输出总量, (轮次 + 1) × 32768),轮次从 0 计
  4. 终止原因 22 而响应没有 token 时请求失败

各轮正文、思考与工具事件按顺序输出为一个响应,终态取最后一轮。usage 以最后一轮为基础,visible output、thought 与 tool tokens 逐轮累加,total 为最后一轮 total 加之前各轮的这三项。未指定输出上限时输出总量为模型的 inputTokenLimit。输出总量超过 32768 的自动续写请求只经 Playground 调度,未指定输出上限且含 File Search、serviceTier、store:false 等经 Build 通道发送的设置时仍可经 Build,按 Build 的单轮上限发送;请求期限为 REQUEST_TIMEOUT,每个续写轮开始时重新计时。每个续写轮在日志中记一条“上游调用”,模式后附 续写=<轮次>。

Finish 与错误

code reason code reason
0 unspecified 1 stop
2 max_tokens 3 safety
4 recitation 5 other
6 language 7 blocklist
8 prohibited_content 9 spii
10 malformed_function_call 11 image_safety
12 unexpected_tool_call 13 too_many_tool_calls
14 image_prohibited_content 15 image_other
16 no_image 17 image_recitation
18 missing_thought_signature 19 malformed_response
22 continuation 其他整数 provider_<code>

Build 通道的 Gemini API 终止原因去掉 FINISH_REASON_ 前缀后转为上表的同名小写原因,上表没有的名称为 provider_<小写名称>。上游以 malformed_function_call、unexpected_tool_call 或 malformed_response 结束,或流在完成帧之前中断、以 5xx 流尾状态结束,且这次生成没有输出正文、函数调用与媒体时(不输出给客户端的搜索、网址上下文、地图与文件检索步骤不计入,MCP 调用计入),服务在同一账户上以同一请求重新生成,最多再生成 3 次,之后按最后一次的终止原因或中断错误结束;被重新生成取代的那一次的网页来源与引用不输出,每次重新生成从头匹配停止序列,上一次暂存的停止序列前缀不输出,重新生成的请求发送失败时本次生成以该错误结束。两个通道第一次带终止原因的帧中的内容事件标记为结束帧,自动续写中转入下一轮的帧不标记;Gemini 流式输出把结束帧的内容放进最后一块。

候选 field 5($[0][frame][0][0][4])为安全评级 [[null, null, 类别, 概率, blocked?], ...],类别编号与安全设置相同,概率 NEGLIGIBLE=1、LOW=2、MEDIUM=3、HIGH=4;输入拒绝帧 [null,[block_reason,ratings?,message]] 的 ratings 为同形数组。Build 通道读取候选与 promptFeedback 的 safetyRatings。

generation config、安全设置、工具与转写配置在选择账户前按各账户已载入的模型目录校验,任一账户的条目接受即通过。

  • 流式请求在写出响应头前等待首个事件:参数错误与首个事件之前的上游错误按非流式返回 HTTP 状态与错误对象;10 秒内没有事件时先写出响应头,此后的错误以各协议的流内错误事件返回
  • 非流式请求收齐上游事件后再输出,上游流中途中断或在完成帧之前结束时换号重发
  • NONSTREAM_KEEPALIVE=true 时,Chat Completions、Responses、Messages、Gemini generateContent、Interactions 与图片生成的非流式请求在 10 秒内没有结果时先写出 200 与 Content-Type: application/json,之后每 10 秒写出一个换行,结果就绪后写出 JSON 正文;此后的错误以各协议的错误对象作为正文,访问日志与请求账本记录错误的 HTTP 状态
  • FAKE_STREAM=true 时,上述协议的流式请求按非流式方式生成:收齐上游事件、中途中断时换号重发,再以各协议的流式事件输出;等待期间按下文的流式心跳保持连接

错误响应根形状为 [null,[code,message,...]]。输入被上游拒绝时帧为 [null,[block_reason,null,message]]:

  • Gemini GenerateContent 返回 200 与不含 candidates 的 promptFeedback:{blockReason,blockReasonMessage},流式时作为唯一一帧发送
  • 其他协议返回 400,错误消息包含拒绝原因与上游说明

协议核心保留 HTTP 状态、协议 code 与 message;公开适配器映射为 OpenAI、Anthropic 或 Gemini 错误对象。Chat、Responses、Anthropic Messages 与 Gemini GenerateContent 将媒体模型的普通文本作为文本结果输出;专用图片端点要求图片结果。终态如下:

  • HTTP/协议错误形成失败
  • 读取上游响应时连接中断或上游流在完成帧之前结束,报告为上游流中断与已接收帧数
  • 上游 finish reason 作为正常终态保留并映射到各公开协议

各协议的具体终态转换如下:

上游终态 OpenAI Chat OpenAI Responses Anthropic Messages Gemini GenerateContent
stop 且包含函数调用 tool_calls,旧式 functions 请求为 function_call completed,保留 function call item tool_use STOP,保留 functionCall Part
stop_sequence stop completed stop_sequence 与实际序列 STOP
max_tokens length incomplete/max_output_tokens max_tokens MAX_TOKENS
continuation length incomplete/max_output_tokens max_tokens CONTINUATION
safety、recitation、blocklist、prohibited_content、spii、图片对应原因与 provider_* content_filter incomplete/content_filter refusal 对应 Gemini 枚举或 OTHER
other、language、malformed_function_call、malformed_response、签名缺失等其他终态 stop,含函数调用时 tool_calls completed end_turn,含函数调用时 tool_use 对应 Gemini 枚举

内容拦截终态优先于同一结果中的工具调用终态,已产生的正文、reasoning、工具事件和 usage 保持在响应中。provider_* 在 Chat choice、Responses response、Anthropic message 或 message_delta 的 provider_finish_reason 中保留原值;Gemini 对 Build 通道的 provider_<名称> 输出大写的原枚举名,对 Playground 的 provider_<编号> 输出 OTHER 并用 finishMessage 保留编号。malformed_response(Playground 编号 19)在 AI Studio 页面显示为 Content blocked。

6. 函数、Google 工具、Drive 与媒体

函数与 Google 工具

根 field 7 是 repeated Tool:

工具 Tool 数组形状
Function declarations [null, [[name, description?, schema?, null, behavior?], ...]]
Code Execution [[]]
Google Search [null,null,null,[null,[searchTypes]]],searchTypes 索引 0 为 []
Image Search 同一 Search tool,searchTypes 索引 1 为 []
URL Context 8 槽数组,索引 7 为 []
Google Maps 11 槽数组,索引 10 为 [],enableWidget 时为 [true]
Computer Use 6 槽数组,索引 5 为 [null, null, environment, null, excludedPredefinedFunctions?],environment 浏览器为 1
MCP 9 槽数组,索引 8 为 [[name, [url, headers?, timeout?, sseReadTimeout?, terminateOnClose?], allowedTools?], ...];headers 为按键排序的 [[key, value], ...],Duration 为 [seconds, nanos],allowedTools 为 [[toolName, ...]]

FunctionDeclaration field 5 为 behavior,只在 Live 会话的函数声明中发送:BLOCKING 编码为 1,NON_BLOCKING 编码为 2;UNSPECIFIED 与省略相同,不写该字段,其他取值在建立会话前返回 invalid_request 错误帧。Build 通道写入 Gemini API 字段 behavior。generateContent 与 Gemini API 一样不使用 behavior。

Search tool 的 index 3 是 [timeRange?,searchTypes]。timeRange 为 [start?,end?],每个时间值编码为 ["<UNIX_SECONDS>"];searchTypes 的索引 0/1 分别启用 web 与 image search。

公开工具名称归一化后再生成上述 Tool 数组:

AI Studio 工具 OpenAI Chat / Responses Anthropic Gemini
function declarations function 空 type 或 custom functionDeclarations
Google Search web_search、web_search_preview web_search_* googleSearch、googleSearchRetrieval
Image Search image_search image_search imageSearch
URL Context url_context web_fetch_*、url_context urlContext
Code Execution code_interpreter code_execution_* codeExecution
Google Maps google_maps google_maps googleMaps
Computer Use — — computerUse
MCP — — mcpServers

Interactions 的 google_search、google_maps、computer_use、mcp_server 与 file_search 工具分别对应上表的 Google Search 或 Image Search、Google Maps、Computer Use、MCP 与 Gemini fileSearch。File Search 只经 Build 通道发送。

根 field 7 按请求声明逐项编码,函数声明和各类 Google 工具按上表对应的 Tool entry 编码。模型的工具范围取自实时能力码,模型不支持的函数声明与 Google 工具在发送前丢弃,声明的工具全部丢弃时工具选择按 auto 处理;模型没有 function declarations 能力时,历史函数调用与结果改写为 {"functionCall":{"args":…,"name":…}}、{"functionResponse":{"name":…,"response":…}} 文本。根 field 14 为 ToolConfig;field 1 retrieval config 为 [[latitude, longitude]?, languageCode?, timezone]。客户端设置 includeServerSideToolInvocations,或请求同时携带函数声明与 Google 工具、MCP 时,field 3 include_server_side_tool_invocations 为 true,由上游在同一轮内执行服务端工具并返回函数调用。声明 URL context 时 field 3 同样为 true:Playground 只在 URL_CONTEXT 工具结果的 url_metadata 中给出各网址的读取状态,响应末帧的 grounding 只有读取成功的来源链接;客户端没有要求工具步骤且没有函数调用时,这些步骤连同其签名不输出,回传工具步骤的签名时上游返回 400 Invalid thought signature。

编码器将全部函数声明合并为一个 Tool entry;Google Search 与 Image Search 合并为一个 search entry 并分别占用 searchTypes 索引 0/1;Code Execution、URL Context 与 Maps 各占一个 entry。Google Maps 与 Code Execution/URL Context 构成互斥工具组,每个请求选择其中一组。Anthropic server tool 的定义规则见“Anthropic Messages”节。

Playground 的 GenerateContent 与 CountTokens 接受最长 63 字符的函数名。更长的名称在函数声明、历史函数调用与函数结果中统一编码为原名的前 50 个字符、_ 与原名 SHA-256 前 6 字节的十六进制,共 63 字符;上游返回的函数调用在交给公开协议前换回声明的原名。写代码助手与 Live 会话按原名发送。

函数 JSON Struct 使用 protobuf Struct/Value 数组:map 为 [[[key,value],...]];Value oneof 索引 0..5 分别表示 null、number、string、bool、Struct、ListValue。对象键排序后编码。

例如以下函数参数:

{
  "city": "Taipei",
  "days": 2,
  "metric": true,
  "note": null,
  "units": ["C", "F"]
}

编码后的 Struct 为:

[
  [
    ["city", [null, null, "Taipei"]],
    ["days", [null, 2]],
    ["metric", [null, null, null, true]],
    ["note", [0]],
    [
      "units",
      [
        null,
        null,
        null,
        null,
        null,
        [[[null, null, "C"], [null, null, "F"]]]
      ]
    ]
  ]
]

完整 function call Part 的关键槽位为:

[
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  ["multiply", [[["a", [null, 21]], ["b", [null, 2]]]], "call_01"],
  null,
  null,
  null,
  "!THOUGHT_SIGNATURE"
]

其中 Part 索引 10 保存 function call,索引 14 保存 thought signature。

Playground 的函数参数载体和结构化输出 Schema 使用以下 protobuf fields:

JSON Schema Field JSON Schema Field
type 1 format 2
description 3 nullable 4
enum 5 items 6
properties 7 required 8
minProperties 9 maxProperties 10
minimum 11 maximum 12
minLength 13 maxLength 14
pattern 15 example 16
oneOf 17 anyOf 18
allOf 19 not 20
maxItems 21 minItems 22
propertyOrdering 23

结构化输出 Schema 归一化规则:

输入结构 编码结果
可选字段显式 null 移除未设置字段;example:null 保留为数据值,const 按常量规则校验,属性名称保留
零参数函数的空定义、null、{} 或 true object 参数结构
开放的 {}、true 与缺少元素定义的 array 开放节点:可空的 anyOf,分支为 string、number、boolean 与元素为这三种的 array
Gemini type:"TYPE_UNSPECIFIED" 按无类型节点处理
非负整数约束写成字符串 int64 或 1.0 按整数编码
items:false 空数组约束 maxItems=0;与正数 minItems 同时设置时返回参数错误
not:false 移除空否定约束
not:true、not:{}、根 false、必填属性的 false 返回禁止所有值的参数错误
可选属性的 false 移除该属性
not:{type:"null"} 设置 nullable=false
字符串或字符串数组形式的 not 字符串枚举排除约束
$schema、default、additionalProperties、exclusiveMinimum、propertyNames、prefixItems 从 wire schema 中省略
required 中未在 properties 定义的属性 补充不限类型的属性定义
指向根 $defs 或 definitions 的本地 $ref Playground 展开为被引用的定义,完整 Schema 写入说明;循环引用保留开放节点
type: [T, "null"] 根类型 T 与 nullable=true
anyOf / oneOf 的 null 分支 移除 null 分支并设置 nullable=true
多个非 null type 开放根节点与完整类型集合的 anyOf
组合 Schema 缺少根 type 相同类型的分支推导根类型;混合类型保留开放根节点,相同 items 可写入根节点
其他节点缺少 type 含 properties 为 object,含 items 或 prefixItems 为 array;字符串约束推导 string,其余为开放节点
array 缺少 items prefixItems 中带类型的项组成 anyOf;其余使用开放元素节点
其他 Schema 字段 按层级与类型编码,完整 Schema 写入说明

结构化输出以客户端的 JSON Schema 为输出契约:无法直接编码的 Schema(如数值 const、单独的 null 类型)按层级与类型编码,根说明附完整 Schema,两个通道使用同一结果。含开放节点,或 JSON Schema 含 additionalProperties(非 false)、prefixItems、propertyNames、exclusiveMinimum、exclusiveMaximum、uniqueItems 的结构化输出在启用 Build 时使用 Build 通道并原样发送,没有账户能经 Build 服务时使用 Playground;Playground 的 Schema 没有任意类型与 additionalProperties 字段,这类请求以 JSON 模式发送(response_mime_type 为 application/json,不带 response_schema),完整 JSON Schema 作为最后一段系统指令。非对象 Schema 返回参数错误。

函数声明以客户端的 JSON Schema 为参数契约。Playground 对开放节点、混合联合、引用、数值枚举与常量生成可发送的参数载体,将完整 Schema 放入工具说明;普通可表达声明保持原编码,历史调用与工具结果保持原值。Build 使用 parametersJsonSchema,保留组合分支与约束。strict:true 和 Gemini VALIDATED 在完整工具事件返回前校验原始参数契约;不符合契约的上游调用返回协议错误。本地无法编译的 Schema(如外部 URL 引用)只随声明发送,不做本地校验。

auto 由模型决定调用,none 省略 tools。指定函数使用声明子集;Playground 将调用要求写入生成指令并核对实际返回,Build 使用原生 functionCallingConfig。客户端工具选择映射如下:

公开协议 自动与关闭 要求调用
OpenAI Chat / Responses 默认、auto、none required、named function
Anthropic 默认、auto、none any、named tool
Gemini 默认、AUTO、NONE、VALIDATED ANY 与 allowedFunctionNames

函数调用响应 Part 为 [name, Struct, callId?];下一轮 function result 使用同一形状并原样带回 thought signature。tool result 显式提供函数名时保留该值;缺少名称时,先按 call ID 关联当前轮尚未返回结果的调用,未匹配且仅剩一个调用时使用其名称。每个结果对应一个调用,调用与结果之间的助手文本不影响关联,新一轮普通对话开始后重新建立关联;存在歧义或缺少调用记录时返回参数错误。函数参数和结果使用 JSON object,非对象的参数与结果封装为 {"result":<VALUE>},与 Build 的 Gemini API 编码相同。

四个协议的工具结果为内容块数组(每个元素带 type)时,文本块以换行相连写成 {"result":"<文本>"},错误结果写成 {"error":"<文本>"};图片、文档、音频与视频块按所属协议的媒体规则转换,作为紧随该函数结果的 Part 发送;其他块以 JSON 文本并入结果文本。Gemini functionResponse.parts 中的 inlineData 与 fileData 同样作为紧随该函数结果的 Part 发送。

Drive 上传与文件 Part

GenerateAccessToken ["users/me"]
  -> response ["<BEARER_TOKEN>"]
GetAppFolder []
  -> response ["<FOLDER_ID>"]
GET clients6.google.com Drive v3 discovery(每个账户第一次上传前一次)
  -> POST content.googleapis.com Drive multipart/related
       part 1: {"name":"<NAME>","parents":["<FOLDER_ID>"]}
       part 2: Content-Transfer-Encoding: base64
  -> {"kind":"drive#file","id":"<FILE_ID>","name":"<NAME>","mimeType":"<MIME>"}
  -> GenerateContent Part field 6 ["<FILE_ID>"]

已知长度的上传与官网对话面板的 gapi 上传相同:key 为页面的 x-goog-api-key;正文以固定分隔串 uhgzr7onafciig6fij3kisl4q 依次写 `

--<分隔串>、元数据部分头与

、元数据 JSON、

--<分隔串>、文件部分头与

、文件的 base64、 --<分隔串>--,Content-Type为multipart/related; boundary="<分隔串>"。上传与 discovery 都带 X-JavaScript-User-Agent: google-api-javascript-client/1.1.0、X-Requested-With: XMLHttpRequest、X-Goog-Encode-Response-If-Executable: base64与X-ClientDetails(账户指纹的 appVersion、platform与 User-Agent 按 encodeURIComponent 编码),经 CORS 预检发送;上传以 bearer token 授权、带Sec-Fetch-Site: cross-site与Sec-Fetch-Storage-Access: none,discovery 以 Cookie、SAPISID 签名与 X-Goog-AuthUser授权、带Sec-Fetch-Site: same-site`。

Drive token、上传和下载使用文件所属账户的固定出口。文件 ID 与账户绑定写入 runtime-state.json;生成请求可以组合不同账户的文件,其他账户的文件会临时复制到本次生成账户;失败尝试的副本随即回收,成功尝试的副本在请求结束后回收。

生成请求的内联附件优先上传到本次生成账户,正文使用 Drive file Part。上传的文件以请求给出的文件名命名,没有文件名时为 inline-media-<序号>,模型以这个名称引用附件。上传的文件以 inline-media 绑定写入该账户的 runtime-state.json,记录 MIME、内容的 SHA-256、请求给出的文件名与最近使用时间,不出现在公开文件接口中;同一账户之后的请求中 MIME、内容与文件名都相同的附件直接引用该文件,同一请求中相同的附件只上传一次;闲置 1 小时且没有进行中的请求引用的文件,在该账户下一次带内联附件的请求结束时删除,没有后续请求时由生成服务每 10 分钟一次的闲置资源回收删除。GenerateContent 返回 404 且请求引用了已上传的内联附件时,服务以 GET https://www.googleapis.com/drive/v3/files/<ID> 查询这些文件,解除已不存在的文件的绑定,在同一账户重新上传后重试一次。GenerateAccessToken 明确返回 401、Code 16 和 OAuth error: unauthorized_client 时,正文保留原始 inline data Part,账户继续参与普通生成调度;其他令牌错误保持失败语义。上传使用公开适配器输出的 MIME 和字节内容。图片、音频、视频、PDF 等附件的支持范围由所选模型决定。普通文本和 YouTube 外部媒体保持各自的 Part 编码。

POST /v1/files 的未知长度上传使用 Drive resumable upload 和 8 MiB 分块,GET /v1/files/{id} 从资源绑定读取文件名、大小、purpose 与创建时间;客户端取消会终止上传并释放账户租约。公开文件字段见“Files、Transcribe 与媒体”节。

Gemini 3.5 Transcribe

gemini-3.5-transcribe 使用 Drive file Part 与 GenerateContent generation config field 32。转录配置子字段如下:

protobuf field 内容
5 word timestamps,启用值为 1
6 speaker labels,启用值为 1
7 repeated custom vocabulary
8 repeated language codes
9 smart transcription,启用值为 2

转录元数据位于响应 Part field 23,子字段 1 为文本、2 为 speaker label、3 为 repeated timestamp span。每个 span 的 field 2 与 field 3 分别是开始和结束时间,时间消息使用 seconds 与 nanos。公开转录端点见“Files、Transcribe 与媒体”节。

Nano、TTS 与 Lyria

三类媒体复用 GenerateContent:

路由 generation config 响应
Nano image modalities [2],image config [aspectRatio?, imageSize?] Part field 3 [mime, base64]
TTS modalities [3],speech config Part field 3 音频 chunk
Lyria modalities [3] Part field 3 音频 chunk

单声音 speech config 为 [[[voiceName]]]。TTS 模型的请求没有设置声音时使用官网默认声音 Zephyr。多说话人 speech config 为 [null,null,[null,[[speaker,[[voiceName]]],...],mode?]],mode 1 为 VERBATIM、2 为 CONVERSATIONAL。文本 Part field 41 为 SpeechMetadata [speaker?, style?];能力码 85 的 TTS 模型要求多说话人请求的每个文本 Part 带 speaker,且台词不写 ## Transcript:。相邻且 MIME 相同的音频 Part 按到达顺序拼接。图片宽高比、图片分辨率与 TTS voice 必须来自当前模型能力选项。

Imagen

GenerateImage 发给实时目录中带 predict 方法的模型,WAA proof 位于 field 3,binding 为提示词:

[
  "models/<MODEL_ID>",
  "<PROMPT>",
  "<WAA_PROOF>",
  [<SAMPLE_COUNT>, "<NEGATIVE_PROMPT>", "<ASPECT_RATIO>", "<IMAGE_SIZE>"]
]

配置数组中未设置的项为 null,末尾的 null 省略。响应 field 1 为 repeated 图片:1 base64 数据、2 MIME、3 被安全策略拦下的原因(字符串,非空即拦下)。

Omni Interaction

模型目录 field 79 类型为 2 且不是后台任务的模型(gemini-omni-1.1-flash、gemini-omni-flash-preview)不接受 GenerateContent,四套公开生成接口对这类模型改用 CreateInteractionStream,账户选择、Worker 与 WAA 与 GenerateContent 相同,WAA proof 位于 field 5,binding 为发送的全部文本以空格连接:

[1, 1, null, <INTERACTION>, "<WAA_PROOF>", 1]
interaction 索引 内容
6 system instruction
17 ["models/<MODEL_ID>", [null,null,null,null,null,<THINKING_LEVEL>,1,<MAX_OUTPUT_TOKENS>]],历史中没有模型输出时配置索引 24 为 [],设置视频任务时为 [<TASK>](1–5 依次为 text_to_video、image_to_video、reference_to_video、edit、extend)
26 [[<STEP>...]],用户 step 为 [[<CONTENT>...]],模型 step 为 [null,[<CONTENT>...]];文本 content 为 [[<TEXT>]],Drive 附件 content 为 [null×8,["<DRIVE_FILE_ID>"]]
53 输出格式 [[[null,null,null,[null,null,null,<ASPECT>,[<SECONDS>],<RESOLUTION>]]]]:宽高比 1 为 16:9、2 为 9:16,分辨率 1–4 为 360p、720p、1080p、4k,省略时取模型 video_output_resolutions 的第一项;任务为 edit 时 interaction 只到索引 26

thinking level 取值 MINIMAL=1、LOW=2、MEDIUM=3、HIGH=4,由 reasoning_effort 或思考预算按模型支持的等级换算,默认使用目录默认等级。Interaction 请求接受 user、assistant 与 tool 消息,tool 消息按 user 处理,相邻同角色消息合并为一个 step,历史函数调用、函数结果与代码执行改写为 Gemini API JSON 文本,assistant 消息中的附件移到下一个 user step;内联附件先上传到所选账户的 Drive,再以 file ID 引用,文件 ID 不参与 binding。音频附件由上游以 code 3 Audio input modality is not enabled for this model 拒绝,映射为 HTTP 400;函数声明与 Google 工具不发送,stop sequences 与 GenerateContent 相同在本地匹配,temperature、topP、topK 与 seed 不发送。

视频设置来自 Interactions response_format 的 {"type":"video","aspect_ratio","duration","resolution"} 与 generation_config.video_config.task,或 Gemini API generationConfig.responseFormat 的 video.aspectRatio、video.duration、video.resolution 与扩展字段 generationConfig.videoConfig.task;Interactions response_modalities 的 video 与 Gemini API generationConfig.responseModalities 的 VIDEO 等同于不带设置的视频输出格式;duration 取 "4s" 或秒数并四舍五入为整秒,宽高比与分辨率换成最接近的上游取值,无法解析的取值与未知任务返回 400。

响应为 [[<EVENT>...], <STATUS>?]。事件索引 10 的 content delta 中 field 1 为正文、field 2 至 5 为图片、音频、文档与视频 [<MIME 枚举>,"<BASE64>"]、field 6 为思考摘要,分别映射为 text、媒体与 reasoning 事件;索引 19 的最终 interaction 状态 3 产生 usage(输入、输出、思考、总 token 位于 usage 索引 0、4、8、9)与 stop 终态,状态 4、5 返回错误。事件列表后的 google.rpc 状态按 code 映射 HTTP 状态,额度 code 8 为 429;首个正文事件之前的错误进入换号与冷却,之后的错误以流内 error 结束。

媒体 MIME 枚举与官网前端相同,枚举为 null 或不在表中时取该类的默认 MIME:

字段 枚举 默认
图片 field 2 1 png、2 jpeg、3 webp、4 heic、5 heif、7 gif、8 bmp、9 tiff image/jpeg
音频 field 3 1 wav、2 mp3、3 aiff、4 aac、5 ogg、6 flac、7 mpeg、8 m4a、9 l16、10 s16le、11 opus、12 alaw、13 mulaw audio/wav
文档 field 4 1 pdf application/pdf
视频 field 5 1 mp4、2 mpeg、3 mpg、4 mov、5 avi、6 x-flv、7 webm、8 wmv、9 3gpp video/mp4

后台 Interaction 任务

模型目录 field 79 为后台任务的模型(deep-research-preview-04-2026、deep-research-max-preview-04-2026、antigravity-preview-09-2026)经两个 RPC 生成:CreateInteraction 创建任务,GetInteractionStream 按 interaction ID 读取任务的增量与终态。两个 RPC 的 WAA proof 都位于 field 5,CreateInteraction 的 binding 为发送的全部文本以空格连接,GetInteractionStream 的 binding 为 interaction ID:

[null, 1, 1, <INTERACTION>, "<WAA_PROOF>", 1]
["<INTERACTION_ID>", 1, null, null, "<WAA_PROOF>", 1, "models/<AGENT>"]
interaction 索引 内容
6 system instruction
7 工具列表,见下文
16 续接的上一轮 interaction ID
18 agent 目标,见下文
22 Antigravity 的远程环境 [null,null,1]
26 与 Omni Interaction 相同的 step 列表,见下文

agent 目标的 field 1 为 agent 名称。Deep Research 为 ["<AGENT>", null, [<思考摘要>, <可视化>, <协作规划>]]:思考摘要 1 为 auto、2 为 none,可视化 2 为 auto、1 为 off,协作规划开启时为 true、关闭时省略,默认 [1,2]。field 79 InteractionConfig 的 field 6 给出默认模型的 agent(Antigravity)为 ["<AGENT>"],指定模型或 token 上限时 field 12 为 ["<MODEL>",null,null,null,null,null,<MAX_TOTAL_TOKENS>]。公开 Interactions 的 agent_config 按官方取值写入这些位置。

工具列表依次为代码执行 [null,[]]、函数声明 [["<NAME>","<DESCRIPTION>",<PARAMETERS>]](参数为 google.protobuf.Value)、Google 搜索 [null,null,null,null,null,[]] 与 URL 上下文 [null,null,[]],Interactions 请求带 tools 时只用列出的工具,空列表时省略索引 7;其他请求与不带 tools 的 Interactions 请求在模型目录 field 82 默认开启的代码执行(9)、Google 搜索(12)与 URL 上下文(13)之上加入请求的工具,Deep Research 默认为搜索与 URL 上下文,Antigravity 另有代码执行;没有任何工具时省略索引 7。MCP 服务器、File Search、Computer Use 与其他 Google 工具在发送前返回 400 INVALID_ARGUMENT。

step 列表只包含用户内容:历史中的模型轮、服务端工具步骤、代码执行与函数调用不发送,其中的附件也不上传,相邻的用户内容合并为一个 step。公开 Interactions 以 previous_interaction_id 续接同一 agent 的后台任务时,索引 16 为该任务的 interaction ID,step 列表只有本次输入,请求固定使用创建该任务的账户。

CreateInteraction 响应索引 0 为 interaction ID。GetInteractionStream 的事件格式与 Omni Interaction 相同;content delta 另有 field 2 图片 [1,"<BASE64 PNG>"] 与 field 10 引用 [[[<START>,<END>,null,["<URL>"]]...]],起止为正文中引用标记的字符位置,分别映射为 image/png 媒体与 citation 事件。最终 interaction 不含 usage,状态 3 产生 stop 终态。调用方在终态前断开时,服务以 ["interactions/<INTERACTION_ID>"] 发送 CancelInteraction 停止上游任务;取消在后台以同一账户发送,调用方释放账户租约后取得请求槽位,期限 1 分钟。

Build 代理

官网 Build 应用经宿主页调用 MakerSuite 代理 RPC 访问 Gemini API,免费账户在两个通道上计入同一模型的同一份每日请求次数。UPSTREAM_CHANNELS 启用 build 时,生成请求在 Build 通道上编码为 Gemini API JSON:

["/v1beta/models/<MODEL_ID>:streamGenerateContent", "<GEMINI_API_JSON>", "<WAA_PROOF>"]
["/v1beta/models/<MODEL_ID>:generateContent", "<GEMINI_API_JSON>", "<WAA_PROOF>", "POST"]

前者发往 ProxyStreamedCall,后者发往 ProxyUnaryCall。WAA proof 位于 field 3,binding 为路径与请求体以空格连接后的 SHA-256。两个 RPC 的选择与权益头、模型目录、资格、调度与冷却、请求字段映射、响应解码、错误映射与未接入范围见 Build 通道。Playground 目录没有的 embedding、Live 与实时音乐模型只经 Build:embedding 经 ProxyUnaryCall 调用 :batchEmbedContents,Part 分辨率不同的计数与 Playground 目录没有的模型的计数经 ProxyUnaryCall 调用 :countTokens,Live 与实时音乐经宿主页 WebChannel v1/proxy:proxyBidiStreamedCall 转发 Gemini Live JSON,每条消息为 [路径, JSON, WAA proof]。

Live 与 Robotics WebSocket

GET /v1/live 与 GET /v1/robotics/stream 升级为 WebSocket,首个客户端帧为 setup,公开帧与事件见“Live 与 Robotics 公开帧”节。两个入口都使用客户端提供的模型,并由实时模型目录的 bidiGenerateContent 方法选择账户;Build 目录以 bidiGenerateMusic 提供的模型(如 lyria-realtime-exp)为实时音乐会话。Playground 目录没有的 Live 与实时音乐模型经 Build 通道,帧与事件相同,wire 见 Build 通道。上游握手、backchannel 就绪和 setup complete 共用 INIT_TIMEOUT,随后依次发送 session_opened 与 setup_complete。

上游 WebChannel 由握手、前向 POST、长轮询 backchannel 与 terminate 组成。握手 query 使用 VER=8、随机 RID、CVER=22、X-HTTP-Session-Id=gsessionid 与 count=0;响应 header 给出 gsessionid,首个控制 envelope 为:

[[0,["c","<SID>","",8]]]

后续前向请求的 query 字段为 VER、gsessionid、SID、RID、AID、zx、t;form 字段依次为 count=<N>、ofs=<OFFSET>、req0___data__ 至 req<N-1>___data__。客户端消息按到达顺序排队,同一时间只有一个前向 POST,在途期间到达的消息合并进下一个 POST,每个 POST 最多 25 条,与官网页面一致。audio 与 image 帧入队即返回,text、tool_response、media_end 等待自身所在 POST 的 ACK,因此 media_end 返回时此前的媒体帧均已送达;前向 POST 失败后,队列内与后续发送均返回该错误。成功响应是三个整数的 ACK 数组,三个槽只校验整数形状,第二槽不绑定本地 RID、AID 或 ofs。HTTP 200 且 ACK 合法后提交 RID+1 与 ofs+N;失败、取消或 ACK 无效时保持原值。

backchannel 使用 RID=rpc、当前 SID、gsessionid 与 AID。每个网络帧为十进制长度、LF 和对应 JSON 文本,长度按 UTF-16 码元计数:

<DECIMAL_UTF16_LENGTH><LF>
<JSON_TEXT>

JSON 根值包含 repeated [serverAID,payload] envelope。payload 解码成功并按顺序发布后,将 AID 提交为 max(currentAID,serverAID)。首次 backchannel 建立后的临时读取失败保留 SID、gsessionid 与已提交 AID 并重新连接;首次建立失败、协议终态、显式 close 或不可恢复错误进入关闭链。会话状态为 new -> handshaking -> ready -> reconnecting -> ready,关闭路径依次进入 closing -> closed。

tool_call 事件携带单个函数调用;一条上游消息包含多个调用时按顺序发送多条事件。tool_call_cancellation.tool_call_ids 携带被取消的调用 ID。新的 session_resumption.session_token 原子替换上一枚 token;后续 setup 携带该 token 时绑定原账户恢复。

Live 纯文本与实时音乐使用模型 scope,Live 音频/图像和 Robotics 使用 bidi-media:<modelID> scope,经 Build 通道时 scope 前加 build:。上游 Code 7 通过 error 事件返回并结束当前连接,Code 13 以 HTTP 500 的 error 事件结束连接。

上游 Bidi 客户端 wire 使用六槽或七槽稀疏数组。setup 位于外层 field 7:

setup JSON 索引 protobuf field 内容
0 1 models/<MODEL_ID>
1 2 generation configuration
2 3 tools
6 7 [sessionToken];无 token 时 Live 对话与 Robotics 为 [],实时翻译与转录省略
7 8 [104857,[52428]] buffering 参数;实时翻译与转录省略
9 10 输入音频转录参数;空数组,实时转录的语言写在子索引 7
10 11 固定空数组
15 16 timezone [null,null,null,null,[zone]]

Live 对话与 Robotics 的 configuration 使用 18 槽数组:

JSON 索引 内容
14 输出 modalities;TEXT=[1]、AUDIO=[3]
15 Live voice [[["Zephyr"]]]
16 thinking [1,null,null,level];Live Minimal=4、Robotics High=3
17 MediaResolution 固定值 2

实时翻译模型不接受 MediaResolution,configuration 使用 31 槽:索引 13 为 0、14 为 [3]、30 为 TranslationConfig [echoTargetLanguage 0/1, targetLanguageCode]。实时转录模型只接受 TEXT 输出,configuration 为 [null×14,[1]]。两者均不带 voice 与 thinking。上游在 serverContent 索引 5、6 返回输入与翻译文本,实时转录在索引 10 返回当前累计的临时输入转写,映射为 interim_input_transcription,音频结束后在索引 5 返回最终输入转写。

最小 setup 外层形状:

[
  null, null, null, null, null, null,
  [
    "models/<MODEL_ID>",
    [null, null, null, null, null, null, null, null, null, null, null, null, null, null, [3], [[["Zephyr"]]], [1, null, null, 4], 2],
    null,
    null, null, null,
    [],
    [104857, [52428]],
    null,
    [],
    [],
    null, null, null, null,
    [null, null, null, null, ["Asia/Taipei"]]
  ]
]

后续客户端 wire:

公开帧 外层位置 子消息
text index 2 / field 3 realtime input index 4 保存文本
audio index 2 / field 3 realtime input index 1 保存 [mime,base64]
image index 2 / field 3 realtime input index 3 保存 [mime,base64]
media_end index 2 / field 3 realtime input index 2 为 1
tool_response index 3 / field 4 子消息 index 1 保存 repeated [name,Struct,id,willContinue?],will_continue 为真时 index 3 为 1

setup 与每个后续客户端 wire 都在发送前把 fresh WAA proof 写入外层 index 5 / field 6。snapshot binding 输入:

wire binding prompt
setup models/<MODEL_ID>,随后按声明顺序追加每个 name + " " + description,各段以单个空格连接
text、audio、image、media end 空字符串
tool response 第一条 function response 的 call ID

服务端业务 message 索引:

JSON 索引 内容
1 setup complete
2 server content
3 tool calls
4 tool cancellation
5 usage raw
6 go away raw
7 session resumption

server content 的 index 0/1/2/4/5/6 分别为 model content、turn complete、interrupted、generation complete、input transcription、output transcription;model content 的 index 0 是 repeated Part。transcription 子索引 0/1/2/3 分别为 text、finished、duration milliseconds、language code。tool calls 位于 message index 3 的子索引 1,每项为 [name,Struct,id];tool cancellation 位于 message index 4 的子索引 0,值为 repeated call ID。session resumption 子索引 0/1 分别为 token 与 resumable。对象状态错误形状为 {"__sm__":{"status":[[[code,message]]]}};字符串 payload "noop"、"close"、"stop" 分别表示空操作、正常关闭与错误停止。

7. 公开端点、状态映射与实现

协议 端点
OpenAI Chat GET /v1/models、GET /v1/models/{id}、POST /v1/chat/completions
OpenAI Responses POST /v1/responses、POST /v1/responses/input_tokens、POST /v1/responses/compact、GET /v1/responses/{id}、DELETE /v1/responses/{id}、GET /v1/responses/{id}/input_items、POST /v1/responses/{id}/cancel
OpenAI Embeddings POST /v1/embeddings
OpenAI 媒体 POST /v1/images/generations、POST /v1/images/edits、POST /v1/audio/speech、POST /v1/videos、GET /v1/videos、GET /v1/videos/{id}、DELETE /v1/videos/{id}、GET /v1/videos/{id}/content
Anthropic POST /v1/messages、POST /v1/messages/count_tokens
Gemini GET /v1beta/models、GET /v1beta/models/{model}、POST /v1beta/models/{model}:generateContent、:streamGenerateContent、:countTokens、:embedContent、:batchEmbedContents、:predict、:predictLongRunning、GET /v1beta/operations/{id}、GET /v1beta/models/{model}/operations/{id}

各协议输出对象的字段顺序与官方输出相同:Gemini GenerateContent、模型、计数、文件与错误对象按 Gemini API 官方响应与 proto 字段号的顺序,Chat、Responses、Anthropic 与 OpenAI 其余资源按官方文档响应示例的顺序,Interactions 为 type 在前、其余按字母序;顺序表由官方响应与文档生成,内嵌于 internal/api/field_order.json,表中没有的字段排在已知字段之后并按字母序。函数参数、元数据与 JSON Schema 等调用方数据保持原有顺序。

扩展端点:

协议 端点
OpenAI 与 Anthropic 文件 POST /v1/files、GET /v1/files、GET /v1/files/{id}、GET /v1/files/{id}/content、DELETE /v1/files/{id}
OpenAI 转录与翻译 POST /v1/audio/transcriptions、POST /v1/audio/translations
实时 WebSocket GET /v1/live、GET /v1/robotics/stream
Gemini Interactions POST /v1beta/interactions、GET /v1beta/interactions/{id}、DELETE /v1beta/interactions/{id}、POST /v1beta/interactions/{id}/cancel,/v1 前缀相同
Gemini 文件 POST /upload/v1beta/files、GET /v1beta/files、GET /v1beta/files/{id}、DELETE /v1beta/files/{id}

动态路由的注册形状为 GET /v1/models/{model...}、GET /v1beta/models/{model...}、GET /v1/responses/{response}、DELETE /v1/responses/{response}、GET /v1/responses/{response}/input_items、POST /v1/responses/{response}/cancel、GET /v1/files/{file}、GET /v1/files/{file}/content、DELETE /v1/files/{file}、GET /v1/videos/{video}、DELETE /v1/videos/{video}、GET /v1/videos/{video}/content、POST /v1beta/models/{action}、GET /v1beta/operations/{operation}、GET/DELETE /v1/interactions/{id}、GET/DELETE /v1beta/interactions/{id}、POST /v1/interactions/{id}/cancel、POST /v1beta/interactions/{id}/cancel 与 GET/DELETE /v1beta/files/{file};端点表中的 {id} 表示对应资源标识。

公开 /v1 与 /v1beta 接受 Authorization: Bearer、X-API-Key、X-Goog-API-Key 或 ?key=,任一来源与配置的 key 相同即通过;配置为空时关闭本地 API key 校验,此时 Origin 为 null 或非 localhost、非回环地址的 http/https 页面请求按 API key 错误拒绝(OpenAI 与 Anthropic 路由 401,Gemini 路由与官方相同:没有 key 为 403,带 key 为 400),不带 Origin 的客户端与其他 scheme 不受限制。/v1*、/upload/ 与 /health 响应允许任意 origin,并以 Access-Control-Expose-Headers: * 暴露响应头;OPTIONS 预检不经过 API key 校验,允许 GET/POST/PUT/DELETE/OPTIONS,Access-Control-Allow-Headers 回显请求的 Access-Control-Request-Headers。/v1* 请求体上限约为 684 MiB,可容纳 Base64 编码的 512 MiB 文件。/upload/v1beta/files 使用相同的认证与请求体上限;可续传上传的分块请求发往 start 响应 X-Goog-Upload-URL 给出的地址,凭其中的 upload_id 鉴权,不需要 API key。

/api 控制面在 ADMIN_AUTH_ENABLED=false 时要求来源地址为 loopback 且 Host 为 localhost 或回环地址;开启登录后,通过管理员账号和密码签发的 Cookie 会话访问。管理请求执行 same-origin 校验并携带 Cache-Control: no-store。全部响应携带 X-Frame-Options: DENY、Content-Security-Policy: frame-ancestors 'none'、X-Content-Type-Options: nosniff 与 Referrer-Policy: no-referrer。GET /health 返回 {"status":"ok"}。

POST /api/auth/login 接受 {"username":"<ADMIN_USERNAME>","password":"<ADMIN_PASSWORD>","remember":false},成功返回 {"enabled":true,"authenticated":true,"username":"<ADMIN_USERNAME>"}:

  • 会话 Cookie 为 aistudio_admin,Path 为 /api,使用 HttpOnly、SameSite=Strict;HTTPS 或代理设置 X-Forwarded-Proto: https 时附带 Secure
  • 有效期 12 小时;remember 为 true 时有效期 30 天,会话写入 runtime/admin-sessions.json,管理进程重启后保留,管理员账号或密码变化后失效
  • 登录失败返回 401,同一来源一分钟内连续失败 5 次后返回 429 与 Retry-After: 60

GET /api/auth/session 返回相同的状态结构,未登录时账号为空。POST /api/auth/logout 返回 204,撤销当前会话并取消关联管理请求。

控制能力 端点
管理登录 GET /api/auth/session、POST /api/auth/login、POST /api/auth/logout
状态与模型 GET /api/status、GET /api/models
生成服务 POST /api/control/start、POST /api/control/stop
账户 GET /api/accounts、POST /api/accounts、GET/POST /api/accounts/import/chrome、GET /api/accounts/import/browsers、POST /api/accounts/import/cookies/discover、POST /api/accounts/import/cookies、PUT /api/accounts/{id}、DELETE /api/accounts/{id}
账户任务 GET /api/accounts/tasks、DELETE /api/accounts/tasks/{id}
账户认证与刷新 POST /api/accounts/{id}/login、POST /api/accounts/{id}/refresh、GET /api/login-view/{view}(WebSocket)
远程配对 GET /api/pairing、POST /api/pairing、POST /api/pairing/accounts、PUT /api/pairing/accounts/{account}/cookies
配置 GET /api/config、PUT /api/config、GET /api/first-event-latency
冷却与请求 GET /api/cooldowns、GET /api/requests、POST /api/requests/{id}/cancel
用量与正文 GET /api/usage、GET /api/usage/records、GET /api/usage/records.csv、GET /api/requests/{id}/body
日志与事件 DELETE /api/logs、GET /api/events

管理 API 使用 DTO(data transfer object)表示请求、响应和事件对象。端点结果:

端点 成功状态 body
GET /api/status 200 AdminStatus
GET /api/models 200 {"models":[Model,...]}
GET /api/accounts 200 {"accounts":[AdminAccount,...]}
POST /api/accounts 202 {"task":AccountTask}
GET /api/accounts/import/chrome 200 {"profiles":[ChromeImportProfile,...]}
POST /api/accounts/import/chrome 202 {"task":AccountTask}
GET /api/accounts/import/browsers 200 {"browsers":[CookieBrowser,...]}
POST /api/accounts/import/cookies/discover 200 {"accounts":[CookieBrowser,...]}
POST /api/accounts/import/cookies 202 {"task":AccountTask}
GET /api/accounts/tasks 200 {"tasks":[AccountTask,...]}
DELETE /api/accounts/tasks/{id} 204 空 body
GET /api/pairing 200 PairingToken
POST /api/pairing 201 PairingToken
POST /api/pairing/accounts 201 {"account":AdminAccount,"renewal_token":"<续签凭据>"}
PUT /api/pairing/accounts/{account}/cookies 200 {"account":AdminAccount}
PUT /api/accounts/{id} 200 {"account":AdminAccount}
POST /api/accounts/{id}/login 202 {"task":AccountTask}
POST /api/accounts/{id}/refresh 200 AccountRefresh
DELETE /api/accounts/{id} 204 空 body
POST /api/control/start、stop 200 AdminStatus
GET /api/config、PUT /api/config 200 RuntimeConfig
GET /api/first-event-latency 200 {"latencies":[FirstEventLatency,...]}
GET /api/cooldowns 200 {"cooldowns":[AdminCooldown,...]}
GET /api/requests 200 {"requests":[AdminRequest,...]}
POST /api/requests/{id}/cancel 204 空 body
GET /api/usage 200 UsageReport
GET /api/usage/records 200 UsageRecordPage
GET /api/usage/records.csv 200 带 UTF-8 BOM 的 CSV 附件
GET /api/requests/{id}/body 200 RequestBody
DELETE /api/logs 204 空 body
GET /api/events 200 SSE {"type":"<TYPE>","data":<DTO>}
  • POST /api/pairing/accounts 的令牌无效或过期时返回 401 pairing_token_invalid,账户已存在时返回 409 account_exists
  • PUT /api/pairing/accounts/{account}/cookies 的续签凭据与该账户不符时返回 401 pairing_renewal_invalid,账户不存在时返回 404 account_not_found,Cookie 无法生成 SAPISID 授权时返回 400 invalid_account
  • 一份 Cookie 可包含同一浏览器中多个 Google 账户的会话,第 N 个会话对应官网 /u/N/ 与请求头 X-Goog-AuthUser: N。POST /api/accounts/import/cookies/discover 从 u/0 起依次打开各会话的对话页,列出每个会话登录的账户;GET /api/accounts/import/browsers 为每个浏览器的每个会话各列一项。POST /api/accounts/import/cookies 中每项的 auth_user 选择导入的会话,省略时为 0;账户的 auth_user 写入 account.json,运行时以 /u/N/ 页面与 X-Goog-AuthUser: N 访问官网,浏览器重新登录后为 0
  • 添加、导入与重新登录账户在账户任务中运行:请求解析 body 后返回 202 与任务,任务不随请求或管理页面关闭而结束;任务中的账户依次处理,单个账户失败时在该项记下错误码与原因后继续下一个,Cookie 无法解析或缺少登录 Cookie 为 invalid_cookies,调试地址连接或读取失败为 cdp_unavailable,账户已存在为 account_exists;有账户失败时任务以 failed 结束,否则为 done。结束的任务保留到 DELETE /api/accounts/tasks/{id} 关闭,对进行中的任务调用它会取消任务,任务不存在时返回 404 task_not_found;任务列表变化时 GET /api/events 推送 account_tasks 事件,连接建立时先推送当前列表
  • GET /api/pairing 返回仍在有效期内的配对令牌,没有时返回 404 pairing_token_missing;POST /api/pairing 签发新令牌,此前的令牌随之失效
  • GET /api/requests/{id}/body 在没有保存正文时返回 404 request_body_not_found
  • POST /api/accounts 与 POST /api/accounts/{id}/login 的 body 可带 view,即管理页面为本次登录生成的登录窗口 ID;POST /api/accounts/{id}/login 也接受空 body。服务器没有图形界面,或请求来自非回环地址、带 Forwarded 或 X-Forwarded-For 时,登录画面经同一 ID 的 GET /api/login-view/{view} 传递,任务的 view 为该 ID;登录窗口断开后以同一 ID 重新连接,继续显示当前画面
  • GET /api/login-view/{view} 推送 {"type":"status","status":"starting|waiting|saving"}、{"type":"dialog","dialog":{"kind","message","value"}|null},以及 {"type":"frame","context","url","title","width","height","scale"} 后紧跟一条 JPEG 二进制消息;客户端发送 {"type":"pointer","action":"move|down|up","x","y","button","context"}、{"type":"wheel","x","y","dx","dy","context"}、{"type":"key","action":"down|up","key","context"}、{"type":"text","text","context"} 与 {"type":"dialog","accept","text"},坐标与宽高为页面 CSS 像素,key 为 KeyboardEvent.key

管理 DTO 字段:

DTO 字段
AdminStatus state、running、ready、version、active_requests、accounts、camoufox
AdminAccountCounts total、ready、busy、cooldown、auth_required
AdminCamoufox ready、可选 download(received、total)
AdminAccount id、label、enabled、state、proxy、locale、timezone、models、benefit_tier、message、可选 pairing_renewed_at
AccountCreateInput proxy、locale、timezone
AccountInput label、enabled、proxy、locale、timezone
ChromeImportProfile id、profile、display_name、email、locale
AccountRefresh account、previous_tier、tier、previous_models、models
ChromeImportInput accounts(每项 id 与 email)、proxy、locale、timezone
CookieImportInput cookies、proxy(识别 Cookie 中的账户时提交)
CookieAccountsInput items(每项 email、cookies 或 cdp、可选 auth_user:Cookie 中的会话序号 0–9,默认 0)、proxy、locale、timezone;cdp 导入时 locale、timezone 为空则取该浏览器页面的语言与时区
AccountTask id、kind(login、relogin、chrome、cookies、browser)、可选 view、state(running、done、failed)、items、started_at
AccountTaskItem label(账户邮箱,浏览器登录完成前为空)、state(pending、running、done、failed)、可选 code、error
CookieBrowser address、browser、email、auth_user、locale、timezone、imported、signed_out、error
PairingToken token、expires_at
AccountStateInput label、locale、timezone、storage_state、可选 auth_user(默认 0)、可选 fingerprint
AdminCooldown account_id、account_label、model_id、until、可选 reason
AdminRequest id、model、account_id、account_label、state、started_at
AdminLog time、level、source、message、event;请求事件携带 request,包含 id、state、HTTP status、model、duration_ms、tool_calls、usage 与诊断字段,字段口径见 logging.md
AdminEvent type、data
UsageLatency avg_ms、p50_ms、p95_ms、p99_ms
UsageStats requests、succeeded、failed、canceled、rate_limited、input_tokens、cached_tokens、reasoning_tokens、reply_tokens、total_tokens、duration、first_event、queue_avg_ms、可选 last_at
UsageReport from、to、bucket_seconds、generated_at、可选 latest_at、totals、previous、recent、cost、previous_cost、unpriced_models、buckets、stack_by、series、groups、pairs、options
UsageRecord id、time、protocol、path、model、account、channel、status、state、duration_ms、first_event_ms、queue_ms、input_tokens、cached_tokens、reasoning_tokens、reply_tokens、total_tokens、tool_calls、error、attempts、has_body
UsageRecordPage items、可选 next_cursor
RequestAttempt account、channel、error、duration_ms、可选 hedge、superseded
FirstEventLatency model、channel、samples、p95_ms
RequestBody id、time、request、request_size、response、response_size

AdminStatus.state 为 STOPPED、LAUNCHING 或 RUNNING;running 只在 RUNNING 为 true;ready 要求 RUNNING 且至少一个账户处于 ready 或 busy;version 来自构建信息;active_requests 是当前进程请求注册表数量;camoufox.ready 表示本机已有所需版本的 Camoufox,下载进行时 camoufox.download 给出已收与总字节,续传时已收字节包含已下载部分,总字节未知时为 0。AdminAccount.message 保存当前状态原因,models 是该账户实时目录 ID。until 与 started_at 使用 RFC 3339 JSON time。

GET /api/usage 的参数:

参数 含义
from、to 必填,RFC 3339 时间
tz IANA 时区,默认 UTC
bucket 分桶秒数 60、300、900、3600、86400,或 auto
model、account、channel、protocol、state 维度筛选,逗号分隔多个取值
stack series 的堆叠维度,默认 model
  • 统计区间为 [from, to),长度不超过 93 天,分桶数不超过 1500
  • tz 决定按天分桶的自然日与分钟、小时分桶的对齐
  • 同一维度的多个取值为或,不同维度之间为且
  • stack 取上述五个筛选维度之一

auto 按范围长度选择粒度:2 小时以内 1 分钟,12 小时以内 5 分钟,8 天以内 1 小时,更长按天。buckets 从包含 from 的对齐分桶开始,空分桶补零;previous 是紧邻 from 之前的等长周期;recent 统计最近 5 分钟。cost、previous_cost 与每个分桶的 cost 是按 Gemini API 与 Vertex AI 公布的当前文本单价估算的美元费用:未命中缓存的输入 token × 输入单价 + 缓存命中 token × 缓存单价 +(推理 + 回复)token × 输出单价,按提示长度分档的模型按每个请求的输入 token 选档,单价表只含文本生成模型,图片、音频、视频、语音与嵌入模型计为 0,unpriced_models 按名称列出范围内有 token 但没有单价的模型。succeeded 包含 completed、tool_calls、limited 与 blocked,rate_limited 是 HTTP 429 的失败数;duration 与 first_event 只统计成功请求,分位数相对误差约 0.5%。groups 按 model、account、channel、protocol、state 与 HTTP 状态码 status 列出全部取值,pairs 是账户与模型的组合,series 取请求数前 8 的取值,其余合并为 other: true 的一组。options 列出范围内出现过的维度取值,不受筛选影响。latest_at 是账本中最新一条记录的完成时间。

GET /api/usage/records 与 records.csv 接受同样的 from、to 与维度筛选,另有 status(HTTP 状态码)与 q(匹配请求 ID 或错误文本的子串)。记录按完成时间与 ID 倒序;limit 为 1 到 200,默认 50;next_cursor 原样传回 cursor 读取更早的一页。attempts 列出本次请求在最终结果之前未成功的上游尝试(account、channel、error、duration_ms)。CSV 导出范围内全部符合条件的记录,以 =、+、-、@、制表符或回车开头的文本加单引号前缀。

Chrome 导入列表按 Preferences.account_info 中的 Gaia ID 与邮箱逐个列出账号,同一 Profile 可以包含多个账号,同一邮箱只列出一次。ChromeImportProfile.id 为 <Profile>/<Gaia ID>;导入读取 token_service 中 service 为 AccountId-<Gaia ID> 的凭据。管理页列表默认不勾选,并提供全选。CLI 的 --profile 导入该 Profile 下的全部账号,交互编号对应单个账号。

POST /api/pairing 需要管理会话,签发 10 分钟内有效的配对令牌;再次签发使上一令牌失效。服务只在内存中保存令牌的摘要,管理进程重启后令牌失效。POST /api/pairing/accounts 不经过管理会话、loopback 与 same-origin 检查,凭 Authorization: Bearer <token> 导入一个账户,令牌有效期内可多次调用;body 上限 1 MiB。AccountStateInput.storage_state 必须能生成 SAPISID 授权,邮箱取认证扩展中的来源邮箱,没有时取 label;fingerprint 是隔离登录生成的 camoufox-fingerprint.json 内容。配对导入的账户使用服务端默认代理。上传成功的响应带该账户专属的 renewal_token,服务只在账户目录的 pairing-renewal.json 保存它的 SHA-256。PUT /api/pairing/accounts/{account}/cookies 同样不经过管理会话,凭 Authorization: Bearer <renewal_token> 以 body {"cookies":[StateCookie,...]}(上限 1 MiB)替换该账户认证状态中的 Cookie,认证扩展保持不变;处理时等该账户进行中的请求结束,重置该账户的 WAA Worker,账户回到 ready,pairing-renewal.json 记下续签时间,AdminAccount.pairing_renewed_at 为该时间(RFC 3339),没有经配对续签的账户不带这个字段。续签凭据只能更新签发它的账户,账户删除时随账户目录删除。

  • AccountCreateInput 启动隔离 Camoufox 登录,邮箱由 AI Studio 页面读取
  • ChromeImportInput.account_ids 可一次选择多个账号
  • CookieImportInput.cookies 接受 Cookie 扩展导出的 storage state 或 Cookie 数组 JSON、Netscape cookies.txt 和一行 Cookie 请求头,只保留 google.com 及其子域的 Cookie,label 为账户邮箱;cdp 非空时改从该远程调试地址读取浏览器的全部未分区 Cookie
  • AccountInput.label 必须与不可变的 Google 邮箱 ID 一致,locale 与 timezone 必须非空;proxy 使用 HTTP、HTTPS 或 SOCKS5 origin,可带 user:password@,不含 path、query 或 fragment

新增、导入、登录和验证成功后立即刷新该账户模型目录,并发布最新账户与模型事件。

PUT /api/accounts/{id} 的提交顺序固定为:校验不可变邮箱 ID,取得账户独占租约,创建未发布的新固定出口,关闭当前 Worker 并把新 Worker 配置标记为 pending(尚未发布),在模型目录写锁内原子写入 account.json 并更新账户池,随后发布 Worker 配置、替换固定出口、释放租约并重建模型缓存。account.json 写入是唯一持久提交点。提交前的出口创建、Worker 关闭或写入错误会丢弃这份待发布配置并保持旧配置;已经关闭的 Worker 由后续请求按旧配置重建。持久写入后,新配置、Worker 配置与固定出口共同成为已提交状态。租约释放错误保留该提交状态并返回原始 unlock 错误;释放成功后记录完成日志并同步模型缓存。

RuntimeConfig 字段。response-only 表示字段由服务器填充,客户端提交的值不参与保存:

字段 读写与生效时机
auth_states、proxy、init_timeout、request_timeout 保存值;下一次启动生成服务时使用
warm_worker_limit、max_active_workers、warm_startup_concurrency、per_account_concurrency 保存值;下一次启动生成服务时使用
build_native_nonstream 保存值;下一次启动生成服务时决定非流式请求是否优先选择 Build
nonstream_keepalive、fake_stream 保存值;下一次启动生成服务时决定非流式请求是否保活、流式请求是否按非流式生成
youtube_links 保存值;下一次启动生成服务时决定是否把用户消息文本中的 YouTube 链接作为视频外部媒体发送
first_event_hedge 保存值;off、auto 或正整数秒,下一次启动生成服务时决定原请求等待首字多久后发起备用请求
auto_start 保存值;下一管理进程就绪后是否自动启动生成服务
request_body_log 保存值;保存后立即决定是否保存请求与响应正文
admin_auth_enabled、admin_username 保存值;下一管理进程使用
admin_password 只写;省略时保留现值,下一管理进程使用
admin_password_set response-only;是否已保存管理密码
listen_addr、proxy_api_key 保存值;下一管理进程使用
active_listen_addr、active_proxy_api_key response-only;当前管理进程固定值
management_restart_required response-only;保存的监听地址、API key 或管理凭据与当前管理进程不同
service_restart_required response-only;保存的生成服务配置与当前生成服务实例不同

PUT /api/config 原子保存配置。监听地址、API key 和管理凭据在管理进程重启后生效;Worker 容量保存后立即作用于当前生成服务;账户路径、代理、timeout、临时对话与上游通道选项在 Stop/Start 创建的新生成服务实例中生效。启动时读取最新配置;配置加载、校验、实例创建失败或启用前取消时保留原实例,切换到新实例后由它完成启动或进入 STOPPED。

GET /api/events 的初始顺序为 status、models、accounts、最近 200 条 log、cooldowns、按开始时间排序的活动 request。后续事件的 data 形状:

type data
status AdminStatus
models {"models":[Model,...]}
accounts {"accounts":[AdminAccount,...]}
log AdminLog
cooldowns [AdminCooldown,...]
request AdminRequest,状态变化时重复发送同一 ID

管理错误统一为:

{"error":{"code":"invalid_request","message":"..."}}

控制面错误码包括 control_plane_forbidden、control_plane_origin_forbidden、invalid_request、invalid_account、account_not_found、account_busy、account_required、request_not_found 和 upstream_error。

HTTP 管理错误码
400 invalid_request、invalid_account、account_required
403 control_plane_forbidden、control_plane_origin_forbidden
404 account_not_found、request_not_found
409 account_busy
上游状态或 502 upstream_error

运行状态机如下。page catalog 表示账户会话页面载入时的 GetAiStudioBenefitTier 与 ListModels 响应,pending account 表示等待下一轮目录重试的账户:

process start
  -> control plane ready
  -> STOPPED

POST /api/control/start
  -> LAUNCHING
  -> load CachedModels
  -> if cache is empty, read the page catalog of every enabled ready/busy account
     and wait for the first non-empty live catalog
  -> prewarm up to WARM_WORKER_LIMIT workers
     with WARM_STARTUP_CONCURRENCY bootstraps
  -> first worker ready, or every warmable account is cooling
  -> RUNNING
  -> with a cache, read page catalogs after the first worker result
  -> continue the catalog sync and remaining worker prewarm in background
  -> every 30s, reload the page of every pending account
  -> every 24h from the catalog sync start, reload the page of every enabled ready/busy account one at a time

request
  -> if no catalog has the model, wait for the running 24h round,
     or start one now when the last round began over 10 minutes ago
  -> resolve model and endpoint capability
  -> acquire one PER_ACCOUNT_CONCURRENCY slot
  -> prepare WAA proof
  -> send MakerSuite RPC
  -> stream frames
  -> release slot

POST /api/control/stop
  -> cancel launch or active requests
  -> bound catalog sync shutdown to 2s
  -> close WAA workers
  -> bound unfinished lifecycle-transition wait to 12s
  -> STOPPED

请求状态使用 queued、running、completed、cancelled、failed。视频状态使用 queued、completed、failed,对应 progress 0 或 100。

模型目录驻留在当前 generation(runtimeGeneration 表示的一次生成服务实例)的内存中;新 generation 载入各账户目录中目录指纹与 runtime-state.json 一致的 catalog.json 作为缓存,公开目录与请求编码使用的模型条目都由其中保存的 ListModels 响应解析得到。启动先用当前 generation 的 catalog.CachedModels() 建立公开快照。缓存非空时直接进入 Worker 预热,首个 Worker 有结果后为每个 enabled 且处于 ready 或 busy 的账户开始后台目录同步;缓存为空时立即开始。目录同步读取账户会话页面载入时的响应:有常驻 Worker 的账户取它最近一次页面载入,没有的账户在 Worker 容量允许时启动 Worker,否则临时载入一个页面,取得响应后关闭;还没有目录的账户同时读取,已有目录的账户逐个读取。可预热的账户全部处于冷却时,预热不返回错误,生成服务直接进入 RUNNING,预热在最早的冷却结束时开始。每个非空结果到达时立即从 CachedModels 合并公共目录并发布 accounts、models;生成服务已经 RUNNING 时同时触发 Worker 预热,新 generation 的首个非空结果还会解除启动等待。全账户同步结束时,auth_required 集合发生变化会补发一次账户与模型快照,并记录同步成功数、非空数、公共模型数、待重试账户数和耗时。第一个 Worker 就绪后重新读取当前缓存,并在持有账户与配置变化锁时把服务状态设为 RUNNING。

账户状态:

状态 调度语义
ready 认证有效且存在可用槽位
busy 存在独占操作、认证刷新或活动请求
cooldown 全局 * 冷却仍有效
auth_required 账户级认证失败
unavailable 当前运行时不可用
disabled 配置已停用
  • busy 账户仍按 PER_ACCOUNT_CONCURRENCY 判断剩余槽位
  • 模型 scope 冷却不改变账户状态,只影响对应请求的候选分类

认证状态写回携带 authGeneration 与 checkedAt,仅应用账户对象、authGeneration 值与时间均匹配当前状态的结果;相同时间以 ready 为最终状态。模型访问和冷却写回携带 modelAccessGeneration 与 checked_at,仅应用 modelAccessGeneration 值匹配且时间不早于当前状态的结果;相同时间以 verified 为最终状态。verified 表示该账户已经成功调用对应模型或能力。

ModelAccessKey(scope, model) 先移除 models/ 前缀;空 scope 返回 canonical model ID(规范化模型 ID),非空 scope 返回 <scope>:<canonicalModelID>。各能力使用以下值:

能力 scope 成功记录
普通生成 <modelID> 规范事件 EventFinish 到达时写 verified
CountTokens count-tokens:<modelID> 清 scope 冷却,保留普通生成资格
Transcribe <modelID> 非空 text 或 segments 写 verified
Live 文本 <modelID> setup complete 写 verified;每次 text 开始一次模型资格检查
Live 音频/图像 bidi-media:<modelID> media 开始媒体资格检查
Robotics bidi-media:<modelID> text 开始模型资格检查

Code 7 保留当前 operation scope 的 verified 状态;认证失败更新账户级 auth_required。上传、临时文件清理等非生成失败使用全局 * 冷却。

正文、reasoning、工具、usage 与首事件用于输出和性能统计;终态前断流、客户端取消或错误保持原有验证状态。

Bidi setup 成功使用 lease(本次会话持有的账户租约)的 checkedAt。此后每个会更新模型资格的轮次分配会话内严格递增的 attempt 时间,turn_complete 消费对应 attempt 并写入资格。Code 7 不更新模型资格。Bidi 认证成功与 401 使用相同 attempt 顺序,setup 后较晚返回的 401 可以更新账户为 auth_required。

确认浏览器进程退出后,将 process 和 Worker 状态设置为 closed。关闭失败时保留 Worker、runtime lease、warm 标记与 generation(Worker 实例版本号);后续 Stop 即使服务状态已经是 STOPPED,也会再次执行 Worker reset。Camoufox 关闭阶段上界为 BiDi 3 秒、进程终止与等待 5 秒、profile 删除 2 秒;各阶段错误使用 errors.Join 保留。

模型目录 fan-out 绑定当前生成服务的 context。启动失败、启动取消或 Stop 会取消全部目录任务,并最多等待 2 秒确认后台目录协程退出。Stop 遇到尚未完成的 LAUNCHING 或其他启动/停止切换时,等待 transition channel(切换完成通知 channel)的上界为 12 秒;该上界覆盖 2 秒目录退出与有界 Worker 清理,超时错误与清理错误使用 errors.Join 返回。

按需热替换先启动 pending Worker(正在启动、尚未发布的替代 Worker),再关闭旧 Worker;旧实例成功退出后,替代 Worker 才成为当前 Worker。旧实例关闭和替代 Worker 回收同时失败时,两者都保留等待再次清理,并各占一个活动容量槽;达到容量上限后停止新建 Worker。完整生成服务 Stop/Start 的顺序为:Start 创建新生成服务实例前先重试停止旧实例,旧 PID 未退出时返回停止错误并保留原实例。

Worker 进程故障、Worker 被替换与协议 Code 5 会重建当前账户 Worker 并在原账户重放一次。

模型目录重试的 pending 集合保存等待再次同步的账户 ID。启动期全账户同步、以及新增、登录或在管理端启用后的单账户同步,遇到任意错误或成功返回空目录时加入;返回非空目录时移除;删除账户同时移除。全账户后台同步结束后启动单个 30 秒 ticker(Go 定时器),每次按启动期同步的方式重新载入排序后的待重试账户的会话页面,并在任务开始时复核该 ID 仍在 pending 集合中。错误或空目录继续保留;每个非空成功立即更新账户缓存与公共目录快照、发布 accounts 和 models,并在 RUNNING 状态触发 Worker 预热。批次结束时,auth_required 集合发生变化会补发当前账户与模型快照;即时单账户同步无论成功或失败都立即发布当前快照。启动期同步、单账户同步与 30 秒重试中的每个账户读取占用该账户的一个普通并发槽位,与生成请求和 Worker 启动共用 PER_ACCOUNT_CONCURRENCY。

同一循环从全账户同步开始时起每 24 小时巡检一轮:逐个重新载入全部 enabled 且处于 ready 或 busy 的账户的会话页面,读取页面载入时的 GetAiStudioBenefitTier 与 ListModels 响应(启用 Build 时另读 Build 目录;账户本进程的首次读取先按条款同意处理 GetLoggingContext):

  • 每个账户占用一个普通并发槽位,与生成请求共用 PER_ACCOUNT_CONCURRENCY,槽位已满的账户跳过本轮
  • 请求的模型不在任何账户的目录中时,巡检正在读取一轮的第一个账户则请求等它读完;没有进行中的一轮且距上一轮开始已超过 10 分钟时,巡检立即开始一轮,请求等这一轮读完第一个账户后再查找模型,仍没有时返回模型不存在,其余账户在后台继续读取;下一轮巡检从这一轮开始时计时
  • 读取经认证续签,续签后仍为认证失败时账户转为 auth_required
  • 权益或目录变化时写回 benefit_tier 与目录,权益变化清除该账户的模型资格记录,更新公共目录快照并发布 accounts 和 models
  • 订阅模型的生成遇到额度错误时,同一读取在后台对该账户执行一次,同一账户每分钟最多一次
  • 管理端的立即刷新等待该账户的独占租约,任何状态的账户都执行同一读取,管理页断开连接不中止
  • 账户从未成功读取目录时 benefit_tier 为 Unknown,message 为最近一次读取失败的原因

模型目录投影:

规则 结果
OpenAI model list 与同形单个 model 对象
Anthropic 带 Anthropic-Version 时为 Anthropic Models API 格式
Gemini 模型名称 models/<ID>
单模型解析 正式 ID 优先于别名
多账户同模型 methods、capabilities、能力选项与 access modes 取并集,paid 取逻辑 OR
多账户 token limit 输入和输出上限分别取正数最小值
模型别名 来自 ListModels field 57
请求匹配 model ID/alias、method、capability、AccessModes、账户权益与运行状态
候选排序 verified 与目标模型首事件耗时
capability 约束 端点要求与账户实时能力同时命中
  • 未验证账户仍可进入候选

管理模型对象完整字段:

{
  "id": "gemini-example",
  "name": "Gemini Example",
  "description": "...",
  "methods": ["countTokens", "generateContent"],
  "input_token_limit": 1048576,
  "output_token_limit": 65536,
  "capabilities": {"thinking": true, "capability_code_25": true},
  "capability_options": {"aliases": ["gemini-example-latest"]},
  "access_modes": [3, 4],
  "thinking_levels": ["LOW", "MEDIUM", "HIGH"],
  "default_thinking_level": "MEDIUM",
  "paid": true
}

OpenAI GET /v1/models:

{
  "object": "list",
  "data": [{
    "id": "gemini-example",
    "object": "model",
    "created": 0,
    "owned_by": "google",
    "name": "Gemini Example",
    "description": "...",
    "supported_generation_methods": ["countTokens", "generateContent"],
    "input_token_limit": 1048576,
    "output_token_limit": 65536,
    "capabilities": {},
    "capability_options": {},
    "access_modes": [],
    "thinking_levels": ["low", "medium", "high"],
    "default_thinking_level": "medium",
    "paid": true,
    "channels": ["playground", "build"]
  }]
}

支持思考档位的模型带 thinking_levels 与 default_thinking_level:档位按目录 field 72 的顺序排列,默认档位是请求未指定思考参数时使用的档位。管理模型对象与 Gemini 条目使用 MINIMAL、LOW、MEDIUM、HIGH,OpenAI 条目使用对应的小写值,与 reasoning_effort 的取值相同。

请求携带 Anthropic-Version 时,同一路由返回:

{
  "data": [{"type":"model","id":"gemini-example","display_name":"Gemini Example","created_at":"1970-01-01T00:00:00Z","max_input_tokens":1048576,"max_tokens":65536,"capabilities":{"batch":{"supported":false},"citations":{"supported":false},"code_execution":{"supported":true},"context_management":{"supported":true,"clear_thinking_20251015":{"supported":true},"clear_tool_uses_20250919":{"supported":true},"compact_20260112":{"supported":true}},"effort":{"supported":true,"low":{"supported":true},"medium":{"supported":true},"high":{"supported":true},"xhigh":{"supported":false},"max":{"supported":false}},"image_input":{"supported":true},"pdf_input":{"supported":true},"structured_outputs":{"supported":true},"thinking":{"supported":true,"types":{"enabled":{"supported":true},"adaptive":{"supported":true}}}},"lifecycle":"active","line":null,"deprecated_at":null,"retires_at":null}],
  "has_more": false,
  "first_id": "gemini-example",
  "last_id": "gemini-example"
}

max_input_tokens 与 max_tokens 取实时目录的输入与输出 token 上限,目录缺失时为 null。capabilities 按实时目录给出:thinking 及其 enabled、adaptive 两种类型随模型是否支持思考,effort 的 low、medium、high 对应模型支持的思考档位,xhigh 与 max 按 high 执行,supported 为 false;image_input 与 pdf_input 随对话模型,code_execution 与 structured_outputs 随目录的代码执行与结构化输出能力;batch 与 citations 的 supported 为 false,context_management 与其三种编辑为 true。limit 为 1–1000 的整数,超出范围返回 400 invalid_request_error;省略时为 20。after_id 返回该模型之后的一页,before_id 返回之前的一页,has_more 表示该方向是否还有模型,first_id、last_id 为本页首尾 ID。lifecycle(含 lifecycle[] 与逗号分隔写法)不包含 active 时返回空列表。单模型路由返回与列表项相同的对象,失败响应使用 Anthropic 错误对象。

Gemini GET /v1beta/models 返回 {"models":[...]},单模型路由直接返回一个对象。字段为 name、baseModelId(模型 ID)、displayName、description、supportedGenerationMethods(上游目录中该模型的方法里本服务提供的 generateContent、countTokens、createCachedContent、embedContent、batchEmbedContents、predict、predictLongRunning,按上游顺序)、inputTokenLimit、outputTokenLimit、可选 temperature、maxTemperature、topP、topK、modelStage(ListModels field 23 或 Build 目录给出的模型阶段)、thinking、thinkingLevels、defaultThinkingLevel、capabilities、capabilityOptions、accessModes、paid、channels。

生成服务未进入 RUNNING 且还没有任何账户目录时,模型列表与单模型查询返回 503,与生成请求相同。

GET /v1/models/{model} 与 GET /v1beta/models/{model} 接受 models/ 前缀;这两个模型查询入口以及生成、计数、视频、转录与 Bidi 同时接受 canonical ID 和 capability_options.aliases 中的 alias;alias 在调度和发送上游前换成对应的 canonical ID。

管理模型中的 description、token limits、capabilities、capability options、access modes 与 false paid 使用 omitempty;OpenAI 和 Gemini 响应始终包含身份、methods 与 token limits,并在 map/slice 非空或 paid=true 时增加对应扩展字段。

管理目录合并全部账户的上游实时模型集合,顺序沿用各账户 ListModels 的上游顺序:只出现在后一个账户目录中的模型排在它在该目录中的前一个模型之后,没有前一个已知模型时排在该目录首个已知模型之前,该目录没有已知模型时排在末尾;在此顺序上依次排列有可用通道的普通模型、经后台任务生成的 agent(interaction_task,如 Antigravity 与 Deep Research,不论有无可用通道)与没有可用通道的普通模型。公开目录保留当前公开协议承载其调用方法、且已启用通道可以提供的模型;启用 Build 通道时同时包含 Build 独有的可生成模型,channels 列出可调用该模型的通道,见 Build 通道。启用账户的权益都不满足 AccessModes 的模型同样列出,不含 channels。短期冷却和忙碌状态由请求调度处理。

主要请求格式:

端点 必需字段 主要结果
/v1/chat/completions model Chat completion 或增量 chunk
/v1/responses model Response object 或 response.* 事件
/v1/responses/input_tokens model 或 previous_response_id {"object":"response.input_tokens","input_tokens":<INT>}
/v1/files multipart file、可选 purpose OpenAI file object
/v1/messages model Anthropic message 或 message 事件
:generateContent / :streamGenerateContent 路径中的模型 Gemini candidates、usage 与 grounding metadata
/v1/images/generations prompt b64_json 或 data URL
/v1/audio/speech model、input MP3、Opus、AAC、FLAC、WAV 或 PCM body
/v1/audio/transcriptions multipart file 文本或转录 JSON
/v1/videos prompt 或 input_reference 长任务对象,随后轮询并下载内容

生成与计数请求需要系统提示或对话内容中的至少一项,只有系统提示时以它作为 user 轮发送。请求以 assistant 轮结尾时,gemini-3.1-pro-preview、gemini-3.1-flash-lite、gemini-3-flash-preview、gemini-omni-1.1-flash、gemini-nano-banana-2.1 与 gemma- 开头的模型原样以 model 轮结尾发送,由模型原生续写。其余模型(包括 -latest 别名与 -build 写代码助手)在 CONTINUATION_REWRITE 打开时改写末尾连续 assistant 轮:CONTINUATION_PROMPT 非空时,这些轮的正文与代码执行内容以 <assistant_prefix> 包裹,连同该提示词写入系统指令;为空时这段正文作为最后一轮 user 发送。改写后模型从前缀之后续写,响应只返回续写部分,末尾未回传结果的函数调用由模型重新生成。CONTINUATION_REWRITE 关闭时所有模型原样发送,Playground 以 400 Requests ending with a model turn are not supported 拒绝的模型返回该错误。各生成入口与计数接口按同一规则转换,countTokens 接受以 model 轮结尾的请求。

四套生成入口共享同一规范请求,输入映射如下:

能力 OpenAI Chat OpenAI Responses Anthropic Gemini
system system / developer messages instructions 和 system/developer message items system 字符串或 text blocks systemInstruction text parts
text 字符串或 text content part 字符串、message item 字符串或 text block Part text
image/document Base64 data URL、file_id input_image、input_file base64、URL 或 file source inlineData、fileData
audio input input_audio Base64 message content 中的 input_audio base64 document source inlineData
video video_url Base64 data URL、file_id、http(s) URL input_video base64 source inlineData、fileData
YouTube video_url / input_video input_video URL source fileData.fileUri
function call assistant tool_calls 或旧式 function_call function_call item tool_use block functionCall Part
function result tool message function_call_output item tool_result block functionResponse Part
structured output response_format text.format output_config.format 或 beta output_format responseMimeType 与 response schema,或 responseFormat 的 text 项;image 项为图片比例与尺寸
thinking reasoning_effort、reasoning.effort 或 extra_body.google.thinking_config;include_thoughts 为 false 时不输出思考 reasoning.effort;reasoning.summary 决定是否输出思考摘要 thinking.budget_tokens、output_config.effort;thinking.type 决定是否输出思考 thinkingConfig;includeThoughts 决定是否输出思考

Gemini 附件与 predictLongRunning 的图片输入接受 inlineData / inline_data、fileData / file_data、mimeType / mime_type 和 fileUri / file_uri。同一别名对同时出现时,外层优先选择驼峰对象,内层优先选择非空驼峰值。

媒体 Base64 输入接受标准和 URL-safe 字母表、可选的 = 填充,以及 data:<MIME>;base64, 前缀。GIF 内联图片和 OpenAI 视频 input_reference 表单附件提取首帧,按逻辑画布尺寸与帧偏移编码为 PNG 后发送。透明首帧保留透明背景;不透明首帧的未覆盖区域使用全局色表中的背景色。

OpenAI Chat 与 Anthropic 省略转换后没有 parts 的空历史消息;纯空白文本、工具调用、工具结果及媒体保留原有内容。

生成参数映射:

参数 规则
OpenAI max tokens max_completion_tokens 优先于 max_tokens
Anthropic max tokens max_tokens 映射 generation config field 4
Gemini max tokens maxOutputTokens 映射 generation config field 4
temperature / topP / topK / seed 映射 generation config fields 5 / 6 / 7 / 19
stop sequence 映射 generation config field 2
stop sequence 命中 本地匹配并返回实际命中的序列
structured output MIME type 映射 field 8,Schema 映射 field 9
OpenAI parallel_tool_calls false 时本轮最多一个函数调用
Responses truncation auto 移除最早的完整对话轮次
Anthropic thinking enabled 写入 budget_tokens;adaptive 使用模型默认思考
Anthropic thinking type disabled 使用模型最低思考配置
  • OpenAI Chat 与 Responses 的 parallel_tool_calls 省略或为 true 时允许并行;Responses 同时把该值写入响应元数据
  • Responses truncation:auto 按上游权威计数移除最早的完整对话轮次,保留最新轮次与工具调用/结果配对;省略或 disabled 时保留完整输入
  • Anthropic 省略 thinking 或 thinking.type:"disabled" 时不返回思考正文,续接签名以 redacted_thinking 保持;未知 type 返回 400 invalid_request_error
  • Chat、Responses 与 Gemini 的协议专属参数见各协议小节

OpenAI Chat Completions

POST /v1/chat/completions 请求字段:

字段 类型与语义
model 必需模型 ID
messages message 数组
stream boolean
stream_options.include_usage 在 finish chunk 后发送 usage-only chunk
tools function、custom 或 Google server tool 数组
tool_choice 省略/auto/none/required、named function 或 custom 对象、allowed_tools
web_search_options 对象,开启 Google Search
temperature、top_p、top_k 可选采样值
max_tokens、max_completion_tokens 后者优先
frequency_penalty、presence_penalty 不影响生成
n 1–128
parallel_tool_calls 省略/true/false
logprobs、top_logprobs、logit_bias 不影响生成
stop string 或 string array
response_format {type:"text"}、{type:"json_object"} 或 {type:"json_schema",json_schema:{schema}}
modalities、audio ["text","audio"] 与 {voice,format},voice 为声音名或 {id},format 为 wav、mp3、flac、opus、aac、pcm16
reasoning_effort thinking effort
reasoning.effort nested thinking effort
extra_body.google.thinking_config Gemini OpenAI 兼容层的 thinking_level、thinking_budget 与 include_thoughts
seed 64 位整数
functions、function_call 旧式函数声明与函数选择
  • allowed_tools 的 mode 与工具列表映射为调用模式与允许的函数名,请求只发送列表中的函数与托管工具对应的 Google 工具
  • web_search_options 的搜索深度与近似位置写入搜索指令
  • n 大于 1 时每个 choice 独立并发生成,带 seed 时第 i 个 choice 使用 seed+i;choices 按 index 排列,各自带 finish_reason;usage 的输入与缓存命中按一次计,输出、思考与音频 token 为各 choice 之和;任一生成失败时整个请求返回该错误;流式请求在首个 choice 就绪后开始输出,其余 choice 的启动错误以流内错误返回
  • frequency_penalty、presence_penalty、logprobs、top_logprobs 与 logit_bias 接受任意值;非流式响应的 choices[].logprobs 为 null
  • stop 中的空字符串从停止条件中移除
  • reasoning.effort 与 reasoning_effort 映射到同一配置,两者同时提供时以 reasoning.effort 为准
  • json_schema.schema 原样作为 responseJsonSchema 发送;Chat json_schema.description 与 Responses text.format.description 写入 Schema 顶层 description,Schema 自带的 description 接在其后(空一行)
  • modalities 含 audio,或省略 modalities 而设置 audio 时输出音频:请求 AUDIO 模态与 audio.voice 声音,format 默认 wav。非流式响应的 message.audio 为 {id,data,expires_at,transcript},content 为 null,模型正文写入 transcript。流式响应的音频位于 delta.audio:pcm16 逐块输出 {id,data},其他格式在结束时输出一个完整的 {id,data,expires_at};正文以 {id,transcript} 增量输出,pcm16 的最后一块为 {id,expires_at}。音频回复以 WAV 与 transcript 保存在续接状态中,与 Responses 共用最近 256 个条目;assistant 消息的 audio:{id} 引用它时,该轮以这段音频与 transcript 发给上游,ID 不存在时返回 400 invalid_request
  • extra_body.google.thinking_config 按 Gemini thinkingConfig 处理:thinking_level 优先于 reasoning_effort,thinking_budget 为 -1 时使用模型默认思考设置,include_thoughts 为 false 时不输出 reasoning_content
  • functions 按 function 工具发送,function_call 的 none、auto 与 {name} 按 tool_choice 处理,每轮最多一个调用;带 functions 的请求以 assistant function_call:{name,arguments} 返回调用,finish_reason 为 function_call,流式为 delta.function_call。历史中的 assistant function_call 与 function 角色消息按函数调用与函数结果发送

message 字段为 role、content、可选 name、tool_call_id、tool_calls、function_call,assistant 另有 refusal 与 audio。system、developer、user 与 assistant 消息的 name 以 <name>: 写在该消息第一段文本前,例如 {"role":"system","name":"example_user","content":"Hi"} 在系统指令中为 example_user: Hi;tool 消息的 name 为函数名。assistant tool call:

{
  "id": "call_01",
  "type": "function",
  "function": {"name":"get_weather","arguments":"{\"city\":\"Taipei\"}"},
  "extra_content": {"google":{"thought_signature":"<SIGNATURE>"}}
}

content 可以是 string 或 Part 数组。Part 字段:

type 其他字段
text、input_text、output_text text
image_url、input_image image_url string 或 {"url":"..."};也可只给 file_id;可选 detail
video_url、input_video video_url string 或 {"url":"..."};也可只给 file_id
input_file、file file_id,或 filename + file_data,filename 为附件给模型的名称;Chat file 的字段位于嵌套 file 对象
input_audio input_audio.data、input_audio.format
refusal refusal,作为所在消息的文本

detail 为 low、high 与 Responses 的 original 时分别设置该 Part 的 MEDIA_RESOLUTION_LOW、MEDIA_RESOLUTION_HIGH、MEDIA_RESOLUTION_ULTRA_HIGH,auto 与省略时使用模型默认分辨率;Chat 的 detail 位于 image_url 对象中。OpenAI image_url / input_image 与 video_url / input_video 值为 data URL 时形成 inline data,值为 YouTube URL 时形成 external media,Gemini Files API 文件 URI 保持文件引用,其他 http(s) URL 由服务端下载后作为内联媒体发送,其他非 data 字符串按已上传 file ID 解析。data URL 接受 Base64 与百分号编码数据,省略 MIME 时按内容判断类型,MIME 参数不发送。同一请求内相同 URL 只下载一次;下载随请求取消,大小上限与内联媒体相同(512 MiB),MIME 取响应 Content-Type,缺失、无法解析或为 octet-stream 时按内容判断;URL 主机或任一重定向目标解析到本机、私网、链路本地、组播或未指定地址时不连接,按下载失败处理;下载失败返回 400,错误信息包含 URL 与原因。file_data 接受 data URL 或 Base64 文件内容,没有声明 MIME 时按 /v1/files 的规则依次按文件内容与 filename 扩展名判断。

function tool 使用 {"type":"function","function":{"name","description","parameters","strict"}}。strict:true 启用参数契约校验。Google tool type 为 web_search、web_search_preview、image_search、url_context、code_interpreter、google_maps。custom tool {"type":"custom","custom":{name,description,format}} 声明为只有字符串参数 input 的函数,grammar 格式的语法与定义写入函数描述;调用以 {"type":"custom","custom":{name,input}} 返回,历史中的 custom 调用以 {"input":<INPUT>} 发送。历史函数调用的 arguments 不是 JSON object 时以 {"_raw":"<原文>"} 发送。

非流式响应:

{
  "id": "chatcmpl_...",
  "object": "chat.completion",
  "created": 0,
  "model": "gemini-example",
  "provider_model": "gemini-provider-id",
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "...",
      "reasoning_content": "...",
      "tool_calls": [],
      "annotations": []
    },
    "logprobs": null,
    "finish_reason": "stop",
    "provider_finish_reason": "provider_19"
  }],
  "usage": {
    "prompt_tokens": 10,
    "completion_tokens": 20,
    "total_tokens": 30,
    "completion_tokens_details": {"reasoning_tokens": 5}
  }
}

provider_model、provider_finish_reason、reasoning_content、tool_calls、annotations 和 usage 仅在有对应数据时出现。service_tier 为上游用量报告的服务等级:flex 或 priority,其余为 default。annotation 形状为 {"type":"url_citation","url_citation":{"url","title","start_index","end_index"}},start_index、end_index 为 content 中的字符下标;上游没有正文区间的来源两者为 0。

Chat SSE 顺序:

  1. 每个 choice 一个 role chunk:delta={"role":"assistant","content":""}
  2. 正文 delta.content、思考 delta.reasoning_content、工具 delta.tool_calls、媒体或代码渲染 delta.content
  3. 各 choice 结束时发送引用 delta.annotations
  4. 随后发送该 choice 的 finish chunk:finish_reason,可选 provider_finish_reason
  5. include_usage=true 且上游有 usage 时,在全部 choice 结束后发送 choices:[] 的 usage-only chunk
  6. data: [DONE]

每个普通 chunk 为 {id,object:"chat.completion.chunk",created,model,choices:[{index,delta,finish_reason}],usage?},index 标识所属 choice。响应头已发送后的失败为 data: {"error":{"message","type","code"}}。

OpenAI Responses

POST /v1/responses 请求字段:

字段 类型与语义
model 必需模型 ID
input string 或 input item 数组
instructions 顶层 system instruction
stream boolean
tools、tool_choice function、custom、namespace(可含 custom)、local_shell/shell/apply_patch 与 Google tools;choice 支持 auto/none/required、named function/custom、allowed_tools、apply_patch/shell 与托管工具类型
temperature、top_p、max_output_tokens 生成参数
reasoning {"effort":"...","summary":"..."},generate_summary 与 summary 同义
text `{"format":{"type":"text
previous_response_id 当前进程内已保存的前一 Responses 响应 ID,Interactions 资源 ID 视为不存在
parallel_tool_calls 省略/true/false
truncation 省略/disabled/auto
metadata string-to-string object
store 省略/true/false
background boolean
include reasoning.encrypted_content、web_search_call.action.sources、code_interpreter_call.outputs
max_tool_calls 正整数;声明内置工具或 MCP 时以 Make at most <N> built-in tool calls in this response. 追加到本次指令,响应回传该值
context_management [{"type":"compaction","compact_threshold":<token>}]
conversation、prompt 本服务不保存这两类对象,引用它们的请求返回 404 not_found
  • namespace 内的函数以全名编码,输出恢复 namespace 与原函数名,不同 namespace 可声明同名函数
  • store 省略或为 true 时保存当前进程会话节点与输出项;false 只返回本次结果,不建立节点,既有续接链保持不变
  • background:true 的非流式请求立即返回 status:"queued" 的响应对象(带 Content-Length 与 Connection: close),生成在服务端继续,开始后保存为 in_progress,结束后保存为最终对象;客户端连接关闭不影响生成。该响应不论 store 取值都会保存,供查询、取消与续传
  • background:true 且 stream:true 时,事件依次为 queued 状态的 response.created 与 response.queued、response.in_progress、输出项事件与终止事件,全部写入事件记录;客户端断开后生成继续,GET /v1/responses/{id}?stream=true&starting_after=<sequence_number> 从该序号之后续传并跟随到结束,不带 starting_after 时从头回放
  • context_management 的 compaction 阈值被超过时(输入 token 按 countTokens 计),先按 compaction_trigger 的方式压缩当前上下文,再以被压缩部分中的 developer 与 system 消息、保留的条目与 compaction 项作为输入生成;compaction 项排在 output 首位,流式时在其他输出项之前写出它的 output_item.added 与 output_item.done

input item 字段为 type、id、role、content、call_id、name、namespace、arguments、input、action、operation、status、output、encrypted_content。支持 message、function_call、function_call_output、reasoning item 与下文列出的工具历史项。message content Part:

type 字段
input_text、output_text text
input_image image_url string 或 {url};也可只给 file_id
input_file file_id、file_url,或 filename + file_data,filename 为附件给模型的名称
input_audio input_audio:{data,format}
input_video video_url string 或 {url};也可只给 file_id
refusal refusal,作为所在消息的文本

Responses 的图片、视频与文件 Part 复用上述 data URL、file ID 与 YouTube 规则。

其他 input item 映射:

item 映射
system/developer message 文本进入系统指令,图片与文件移到首个 user 轮
custom_tool_call 函数调用,参数为 {"input":<INPUT>}
local_shell_call local_shell 函数调用,参数为去掉 type 的 action
shell_call shell 函数调用,参数为 action
apply_patch_call apply_patch 函数调用,参数为 operation
custom_tool_call_output、local_shell_call_output、shell_call_output、apply_patch_call_output 按 call_id 关联的函数结果
computer_call computer 函数调用,参数为 action,或 {"actions":[...]}
web_search_call、code_interpreter_call、file_search_call、mcp_call、mcp_list_tools、mcp_approval_request、tool_search_call、tool_search_output、program、program_output assistant 文本摘要 <type> <JSON>;输入含 mcp_approval_response 时 mcp_approval_request 为 mcp__<server_label>__<name> 函数调用,带 approval_request_id 的 mcp_call 并入对应函数结果
additional_tools tools 并入请求的工具列表
configuration_update 最后一个带 reasoning.effort 的项覆盖请求的推理强度
image_generation_call assistant 文本摘要与 result 图片
computer_call_output 按 call_id 关联的 computer 函数结果 {"type":"computer_screenshot"},截图作为图片
mcp_approval_response 对应批准请求的函数结果:批准时为服务调用该 MCP 工具得到的 output 与 error,拒绝时为带 reason 的拒绝说明;批准请求取自输入或 previous_response_id 的输出,找不到时返回 400;/v1/responses/input_tokens 与 /v1/responses/compact 不调用工具,批准的函数结果的 output 与 error 均为 null
item_reference 当前进程保存的同 ID 输入项或输出项
compaction 摘要 user 轮与原样保留的条目,见下文上下文压缩
compaction_trigger 压缩当前上下文,必须是最后一个输入项,其他位置返回 400

文本摘要的 JSON 省略 id、type 与 status。函数结果项缺少 call_id 时使用 id;apply_patch_call_output 的结果为 {"status","output"}。没有 type 与 role、只带 id 的项按 item_reference 展开,找不到同 ID 的项时返回 400。system/developer message 的图片与文件在没有 user 轮时单独组成首个 user 轮。

Responses tool 字段:

tool type 字段
function name、description、parameters、strict;省略 strict 时参数 Schema 的每个对象都设 additionalProperties: false 且全部属性必填即按 strict 校验,否则按非 strict,响应的 tools 回显实际取值
web_search、web_search_2025_08_26、web_search_preview、web_search_preview_2025_03_11 search_context_size、user_location、filters.allowed_domains、search_content_types
image_search、url_context、google_maps type
code_interpreter container
custom 只有字符串参数 input 的函数,grammar 写入描述
local_shell 函数,参数为 command、working_directory、timeout_ms
shell 函数,参数为 commands、timeout_ms、max_output_length;environment.skills 的名称、路径与说明写入描述
apply_patch 函数,参数为 type、path、diff
image_generation 图片模型按与 POST /v1/images/generations 相同的规则处理 size、quality、output_format 与 output_compression;input_image_mask 见下文
computer_use_preview、computer 名为 computer 的函数;computer_use_preview 的 display_width、display_height 与 environment 写入描述,参数为单个 action,computer 的参数为 actions 列表
mcp 上游 MCP 服务器:server_label、server_url、authorization、headers、allowed_tools(数组或 tool_names),server_description 写入系统指令
file_search、tool_search、programmatic_tool_calling 接受但不声明
  • web search 工具的 search_context_size、user_location 与 filters.allowed_domains 写入搜索指令,域名限制使用 site: 查询;上游 grounding query 与 sources 原样返回
  • search_content_types 只含 image 时只开启图片搜索,同时含 text 时同时开启网页搜索;图片搜索查询同样输出为 web_search_call
  • mcp 工具的 require_approval 省略或为 always 时全部工具需要批准,为 never 时全部不需要;为对象时 never 过滤匹配且 always 过滤不匹配的工具不需要批准,其余需要批准,过滤的 tool_names 与 read_only 同时给出时都要满足。不需要批准的工具由上游在生成中直接调用;需要批准的工具由服务经出口代理读取 tools/list,声明为 mcp__<server_label>__<name> 函数,模型调用时输出 mcp_approval_request 项(id 为 mcpr_ 加调用 ID)并结束本轮;下一轮输入给出 mcp_approval_response 且 approve 为 true 时,服务以 tools/call 调用该工具,结果以带 approval_request_id 的 mcp_call 项排在本轮输出首位,客户端回传该 mcp_call 时不再调用。需要批准的工具按 tool_choice 展开:为 none 或指定函数时不读取 tools/list,为 mcp 或 allowed_tools 时只声明其中列出的服务器与工具,allowed_tools 同时列出函数时,声明的 MCP 工具函数也加入允许调用的函数;additional_tools 输入项中的 mcp 工具与 tools 中的相同。connector_id 返回 400;allowed_tools.read_only:true 时服务经出口代理以 server_url 与请求头读取该服务器的 tools/list,只允许 annotations.readOnlyHint 为 true 的工具,同时给出 tool_names 时取交集,没有允许的工具时不连接该服务器,tools/list 失败返回 400 并说明原因;上游的 MCP 调用输出为 mcp_call 项,output 为工具结果文本
  • namespace 的 description 写在其中各函数描述之前
  • code_interpreter.container 为容器 ID 字符串时忽略;为对象时其 file_ids 作为文件引用附到最后一个 user 轮,没有 user 轮时作为新的 user 轮

image_generation 的 input_image_mask:{image_url} 读取 data URL 或下载 http(s) 图片,{file_id} 读取 /v1/files 上传的文件,按 /v1/images/edits 的 mask 转为 PNG 遮罩,连同同一句说明插在最后一个 user 轮最后一个媒体之后(该轮没有媒体时插在开头),只发给本次生成,不进入续接历史;遮罩无法读取或解码时返回 400。

tool_choice 的 allowed_tools 映射为 mode(auto 或 required)与允许的函数名,请求只发送列表中的函数与托管工具对应的 Google 工具;web_search、web_search_2025_08_26、web_search_preview、web_search_preview_2025_03_11、code_interpreter、url_context、google_maps 与 image_search 映射为 required,本次只允许该工具;computer、computer_use、computer_use_preview 映射为必须调用 computer 函数;mcp 映射为 required,带 name 时只允许该服务器的该工具;file_search、image_generation、programmatic_tool_calling 与 tool_search 映射为 auto。

响应 shell 的字段始终存在:

{
  "id": "resp_...",
  "object": "response",
  "created_at": 0,
  "completed_at": null,
  "status": "in_progress",
  "error": null,
  "incomplete_details": null,
  "instructions": null,
  "metadata": {},
  "model": "gemini-example",
  "output": [],
  "output_text": "",
  "parallel_tool_calls": true,
  "previous_response_id": null,
  "reasoning": null,
  "temperature": null,
  "text": {"format":{"type":"text"}},
  "tool_choice": "auto",
  "tools": [],
  "top_p": null,
  "truncation": "disabled",
  "max_output_tokens": null,
  "max_tool_calls": null,
  "service_tier": "auto",
  "background": false,
  "usage": null
}

完成对象可以增加 provider_model 与 provider_finish_reason。completed_at 在 status 为 completed 时为完成时间的 Unix 秒数,其余为 null;service_tier 在生成前为请求值(省略时为 auto),生成后为上游用量报告的服务等级:flex 或 priority,其余为 default。status 为 completed、incomplete 或 failed;长度终态使用 incomplete_details.reason=max_output_tokens,策略终态使用 content_filter。

output item 联合类型:

type 字段
reasoning id、status、summary:[{type:"summary_text",text}]、可选 encrypted_content;摘要文本只在请求 reasoning.summary(或 generate_summary)为 auto、concise、detailed 时返回
message id、status、role:"assistant"、content:[{type:"output_text",text,annotations}]
function_call id、status、call_id、name、arguments
custom_tool_call id、status、call_id、name、input,可选 namespace
local_shell_call id、status、call_id、action:{type:"exec",command,env,...}
shell_call id、status、call_id、action:{commands,timeout_ms,max_output_length}、environment:null
apply_patch_call id、status、call_id、operation:{type,path,diff}
code_interpreter_call id、status、code、container_id:"aistudio"、outputs:[{type:"logs",logs}];include 不含 code_interpreter_call.outputs 时 outputs 为 null
image_generation_call id、status、Base64 result
web_search_call id、status、action

output 按生成顺序排列:相邻的思考并入同一 reasoning 项,相邻的正文并入同一 message 项,被其他输出项隔开的正文分为多个 message 项。请求 include 含 reasoning.encrypted_content 时,函数调用的思考签名写入紧邻其前的 reasoning 项,前一项不是 reasoning 时为单独的 rs_<call_id> reasoning 项。

message 的 url_citation 为 {"type":"url_citation","url","title","start_index","end_index"},按上游正文区间归入所在 message 项,start_index、end_index 为该项文本中的字符下标;上游没有正文区间的来源写入以正文结束的最后一个 message 项,两者为 0。

web_search_call.action 为 {"type":"search","query":"<首个查询>","queries":[...]},上游每个搜索调用步骤在发生处输出一项,queries 为该步骤的查询,grounding 中出现步骤之外的新查询时再新增一项,查询按首次出现去重;请求 include 含 web_search_call.action.sources 时最后一个 search 动作带 sources:[{"type":"url","url":"..."}],来源随末尾的 grounding 到达,按 URI 去重,流式中写在 response.completed 的该项上。GET /v1/responses/{id} 的 include[](也接受 include)与创建时的 include 合并后决定返回的 sources 与 outputs。URL Context 读取的每个网址在读取结果到达时输出一项 web_search_call,action 为 {"type":"open_page","url":"..."},网址按首次出现去重,urlRetrievalStatus 不是 URL_RETRIEVAL_STATUS_SUCCESS 时 status 为 failed,流式中该项没有 response.web_search_call.completed。code_interpreter_call.status 在没有结果时为 incomplete,成功结果为 completed,非 OUTCOME_OK 结果为 failed;stdout 写入 outputs[].logs,失败文本加 stderr: 前缀。流式 output_item.added 使用 in_progress,对应 output_item.done 使用最终状态;流式与非流式的 output 相同,每项 output_item.done 之后才 added 下一项,code_interpreter_call 在执行结果到达时 done。

Responses usage:

{
  "input_tokens": 10,
  "output_tokens": 20,
  "total_tokens": 30,
  "input_tokens_details": {"cached_tokens":0,"cache_write_tokens":0},
  "output_tokens_details": {"reasoning_tokens":5}
}

每个 Responses SSE payload 都包含 type 和从 0 单调递增的 sequence_number:

事件 事件字段
response.created、response.in_progress response shell
response.output_item.added、response.output_item.done output_index、item
response.reasoning_summary_part.added、response.reasoning_summary_part.done item_id、output_index、summary_index、part
response.reasoning_summary_text.delta item_id、output_index、summary_index、delta
response.reasoning_summary_text.done 上述索引与 text
response.content_part.added、response.content_part.done item_id、output_index、content_index、part
response.output_text.delta item_id、output_index、content_index、delta、logprobs:[]
response.output_text.done 上述索引与 text、logprobs:[]
response.output_text.annotation.added item_id、output_index、content_index、annotation_index、annotation
response.function_call_arguments.delta item_id、output_index、delta
response.function_call_arguments.done item_id、output_index、arguments、name
response.custom_tool_call_input.delta item_id、output_index、delta
response.custom_tool_call_input.done item_id、output_index、input
response.image_generation_call.in_progress、response.image_generation_call.completed item_id、output_index
response.code_interpreter_call.in_progress、response.code_interpreter_call.interpreting、response.code_interpreter_call.completed item_id、output_index
response.code_interpreter_call_code.delta item_id、output_index、delta
response.code_interpreter_call_code.done item_id、output_index、code
response.web_search_call.in_progress、response.web_search_call.searching、response.web_search_call.completed item_id、output_index
response.completed、response.incomplete、response.failed 完整 response

声明 web_search 时请求上游返回服务端工具步骤,web_search_call 与正文、代码执行和网址读取按发生顺序输出,正文随到随写。上游在正文后失败时,已产生的 delta 按原顺序位于 response.failed 之前,response.failed 的 output 为已写出的输出项。

上下文压缩:

  • POST /v1/responses/compact 为无状态端点,接受 model(必需)、input、instructions、tools 与 previous_response_id;input 的转换、item_reference、媒体与续接链同 POST /v1/responses
  • 压缩先在续接链与输入的条目中确定原样保留部分:从最新条目向前,以完整的模型侧条目组(reasoning、assistant 消息与各类调用,连同其后的工具输出)或 user 消息为单位累计,约 20000 token 内的部分原样保留,最新一组总是保留,切点不落在工具输出上;token 按每 4 字节 1 个估算,消息只计文本、每张图片计 765,其他条目不计 encrypted_content
  • 原样保留部分之前的条目去掉 developer 与 system 消息后由请求的模型非流式生成摘要,去掉后没有条目时不调用上游、摘要为空:系统指令与工具同请求,tool_choice 为 none,末尾追加一个 user 轮,为 OMP 的结构化交接摘要提示词(Goal、Constraints & Preferences、Progress、Key Decisions、Next Steps、Critical Context、Additional Notes);输入已含 compaction 项时,只摘要其原样条目与之后的新条目,旧摘要以 <previous-summary> 包裹作为首个 user 轮,末尾改用增量摘要提示词;没有需要摘要的条目时不调用上游;摘要的结束原因不是 stop 时返回错误
  • compaction 项为 {"id":"cmp_...","type":"compaction","encrypted_content":"<明文 JSON>"},encrypted_content 为 {"v":1,"summary":"<摘要>","items":[<原样保留的条目>]},条目保持输入原文,含 reasoning 的 encrypted_content 思考签名与调用 ID
  • compact 响应为 {"id":"resp_...","object":"response.compaction","created_at":0,"output":[...],"usage":{...}};output 先是原样保留部分之前的 user 消息:从最新向前累计到 64000 token,跨预算的一条只保留首尾文本并在中间写入 …N tokens truncated…,跳过以 <environment_context>、<user_instructions>、<additional_context>、<skills、<token_budget>、<model_switch> 开头的上下文消息;最后是 compaction 项;usage 为生成摘要的用量,不调用上游时各项为 0
  • 输入中的 compaction 项只展开最后一个:其前的条目保留,与原样条目中 user 消息文本相同的 user 消息各去掉一条,更早的 compaction 项丢弃;之后依次接摘要 user 轮(Prior model work/tool state available.、MUST build on prior work; NEVER duplicate prior work. 与 <summary> 包裹的摘要)、原样条目与 compaction 项之后的条目;encrypted_content 不是本服务生成的 JSON 时返回 400
  • POST /v1/responses 以 compaction_trigger 结尾时按 compact 的方式压缩,响应 output 只有一个 compaction 项,output_text 为空;流式事件依次为 response.created、response.in_progress、response.output_item.added(encrypted_content:"")、response.output_item.done 与 response.completed,调用上游生成摘要时带 usage;保存的响应不接续前序节点,续接上下文为 compact 输出的条目展开后的内容

Anthropic Messages

POST /v1/messages 请求字段:

字段 类型与语义
model 必需模型 ID
messages {role,content} 数组,role 为 user、assistant、system
system string 或 text block 数组
max_tokens 正整数,省略时使用模型默认输出上限
stop_sequences string array
stream boolean
temperature、top_p、top_k 生成参数
tools、tool_choice custom/server tools、Anthropic 定义的客户端工具与 auto/none/any/named tool
thinking {type:"enabled",budget_tokens:<INT>}、{type:"adaptive"} 或 {type:"disabled"},可选 display:"summarized" 或 "omitted"
output_config {effort?:"...",format?:{type:"json_schema",schema}}
context_management {edits:[...]},见下文上下文管理
  • system 消息以 <system-reminder> 包裹并入相邻的用户内容:前一条为 user 时追加在其末尾,否则并入下一条 user 消息、排在其 tool_result 之后,使函数调用之后紧跟函数结果
  • system 消息中的 tool_addition 与 tool_removal 块按出现顺序增删声明的工具:tool_reference 按 name 引用 tools 中的工具(含 defer_loading 工具,tools 中的工具都声明给上游),tool_definition 的 definition 加入工具列表,tool_removal 移除同名工具
  • output_config.format 的 json_schema 设置结构化输出,其他 type 返回 400 invalid_request_error
  • thinking.display:"omitted" 时 thinking block 的正文为空,签名照常返回

message content 可以是 string 或 block 数组:

block type 字段
text text
thinking thinking、signature
redacted_thinking data
image、document source:{type,media_type,data,url,file_id,content};document 的 title 为附件给模型的名称,context 作为文档之前的文本
tool_use id、name、object input
tool_result tool_use_id、content、is_error
server_tool_use、mcp_tool_use id、name、input,mcp_tool_use 另有 server_name
web_search_tool_result tool_use_id、content:[{type:"web_search_result",url,title,encrypted_content,page_age}] 或 {type:"web_search_tool_result_error",error_code}
search_result source、title、content
web_fetch_tool_result tool_use_id、content:{type:"web_fetch_result",url,content:<document>} 或错误对象
code_execution_tool_result、bash_code_execution_tool_result、text_editor_code_execution_tool_result、tool_search_tool_result、advisor_tool_result、mcp_tool_result tool_use_id、content
compaction content、encrypted_content
container_upload file_id

image / document 的 Base64 source 使用 type:"base64"、media_type、data;URL source 使用 type:"url" 与非空 url,YouTube 链接作为视频引用,其他 http(s) URL 由服务下载为内联媒体,规则与 GenerateContent 的 fileData 相同。document 的 type:"text" source 以 data 作为文本,type:"content" source 按原顺序展开字符串或 content block;type:"file" source 与 container_upload 以 file_id 引用 /v1/files 上传的文件。服务端工具历史块在原位置以文本续接:server_tool_use 与 mcp_tool_use 写为工具名与 input,web_fetch_tool_result 写为 URL 并展开其中的 document,抓取失败时写为错误码,search_result 写为标题、来源与正文,其余工具结果写为 block type 与 content JSON。code_execution_tool_result 的 code_execution_tool_result_error 在 error_code 为 execution_time_exceeded 时回传为超时,其他错误码回传为失败并以错误码作为输出。tool_result.is_error=true 把合法 JSON content 包装为 {"error":<CONTENT>};普通标量或数组结果包装为 {"result":<CONTENT>}。

custom tool 为 {name,description,input_schema},可选 type:"custom"。server tool 字段:

type 必需 name
web_search_* web_search
image_search image_search
web_fetch_* web_fetch
code_execution_* code_execution
url_context url_context
google_maps google_maps

web_search_* 的 allowed_domains、blocked_domains 与 user_location 写入搜索偏好,域名限制使用 site: 与 -site: 查询;web_fetch_* 的 allowed_domains 与 blocked_domains 作为读取 URL 的域名范围(含子域名)写入系统指令;调用次数由上游决定,其余选项不改变上游请求。bash_*、text_editor_*、memory_* 以请求中的 name 声明为函数,描述与参数由服务固定,参数分别为 {command,restart}、{command,path,file_text,old_str,new_str,insert_line,insert_text,view_range}(text_editor_20241022 与 text_editor_20250124 的 command 另含 undo_edit)与再加 old_path、new_path 的 memory 命令,模型调用以 tool_use 返回由客户端执行;computer_20241022、computer_20250124、computer_20251124 同样以 name 声明为函数,说明写明 display_width_px×display_height_px 的屏幕尺寸(缺少时返回 400 invalid_request_error),参数为 action、coordinate、start_coordinate、text,action 取 key、type、mouse_move、left_click、left_click_drag、right_click、middle_click、double_click、screenshot、cursor_position,computer_20250124 起另有 triple_click、left_mouse_down、left_mouse_up、scroll、hold_key、wait 与参数 scroll_direction、scroll_amount、duration、key,enable_zoom:true 时另有 zoom 与参数 region;tool_search_tool_*、advisor_* 与类型名含 toolset 的工具不声明到上游。

请求级 mcp_servers:[{type:"url",name,url,authorization_token?,tool_configuration?:{enabled?,allowed_tools?}}] 作为上游 MCP 服务器,authorization_token 以 Authorization: Bearer 发送,enabled:false 的服务器不发送;mcp_toolset 的 mcp_server_name 必须是其中的服务器,default_config 与 configs 按工具启用情况得出允许列表,默认启用而单独停用部分工具时服务经出口代理读取该服务器的 tools/list,允许全集中未停用的工具,tools/list 失败返回 400 并说明原因。上游的 MCP 调用输出为 mcp_tool_use(server_name、name、input)与 mcp_tool_result(is_error、content)块。

上下文管理 context_management.edits 按数组顺序执行,token 数用内嵌 Gemma 3 分词模型在本地估算:

edit type 处理
clear_thinking_20251015 去掉最近 keep.value 个思考轮之前的思考块
clear_tool_uses_20250919 超过 trigger 时把较早的工具结果替换为 [cleared]
compact_20260112 超过 trigger.value 时以摘要替换全部历史
  • clear_thinking_20251015:keep 为 {type:"thinking_turns",value:N} 时,最近 N 个带 thinking 或 redacted_thinking 的 assistant 轮之前的这两类块从历史中去掉,其思考签名不发给上游;省略 keep、"all" 与 {type:"all"} 保留全部
  • clear_tool_uses_20250919:trigger 默认 {type:"input_tokens",value:100000},tool_uses 按历史中的工具调用次数计;超过时保留最近 keep.value(默认 3)次调用,更早且不在 exclude_tools 中的调用,tool_result 与 mcp_tool_result 的 content 替换为 [cleared],其余服务端工具结果替换为 [cleared] text block;clear_tool_inputs 为 true 或包含该工具名时调用的 input 改为 {};清理的 token 少于 clear_at_least.value 时不清理
  • compact_20260112:输入超过 trigger.value(默认 150000)时,请求的模型以 instructions 非流式生成摘要,省略时使用官方文档的摘要提示词,tool_choice 为 none;摘要以 <summary> 包裹时取其中的文本,与 Responses 相同的摘要 user 轮替换全部历史后继续生成。响应 content 首个 block 为 {type:"compaction",content:<摘要>,encrypted_content:null},pause_after_compaction:true 时只返回该块,stop reason 为 compaction
  • 未知 edit type 与 keep、trigger 形状返回 400 invalid_request_error
  • 带 context_management 时,非流式响应与流式 message_delta 输出 context_management:{applied_edits:[...]},列出实际清理的编辑及其 cleared_tool_uses 或 cleared_thinking_turns 与 cleared_input_tokens;带 compact_20260112 时 usage.iterations 依次为压缩与生成的 {type,input_tokens,output_tokens,cache_creation_input_tokens,cache_read_input_tokens},暂停时只有压缩一项、顶层 input 与 output 为 0
  • 输入中最后一个 compaction 块之前的全部消息与块被丢弃,其 content 写为摘要 user 轮,块之后的内容照常续接
  • count_tokens 执行清理编辑、不触发压缩,带 context_management 时另返回 context_management:{original_input_tokens},为清理前的计数

server tool 接受对应 type、name 与任意工具选项(如 Claude Code WebSearch 的 search_profile);带 description 或 input_schema 时返回 400 invalid_request_error。tool choice 接受省略、{"type":"auto"}、{"type":"none"}、{"type":"any"} 与 {"type":"tool","name":"FUNCTION_NAME"}。custom tool 的 cache_control 等客户端提示保留生成能力,strict:true 校验完整返回参数。

非流式响应:

{
  "id": "msg_...",
  "type": "message",
  "role": "assistant",
  "model": "gemini-example",
  "content": [
    {"type":"thinking","thinking":"...","signature":"..."},
    {"type":"text","text":"...","citations":null},
    {"type":"tool_use","id":"call_01","name":"get_weather","input":{}}
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "stop_details": null,
  "usage": {"input_tokens":10,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":20,"server_tool_use":null,"service_tier":"standard","inference_geo":null},
  "container": null,
  "provider_model": "gemini-provider-id",
  "provider_finish_reason": "provider_19"
}

stop_details、container 与 usage.inference_geo 为 null;usage.server_tool_use 在发生网页搜索或网址读取时为 {web_search_requests,web_fetch_requests},其余为 null;usage.service_tier 在上游用量报告 priority 时为 priority,其余为 standard。text block 带 citations,没有引用时为 null。

content 输出 block 为 text、thinking、redacted_thinking、tool_use、server_tool_use、web_search_tool_result 或 compaction;thinking block 总带 signature,签名不在该 block 上时为空字符串。stop reason 为 end_turn、tool_use、stop_sequence、max_tokens、pause_turn、compaction 或 refusal。POST /v1/messages/count_tokens 接受同一 message/system/tools 输入并返回 {"input_tokens":<INT>};它提供独立计数估算,PDF 等媒体请求的最终用量以生成响应 usage.input_tokens 为准。

Anthropic 响应中的媒体编码为 text block 中的 Markdown 链接,MEDIA_OUTPUT=inline 时为 data URL,url 时为本服务的 /media/<文件名> URL,代码编码为 fenced text。Google Search 的每个去重查询生成一组 server_tool_use 和 web_search_tool_result,结果按 URL 去重,来源集合覆盖本次搜索的全部查询。声明 web_search 时请求上游返回服务端工具步骤,每组搜索块位于对应搜索调用步骤之后;来源随上游末尾的 grounding 到达,流式响应中开头思考之后的块等到 grounding 到达后按发生顺序写出,等待期间发送 ping。usage.server_tool_use.web_search_requests 记录上游报告的去重查询数。grounding 中带正文区间的来源把搜索回答拆成多个 text block:被来源支撑的区间单独成块,citations 为 [{"type":"web_search_result_location","url","title","encrypted_index","cited_text"}],cited_text 为该区间的回答正文,encrypted_index 与 encrypted_content 同样由本服务加密;其余正文的 citations 为 null。流式响应中带引用的块在 content_block_start 之后先以 citations_delta{citation} 逐条给出引用,再写出正文。URL Context 读取的每个网址按首次出现生成一组 server_tool_use(name:"web_fetch"、input:{"url":...})和 web_fetch_tool_result:读取成功时 content 为 {"type":"web_fetch_result","url":...,"retrieved_at":null,"content":{"type":"document","source":{"type":"text","media_type":"text/plain","data":""}}},上游不返回网页正文;URL_RETRIEVAL_STATUS_UNSAFE 为 {"type":"web_fetch_tool_result_error","error_code":"url_not_allowed"},URL_RETRIEVAL_STATUS_ERROR 与 URL_RETRIEVAL_STATUS_PAYWALL 为 url_not_accessible,其余状态为 unavailable;web_fetch_requests 为读取的网址数。其余引用在末尾追加 Sources: Markdown 列表。

搜索来源的 encrypted_content 由本服务生成,保存上游返回的 URL、标题与可用摘要。客户端回传的搜索块以文本续接:查询写为 Web search: <query>,配对结果追加到同一文本,每个来源写标题与 URL,能用当前 PROXY_API_KEY 解开的 encrypted_content 追加摘要;来自 Anthropic 服务或以其他 PROXY_API_KEY 生成的来源只保留标题与 URL。错误结果写为 Web search failed: <error_code>;没有配对调用的结果与没有结果的调用(pause_turn 续接)分别单独成文。该字段用于本服务的多轮会话,和 Anthropic 服务的来源令牌分别使用。

Anthropic SSE:

事件 payload
message_start {type,message:{id,type,role,content:[],model,stop_reason:null,stop_sequence:null,stop_details:null,usage:{input_tokens,cache_creation_input_tokens,cache_read_input_tokens,cache_creation,output_tokens,server_tool_use,service_tier,inference_geo},container:null}}
ping {type:"ping"}
content_block_start {type,index,content_block}
content_block_delta {type,index,delta}
content_block_stop {type,index}
message_delta {type,delta:{stop_reason,stop_sequence,provider_finish_reason?},usage,context_management?}
message_stop {type:"message_stop"}
error {type:"error",error:{type,message}}

delta 联合类型为 text_delta{text}、citations_delta{citation}、thinking_delta{thinking}、signature_delta{signature}、input_json_delta{partial_json}、compaction_delta{content,encrypted_content}。compaction block 在 message_start 之后以 index 0 输出,content_block_start 的 content 为 null,一个 compaction_delta 带完整摘要。thinking block 的 content_block_start 带 thinking:"" 与 signature:"",signature 在该 block 关闭前以 signature_delta 发送;redacted thinking 使用一个 start/stop block;tool_use 先发送空 input,再通过 input_json_delta 发送完整参数 JSON。搜索块在来源汇总后以完整的 start/stop block 输出,查询计数随最终 message_delta.usage 返回。

Gemini Interactions

POST /v1beta/interactions 与 POST /v1/interactions 接受同一创建请求,通过 x-goog-api-key、Bearer 或 key 查询参数认证。

{
  "model": "gemini-3.8-flash-tts",
  "input": [{"type":"user_input","content":[{
    "type":"text","text":"Have a wonderful day!",
    "annotations":[{"type":"speech_metadata","style":"cheerful and friendly"}]
  }]}],
  "response_format": {"type":"audio","mime_type":"audio/l16","sample_rate":24000},
  "generation_config": {"speech_config":[{"voice":"Kore"}]},
  "stream": true
}
字段 映射
input 字符串、单个内容块、内容块数组或步骤数组;内容类型为 text、image、audio、video、document
媒体内容 data(Base64)或 uri,可选 mime_type;图片与视频可选 resolution:low、medium、high、ultra_high;音频可选 sample_rate、channels;文档可选 name 作为附件文件名
视频处理 processing:"static"、"agentic" 或 {type:"static",start_offset?,end_offset?,fps?};offset 为带 s 的 Duration 字符串,例如 "2.5s"
输入步骤 user_input、model_output、thought、function_call、function_result、code_execution_call、code_execution_result 与工具 call/result 步骤;function_call 的 signature 或其前 thought 步骤的 signature 作为该调用的思考签名
system_instruction 当前请求的系统指令
generation_config temperature、top_p、top_k、max_output_tokens、seed、stop_sequences、thinking_level、thinking_summaries、speech_config、tool_choice、image_config:{aspect_ratio?,image_size?}、transcription_config
response_format 单对象或数组:{type:"text",mime_type?,schema?}、JSON Schema 对象、{type:"image",mime_type?,aspect_ratio?,image_size?}、{type:"audio",mime_type?,sample_rate?,bit_rate?,delivery?}、{type:"video",aspect_ratio?,duration?,resolution?}
response_modalities text、image、audio、video 的数组;前三项对应 Gemini 输出模态,video 见 Omni Interaction
response_mime_type text/plain 或 application/json
safety_settings [{type,threshold}],取值为小写的类别与阈值枚举名,如 harassment、block_low_and_above
语音配置 speech_config:[{voice,language?}] 或 {speakers:[{speaker,voice}],mode?}
语音文本 文本块 annotations 中的 {type:"speech_metadata",speaker?,style?}
函数与工具 tools:[{type:"function",name,description?,parameters?}] 与内置工具;tool_choice 为 auto、any、none、validated 或 {allowed_tools:{mode?,tools}}
内置工具 {type:"google_search",search_types?}、{type:"google_maps",latitude?,longitude?,enable_widget?}、{type:"computer_use",environment?,excluded_predefined_functions?}、{type:"mcp_server",name,url,headers?,allowed_tools?}、{type:"file_search",file_search_store_names,metadata_filter?,top_k?}、url_context、code_execution
请求设置 service_tier、labels、cached_content
agent model 为空时作为模型 ID,用于 Deep Research 等代理
agent_config {type:"antigravity",model?,max_total_tokens?},max_total_tokens 为字符串或数字;{type:"deep-research",thinking_summaries?,visualization?,collaborative_planning?},thinking_summaries 为 auto 或 none,visualization 为 auto 或 off;type 与 agent 的种类不一致或取值不在上述范围时返回 400 INVALID_ARGUMENT
续接 previous_interaction_id、store
  • 媒体内容的 data 与 uri 二选一,复用 Gemini 文件与内联媒体解析:省略 mime_type 时内联数据按内容识别类型,无法识别时返回 400 INVALID_ARGUMENT;uri 为外部 http(s) URL 时由服务下载为内联媒体,规则与 GenerateContent 的 fileData 相同;本服务 Gemini 文件接口返回的 uri 作为文件引用
  • 函数结果通过 call_id 匹配历史调用,没有对应调用时使用自带的 name;is_error:true 的结果以 {"error":<result>} 发送上游;code_execution_call 与 code_execution_result 以代码块文本并入模型轮次;google_search、url_context、google_maps、file_search 与 mcp_server_tool 的 call 与 result 步骤作为服务端工具 Part 发送上游,retrieval 步骤不发送
  • processing_call 和 processing_result 保留服务端媒体处理调用的 id、对应的 call_id 与各自的 signature,作为模型历史续接;流式响应按 step.start、step.delta、step.stop 发布,签名位于 delta
  • 文本 response_format 带 schema 时请求结构化输出,mime_type 默认 application/json;不带 type 或 type 为 JSON Schema 类型的对象直接作为结构化输出 Schema;图片指定 mime_type:"image/jpeg" 时其他格式的图片输出转为 JPEG
  • response_format 中的图片比例与尺寸优先于 generation_config.image_config;带 response_format 时不使用 response_mime_type;response_modalities 中的其他取值返回 400 INVALID_ARGUMENT
  • speech_config 的 language 不发送上游,多说话人 mode 为 verbatim 或 conversational;speech_metadata 保留说话人与风格
  • google_search.search_types 取 web_search、enterprise_web_search、image_search,省略时为 web search;google_maps 的坐标写入检索位置;computer_use.environment 省略时为 browser;mcp_server 与 file_search 存在时响应带服务端工具步骤;retrieval 不发送上游;tool_choice:"any" 要求调用函数,allowed_tools.tools 限定可调用的函数
  • transcription_config 的 timestamp_granularities 含 word 时输出逐词时间,diarization_mode:"speaker" 输出说话人,mode:"smart" 或 {type:"smart"} 使用智能转录;转录文本的 model_output 内容带 annotations
  • service_tier、labels 与 Gemini GenerateContent 的 serviceTier、labels 相同;cached_content 引用显式缓存,缓存不存在或已过期时返回 404 NOT_FOUND
  • MCP 调用输出为 {type:"mcp_server_tool_call",id,name,server_name,arguments},结果为 {type:"mcp_server_tool_result",call_id,result},result 为 MCP 内容项数组 [{type:"text",text}|{type:"image"|"audio",data,mime_type}]
  • interaction 默认保存;previous_interaction_id 重建前序内容,指向同一 agent 的后台任务时改为以上游 interaction 续接(见后台 Interaction 任务),store:false 仅返回本次响应,不能检索或续接;interaction 与 Responses 响应共用最多 256 个保存节点,超出时淘汰最早的节点,服务重启后保留

音频 mime_type 为 audio/wav、audio/l16、audio/mp3、audio/ogg_opus、audio/alaw 或 audio/mulaw,非流式默认 audio/wav,流式默认 audio/l16。TTS 上游为 24 kHz、16-bit 小端、单声道 PCM,Lyria 等返回的 MP3 先解码为 PCM;请求 audio/mp3 且未改采样率、未指定 bit_rate 时原样返回上游 MP3。sample_rate 省略时使用上游采样率,指定时重采样;MP3 取 32、44.1、48 kHz,Ogg Opus 取 8、12、16、24、48 kHz,均为不低于目标采样率的最小值,超出时取最高值。bit_rate 以 bit/s 计,用于 MP3(CBR 32000–320000 取最接近值,默认 192000)与 Opus。输出内容的 mime_type 依次为 audio/wav、audio/l16、audio/mp3、audio/ogg、audio/alaw、audio/mulaw,sample_rate 与 channels 为实际值。上游为 PCM 且不重采样时,audio/l16、audio/alaw、audio/mulaw 逐块输出,其余情况在音频汇总完成后发送一个完整块。请求同时含文本与音频而模型只能生成文本时按文本生成。delivery 取任意值时都内联返回。创建请求在当前连接内执行;非流式 background:true 时先返回 in_progress 的 interaction 并关闭连接,生成在服务内继续,终态可经检索读取。

webhook_config:{uris,user_metadata} 随 background:true 使用,否则返回 400 INVALID_ARGUMENT,uris 为 http 或 https 地址。后台交互结束时服务向每个地址 POST {type,version:"v1",timestamp,data:{id},user_metadata},请求头带 webhook-id 与 webhook-timestamp:type 按终态为 interaction.completed(含 incomplete)、interaction.requires_action、interaction.failed(data 另有 error_code 与 error_message)或 interaction.cancelled;应答不是 2xx 或 10 秒内没有应答时,从 1 秒起按倍数退避(间隔最长 1 小时)重试 24 小时。

非流式响应包含 id、object:"interaction"、model、created、updated、status、steps 与 usage,以 previous_interaction_id 续接时同时带该字段。steps 的 model_output.content 保存文本或媒体,带引用的文本内容含 annotations,每项为 {type:"url_citation",url,title,start_index,end_index},下标为该段文本中的字节位置;音频位于 {type:"audio",data,mime_type,sample_rate,channels};SDK 的 output_audio 与 output_text 从这些步骤读取。正文、图片与函数调用携带的思考签名作为其前 thought 步骤的 signature 输出,按步骤回传时签名回到其后第一个模型 Part。函数调用作为 function_call 步骤返回,状态为 requires_action;正常生成与命中停止序列的状态为 completed,输出限额与内容拦截的状态为 incomplete。usage 包含 total_input_tokens、total_cached_tokens、total_output_tokens、total_thought_tokens、total_tool_use_tokens 与 total_tokens;上游给出模态细分时另有 input_tokens_by_modality、cached_tokens_by_modality、output_tokens_by_modality、tool_use_tokens_by_modality,元素为 {modality,tokens},modality 为小写模态名;使用 Google Search 或 Google Maps 时 grounding_tool_count 按 {type:"google_search"|"google_maps",count} 给出调用次数。

SSE 使用相同的事件名与 JSON event_type:interaction.created → step.start → step.delta → step.stop → interaction.completed。background:true 的流式与后台生成写入事件记录,每个事件带从 1 递增的 event_id;客户端断开后生成继续,GET 带 stream=true 与 last_event_id 从下一个事件继续读取。步骤以 index 对应,引用在其所在文本之后以 {type:"text_annotation_delta",annotations} 增量输出,音频增量为 {type:"audio",data,mime_type,sample_rate,channels}。10 秒无语义事件时发送 : ping,上游错误或缺失终态发送 error 事件并结束;客户端断开会取消上游生成。流开始前使用 Gemini HTTP 错误对象。

GET /v1beta/interactions/{id} 返回创建时的完整 interaction;include_input=true 时 steps 先列出请求输入,字符串与连续的内容块合并为 user_input 步骤;stream=true 时,background:true 创建的 interaction 从其事件记录输出:生成进行中时跟随到 interaction.completed 或 error,结束后输出完整记录;其他 interaction 按创建流的事件格式重放保存的内容。两种输出的每个事件都带递增的 event_id,查询参数 last_event_id 从其后的事件继续,不是正整数时返回 400 INVALID_ARGUMENT。POST /v1beta/interactions/{id}/cancel 返回该 interaction 的终态对象。DELETE /v1beta/interactions/{id} 返回 {},之后检索返回 404 NOT_FOUND,作为 previous_interaction_id 或 Responses 的 previous_response_id 返回 400。/v1 前缀行为相同。

Embeddings

POST /v1/embeddings 请求字段为 model、input,可选 dimensions、encoding_format。input 是字符串或字符串数组,token 数组与空数组返回 400;dimensions 为正整数,写入每条请求的 outputDimensionality;encoding_format 为 float(默认)或 base64,base64 为小端 float32。响应为 {"object":"list","data":[{"object":"embedding","index":0,"embedding":[...]}],"model":"<MODEL>","usage":{"prompt_tokens":N,"total_tokens":N}}。

:embedContent 接受 content、taskType、title、outputDimensionality,返回 {"embedding":{"values":[...]},"usageMetadata"?:{"promptTokenCount"}}。:batchEmbedContents 接受 requests[],每项字段相同并可带与路径一致的 model,返回 {"embeddings":[...],"usageMetadata"?:{"promptTokenCount"}};promptTokenCount 为上游 tokenCount,上游没有时省略。字段同时接受 snake_case;缺 content 或 model 与路径不一致时返回 400 INVALID_ARGUMENT。

三个端点都经 Build 通道调用上游 batchEmbedContents,超过 100 条时按顺序分批并合并结果,上游 tokenCount 计为输入 token。Build 未启用或没有可调用账户时返回 404 model_not_found / NOT_FOUND。

Gemini GenerateContent

POST /v1beta/models/{model}:generateContent、:streamGenerateContent 与 :countTokens 接受:

{
  "contents": [{"role":"user","parts":[{"text":"Hello"}]}],
  "systemInstruction": {"role":"user","parts":[{"text":"Be concise"}]},
  "generationConfig": {},
  "tools": [],
  "toolConfig": {},
  "safetySettings": [{"category":"HARM_CATEGORY_HARASSMENT","threshold":"BLOCK_ONLY_HIGH"}]
}

请求体各层消息字段同时接受 proto 字段名与 lowerCamelCase 名,例如 system_instruction、generation_config.response_mime_type、tools[].function_declarations、tool_config.function_calling_config 和 function_call;同一层两种写法并存时使用驼峰字段。functionCall.args、functionResponse.response、parameters、parametersJsonSchema、responseSchema、responseJsonSchema 与 partMetadata 的取值按原样使用,其中的键名不转换。

Content 字段为 role 与 parts。Part oneof:

Part 字段
text/thought text、可选 thought、thoughtSignature
inline data inlineData:{mimeType,data,displayName?}
file data fileData:{mimeType?,fileUri,displayName}
function call functionCall:{id,name,args}
function response functionResponse:{id,name,response}
server tool call toolCall:{id?,toolType,toolName?,args?}
server tool response toolResponse:{id?,toolType?,response?}
executable code executableCode:{language,code}
code result codeExecutionResult:{outcome,output,error}

服务端工具步骤的 toolType 为 GOOGLE_SEARCH_WEB、URL_CONTEXT、GOOGLE_MAPS、MEDIA_PROCESSING 或 MCP 调用的 CUSTOM;MCP 调用的 toolName 为 <服务器名>:<工具名>,MCP 结果的 response.call_tool_result_json 为 MCP CallToolResult 的 JSON 文本。媒体 Part 可带 mediaResolution:{level},level 为 MEDIA_RESOLUTION_LOW、MEDIA_RESOLUTION_MEDIUM、MEDIA_RESOLUTION_HIGH 或 MEDIA_RESOLUTION_ULTRA_HIGH;各 Part 分辨率不同或与 generationConfig.mediaResolution 不同时请求经 Build 通道发送,Playground 通道使用所有 Part 共同的分辨率。inlineData.displayName 与 fileData.displayName 作为附件文件名发送,代码执行按该文件名读取附件。

不含数据字段且没有 thoughtSignature 的 Part 不发送;同一 Part 含多个数据字段时返回 400 INVALID_ARGUMENT。fileData.fileUri 为 YouTube 链接时作为外部视频,为本服务 /upload/v1beta/files 返回的文件 URI 或 /v1/files 文件 ID 时作为文件引用,为其他 http(s) URL 时由服务下载为内联媒体;其他 Gemini Files API URI 不下载。外部 URL 在同一请求内只下载一次,上限 512 MiB,MIME 依次取响应 Content-Type、mimeType 与内容识别;主机或任一重定向目标解析到本机、私网、链路本地、组播或未指定地址时不连接,按下载失败处理;下载失败返回带 URL 与原因的 400 INVALID_ARGUMENT。:countTokens 同样先下载外部 URL 再计数。

视频 Part 可设置 mediaProcessing 为 STATIC、AGENTIC 或 MEDIA_PROCESSING_UNSPECIFIED。省略时沿用模型默认处理方式。AGENTIC 使用模型目录的 agentic_video 能力,并返回 toolType:"MEDIA_PROCESSING" 的服务端 toolCall 与 toolResponse;调用标识与 thoughtSignature 随完整模型 Part 一起用于下一轮历史。

静态视频的 videoMetadata 可设置 startOffset、endOffset 与 fps,与该 Part 的视频附件一起参与生成及 token 计数。offset 为非负秒数 Duration 字符串,支持最多九位小数,例如 "2.5s";显式 "0s" 保留起点,终点须晚于起点。FPS 范围为 (0,24],静态参数与 AGENTIC 互斥。例如:

{
  "fileData": {"mimeType":"video/*","fileUri":"https://www.youtube.com/watch?v=<VIDEO_ID>"},
  "mediaProcessing": "STATIC",
  "videoMetadata": {"startOffset":"2s","endOffset":"4s","fps":0.5}
}

这些参数与媒体处理历史适用于上游使用 GenerateContent 的模型;使用原生 CreateInteractionStream 或 CreateInteraction 的模型收到这些参数时返回参数错误。

generationConfig 全字段:

类别 字段
sampling temperature、topP、topK、frequencyPenalty、presencePenalty、seed
media mediaResolution:MEDIA_RESOLUTION_LOW、MEDIA_RESOLUTION_MEDIUM、MEDIA_RESOLUTION_HIGH
output limits candidateCount、maxOutputTokens、stopSequences
log probabilities responseLogprobs、logprobs
structured output responseMimeType、responseSchema、responseJsonSchema、responseFormat.text
modalities responseModalities
image imageConfig:{aspectRatio,imageSize}、responseFormat.image
audio responseFormat.audio:{mimeType?,sampleRate?,bitRate?,delivery?}
thinking thinkingConfig:{thinkingBudget,thinkingLevel,includeThoughts}
transcription audioTranscriptionConfig:{languageCodes,customVocabulary,adaptationPhrases,wordTimestamp,diarization,languageAuto,languageHints,mode}
civic answers enableEnhancedCivicAnswers
speech speechConfig

thinkingConfig.includeThoughts 为 true 时输出 thought:true 的思考 Part,省略或为 false 时不输出思考正文;思考签名照常随 Part 返回,thoughtsTokenCount 照常统计。thinkingConfig.thinkingBudget 为 -1(动态思考)时使用模型默认思考设置,与模型名后缀 (-1) 相同。

responseFormat 取单个对象 {text?,image?,audio?} 或这类对象的数组。text.mimeType 取 application/json、text/plain 或 APPLICATION_JSON、TEXT_PLAIN,与 text.schema 一起按 responseMimeType 与 responseJsonSchema 发送;image.aspectRatio 取 ASPECT_RATIO_SIXTEEN_BY_NINE 这类枚举名或 16:9,image.imageSize 取 IMAGE_SIZE_FIVE_TWELVE、IMAGE_SIZE_ONE_K、IMAGE_SIZE_TWO_K、IMAGE_SIZE_FOUR_K 或 512、1K、2K、4K,按 imageConfig 发送;audio 决定输出音频的编码。image.mimeType 只有 IMAGE_JPEG,与上游图片输出相同。image.delivery 或 audio.delivery 为 URI 时,对应的输出图片或音频上传为 Files API 文件,候选 Part 为 {"fileData":{"mimeType","fileUri":"https://generativelanguage.googleapis.com/v1beta/files/<id>"}},文件按 GET /v1beta/files/{id} 查询、按 :download 下载,也可直接作为后续请求的 fileData.fileUri;音频以 URI 交付时流式请求同样在结束时输出一个合并的音频;其他取值内联返回。上传失败时以该错误结束生成。

responseJsonSchema 与 responseFormat.text.schema 原样作为 JSON Schema 使用,additionalProperties、prefixItems、propertyNames、数值枚举与 type:"null" 都保留;含 Playground Schema 无法表达的约束时请求经 Build 通道以 responseFormat.text 发送。responseSchema 按 OpenAPI Schema 子集处理。

responseFormat.audio.mimeType 取 AUDIO_WAV、AUDIO_L16、AUDIO_MP3、AUDIO_OGG_OPUS、AUDIO_ALAW、AUDIO_MULAW,省略时为 AUDIO_WAV,其他取值返回 400 INVALID_ARGUMENT。非流式输出把全部音频合并为一个 inlineData;WAV 为 RIFF WAVE,其他编码的 MIME 带 rate 与 channels 参数,例如 audio/mp3;rate=32000;channels=1。sampleRate 与上游采样率不同时重采样,bitRate 用于 MP3 与 Opus。流式请求中 AUDIO_L16、AUDIO_ALAW、AUDIO_MULAW 在采样率不变时逐块输出,其他格式在结束时输出一个合并的音频块。

audioTranscriptionConfig 的 wordTimestamp 输出逐词时间,diarization 输出说话人,mode:"SMART" 使用智能转录,languageAuto 与 languageHints.languageCodes 设置语言识别。enableEnhancedCivicAnswers 经 Build 通道发送;Playground 通道的非图像请求固定开启该选项。

candidateCount 取省略、0 或 1 至 8;大于 1 时每个候选单独生成,候选 0 沿用请求 ID,候选 i 的请求 ID 为 <id>-<i>,带 seed 时使用 seed+i;任一候选失败时整个请求返回该错误,:streamGenerateContent 在首个候选就绪后开始输出,其余候选的启动错误以流内错误返回;用量的 promptTokenCount 与 cachedContentTokenCount 按一次计,候选输出与思考 token 为各候选之和。frequencyPenalty、presencePenalty、responseLogprobs 与 logprobs 接受任意值,不发送上游,响应不含 logprobs。

responseModalities 接受 TEXT、IMAGE、AUDIO、VIDEO 与 MODALITY_UNSPECIFIED,MODALITY_UNSPECIFIED 不发送,只含该值时按省略处理,VIDEO 按 Omni Interaction 的视频输出格式处理;请求的模态先与模型可生成的模态取交集:TTS 与音乐模型为 AUDIO,图像模型为 IMAGE、TEXT,其他模型为 TEXT;没有交集时保持原样,此时 AUDIO 与其他模态同时出现返回参数错误。图像模型省略模态时发送 [IMAGE,TEXT],仅请求 IMAGE 时发送 [IMAGE];imageConfig 保留显式宽高比与尺寸,支持输出分辨率的模型省略图片配置时使用 1K。

speechConfig.voiceConfig 与 multiSpeakerVoiceConfig 互斥;单声音必须提供 prebuiltVoiceConfig.voiceName,每个多说话人条目必须提供非空 speaker 与 voiceConfig.prebuiltVoiceConfig.voiceName;multiSpeakerVoiceConfig.mode 可选 VERBATIM 或 CONVERSATIONAL。文本 part 的 speechMetadata(或 speech_metadata){speaker,style} 写入 Part field 41。能力码 85 的模型把未带 speaker 的文本按行拆分,以配置中说话人名加冒号开头的行开始新分段,续行并入上一分段,首个说话人行之前的文本不发送;没有匹配行的文本原样发送。旧 TTS 模型把 speechMetadata 写回 speaker: 台词 前缀与 style\n\n 说明段落。audioTranscriptionConfig.mode:"SMART" 与 wordTimestamp 或 diarization 互斥;language code detect 归一为空自动检测。

单声音 speech config:

{"voiceConfig":{"prebuiltVoiceConfig":{"voiceName":"Kore"}}}

多说话人:

{
  "multiSpeakerVoiceConfig": {
    "speakerVoiceConfigs": [{
      "speaker": "Speaker A",
      "voiceConfig": {"prebuiltVoiceConfig":{"voiceName":"Kore"}}
    }]
  }
}

tool group 字段:

工具 字段
functions functionDeclarations:[{name,description,parameters,parametersJsonSchema,response,responseJsonSchema}]
search googleSearch 或 googleSearchRetrieval
URL urlContext
code codeExecution
maps googleMaps:{enableWidget?}
image search imageSearch
computer use computerUse:{environment,excludedPredefinedFunctions?,disabledSafetyPolicies?,enablePromptInjectionDetection?}
MCP mcpServers:[{name,streamableHttpTransport:{url,headers?,timeout?,sseReadTimeout?,terminateOnClose?}}]
file search fileSearch:{fileSearchStoreNames,metadataFilter?,topK?}

response 与 responseJsonSchema 描述函数返回值,经 Build 通道以 responseJsonSchema 发送,Playground 通道没有对应字段。googleSearch.searchTypes 可以包含 webSearch 与 imageSearch 空对象;未提供或两项均未启用时默认 web search。googleMaps.enableWidget 为 true 时 groundingMetadata 带 googleMapsWidgetContextToken;toolConfig.retrievalConfig:{latLng:{latitude,longitude},languageCode} 为地图与搜索提供位置与语言。computerUse.environment 为 ENVIRONMENT_BROWSER 或省略时两个通道都可使用,其他环境、disabledSafetyPolicies 与 enablePromptInjectionDetection 经 Build 通道发送。MCP 服务器由上游连接并调用,toolConfig.includeServerSideToolInvocations:true 时响应带 toolType:"CUSTOM" 的调用与结果 Part。fileSearch 按原样经 Build 通道发送,上游拒绝时返回上游错误。timeRangeFilter.startTime/endTime 使用 RFC 3339 Nano。googleSearchRetrieval 映射为 web search,dynamicRetrievalConfig 不发送上游。tool choice 位于 toolConfig.functionCallingConfig:{mode,allowedFunctionNames},接受 AUTO、NONE、ANY、VALIDATED 与按 AUTO 处理的 MODE_UNSPECIFIED;allowedFunctionNames 使用已声明函数的子集。

:countTokens 也接受把生成请求放在 generateContentRequest(或 generate_content_request)中的包装形式,按其中的 contents、systemInstruction 与 tools 计数。

systemInstruction 的各文本 Part 作为系统指令的独立分段发送,图片与文件 Part 移到首个 user 轮开头,函数调用与函数结果各以 Gemini API JSON 文本(如 {"functionCall":{"args":{"city":"Paris"},"name":"get_weather"}})作为一个分段。

serviceTier 取 standard、flex、priority,store:false 与 labels 经 Build 通道发送;safetySettings 中的 HARM_CATEGORY_JAILBREAK 同样经 Build 通道发送。Build 通道响应的 usageMetadata.serviceTier 为上游实际使用的等级。

cachedContent 引用本服务 cachedContents 接口创建的显式缓存:缓存的系统指令、内容与工具排在请求之前,请求未设置工具调用方式时沿用缓存的 toolConfig。缓存不存在或已过期时生成、计数与 Interactions 请求返回 404 NOT_FOUND,不发送上游。

:countTokens 返回:

{"totalTokens": 20, "systemInstructionsTokens": {"partTokens": [4]}, "contentTokens": [{"partTokens": [2], "roleTokens": 1}, {"partTokens": [1], "roleTokens": 1}, {"partTokens": [7, 3], "roleTokens": 1}], "promptTokensDetails": [{"modality":"TEXT","tokenCount":20}]}

systemInstructionsTokens.partTokens 为系统指令各 Part 的 token 数,没有系统指令时为 {};contentTokens 按请求顺序列出各 content 的 partTokens 与 roleTokens;带工具时 toolTokens 按请求顺序列出各工具,函数声明工具为 {functionDeclarationTokens},其他工具为 {}。promptTokensDetails 为上游给出的模态细分。引用显式缓存时,systemInstructionsTokens、contentTokens 与 toolTokens 只含请求自身的内容,cachedContentTokenCount 与 cacheTokensDetails 为缓存部分的 token 数与模态细分,totalTokens 与 promptTokensDetails 包含缓存部分。Playground 计数只有请求级分辨率,Part 分辨率不同的计数请求与 Playground 目录没有的模型经 Build 通道的 countTokens 计数。

显式缓存

方法 路径 结果
POST /v1beta/cachedContents 创建,返回 CachedContent
GET /v1beta/cachedContents 按创建时间从新到旧分页列出,pageSize 默认 10、最大 1000
GET /v1beta/cachedContents/{id} 返回 CachedContent
PATCH /v1beta/cachedContents/{id} 按 updateMask 更新过期时间与显示名称
DELETE /v1beta/cachedContents/{id} 删除,返回 {}

创建请求为 {model,displayName?,systemInstruction?,contents?,tools?,toolConfig?,ttl?|expireTime?},ttl 为正的 Duration 字符串,例如 "600s",两者都省略时存活 1 小时;创建与更新请求同时给出 ttl 与 expireTime 时返回 400 INVALID_ARGUMENT。CachedContent 为 {name:"cachedContents/<id>",model,displayName?,createTime,updateTime,expireTime,usageMetadata:{totalTokenCount}},totalTokenCount 为创建时对缓存内容的计数。PATCH 的查询参数 updateMask 为逗号分隔的字段名,只更新其中列出的字段:ttl、expireTime(也接受 expire_time、expiration)更新过期时间,displayName(也接受 display_name)更新显示名称;列出过期时间而请求没有 ttl 或 expireTime、或列出其他字段时返回 400 INVALID_ARGUMENT;省略 updateMask 时更新请求中出现的这些字段,两者都没有时返回 400 INVALID_ARGUMENT。缓存保存在服务进程内存中,重启后失效;生成请求每次发送缓存的完整内容,promptTokenCount 包含缓存部分;usageMetadata.cachedContentTokenCount 与 cacheTokensDetails、Interactions 的 usage.total_cached_tokens 与 cached_tokens_by_modality 为缓存的 token 数与模态细分,上游隐式缓存命中更多时取上游的值。expireTime 早于当前时间的缓存创建或更新后即过期;读取、更新与删除未知或已过期的资源名返回 403 PERMISSION_DENIED(CachedContent not found (or permission denied)),分页列表的 pageToken 取上一页的 nextPageToken。

非流式生成响应:

{
  "candidates": [{
    "content": {"parts":[],"role":"model"},
    "finishReason": "STOP",
    "index": 0,
    "finishMessage": "...",
    "citationMetadata": {},
    "groundingMetadata": {}
  }],
  "usageMetadata": {
    "promptTokenCount": 10,
    "candidatesTokenCount": 20,
    "totalTokenCount": 35,
    "thoughtsTokenCount": 5
  },
  "modelVersion": "gemini-provider-id",
  "responseId": "request-id",
  "turnToken": "v1_..."
}

modelVersion 为生成所用的模型:Build 通道取上游响应的 modelVersion,以 gemini-flash-latest 等别名请求时为别名当前指向的模型;Playground 通道为目录模型 ID。responseId 为上游响应的 responseId:Build 通道取响应的 responseId,Playground 通道取 turnToken 的 field 2,上游没有给出时为本服务请求 ID。turnToken 为上游响应的轮次令牌,两个通道都输出;Build 通道非流式响应另带上游的 debugInfo,候选结束时带上游的 detailedFinishReason。finishReason 使用 Gemini API 的枚举名,包括 MISSING_THOUGHT_SIGNATURE、MALFORMED_RESPONSE 与 CONTINUATION;Build 通道返回的其他枚举名原样输出,Playground 未知编号输出 OTHER。finishMessage 为上游给出的结束说明,例如上游过滤生成结果时的原因;没有上游说明且结束原因为 OTHER 时写入 AI Studio finish reason <编号>。候选带 safetyRatings:[{category,probability,blocked?}],输入被拦截时 promptFeedback 同样带 safetyRatings。候选没有输出 Part 时省略 content。candidateCount 大于 1 时,candidates 按 index 0 到 n-1 排列,各自携带 finishReason。:streamGenerateContent 按到达顺序输出各候选的增量块,每块只含一个带 index 的候选;最后一块列出全部候选,各自带该候选上游结束帧中的 content、finishReason 与该候选的 groundingMetadata、citationMetadata,并带合计的 usageMetadata。非流式候选同时返回 groundingMetadata 与上游引用的 citationMetadata。

输出 Part 使用与输入相同的 text、thought、thoughtSignature、inlineData、fileData、functionCall、toolCall、toolResponse、executableCode、codeExecutionResult。转录文本可以携带:

{
  "text": "Hello.",
  "audioTranscription": {
    "text": "Hello.",
    "speakerLabel": "spk:0",
    "words": [{"word":"Hello.","startOffset":"0.200s","endOffset":"0.800s"}]
  }
}

groundingMetadata 字段为 searchEntryPoint、groundingChunks、groundingSupports、retrievalMetadata、webSearchQueries、googleMapsWidgetContextToken。searchEntryPoint 包含 renderedContent、sdkBlob;groundingChunks 元素的 oneof 为 web:{uri,title,domain?,siteName?,searchResultMapping?}、image:{sourceUri,imageUri,title,domain}、retrievedContext:{uri,title,text} 或 maps:{uri,title,text,placeId,placeAnswerSources?};groundingSupports 元素包含 segment:{partIndex,startIndex,endIndex,text}(值为 0 的下标省略)、groundingChunkIndices、可选 confidenceScores 与图片搜索结果对应的 renderedParts;Build 通道上游给出的 chunk origin、referenceId 与 support origin 原样输出;图片搜索的检索词写入 imageSearchQueries;retrievalMetadata 包含 googleSearchDynamicRetrievalScore。citationMetadata.citationSources 的元素包含 uri、title、startIndex、endIndex 与可选 license。URL Context 读取的网址写入候选的 urlContextMetadata.urlMetadata[],元素为 retrievedUrl 与 urlRetrievalStatus,Build 通道取自上游 urlContextMetadata,Playground 通道取自 URL_CONTEXT 工具结果;groundingMetadata 只在有搜索、检索或地图依据时输出。

非流式结果合并相邻、同类且无签名边界的正文或思考片段。工具、媒体与带转录元数据的 Part 保持独立;独立签名附着于前一未签名 Part,缺少可附着内容时用 {"text":"","thoughtSignature":"..."} 承载。

:streamGenerateContent 带 alt=sse 时使用 SSE;不带时与官方 REST 一样返回 application/json 的 JSON 数组,元素之间以 \r\n,\r\n 分隔,不写保活行。每个内容事件发送一个部分 GenerateContentResponse,包含 responseId、modelVersion、turnToken、该事件所在上游帧的累计 usageMetadata 与一个带 content 的 candidate Part;上游带结束原因的那一帧中的内容 Part(包括只带签名的空文本 Part)不单独成块,与 finishReason、可选 finishMessage、groundingMetadata、citationMetadata 和最终 usageMetadata 一起放在最后一帧。响应头后的错误为 SSE 帧 data: {"error":{"code","message","status"}} 或 JSON 数组中的同形元素。

Files、Transcribe 与媒体

POST /v1/files 接受 multipart file 与可选 purpose,两者可以按任意顺序到达。文件上限 512 MiB,请求额外允许 1 MiB multipart overhead;普通 scalar part 上限 64 KiB。filename 与非空 file 必需;purpose 省略或为空时为 user_data。Content-Type 为空、无效、不含子类型或为 application/octet-stream 时从文件前缀检测不带参数的 MIME,Ogg 前缀记为 audio/ogg,WAV 前缀记为 audio/wav;前缀无法识别时依次按 FLAC 头、MPEG 音频帧头与扩展名(flac、mp3、mp4、mpeg、mpga、m4a、ogg、wav、webm,其余扩展名查系统 MIME 表)确定。/v1/files 与 /upload/v1beta/files 收到的 GIF 按首帧画在逻辑画布尺寸的白底上,编码为质量 92 的 JPEG 后保存,文件名不变,MIME 为 image/jpeg。

File object:

{
  "id": "file_...",
  "object": "file",
  "bytes": 1234,
  "created_at": 0,
  "filename": "document.pdf",
  "purpose": "assistants",
  "status": "processed"
}

POST /v1/files 与 GET /v1/files/{id} 返回该对象。GET /v1/files/{id}/content 返回原始 body,并设置 Content-Type、attachment Content-Disposition 和已知时的 Content-Length。DELETE /v1/files/{id} 返回:

{"id":"file_...","object":"file","deleted":true}

未知文件返回 404 file_not_found,超过大小限制返回 413 file_too_large。Drive 账户绑定与跨账户复制见“Drive 上传与文件 Part”节。

GET /v1/files 按创建时间从新到旧返回 {"object":"list","data":[File object],"first_id","last_id","has_more"}。order 为 asc 或 desc(默认),after 为上一页最后一个文件 ID,limit 为 1–10000、默认 10000,purpose 只返回该用途的文件。未知的 after 返回空页;limit 越界或 order 无效返回 400。

请求带 anthropic-version,或 anthropic-beta 含 files-api- 时,同一组路径按 Anthropic Files API 返回。文件对象为 {"id","type":"file","filename","mime_type","size_bytes","created_at":"<RFC 3339>","downloadable":true}。上传只需 file 段,用途记为 user_data。删除返回 {"id","type":"file_deleted"}。错误为 Anthropic 错误对象,未知文件为 404 not_found_error。列表按创建时间从新到旧返回 {"data","next_page","first_id","last_id","has_more"}:limit 为 1–1000、默认 20;page 取上一页的 next_page(形如 page_<文件 ID>),也接受 after_id 与 before_id;ids(也接受 ids[] 或逗号分隔)只返回列出的文件且不分页;带 scope_id 时返回空列表。文件 ID 与 OpenAI 文件相同,可用于 Messages 的 {"type":"file","file_id"} source。

POST /upload/v1beta/files 按 X-Goog-Upload-Protocol 或 uploadType 接受 resumable 与 multipart。可续传上传先发送 X-Goog-Upload-Command: start,请求体为可选的 {file:{name?,displayName?,mimeType?}}(接受 display_name 与单引号字符串),X-Goog-Upload-Header-Content-Type 声明类型,响应头 X-Goog-Upload-URL 给出上传地址;分块以 X-Goog-Upload-Command: upload 或 upload, finalize 与 X-Goog-Upload-Offset 发往该地址,偏移与已接收字节数不符时返回 400,query 返回 X-Goog-Upload-Size-Received,cancel 结束上传;地址闲置 1 小时后失效。multipart 请求体由可省略的 JSON 元数据段与文件段组成,multipart/related 与 multipart/form-data 均可。显示名依次取 displayName、文件段的 filename 与 X-Goog-Upload-File-Name,均缺失时为 file;类型依次取文件段 Content-Type、X-Goog-Upload-Header-Content-Type、mimeType,均缺失或为 application/octet-stream 时按内容识别。完成时返回 {file:File} 与 X-Goog-Upload-Status: final。

File 为 {name:"files/<id>",displayName,mimeType,sizeBytes,createTime,updateTime,uri,state:"ACTIVE",source:"UPLOADED",sha256Hash?,videoMetadata?},uri 为 https://generativelanguage.googleapis.com/v1beta/files/<id>,可直接用作 fileData.fileUri 与 Interactions 媒体内容的 uri。sha256Hash 为上传时计算的文件内容 SHA-256 的 Base64;MP4 与 QuickTime 视频带 videoMetadata:{videoDuration},例如 "4s"。GET /v1beta/files/{id} 返回 File,DELETE /v1beta/files/{id} 返回 {},未知文件返回 404 NOT_FOUND。GET /v1beta/files 按创建时间从新到旧返回 {files,nextPageToken?},pageSize 默认 10、最大 100,pageToken 取上一页的 nextPageToken。Gemini 文件与 /v1/files 共用存储、512 MiB 上限与 Drive 账户绑定。

元数据的 file.name 指定文件 ID,形如 files/<id>,<id> 为 1–40 个小写字母、数字或 -,首尾不能为 -;格式无效返回 400 INVALID_ARGUMENT。ID 已属于另一个文件时,multipart 上传与可续传上传的完成请求返回 409 ALREADY_EXISTS,消息为 <id> already exists.,可续传上传的开始请求照常返回上传地址。未指定时由服务分配 ID,分配的 ID 长于 40 个字符。指定的 ID 用于读取、下载、删除与 fileData.fileUri。

POST /v1/audio/transcriptions multipart 字段:

字段 取值与处理
file 必需非空;audio/*、video/mp4、video/webm;最大 512 MiB;分段 Content-Type 按 POST /v1/files 的规则识别
model 默认 gemini-3.5-transcribe;接受可选 models/ 前缀
response_format json、text、srt、verbose_json、vtt、diarized_json;默认 json
language 语言码;detect 与 auto 映射为空自动检测
temperature 0..2
custom_vocabulary 可重复文本字段或 JSON string array
word_timestamps、speaker_labels、smart_transcription true 或 false
timestamp_granularities[] word 或 segment,可重复;其他取值返回 400 invalid_request
stream true 时以 SSE 返回
prompt 当前 wire 无对应字段,忽略

smart_transcription=true 与显式 true 的 word timestamps 或 speaker labels 互斥,custom vocabulary 与 word timestamps 互斥,冲突组合返回 400 invalid_request。每次账户尝试创建临时 Drive file,生成结束、失败或取消后在同账户清理。

text 格式返回 text/plain; charset=utf-8。srt 与 vtt 按 segments 每段生成一条字幕,分别返回 text/plain; charset=utf-8 与 text/vtt; charset=utf-8。srt、vtt、verbose_json 与 diarized_json 在未设置 word_timestamps、smart_transcription 不为 true 且没有 custom_vocabulary 时请求词级时间戳;diarized_json 在未设置 speaker_labels 且 smart_transcription 不为 true 时请求说话人。json 返回 {"text","usage"?},usage 为 {"type":"tokens","input_tokens","output_tokens","total_tokens","input_token_details"?:{"audio_tokens","text_tokens"}},上游没有用量时省略。verbose_json:

{
  "task": "transcribe",
  "language": "en",
  "duration": 1.25,
  "text": "Hello",
  "segments": [{"id":0,"seek":0,"start":0,"end":1.25,"text":"Hello","tokens":[],"temperature":0,"avg_logprob":0,"compression_ratio":0,"no_speech_prob":0,"speaker":"Speaker 1"}],
  "words": [{"word":"Hello","start":0,"end":1.25,"speaker":"Speaker 1"}],
  "usage": {"type":"duration","seconds":1.25}
}

language 是规范化后的请求语言;detect / auto 时为空并省略。segments 来自 response Part field 23,speaker 在上游给出说话人时出现。words 只在 timestamp_granularities[] 含 word 或 word_timestamps=true 时返回,单词数与 timestamp span 数一致时生成。duration 对 WAV 输入取文件头的时长,其他格式取最后一个词的结束时间与上游 AUDIO 输入 token 数除以 32 两者中的较大值。diarized_json 为 {"task","duration","text","segments":[{"type":"transcript.text.segment","id":"seg_0","start","end","text","speaker"}],"usage"?},usage 与 json 相同。

stream=true 时,上游每段转录正文写出一个 {"type":"transcript.text.delta","delta"} 事件;diarized_json 改为每个分段写出一个 transcript.text.segment 对象;结束时写出 {"type":"transcript.text.done","text","usage"?}。事件流开始前出错按非流式返回错误,开始后出错写出 {"error":{...}} 数据帧。流式开始输出后不再切换账户重试。

POST /v1/audio/translations 接受 file、model、prompt、response_format(json、text、srt、verbose_json、vtt,默认 json)与 temperature(0–2)。服务先按转录规则转录音频,再用文本模型把转录译为英文:model 是转录模型或省略时(默认 gemini-3.5-transcribe),由 gemini-flash-latest 翻译;model 是其他模型时,由 gemini-3.5-transcribe 转录、该模型翻译。srt、vtt 与 verbose_json 请求词级时间戳并逐段翻译,保留每段起止时间;json 与 text 整段翻译。翻译请求用 JSON Schema 要求输出与分段数相同的字符串数组;prompt 作为译文的上下文与风格说明,temperature 作用于翻译。json 返回 {"text"};verbose_json 返回 {"task":"translate","language":"english","duration","text","segments","usage":{"type":"duration","seconds"}},不含 words。转录为空时不调用翻译;译文段数与转录不一致时返回 502 upstream_error。

POST /v1/images/generations:

字段 取值与处理
model 省略时取公开目录顺序中支持 generateContent 的首个 image_route 模型
prompt 必需
n 默认 1,范围 1–10
size auto 或 WIDTHxHEIGHT,为输出图片尺寸
quality auto、low/standard=1K、medium/hd=2K、high/xhigh/max=4K
output_format png(默认)、jpeg(也接受 jpg)或 webp
output_compression 0–100,默认 100,为 JPEG 质量
response_format url 返回 data URL;省略或其他值返回 Base64 b64_json
stream boolean
safety_identifier、user 响应回传 safety_identifier,为空时回传 user
background、moderation、style、partial_images 没有上游对应项,不影响请求
  • 每张图片单独生成,按序合并到 data
  • size 取模型 image_aspect_ratios 中比值最接近的宽高比,目录未列出时在 1:1、2:3、3:2、3:4、4:3、4:5、5:4、9:16、16:9、21:9 中选择;分辨率取 image_output_resolutions 中能覆盖 size 的最小一档(按与 size 等面积的正方形边长比较,512、1K、2K、4K 依次为 512、1024、2048、4096),超过全部档位时取最大一档
  • 模型列出 image_output_resolutions 时,quality 取其中最接近的分辨率;它高于 size 对应的分辨率时按 quality 生成
  • 生成的图片从中央取与 size 同宽高比的最大区域,缩放为 size;生成的图片任一边小于 size、或 size 为 auto 与省略时保持生成尺寸
  • 输出按 output_format 编码,WebP 为无损编码
  • stream:true 时以 SSE 返回,每张图片一个 image_generation.completed 事件

响应为 {"created":<UNIX>,"background":"opaque","data":[{"b64_json":"...","revised_prompt":"..."}],"output_format","quality","size","usage","safety_identifier"?},response_format 为 url 时 data 项为 {"url":"data:<MIME>;base64,...","revised_prompt":"..."}。size 为输出图片的实际宽高;quality 为请求的 low、medium、high、xhigh 或 max,其余按生成分辨率记为 low(512、1K)、medium(2K)或 high(4K);usage 为各张图片上游用量的合计 {input_tokens,input_tokens_details:{text_tokens,image_tokens},output_tokens,output_tokens_details:{text_tokens,image_tokens},total_tokens},图片 token 取上游按模态细分的 IMAGE 项。revised_prompt 只在上游同时返回文本时出现。任一张未返回最终图片时返回 HTTP 502 upstream_error,结束原因不是正常结束时写入错误消息,例如 image_recitation;其他生成错误按该错误返回,不返回部分结果。流式事件为 {"type":"image_generation.completed","b64_json","usage","background","created_at","output_format","quality","safety_identifier"?,"size"},size 为该张图片的实际宽高,usage 为该张图片的上游用量,在全部图片生成后依次发送,不发送 partial image 事件;生成失败时按非流式返回错误。

POST /v1/images/edits 接受 multipart 的 image 或 image[](一个或多个文件)、prompt、mask,以及与图片生成相同的 model、n、size、quality、output_format、output_compression、response_format、stream、safety_identifier、user,响应格式也相同,流式事件类型为 image_edit.completed。输入图片按顺序作为参考图写在提示词之前;分段 Content-Type 缺失或为 application/octet-stream 时按内容识别,GIF 取首帧转为 PNG。mask 中完全透明的像素转为白色、其余为黑色,生成 PNG 遮罩,放在输入图片之后,并附说明“白色为编辑区域、黑色保持不变”。background、input_fidelity、partial_images 没有上游对应项,不影响请求。缺少图片或提示词、遮罩无法解码时返回 400。

POST /v1/audio/speech:

字段 取值与处理
model、input 必需
voice 默认 Zephyr
response_format 默认 mp3;支持 mp3、opus、aac、flac、wav、pcm
speed 0.25..4.0
instructions 文本 part 的 speechMetadata.style
stream_format audio(默认)返回音频文件;sse 以 SSE 返回;其他取值返回 400 invalid_request
  • speed 省略、0 或 1 为正常语速,其他值以 Speak at <speed> times the normal speaking rate. 追加到语音风格
  • 旧 TTS 模型以 instructions + "\n\n" + input 形成提示

stream_format:"sse" 时,pcm 按上游音频分块逐个写出 {"type":"speech.audio.delta","audio":"<Base64>"},其他格式在生成结束后编码整段音频并写出一个 speech.audio.delta;最后写出 {"type":"speech.audio.done","usage":{"input_tokens","output_tokens","total_tokens"}}。生成出错时写出 {"error":{...}} 数据帧。

上游返回 MP3(Lyria 等)时先解码为 PCM,mp3 原样返回上游数据。pcm 返回 PCM body 与采样参数;上游返回 PCM16 WAV 时先提取音频数据。wav 将 PCM 按有效 rate 与 channels 封装为 16-bit WAV;原生 WAV 保留对应音频格式,多个片段先合并 PCM 数据再封装。mp3 为 MPEG-1 Layer III 192 kbit/s CBR(audio/mpeg,32/44.1/48 kHz),opus 为 Ogg Opus(audio/opus),aac 为 ADTS AAC-LC(audio/aac,44.1/48 kHz),flac 为 16-bit FLAC(audio/flac)。响应设置 Content-Type 与 Content-Length。

旧 TTS 模型的语音请求按官网 wire 在首个文本前写入 ## Transcript:\n,AUDIO-only generation config 不写默认 maxOutputTokens;responseModalities 与 speechConfig 分别写入官网确认的槽位。

Imagen

Gemini POST /v1beta/models/{model}:predict 以 Imagen 模型生成图片,{model} 为实时目录中带 predict 方法的模型:

{
  "instances": [{"prompt": "a red apple"}],
  "parameters": {"sampleCount": 1, "aspectRatio": "1:1", "negativePrompt": "blur", "imageSize": "2K", "includeRaiReason": true}
}
字段 取值与处理
instances 一个或多个实例,prompt 为提示词;每个实例按同一组参数依次生成一次
sampleCount 图片数
aspectRatio 宽高比
negativePrompt 反向提示词
imageSize 输出分辨率
includeRaiReason 为 true 时返回被拦下图片的原因

响应 predictions[] 按 instances 顺序排列,每项为 bytesBase64Encoded 与 mimeType;某个实例生成出错时返回该错误。被安全策略拦下的图片在 includeRaiReason 为 true 时以 {"raiFilteredReason": "<上游给出的原因>"} 列出,否则省略;全部图片被拦下时响应为 {}。模型不在实时目录或没有 predict 方法时返回 404 NOT_FOUND,上游错误按 Gemini 错误体返回。

Video

OpenAI POST /v1/videos 接受 JSON 或 multipart:

字段 取值与处理
model 省略时取公开目录顺序中首个视频模型(generateContent 模型列出 video_output_resolutions)
prompt 有 input_reference 时可以为空,否则必需
seconds 整数字符串;默认 4;按模型选项取最接近值
size 1280x720、720x1280(默认)、1792x1024、1920x1080、1024x1792、1080x1920
input_reference JSON 中为 file ID/data URL;multipart 中为文件
  • input_reference 文件段的 Content-Type 缺失、无效或为 application/octet-stream 时按内容识别图片类型

OpenAI video object:

{
  "id": "operation-id",
  "object": "video",
  "model": "gemini-omni-1.1-flash",
  "status": "queued",
  "progress": 0,
  "created_at": 0,
  "size": "720x1280",
  "seconds": "4",
  "prompt": "lake at dawn",
  "completed_at": null,
  "expires_at": null,
  "error": null,
  "remixed_from_video_id": null
}

prompt 为创建任务时的提示词,completed_at 为结果视频登记时的 Unix 秒数,未完成时为 null;expires_at 与 remixed_from_video_id 为 null,error 在失败时为错误对象,其余为 null。GET /v1/videos/{id} 返回当前对象。完成时 status 为 completed、progress 为 100;服务重启前没有生成完成的任务按本地记录返回 status 为 failed、progress 为 100 的对象,并带 error:{"code":"video_not_found","message":"服务重启前任务没有生成完成"}。GET /v1/videos/{id}/content 接受省略或 variant=video,未完成时返回 409 video_not_ready;成功下载设置媒体 Content-Type、attachment; filename="video.mp4" 和已知的 Content-Length。

GET /v1/videos 从资源绑定列出视频,按创建时间从新到旧返回 {"object":"list","data":[video object],"first_id","last_id","has_more"}。order 为 asc 或 desc(默认),after 为上一页最后一个视频 ID,limit 为 0–100、默认 20。页内每个视频给出与 GET /v1/videos/{id} 相同的对象;读取任务状态失败时返回该错误。DELETE /v1/videos/{id} 先读取任务状态:已完成的删除 Drive 结果文件,并解除结果文件与任务的绑定;失败的只解除任务绑定;都返回 {"id","object":"video.deleted","deleted":true}。未结束的任务返回 409 video_not_ready。未知或已删除的视频在查询、下载与删除时都返回 404 video_not_found。

视频创建成功后按 operation ID 写入以下资源绑定:

{
  "kind": "video-operation",
  "created_at": "2026-01-01T00:00:00Z",
  "video": {
    "model": "gemini-omni-1.1-flash",
    "seconds": "4",
    "size": "720x1280",
    "prompt": "lake at dawn",
    "completed_at": 1767225900
  }
}

model、实际发送的 seconds、size、prompt、结果视频登记时间 completed_at 与 UTC created_at 随创建账户持久保存,后续查询从资源绑定恢复;生成服务或进程重新启动后,OpenAI POST 与 GET 仍返回相同字段。size 为宽高比与分辨率换成模型支持的值后实际生成的尺寸:360p 为 640x360 或 360x640,720p 为 1280x720 或 720x1280,1080p 为 1920x1080 或 1080x1920,4k 为 3840x2160 或 2160x3840。公开对象的 created_at 是绑定创建时间的 Unix 秒。

Gemini :predictLongRunning 请求:

{
  "instances": [{
    "prompt": "...",
    "image": {
      "inlineData": {"mimeType":"image/jpeg","data":"..."}
    }
  }],
  "parameters": {
    "numberOfVideos": 1,
    "sampleCount": 1,
    "aspectRatio": "16:9",
    "durationSeconds": 4,
    "resolution": "720p"
  }
}

instances 有一个或多个,每个实例至少有非空 prompt、image、lastFrame 或 referenceImages 之一;image 必须在 inlineData 与 fileData:{mimeType,fileUri} 中选择一个。numberOfVideos 为 0 时读取 sampleCount,两者均为 0 时默认 1,范围 1–4,为每个实例各生成这些视频;每个视频创建一个任务。durationSeconds 接受 JSON integer 或十进制字符串。duration、aspect ratio 与 resolution 省略时分别为 4、16:9、720p,并换成实时模型 video_durations_seconds、video_aspect_ratios、video_output_resolutions 中最接近的取值(时长按秒数、宽高比按比值对数、分辨率按像素高度,距离相同时取较大值);负数时长返回 400,模型列出对应选项时无法解析的宽高比与分辨率返回 400,未列出时原样发送。创建返回 {"name":"operations/<ID>"},多个视频时 <ID> 为各任务 ID 按实例顺序以 ~ 连接;中途创建失败时停止,已创建的任务照常返回,第一个即失败时返回该错误。Gemini operation 使用同一份持久元数据恢复创建账户;Gemini 响应只包含 name、done 与完成后的 response.generateVideoResponse.generatedSamples。

GET /v1beta/operations/{id} 与 GET /v1beta/models/{model}/operations/{id}:

{
  "name": "operations/<ID>",
  "done": true,
  "response": {
    "generateVideoResponse": {
      "generatedSamples": [{
        "video": {"uri":"http://<HOST>/v1beta/files/<FILE_ID>:download?alt=media","mimeType":"video/mp4"}
      }]
    }
  }
}

response 在全部任务 done 时出现,带 "@type":"type.googleapis.com/google.ai.generativelanguage.v1beta.PredictLongRunningResponse",generatedSamples 按创建顺序列出有产物的任务,uri 为各任务结果视频的 Files API 下载地址;无产物时为空。任务生成失败时 operation 带 error:{code,message,status},code 为 google.rpc.Code 数值,例如 RESOURCE_EXHAUSTED 为 8;服务重启前没有生成完成的任务带 error:{"code":5,"message":"服务重启前任务没有生成完成","status":"NOT_FOUND"};查询任务状态失败时返回该错误。

两个入口按模型 ID 或目录别名找到能输出视频的模型(generateContent 模型列出 video_output_resolutions,如 gemini-omni-1.1-flash),在可调用该模型的账户上创建 omni- 开头的任务 ID 并立即返回,服务在后台按 Omni Interaction 生成;模型不输出视频时返回 404:

  • 宽高比与分辨率换成模型选项中最接近的取值,时长换成 video_duration_range 范围内的秒数
  • 按输入核对模型目录的 video_tasks:有参考图时为 reference_to_video,只有起始图时为 image_to_video,没有图片时为 text_to_video,目录没有列出该任务时返回 400;请求带参考图或起始图任务,文字生成视频以及提示词为空、只有图片时与官网一样不带任务;图片在提示词之前,提示词为空时内容只有图片;反向提示词以 \n\nNegative prompt: <文本> 附加在提示词末尾;尾帧返回 400
  • 生成的 MP4 上传到创建账户的 Drive,以官网视频页的文件名绑定为任务结果,查询、下载、列出与删除见上文
  • 请求没有指定账户时,生成账户在冷却中或上游返回 401、403、429 与 5xx 时换另一个能运行该模型的账户重新生成,图片输入重新上传到该账户,任务与结果仍属于创建账户;指定账户时以该错误结束
  • 生成失败时 Gemini operation 为 done 并带 error:{code,message,status},OpenAI 对象 status 为 failed 并带 error:{"code":"video_generation_failed","message"}
  • 服务重启时尚未完成的任务为已结束且没有结果,说明为 服务重启前任务没有生成完成

Live 与 Robotics 公开帧

连接升级后 10 秒内发送 setup:

{
  "type": "setup",
  "model": "gemini-live-model",
  "input_modalities": ["text", "audio", "image"],
  "output_modalities": ["audio"],
  "tools": [{"name":"get_weather","description":"...","parameters":{"type":"object"}}],
  "session_token": ""
}

Live input modalities 是 text/audio/image 的非空子集,output 按模型能力确定:普通 Live 模型为 ["audio"];实时翻译模型(能力码 46)要求 output ["audio"] 与 "translation":{"target_language_code":"es","echo_target_language":false},输入音频的原文经 input_transcription、译文经 output_transcription 与 media 返回;实时转录模型(能力码 77)要求 output ["text"],可带 "transcription":{"language_codes":["en"]},转写经 interim_input_transcription(当前累计文本)与 input_transcription(最终文本)返回。两类模型不接受 tools,其他模型不接受 translation 与 transcription。Robotics input/output 必须分别为 ["text"] 与 ["text"],不接受 translation 与 transcription。实时音乐模型 input/output 为 ["text"] 与 ["audio"],不接受 tools、translation 与 transcription。数组不接受空字符串或重复项。

setup 之后的客户端对象统一字段为 type、可选 text、mime_type、Base64 data、tool_responses、weighted_prompts、music_config、playback_control。各帧字段:

type 字段
text text
audio mime_type:"audio/pcm"、data
image mime_type:"image/jpeg"、data
media_end 无附加字段
tool_response tool_responses:[{id,name,content,will_continue?}]
music_prompts weighted_prompts:[{text,weight}]
music_config music_config 对象,字段同 Gemini API LiveMusicGenerationConfig
playback playback_control:"play"|"pause"|"stop"|"reset_context"
close 无附加字段
  • text 帧要求 setup 声明 text 输入,tool_response 帧要求 setup 声明 tools,music_prompts 的 text 非空
  • audio 与 image 省略 mime_type 时分别使用 audio/pcm 与 image/jpeg
  • music_config 的键可用 snake_case 或 camelCase
  • 实时音乐会话只接受 music_prompts、music_config、playback 与 close,Live 与 Robotics 会话不接受这三种帧
  • tool_response 批量发送函数结果,保留调用的 id 与 name
  • setup 的函数声明可带 behavior:NON_BLOCKING 的函数在模型继续对话时异步执行;对它的调用回复 will_continue: true 的中间结果后,同一调用还能继续回复,最后一次回复省略 will_continue

tool_response 示例:

{"type":"tool_response","tool_responses":[{"id":"call-1","name":"get_weather","content":{"temperature":26}}]}

服务端对象字段全集:

{
  "type": "text",
  "model": "gemini-live-model",
  "text": "...",
  "mime_type": "audio/l16;rate=24000",
  "data": "<BASE64>",
  "transcription": {"text":"...","finished":true,"duration_ms":1000,"language_code":"en"},
  "tool_call": {"id":"call-1","name":"get_weather","arguments":{}},
  "tool_call_ids": ["call-1"],
  "session_token": "...",
  "resumable": true,
  "raw": {},
  "error": "...",
  "code": "...",
  "retryable": true
}

按 type 使用对应字段:session_opened{model}、setup_complete、text{text}、media{mime_type,data}、input_transcription/output_transcription/interim_input_transcription{transcription}、tool_call{tool_call}、tool_call_cancellation{tool_call_ids}、interrupted、generation_complete、turn_complete、session_resumption{session_token,resumable}、usage{raw}、go_away{raw}、provider{raw}、closed、error{error,code,retryable,raw?}。

首帧或后续客户端字段无效时发送 {type:"error",code:"invalid_request",error:"..."}。权益不足、候选账户均在冷却与生成服务已停止时,code 与 HTTP 错误表的 OpenAI 列相同。上游错误保留原始 error 内容。客户端单帧上限 8 MiB,超限发送 WebSocket close code 1009。每次写操作上限 10 秒;会话结束等待读取和发送 goroutine(Go 协程)的上限各 5 秒。

流式端点使用 text/event-stream,每个 SSE frame 以空行结束;Gemini 不带 alt=sse 的请求返回 JSON 数组:

协议 首事件 内容序列 usage 终止事件
OpenAI Chat assistant role chunk chat completion delta include_usage=true 时位于 finish chunk 之后 data: [DONE]
OpenAI Responses response.created、response.in_progress output item / content part / delta / done 完成 response 的 usage response.completed 或 response.incomplete
Anthropic message_start content_block_start、delta、content_block_stop message_delta.usage message_stop
Gemini candidate Part GenerateContentResponse 增量 最后一帧 usageMetadata 最后一帧 finish reason

上游语义事件间隔达到 10 秒时,OpenAI 两种协议发送 SSE 注释帧 : ping,Anthropic 发送 ping 事件,Gemini SSE 发送空行,均立即 flush。OpenAI Chat 先发送 assistant role chunk,Responses 先发送 response.created 与 response.in_progress,Anthropic 先发送 message_start;这些起始事件在账户调度期间即可到达客户端。Gemini 的首个帧来自上游语义事件或保活空行。

公开适配规则:

规范事件 OpenAI Chat Responses Anthropic Gemini
text message/content delta output_text text block candidate text Part
reasoning reasoning_content reasoning summary,请求设置 reasoning.summary 时输出 thinking block,请求启用 thinking 时输出 thought Part,includeThoughts 为 true 时输出
function tool_calls,旧式 functions 请求为 function_call function_call item tool_use block functionCall Part
function result tool message function_call_output tool_result functionResponse Part
code execution 可读 Markdown code_interpreter item text block executableCode/result Part
grounding/citation annotations output annotations text sources groundingMetadata
media data URL、/media/ URL 或媒体端点 output content content block inlineData Part
usage prompt/completion/total input/output/total input/output prompt/candidates/thoughts/total

Responses 媒体使用 image generation item。

OpenAI Chat 使用 Markdown 图片承载生成图片,MEDIA_OUTPUT=inline 时为 data URL,url 时为本服务的 /media/<文件名> URL;客户端把 assistant message.content 回传下一轮时,适配器将其中的 data URL 图片与本服务已保存的媒体 URL 图片恢复为 inline data Part,保留图片多轮上下文。GET /media/<文件名> 返回保存的媒体,不校验 API key,响应带 immutable 缓存头。图片 Base64 支持标准与 URL-safe 字母表、可选填充及 CR/LF 换行;图片前后的文本保持原顺序。

YOUTUBE_LINKS=true 时,用户文本中的 youtu.be/<ID>、youtube.com/watch?v=<ID>、/shorts/<ID>、/live/<ID> 和 /embed/<ID> 会转换为 video/* 外部媒体 part,并从用户 text part 中移除;重复 URL 合并为一个附件。OpenAI video_url/input_video、Anthropic URL source 与 Gemini fileData.fileUri 使用相同的外部媒体编码。

OpenAI Responses 的 previous_response_id 与 Interactions 的 previous_interaction_id 共用最多 256 个响应节点并重建完整 contents,已结束的节点保存在 runtime/states.db,服务重启后仍可续接。Drive 与视频资源绑定持久化到磁盘。

GET /v1/responses/{id} 返回完整响应对象;DELETE /v1/responses/{id} 返回 {"id":"resp_...","object":"response","deleted":true},以它为 previous_response_id 的已保存响应保留完整上下文;POST /v1/responses/{id}/cancel 终止进行中的 background:true 响应并返回保存的 status:"cancelled" 对象,流式事件记录在取消处结束、不带终止事件;已结束的后台响应返回其最终对象,其他响应返回 400。GET 带 stream=true 只用于 background:true 且 stream:true 创建的响应,其他已保存响应返回 400,starting_after 不是非负整数时返回 400。未保存、已淘汰或已删除的 ID 返回 404 not_found。

GET /v1/responses/{id}/input_items 返回 {"object":"list","data":[...],"first_id":...,"last_id":...,"has_more":...},按续接顺序列出前序响应的输入项与输出项及本次输入项。order 为 asc 或 desc(默认),limit 为 1–100(默认 20),after 与 before 取列表中的项 ID,不在列表中时返回 400。字符串输入与字符串 content 展开为 input_text(assistant 为 output_text)内容数组;缺少 ID 的 message 项编号为 msg_<响应 ID>_<序号>,其他项为 item_<响应 ID>_<序号>。

POST /v1/responses/input_tokens 接受 POST /v1/responses 的 input、instructions、tools 与 previous_response_id,经同一转换与前序上下文拼接后调用上游 CountTokens,不发起生成;省略 model 时使用前序响应的模型。

模型、参数、账户与上游错误按下方状态表投影。客户端取消会关闭上游 reader并释放账户租约。

错误对象与状态语义:

Gemini 列中注明状态码的行以该状态码返回;Interactions 路由与不带 alt=sse 的 streamGenerateContent 的错误对象外层为数组。

情况 HTTP OpenAI Anthropic Gemini
参数、Schema、tool choice 无效 400 invalid_request invalid_request_error INVALID_ARGUMENT
没有符合条件的账户 400 account_required invalid_request_error INVALID_ARGUMENT
启用账户的权益都不满足模型 AccessModes 403 account_required permission_error PERMISSION_DENIED
支持请求的账户均不可调度 503 account_unavailable api_error UNAVAILABLE
本地 API key 无效 401 invalid_api_key authentication_error 400 INVALID_ARGUMENT,details 为 API_KEY_INVALID 的 ErrorInfo 与 LocalizedMessage
没有带 API key 401 invalid_api_key authentication_error 403 PERMISSION_DENIED
模型或方法不存在 404 model_not_found not_found_error NOT_FOUND
本地文件不存在 404 file_not_found not_found_error NOT_FOUND
输入 token 超过模型上限(上游原文含 The input token count exceeds the maximum number of tokens allowed) 400 context_length_exceeded invalid_request_error,消息以 prompt is too long: 开头 INVALID_ARGUMENT
上游拒绝权限 403 upstream_error permission_error PERMISSION_DENIED
视频仍在生成 409 video_not_ready api_error INTERNAL
文件超过 512 MiB 413 file_too_large request_too_large INTERNAL
上游配额或限流(上游给出重试时长时带 Retry-After,Gemini 错误体带 RetryInfo) 429 rate_limit_exceeded rate_limit_error RESOURCE_EXHAUSTED
候选账户均在冷却且 1 分钟内不恢复(带 Retry-After,Gemini 错误体带 RetryInfo) 429 rate_limit_exceeded rate_limit_error RESOURCE_EXHAUSTED
上游过载 529 upstream_error overloaded_error INTERNAL
当前客户端请求被管理端取消 503 request_canceled api_error UNAVAILABLE
生成服务已停止 503 service_stopped api_error UNAVAILABLE
生成服务正在启动且模型目录尚未就绪 503 service_starting api_error UNAVAILABLE
请求期限到期 504 upstream_error timeout_error DEADLINE_EXCEEDED
传输、Content-Type、解码或缺失终态 502 upstream_error api_error INTERNAL
  • “没有符合条件的账户”指候选耗尽且没有符合方法与能力的账户
  • 权益不满足时错误消息写明模型需要的权益:1 为付费 API key,3 为 Google AI Pro 或 Ultra 订阅,4 为 Google AI Ultra 订阅
  • “支持请求的账户均不可调度”指这些账户都处于需要重新登录、不可用或已停用状态,错误消息逐个列出账户、状态与原因
  • 管理端启动生成服务期间到达的公开 API 请求等启动结束再处理;生成服务处于 STOPPED 时,生成与计数端点返回 service_stopped,错误消息说明在管理页面点击“启动服务”或开启“自动启动生成服务”
  • OpenAI 错误对象的 type 在参数、认证、权限与资源不存在时为 invalid_request_error,429 为 requests,其余为 server_error;param 为 null
  • Responses 流中的 response.failed 的 error.code 取官方枚举:429 为 rate_limit_exceeded,400 为 invalid_prompt,其余为 server_error
  • 错误消息以服务的中文说明开头,上游错误随后附上游方法、HTTP 状态、协议错误码与上游原文,例如 AI Studio GenerateContent 返回 HTTP 429、协议错误码 8: You've reached your usage limit…
  • 候选账户均在冷却时,消息在最早恢复时间后附上该冷却的类型与触发它的上游错误,例如 每日限额: AI Studio GenerateContent 返回 HTTP 429、协议错误码 8: … limit: 100, model: gemini-3.8-flash …
  • OpenAI 与 Anthropic 的 5xx 错误消息(含已开始流式响应后的终止事件)在说明前加官方英文开头与冒号:503 为 Service unavailable,504 为 Request timed out,529 为 Overloaded,其余为 Internal server error

上游 RPC 的 HTTP 404 表示传输或上游失败,默认映射为 502;公开 404 对应本地模型目录或本地资源查找失败。客户端自身断开时,访问日志记录 499 并结束响应写入。

错误对象 raw body:

OpenAI Chat / Responses

{
  "error": {
    "message": "Internal server error: upstream response ended before finish frame",
    "type": "server_error",
    "param": null,
    "code": "upstream_error"
  }
}

Anthropic

{
  "type": "error",
  "error": {
    "type": "api_error",
    "message": "Internal server error: upstream response ended before finish frame"
  }
}

Gemini

{
  "error": {
    "code": 502,
    "message": "upstream response ended before finish frame",
    "status": "INTERNAL"
  }
}

已开始流式响应后的终止原文:

# OpenAI Chat
data: {"error":{"message":"...","type":"server_error","param":null,"code":"upstream_error"}}

# OpenAI Responses
event: response.failed
data: {"response":{"id":"resp_...","object":"response","status":"failed","error":{"code":"server_error","message":"..."}}}

# Anthropic
event: error
data: {"type":"error","error":{"type":"api_error","message":"..."}}

# Gemini
data: {"error":{"code":502,"message":"...","status":"INTERNAL"}}

MakerSuite 错误解析:

来源 路径 公开结果
HTTP status response status 保留原状态码
protocol code $[1][0] 映射到协议 error code/type/status
protocol message $[1][1] 写入公开错误的 message
原始形状 [null,[code,message,...]] 解析后进入规范错误事件

请求生命周期:

阶段 HTTP / SSE 行为 资源状态
response headers 前失败 返回对应 HTTP status 与协议 JSON error 释放账户槽位
SSE 已开始后失败 发送 OpenAI error、response.failed、Anthropic error 或 Gemini error frame 关闭上游 reader并释放账户槽位
完成帧 输出 finish reason、usage 与协议终止事件 合并 Set-Cookie并释放账户槽位
客户端取消 结束上游读取 取消请求上下文并释放账户槽位

欢迎二次开发,如果对你有帮助,考虑给仓库点一个Star~