Reverse Engineering Antigravity Models Auth
thumbnail
date
Aug 10, 2026
slug
antigravity-models
status
Published
tags
AI
summary
Reverse engineering wire protocols, binary-searching system prompts, unmasking a secret identity filter, and bringing Gemini 3.6 Flash to Hermes Agent.
type
Post
The Mystery of the 429: How a Single Sentence Broke Google’s Free AI Models in Hermes Agent
Reverse engineering wire protocols, binary-searching system prompts, unmasking a secret identity filter, and bringing Gemini 3.6 Flash to Hermes Agent.
💡 TL;DR: Trying to use Google’s free Antigravity models (Gemini 3.1 Pro, Gemini 3.5 Flash) in Hermes Agent kept throwing429 RESOURCE_EXHAUSTEDerrors, even with 100% quota remaining. The culprit wasn't rate limits or payload size—Google's API silently rejects requests whose system prompt contains the sentence "You are Hermes Agent, an intelligent AI assistant created by Nous Research". Neutralizing that single identity line instantly restored full access.In this post, I cover how I uncovered the filter, sanitized JSON Schemas, fixed Hermes' dual provider resolution system, and wired up full support for the new Gemini 3.6 Flash with reasoning effort mapping.
1. The Dream: Free Frontier Models in Hermes
If you’ve used omp (Oh My Pi), you know the magic of Google Antigravity: direct, zero-cost access to Gemini 3.1 Pro, Gemini 3.5 Flash, Gemini 3.6 Flash, Claude 4.6 via Google, and GPT-OSS 120B.
I do most of my heavy daily coding inside Hermes Agent (by Nous Research). Naturally, I wanted the same free model access in Hermes. Fortunately, Hermes supports third-party provider plugins via
antigravity-provider, an in-process bridge that translates OpenAI-formatted chat completions into Google’s Cloud Code Assist API (v1internal:streamGenerateContent).I installed the plugin, set
provider: antigravity, selected google-antigravity/gemini-3.1-pro, and ran a quick smoke test.That’s when the headaches started.
2. Chapter 1: The Setup Bosses (Imports & Schemas)
Before hitting the main boss, I had to clear two preliminary hurdles.
Hurdle 1: The Invisible Plugin
On the first run, Hermes crashed before making a network call:
The plugin repository used a standard Python
src/ layout (src/antigravity_provider), but Hermes' plugin loader generated an import shim that couldn't locate the package inside the virtual environment.- The Fix: Installing the package in editable mode (
pip install -e ~/.hermes/plugins/antigravity-provider) permanently bound the module to Hermes’ venv, surviving any futurehermes agy loginshim regenerations.
Hurdle 2: Schema Indigestion
Once the plugin loaded, requests reached Google’s Cloud Code Assist endpoints—only to instantly bounce with
400 Bad Request validation errors:Hermes exports rich, expressive JSON Schemas for its tools, using standard keywords like
const, oneOf, anyOf, $ref, and additionalProperties. Google’s Gemini function declaration parser, however, demands strict, minimal schemas.- The Fix: I added a recursive schema sanitizer in
transform.pyto strip unsupported JSON Schema keywords before sending tool definitions upstream:
3. Chapter 2: The Ghost 429 Quota Error
With schemas sanitized, requests were finally formatted correctly. But now, every single attempt failed with a brick wall:
A standard HTTP 429 usually means one thing: you're out of quota.
Except I wasn't.
I opened
omp on the exact same machine, running on the exact same Google OAuth accounts, and executed prompts against Gemini 3.5 Flash without a single hitch. Both accounts showed 100% free quota remaining.Why would
omp work flawlessly while Hermes failed every single time?4. Chapter 3: Reverse Engineering omp
To find out what
omp was doing differently, I dug into ~/.omp/ and inspected its compiled binary:- Multi-Account Rotation:
ompmaintains four Google OAuth accounts inside SQLite (~/.omp/agent/agent.db), automatically rotating when one gets throttled.
- Wire Protocol Parity:
omptalks to the exact same endpoint (https://daily-cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse) using the exact same request envelope (requestType: "agent",userAgent: "antigravity",ideType: "ANTIGRAVITY").
The wire protocol was 100% identical.
I extracted the OAuth tokens from
omp's database and ran isolated test requests using Hermes' Python client:- Small Prompt (
"Reply with exactly: OK"): HTTP 200 OK (worked on all 4 accounts across both endpoints).
- Full Hermes Agent Prompt (19KB system prompt + 36 tool schemas ≈ 41KB): HTTP 429 RESOURCE_EXHAUSTED (failed on all 4 accounts).
Small prompts worked, but full agent prompts failed. That meant it wasn't an account-level quota issue. It was deterministic based on the request payload itself.
5. Chapter 4: The Rabbit Hole — Bisecting the System Prompt
Was it payload size?
I generated a dummy 30KB system prompt packed with 36 heavy tool definitions and sent it. HTTP 200 OK.
Size wasn't the issue. The failure was content-dependent.
I began binary-searching the real 19KB Hermes system prompt line by line, testing slices against the live API. Eventually, I narrowed the failure down from 19,000 characters to a single sentence:
If that sentence was present in the system prompt, Google's API returned HTTP 429 RESOURCE_EXHAUSTED. If I modified a single word, it succeeded.
The Bisect Matrix
Here is what happened when I tested variations of that sentence:
System Instruction Variation | API Result |
"You are Hermes Agent." | ✅ 200 OK |
"You are an intelligent AI assistant created by Nous Research." | ✅ 200 OK |
"You run on Hermes Agent (by Nous Research)." | ✅ 200 OK |
"You are Hermes Agent, an intelligent AI assistant created by Nous Research" | ❌ 429 EXHAUSTED |
"You are Hermes Agent, an intelligent AI assistant created by X Corp" | ✅ 200 OK |
"You are a Helpful Agent, an intelligent AI assistant created by Nous Research" | ✅ 200 OK |
The Revelation 🤯
Google’s Cloud Code Assist API has an upstream filter that intercepts system instructions asserting a competing assistant's identity. When triggered, instead of returning a standard policy error, the API returns a masked
429 RESOURCE_EXHAUSTED.omp never ran into this because it injects Google's own identity string ("You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team...").Hermes' prompt opens with
"You are Hermes Agent, an intelligent AI assistant created by Nous Research"—meaning every single real Hermes prompt was getting caught in Google's identity filter.The Fix
I added a light regex scrubber to
transform.py:The moment that scrub went in, the full 41.8KB prompt returned HTTP 200 OK. All of Hermes’ tool guidance, memory rules, and formatting instructions remained 100% intact—only the brand identity line was sanitized.
6. Chapter 5: The Dual Provider Resolution Architecture
With prompts working in one-shot mode (
hermes -z), I tried switching models in the TUI (/model) and CLI (hermes model). Immediately, a new error popped up:Why did
-z work when model switching failed?Hermes uses two different provider lookup functions:
resolve_runtime_provider(): Used for execution. It queries the in-memory plugin registry whereregister_provider_profile()registersAntigravityProfile. This is whyzworked.
resolve_provider_full(): Used byhermes model,/modelin the TUI, andswitch_model(). It searches:- Config file (
providers:inconfig.yaml) - Built-in provider aliases
- Saved custom providers
models.devcatalog
Because
resolve_provider_full() never checks the runtime plugin registry, passing explicit_provider="antigravity" returned None, crashing the model switcher.The Fix
The error message prescribed the exact fix: add
antigravity to ~/.hermes/config.yaml under providers::To make this permanent for all new setups, I patched
_select_model() in the plugin (antigravity_provider/hermes_plugin.py) to auto-populate this section whenever hermes agy select runs:7. Chapter 6: Adding Gemini 3.6 Flash Support
With the foundation solid, I wanted to add support for Gemini 3.6 Flash.
However, sending a raw model ID of
gemini-3.6-flash returned 404 NOT_FOUND. Google’s Cloud Code Assist API requires a reasoning effort suffix (-low, -medium, or -high) on the wire for 3.6 Flash:gemini-3.6-flash-low
gemini-3.6-flash-medium
gemini-3.6-flash-high
I updated the plugin’s
models.py to declare google-antigravity/gemini-3.6-flash in KNOWN_MODELS and map Hermes’ reasoning effort knob to the correct wire model ID:Now, selecting
google-antigravity/gemini-3.6-flash dynamically maps reasoning effort levels (low, medium, high) directly to Google's expected wire model identifiers.8. Chapter 7: Usage & Analytics
Does Hermes track usage for Antigravity models?
Yes! Hermes logs all token usage into
~/.hermes/state.db under billing_provider='antigravity':Running
hermes insights cleanly aggregates these models alongside your paid providers.📌 Note: The only difference betweenompand Hermes here is thatompqueries Google's internalfetchUsageAPI to render a live "remaining daily quota" meter. Hermes logs spent tokens per session locally.
9. Chapter 8: The Moment of Truth
With all fixes and features in place, I ran full end-to-end verification: