Android Studio 原生 Agent 接第三方 Provider:Gemini 反代不兼容,以及我写的 AS API Bridge

Android Studio 把原生 Agent 能力做进来之后,很多人第一反应都是:能不能接自己的第三方 Provider?

能配。但真用起来,尤其是走「反重力 / CPA 一类反代」去打 Gemini 模型时,协议对不上的问题会很烦人。我后来干脆写了个本地桥接插件:as-api-bridge-plugin

这篇文章把坑和做法讲清楚。

先说结论

Android Studio 新版 AI / Agent 侧,更偏向 OpenAI Responses API/v1/responses)那一套。

而市面上大量第三方网关、反代、OneAPI / NewAPI、以及很多 Gemini 兼容层,实际更稳的是 Chat Completions/v1/chat/completions)流式协议。

两边差的不只是路径名:

  • 请求体结构不同
  • 流式 SSE 事件模型不同
  • tool / function call 的表达不同
  • 有些上游对 JSON Schema 更挑,空 enum 直接 400
  • 有些网关首帧 content: null,Studio 界面会直接打出字面量 null

所以你在 Studio 里配了第三方 Base URL 和 Key,不等于就能顺滑用。配置能通,协议不一定通。

我碰到的具体场景

目标很简单:

  1. Android Studio 原生 Agent 继续用
  2. Provider 走第三方 / 自建网关
  3. 上游实际是反代出来的 Gemini 模型

结果是:

  • 有的请求直接 400
  • 有的能出字,但流式体验差
  • 有的 tool call 直接炸
  • 有的首包把 null 渲染到聊天区

根因基本可以归成一句话:

Studio 按 Responses 说话,反代按 Chat 听;中间缺一层翻译。

为什么「反代 Gemini」更容易踩坑

反代本身没问题,问题在「兼容层」往往只做了最常见路径。

很多反代 / 聚合网关优先保证:

  • /v1/chat/completions
  • 标准 messages
  • 标准 tool_calls
  • SSE data: {choices:[{delta:...}]}

而 Android Studio Agent 侧更像在走:

  • /v1/responses
  • 另一套 input / output item
  • 另一套 function_call 事件流

Gemini 这条线再叠一层:

  • schema 校验更严
  • enum: []、空 required 更容易被拒
  • 流式首帧行为不一定按 OpenAI 官方习惯来

于是就出现一种很典型的状态:

  • Postman 测 Chat 接口正常
  • Studio Agent 一开就不正常
  • 你以为是 Key 或模型名错了,其实是协议形态不对

我的解法:本地桥,不改上游、不改模型名

插件名字叫 AS API Bridge,仓库在:

https://github.com/lategege/as-api-bridge-plugin

思路很直接:

1
2
3
4
5
6
7
8
9
Android Studio Agent
        |
        |  /v1/responses  (SSE)
        v
AS API Bridge  (127.0.0.1)
        |
        |  /v1/chat/completions  (stream=true)
        v
第三方网关 / 反重力反代 / OneAPI / NewAPI / Gemini 兼容层

它干的事主要有五块:

1. Responses → Chat 的实时流式转换

命中转换规则的模型:

  1. 吃 Studio 的 /v1/responses
  2. 转成上游 /v1/chat/completions,并且强制真流式
  3. 把上游 Chat SSE 再转回 Responses SSE 给 Studio

重点是 流式管道,不是等整段生成完再回包。这样首字延迟(TTFT)会好很多,打字机效果也正常。

2. 按模型规则决定「转」还是「透传」

不是所有模型都需要转换。

你可以配通配规则,比如:

1
2
3
4
gemini*
claude-3-5*
gpt-4o
*
  • 命中:走协议转换
  • 未命中:原样透传

模型名本身不改。这个很重要,避免网关侧按模型名做的路由被你手贱改坏。

3. Tool Calls 映射

Responses 里的:

  • function_call
  • function_call_output

会映射到 Chat 侧更常见的:

  • tool_calls
  • role: "tool"

Agent 场景如果没有这层,工具调用基本用不舒服。

4. JSON Schema 清洗

针对 Gemini / 部分网关常见的 400:

  • enum: []
  • required
  • 一些不友好的 schema 边角

请求发出去前先洗一遍,少踩无意义的 Bad Request。

5. 首帧 null 过滤

有些兼容网关第一帧会给:

1
{"delta":{"role":"assistant","content":null}}

Studio 如果直接当文本处理,聊天区就可能冒出字符串 null

插件里对 JSONObject.NULL"null" 做了过滤。这个修在 1.2.2。

在 Android Studio 里怎么配

安装插件

目前按源码构建:

1
2
3
git clone https://github.com/lategege/as-api-bridge-plugin.git
cd as-api-bridge-plugin
./gradlew build

产物大概在:

1
build/distributions/as-api-bridge-plugin-1.2.2.zip

然后:

SettingsPlugins → 齿轮 → Install Plugin from Disk... → 选 zip → 重启。

插件设置

SettingsToolsAS API Bridge

常见配置:

作用例子
Listen Port本地监听端口8088
Upstream Base URL上游网关地址http://127.0.0.1:3000/v1
API Key (Fallback)客户端没带 Key 时兜底sk-xxx
Need Protocol Conversion Models哪些模型要转换gemini*
Auto-start on IDE launch启动 IDE 自动开桥建议开

菜单里也可以手动:

ToolsAS API BridgeStart Bridge / Stop Bridge

Studio 的 Provider 指到本地桥

关键点:

  • Android Studio 的自定义 Provider / Base URL,指到桥:http://127.0.0.1:8088/v1
  • 桥的 Upstream,再指到你的反代 / 网关真实地址

不要让 Studio 直连反代,然后指望反代同时完美兼容 Responses。把翻译放到本地,问题面更小,也更好排障。

推荐的排障顺序

如果还是不通,按这个顺序查:

  1. 桥有没有起来
    本地端口通不通,插件是否 Start 成功。

  2. Studio 是不是打到了桥
    Base URL 是否真的是 127.0.0.1:端口,别还指着上游。

  3. 模型名是否命中转换规则
    Gemini 相关建议先写 gemini*。不确定就临时用 * 验证,确认后再收窄。

  4. 上游 Chat 接口本身是否健康
    用同一 Key 直接打 /v1/chat/completions。上游 Chat 都不稳,桥也救不了。

  5. 是不是 schema / tools 400
    看返回体。若是空 enum 一类,确认你用的是带清洗逻辑的版本。

  6. 是不是首包 null
    升级到 1.2.2+。

这插件解决了什么,没解决什么

解决了

  • Studio Responses 协议和常见 Chat 反代之间的主路径鸿沟
  • Gemini 兼容层上的一部分 schema 拒识
  • tool call 形态差异
  • 流式体验和首帧 null 显示问题
  • 「部分模型要转、部分模型要透传」的现实需求

没打算伪装成

  • 官方完美兼容层
  • 所有 Provider 的万能适配器
  • 对任何非标反代都 100% 语义等价

协议翻译天然有损。尤其是 Responses 和 Chat 在工具调用、输出分片、usage 字段上并不一一镜像。目标是:让 Android Studio 原生 Agent 在第三方 Gemini 反代场景下能稳定工作,不是证明两边协议数学上全等。

为什么我选择做 IDE 插件,而不是外部 nginx

也考虑过外部反代脚本。最后还是做成 Android Studio / IntelliJ 插件,原因很实际:

  • 本地环回,链路短
  • 跟 IDE 生命周期绑在一起,开关方便
  • 设置页直接改规则,不用另维一套服务
  • 鉴权可以优先透传 Studio 自己带的 Header
  • 出问题看日志和端口都在本机,心智负担小

对个人开发者来说,这种「IDE 内一小桥」比再维护一个常驻转换服务更省事。

使用上的一点建议

  1. 先只转 Gemini
    规则从 gemini* 开始,别一上来 * 全开,不好定位。

  2. 上游尽量选真正支持 stream 的 Chat 接口
    桥可以转协议,不能把假流式变真流式。

  3. 模型名保持网关侧原名
    桥的设计就是不改模型名,只改协议。

  4. Agent 场景优先验证 tool call
    纯聊天通了不算完,带工具的链路才是 Agent 真正会炸的地方。

  5. 把桥当适配层,不当业务层
    限流、计费、模型路由还是放上游网关。

仓库和版本

  • 项目:lategege/as-api-bridge-plugin
  • 当前 README 对应版本:1.2.2
  • 技术栈:Kotlin + IntelliJ Platform Plugin
  • 兼容基线:Android Studio / IntelliJ 2024.1+(since-build 241

如果你也在用 Android Studio 原生 Agent,又想接自己的第三方 Provider,尤其是 Gemini 反代,被 /responses/chat/completions 来回抽,可以试试这层本地桥。

有问题直接去仓库提 issue。我这篇更偏复盘和排障思路;安装细节以仓库 README 为准。

build with Hugo, theme Stack, visits 0