AI coding agents can run tests, inspect logs, and produce convincing summaries. The weak point is often the boundary between ?work attempted? and ?work verified.? An agent may stop after a failed command, omit the report, or proceed with a broader tool call than the QA charter intended.

Antigravity hooks let teams run deterministic command handlers at specific points in the agent execution loop. This tutorial builds a small QA guardrail with three hooks: one before a tool runs, one after it completes, and one when the agent is about to stop. The goal is not to make an agent the release authority. It is to make missing approvals, failed checks, and absent evidence harder to overlook.

What Antigravity hooks expose

Google’s official Antigravity hooks documentation describes five lifecycle events: PreToolUse, PostToolUse, PreInvocation, PostInvocation, and Stop. Hooks are command handlers configured in a hooks.json file inside a workspace or user customization directory.

For this QA pattern, three events matter:

  • PreToolUse: inspect a proposed tool call and return allow, deny, ask, or force_ask.
  • PostToolUse: observe the completed step and error field, then record sanitized diagnostics.
  • Stop: inspect termination reason, execution number, idle state, workspace paths, transcript path, and artifact directory; return continue when required work is incomplete.

Hooks receive JSON through standard input and return JSON through standard output. Treat every input field as untrusted. Validate types, normalize paths, and return the smallest supported response.

Hooks complement permissions

Antigravity also has a separate permission engine with Deny, Ask, and Allow lists. Google documents the precedence as Deny, then Ask, then Allow. Keep broad security rules in permissions. Use hooks for task-specific validation such as ?this QA run may execute the approved test script, but anything broader requires a fresh review.?

A hook should never weaken a deny rule or silently broaden access. For sensitive operations, force_ask is useful because it requires a prompt even when a cached approval exists.

Scenario: evidence-gated API regression check

Create a disposable repository containing a harmless API contract test and synthetic data. The required completion evidence is:

  • the approved test command;
  • its exit status;
  • a machine-readable test report;
  • a sanitized log;
  • the build or commit identifier;
  • no active background task;
  • a human-readable summary that does not claim success after a failed check.

Keep all artifacts inside the workspace. Do not connect the lab to production, customer data, billing systems, or real credentials.

Step 1: organize the hook files

.agents/
  hooks.json
scripts/
  qa-pretool-gate.js
  qa-posttool-record.js
  qa-stop-validate.js
evidence/
  hook-events.jsonl
  test-report.xml
  run-summary.json

The scripts should be small, dependency-light, and independently testable. Do not make them call a model. Their value comes from deterministic checks that behave the same way for the same JSON input.

Step 2: configure the three events

{
  "qa-evidence-guard": {
    "PreToolUse": [
      {
        "matcher": "run_command",
        "hooks": [
          {
            "type": "command",
            "command": "node scripts/qa-pretool-gate.js",
            "timeout": 10
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "run_command",
        "hooks": [
          {
            "type": "command",
            "command": "node scripts/qa-posttool-record.js",
            "timeout": 10
          }
        ]
      }
    ],
    "Stop": [
      {
        "type": "command",
        "command": "node scripts/qa-stop-validate.js",
        "timeout": 10
      }
    ]
  }
}

Use paths that resolve consistently for the environment in which Antigravity runs. Keep timeouts short so a broken guardrail fails visibly instead of becoming a new source of hanging automation.

Step 3: design the PreToolUse gate

The gate reads toolCall.name, the proposed command, working directory, step index, and workspace paths. Define a narrow matrix:

Proposed action Decision Reason
Approved read-only test command in the workspace allow Matches the lab charter
Unrecognized command or expanded arguments force_ask Requires human scope review
Production URL, secret path, privilege escalation, or destructive operation deny Outside the lab boundary

Match normalized tokens and exact working directories; avoid broad substring checks. A command that starts similarly to an approved command may still add a dangerous flag or a second operation. Log only the decision, rule identifier, step index, and a redacted command fingerprint.

Step 4: record PostToolUse outcomes

PostToolUse receives the completed step index, an error string when the tool failed, and common metadata such as conversation and artifact paths. Append a JSON Lines record with:

  • step index;
  • success or failure;
  • normalized error category, not the full secret-bearing message;
  • timestamp;
  • expected artifact names present after the command;
  • conversation identifier stored as a one-way fingerprint if correlation is required.

PostToolUse returns an empty JSON object. It observes; it does not retroactively change the tool result. The later Stop validator uses its record to decide whether completion evidence is sufficient.

Step 5: build a bounded Stop validator

The Stop hook runs when the execution loop terminates. Check the termination reason, error, fullyIdle flag, execution number, and evidence files. Return continue only when the missing item can be recovered safely?for example, the test finished but the structured summary was not created.

Cap continuation. A simple policy is:

  1. On the first stop, continue once if a required report is missing and no unsafe error occurred.
  2. If a background task is still active, continue only to collect its bounded result.
  3. After the cap, allow termination and write an incomplete-run marker.
  4. Never convert a failed test into a pass merely because the agent produced more text.

Without a cap, a permanently missing artifact can create an execution loop. Test the cap before enabling the hook for team use.

Step 6: test the hook matrix

Case Expected behavior
Approved command Allowed; successful outcome recorded
Broader command arguments Fresh approval requested
Explicitly forbidden target Denied before execution
Test exits with failure Error recorded; completion cannot claim pass
Report missing after success One bounded continuation requests evidence
Background task not idle Result collection continues within the cap
Artifact still missing after cap Run terminates as incomplete, not successful
Malformed hook input Hook fails closed with a clear diagnostic

Unit-test each script by piping fixture JSON into it and comparing the exact JSON response. Then run one integration test in the disposable Antigravity workspace. Preserve both the hook output and the final test evidence.

Step 7: review failure modes

Check for secrets in hook logs, path traversal, shell injection, oversized inputs, invalid JSON, unavailable interpreters, timeouts, concurrent file writes, and duplicate events. Use atomic append or a dedicated per-conversation evidence file so parallel runs do not corrupt one another.

Also verify that disabling the hook restores the documented baseline and that removing the customization leaves no hidden dependency. Rollback should be a tested operation, not a note in the README.

QA release checklist

  • Permissions deny sensitive targets independently of hooks.
  • PreToolUse allow, force-ask, and deny paths are tested.
  • PostToolUse records success and failure without leaking secrets.
  • Stop checks the report, log, build identifier, and idle state.
  • Continuation is bounded and cannot create an infinite loop.
  • Failed tests remain failed in the final summary.
  • Malformed input fails closed with a useful diagnostic.
  • Parallel runs cannot overwrite each other’s evidence.
  • Disable and rollback behavior is verified.
  • Human QA retains defect, severity, and release authority.

Antigravity hooks are most valuable when they enforce small, observable rules. Gate the proposed action, record the real outcome, and require the evidence needed to review completion. Then let deterministic tests and a human QA engineer decide whether the software is ready.