Google 给 Gemini API 上线了「事件驱动 webhook」,把过去那种「长时任务靠轮询」的做法直接砍掉。覆盖三组事件:Batch(succeeded / cancelled / expired / failed)、Interactions(requires_action / completed / failed / cancelled)、Video Generation(video.generated)。实现走的是 Standard Webhooks 规范:静态(项目级)webhook 用 HMAC-SHA256 签名,动态(单请求)webhook 用非对称 JWT(RS256)签名、公钥经 JWKS 发布;每个 payload 都带 `webhook-signature`、`webhook-id`、`webhook-timestamp` 三个 header。投递语义是 at-least-once,重试窗 24 小时,采用指数回退。官方建议拒绝时间戳早于 5 分钟的请求,以防重放攻击。

两种配置模式的差异很关键。*静态*:通过 WebhookService API 在项目级配置,该项目下所有匹配事件都会触发,用一个共享密钥做 HMAC 验证。*动态*:每次请求里用 `webhook_config` 字段做覆盖,签名用 Google 自己的密钥做非对称 JWT,公钥从 `https://generativelanguage.googleapis.com/.well-known/jwks.json` 拿。动态模式还支持一个 `user_metadata` 字段做路由 —— 这份 metadata 会随 webhook payload 原样回到你的服务器,意味着单一 endpoint 可以按租户、按用户、按工作流自由 fan-out,不需要在自己这一头另起一张「job-ID → 上下文」状态表。Payload 故意做薄:状态快照加上指针,比如 Batch 给你 `output_file_uri`,Video 给你 `file_id` 和 `video_uri`,不直接塞原始输出。服务器收到后应当先回 `2xx`,再异步处理,免得触发重试循环。`webhook-id` 这一头就是你的去重 primitive。

放到生态层面,这一步把 Gemini API 在「事件投递」这一项推到了「持平 + 一点点超」的位置。OpenAI 的 Batch API、Anthropic 的 Message Batches 当前都是 async + 你自己轮询 —— 一次 24 小时的批跑,意味着你这边按时间表反复打 API 等结果,白白吃掉请求预算。Webhook 把这个反过来:你的应用睡觉,等 Google 推过来。视频生成尤其受益(Veo 这一类工作负载,单请求可能跑几十秒到数分钟),用轮询去守它,浪费得更明显。静态/动态这个切分也挺有想法 —— 静态适合「我们就一个团队在跑批,给我一个密钥统一验」,动态适合「我是 SaaS、我跑的是多租户 Gemini 工作负载,每个租户的 webhook 要落到他们各自隔离的 endpoint 上、还要带着他们自己的 metadata 一起回来」。这是一个值得抄进自己产品里的能力形状。

可落地的读法。如果你在跑 Gemini Batch 或视频任务、还在轮询,直接切过来 —— 省 API 调用、缩短「任务完成-我察觉到」之间的尾部延迟、整体也更干净。5 分钟反重放窗 + `webhook-id` 去重的组合意味着你的 webhook handler 必须自带一层幂等(大多数本来就有)。多租户场景里,「动态 webhook + `user_metadata`」就是正解 —— 别想着用静态 webhook 然后在自己一头从 job ID 反推租户。再回头比一下你现在在 OpenAI / Anthropic 那一侧的轮询开销,看看是不是值得去推这两家也补齐 Standard Webhooks 这一档。这件事的信号不是「webhook 是新东西」—— webhook 是老东西;信号是 AI API 终于开始按 Standard Webhooks 这个工程标准被对待了,这意味着「agent + 批处理」的基础设施,从此可以跟你栈里其他东西用同一套运维原语来搭。