Skip to content

Add experimental Antigravity CLI (agy) host - #147

Merged
Saksham Uboweja (SakshamUboweja) merged 5 commits into
microsoft:mainfrom
cagdasyurekli:feat/antigravity-host
Nov 8, 2026
Merged

Saksham Uboweja (SakshamUboweja) merged 5 commits into
microsoft:mainfrom
cagdasyurekli:feat/antigravity-host

Conversation

@cagdasyurekli

Copy link
Copy Markdown
Contributor

Closes #114.

Adds an antigravity host for agy 1.5.1: micro-skills, the loop guard and the session ledger. Tool pruning is not supported (same status as Hermes). macOS and Linux only, like Cursor.

How agy's hooks are mapped (verified live on agy 1.5.1)

agy's hook contract differs from the shared one in ways its own docs don't all state:

  • No UserPromptSubmit, no SessionEnd, and payloads name no event. The hook file passes --event. PreInvocation fires before every model call, and its invocationNum resets to 0 at each prompt. One PreInvocation is expanded (Host.expand) into the tool results the transcript gained since the last call (as PostToolUse events), then the new prompt's UserPromptSubmit. A conversation is folded at the next session start once its transcript is quiet (the existing fold.pending_sessions path).
  • PostToolUse carries no tool result, its "*" matcher never matches, and the result is not yet in the transcript when it fires. By the next PreInvocation it is, so results are read there from transcript_full.jsonl.
  • A PreToolUse hook that prints {} makes agy deny the tool, so none is registered.
  • Output is injectSteps. A systemMessage step at SessionStart persists. An ephemeralMessage at PreInvocation carries the loop guard's redirect. Both were verified to reach the model.
  • Usage comes from each PLANNER_RESPONSE row (input_tokens excludes cached reads; cache_read_tokens, output_tokens). Gemini ids aren't in pricing.py, so the ledger uses its labelled fallback (priced_by: "fallback"). I did not add rates.

Side calls

agy --output-format json --disable-slash-commands --print=<prompt> runs in a throwaway directory with TE_SIDECALL=1 (verified to reach agy's hook processes). agy's headless mode denies any tool that needs permission (verified: a prompt asking for a file write and a shell command left the directory empty, with denied_actions: write_file). The person's own permissions.allow rules in agy's settings still apply to it.

Verification

  • python -m pytest tests experiments/tests: 1117 passed, 18 skipped (26 new tests in tests/test_antigravity.py, fixtures built in code).
  • A live run in a scratch repository, with the bundle installed workspace-locally and an isolated TOKENECONOMIZER_HOME: hooks ran without errors, the turn was recorded (1 tool call, ended green), te fold wrote a ledger row (2 requests, 23,636 input and 853 output tokens), and te status reports it.
  • Not verified live: a redirect firing in a real stuck turn (it needs a learned envelope). It is covered end to end through hook.main in the tests.
  • agy plugin validate plugin passes. --strict flags Claude Code's hooks/hooks.json as not loaded by agy, which is expected.

Note for review

This PR and the grok host PR each add a small render seam to hook.run with different signatures. Whichever lands second needs a small rebase.

🤖 Generated with Claude Code

Adapter for agy 1.5.1's hook contract: SessionStart, PreInvocation and Stop
are translated into the controller's events (tool results are read from the
transcript at the next PreInvocation; invocationNum 0 opens a prompt-turn),
and answers go back as injectSteps. Micro-skills, the loop guard and the
session ledger are supported; tool pruning is not. Side calls run through
`agy -p`.

Refs microsoft#114

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SakshamUboweja

Copy link
Copy Markdown
Collaborator

Thanks, this looks solid overall. A few things before we can merge:

agy_call doesn’t turn off agy’s tools. The other agents’ side calls all run with no tools, since the prompt includes text from the repository. Could you pass agy’s no-tools option if it has one? If it doesn’t, let’s skip side calls for Antigravity for now.

Please take a look at the failing CI checks.

On SessionStart with no saved cursor, reading starts at the top of the transcript, so a resumed conversation replays its old tool calls. Starting at the file’s current size, like the PreInvocation path does, fixes it.

Please rebase on main. README.md conflicts with #149.

…nto feat/antigravity-host

# Conflicts:
#	README.md
- agy has no option that runs a prompt with every tool off, so the plugin makes
  no model call through it: `sidecall.NO_SIDE_CALLS` gives Antigravity no runner,
  and the loop guard never starts a judge for it. Docs now say micro-skills'
  LLM-free facts only.
- SessionStart with no saved cursor starts reading at the transcript's current
  end, as PreInvocation already did, so a resumed conversation does not replay
  its old tool calls.
- The cursor-file permission test is POSIX-only, like the other permission-bit
  tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cagdasyurekli

Copy link
Copy Markdown
Contributor Author

Thanks for the review! Addressed in 8fbbab0:

  • Side calls: agy has no option that turns its tools off (--mode plan and --sandbox still leave read tools), so Antigravity now makes no side calls. agy_call is removed, sidecall.NO_SIDE_CALLS gives the host no runner, and the controller never starts a judge for it. The docs now say only micro-skills' LLM-free facts are supported there.
  • SessionStart replay: with no saved cursor it now starts at the transcript's current size, the same helper the PreInvocation path uses. There's a regression test for a resumed conversation.
  • Windows CI: the cursor-file permission test checks POSIX mode bits, so it's now skipped on Windows like the other permission-bit tests.
  • main: merged in (21d2ba9) and the README conflict with Cursor: count prompts and close turns in headless (-p) runs #149 resolved, keeping both bullets. I merged instead of rebasing so there's no force-push, but I can rebase if you prefer.

Both hosts kept everywhere. The Antigravity adapter's `render` now takes
grok's `(payload, out, ctx)` signature, so `hook.run` merges the expanded
events' answers and renders once, for either host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SakshamUboweja

Copy link
Copy Markdown
Collaborator

Thanks for the fixes. All four earlier points are addressed, and the tests pass on main.

#148 (Grok) is merging first, so this needs one more rebase. It touches the same places this PR does. When you rebase:

In the hook entry point, keep Antigravity's own handling first, ahead of Grok's. Both PRs add a render step that works differently, so the order matters. Your Antigravity tests will fail if it's wrong.
Everywhere else, keep both agents in the lists: the host list, host detection, te doctor, and the docs and README tables.
Then I'll merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SakshamUboweja
Saksham Uboweja (SakshamUboweja) merged commit 508c587 into microsoft:main Nov 8, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for Antigravity (agy) CLI

2 participants