Finally solved: two hours of testing to get the headless Antigravity CLI right

Redaktion · · 5 Min. Lesezeit

I wanted to wire Google’s Antigravity CLI (agy) into an auto-execution pipeline, running headless. The plan was simple: one specific model per run via --model, everything non-interactive via -p/--print, collect the output, process it downstream. The first call looked harmless:

agy -p --model "gemini-3.1-pro" "Reply with ONLY your exact model name."

The reply: Gemini 3.5 Flash. The default — not the model I had requested. No matter what string I put in --model, agy fell back to the standard model every time. No error, no warning, nothing. Two hours later I knew why, and the reason is in no documentation. Here it is, step by step.

Step 1: The model names are not slugs

My first suspicion: wrong model name. agy models cleared that up — and surprised me. The CLI lists models as display names with the reasoning level in parentheses, not as technical slugs:

agy models
# Gemini 3.5 Flash (Medium)
# Gemini 3.5 Flash (High)
# Gemini 3.5 Flash (Low)
# Gemini 3.1 Pro (Low)
# Gemini 3.1 Pro (High)
# Claude Sonnet 4.6 (Thinking)
# Claude Opus 4.6 (Thinking)
# GPT-OSS 120B (Medium)

Important: there is no separate --effort or --reasoning flag. The reasoning level is part of the model string. My slug variants — gemini-3.1-pro, :high, -high — all triggered the fallback. Only the exact display name with parentheses was accepted in interactive mode, visible in the status bar at the bottom right. Even that is documented nowhere cleanly.

Step 2: Don’t ask the model who it is

Armed with the correct name, the next headless test:

agy -p --model "Gemini 3.1 Pro (High)" "Reply with ONLY your exact model name."

Reply: I’m running on the GPT-OSS 120B (Medium) model. That was instructive on two levels. First: --model was ignored again — a different default this time, but in any case not my requested model. Second, and this is the real trap: a model’s self-report is worthless as proof of identity. Models often don’t know their exact name reliably and guess from the system prompt or training data. If you work headless, you can’t rely on it.

Step 3: It’s the order of the flags

The breakthrough came from blunt trial and error: I swapped the flags on the same model. And suddenly the result was correct. That’s the moment the order clicks — and turns everything before it into a footnote.

# WRONG — silently falls back to the default:
agy -p --model "Gemini 3.1 Pro (High)" "Reply with ONLY your exact model name."

# RIGHT — uses the requested model:
agy --model "Gemini 3.1 Pro (High)" -p "Reply with ONLY your exact model name."

--model must come before -p. If -p comes first, the print mode swallows the following model argument and silently falls back to the default — exit code 0, no message. I cross-checked this across all eight models on the list: as soon as --model precedes -p, the correct result comes back every time.

The working pattern

The constellation I now run in the pipeline is exactly one line:

agy --model "<display name (level)>" -p "<prompt>"

Concretely, for three of the models:

agy --model "Gemini 3.1 Pro (High)" -p "..."
agy --model "Claude Opus 4.6 (Thinking)" -p "..."
agy --model "GPT-OSS 120B (Medium)" -p "..."

Three pitfalls that would have caught me otherwise

With the flag order sorted, the main problem is solved, but for unattended runs there are three more points I planned for right away.

  • Non-TTY stdout drop. In pipes, subprocesses or CI, agy -p can silently swallow the reply — exit code 0, but empty stdout (documented as GitHub Issue #76). If you capture agy as a subprocess, you need a pseudo-TTY: script -qfc 'agy --model "..." -p "..."' /dev/null.
  • Name stability. The display strings can change between agy versions. Instead of hardcoding names, I parse agy models once before each run and pull the matching string dynamically.
  • API key paths. GEMINI_API_KEY is ignored on some code paths. For CI I set ANTIGRAVITY_TOKEN or ANTIGRAVITY_API_KEY.

Conclusion

The central, undocumented rule: --model before -p. Plus three guardrails — display name with parentheses instead of a slug, logs instead of self-report, a pseudo-TTY against the stdout drop. With that, agy runs reliably headless for me. The point of all the fiddling: agy is just one engine in a multi-model pipeline that runs several AI coding tools headless and pits their output against each other. I deliberately left the OpenAI models out; I’ll test those separately and add the results later.

Entdecke mehr

Themenuebersicht