Skip to content

Explore supporting Google Antigravity CLI (agy) via cloudcode-pa protocol shim #218

@Oaklight

Description

@Oaklight

Tried wiring agy (Google Antigravity standalone CLI, the Go binary at /usr/bin/agy) to argo-proxy using our existing Gemini CLI override pattern and it doesn't work. Filing here because the actual protocol translation belongs in rosetta, not in argo-proxy.

What agy talks

It talks to cloudcode-pa.googleapis.com via gRPC-transcoded JSON+SSE (?alt=sse flavor). Internally uses connect-go which multiplexes gRPC / gRPC-Web / Connect, but the default outbound is plain JSON, not binary protobuf. So it's not "real gRPC" in the xAI sense.

The internal proto namespace is google.internal.cloud.code.v1internal — methods like v1internal_prediction_service_go_proto.GenerateContent, LoadCodeAssistRequest, FetchAvailableModelsResponse. Not public.

What works empirically

CLOUD_CODE_URL=<host> overrides the cloudcode endpoint. Confirmed via binary string Overriding CloudCodeServerURL via CLOUD_CODE_URL environment variable: %q and the corresponding line in agy's own log. agy also honors GOOGLE_APPLICATION_CREDENTIALS, NODE_EXTRA_CA_CERTS, SSL_CERT_FILE, HTTPS_PROXY.

Auth chain is CLIAuthProvider -> KeyringTokenStorage (libsecret via D-Bus on /org/freedesktop/secrets/aliases/default) -> fileTokenStorage fallback for headless boxes.

What doesn't work

Gemini CLI's GOOGLE_GEMINI_BASE_URL + ~/.gemini/.env + selectedType: gemini-api-key is completely ignored. Tested — agy goes straight to its own OAuth flow.

The API provider enum is closed: GOOGLE_GEMINI / GOOGLE_VERTEX / GOOGLE_EVERGREEN / ANTHROPIC_VERTEX / OPENAI_VERTEX / INTERNAL. Every non-Google provider routes through Vertex BYOK — no direct anthropic.com / openai.com path, no OPENAI_COMPATIBLE escape hatch. BYOK key registration also goes through Google RPCs (SetUserApiProviderKey), not local config.

Interesting find that doesn't help us

agy ships geminiConverter, openaiConverter, anthropicConverter internally. These are response converters used after a successful Google auth — they translate cloudcode-pa replies into OpenAI/Anthropic-shaped responses for IDE consumers (the BYOK feature). The direction is wrong for what we want; we'd need request converters on the way in.

Possible approach

Roughly four moving pieces:

  1. Dump proto descriptors from the agy Go binary. Go binaries embed FileDescriptorProto and they're extractable with reflection on the embedded registry. That gets us most of the cloudcode-pa schema for free without MITM.
  2. Build a cloudcode-pa-shaped surface in rosetta — accepts /v1internal:generateContent?alt=sse etc., translates the cloudcode internal proto into whatever upstream rosetta is already proxying to (OpenAI / Anthropic / Gemini).
  3. Decide on the auth bypass. Cheapest: rosetta accepts any Bearer (or none) on this surface. Harder part is agy-side — its silent-auth step has to succeed before any request goes out. Options: fake KeyringTokenStorage entry, or GOOGLE_APPLICATION_CREDENTIALS pointing at a synthetic token file with a tiny local token server, or external_account credential JSON.
  4. argo-proxy side just points CLOUD_CODE_URL at rosetta and lets rosetta hand off to argo-proxy as the real model backend.

Cost/benefit

Non-trivial. Proto reverse + auth bypass + protocol shim is a real chunk of work, and agy is one client. Counterpoint: same shim covers any future Google CodeAssist consumer (gemini-code-assist plugin, JetBrains plugin, etc.), and step 1+2 give us proto+gRPC infra that would also unlock xAI's real gRPC API as a side effect.

Related

argo-proxy side stub: Oaklight/argo-proxy#122

Metadata

Metadata

Assignees

No one assigned

    Labels

    deferredIntentionally postponed; revisit when preconditions are met

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions