---
name: sdk-test-architecture
type: reference
title: "Antigravity Architecture — JETSKY Ecosystem Reference"
description: "Synthesized architecture of the Google Antigravity platform: Jetsky ecosystem map, auth chain, token lifecycle, model configuration, and gRPC wire protocol"
tags: [architecture, antigravity, jetsky, oauth2, grpc, protobuf, keychain]
timestamp: 2026-07-21
---

# Antigravity Architecture — JETSKY Ecosystem Reference

## What Is JETSKY?

JETSKY is the internal codename for the Google Antigravity platform — a suite of AI-powered coding tools. The ecosystem comprises three principal binaries and a Python SDK, all sharing a unified authentication layer backed by the macOS Keychain.

```mermaid
graph TB
    subgraph "JETSKY Ecosystem"
        Master["Antigravity Master<br/>(Electron)"]
        IDE["Antigravity IDE<br/>(VSCode Fork)"]
        CLI["Antigravity CLI — agy<br/>(Go ARM64, 99MB)"]
        SDK["antigravity-sdk-python<br/>(google.antigravity)"]
    end

    subgraph "Shared Auth Layer"
        KC["macOS Keychain<br/>Service: gemini<br/>Account: antigravity"]
    end

    Master -->|installation_id: aba9d234| KC
    IDE -->|installation_id: aba9d234| KC
    CLI -->|installation_id: 17ac69b8| KC
    SDK -.->|RFC-001: Keychain Derivation| KC

    Master <-->|shared token| IDE
    CLI -->|passive refresh| KC
    KC -->|fresh token| IDE
```

## Binary Inventory

### 1. Antigravity Master (Electron)

The main desktop application. An Electron wrapper providing the graphical UI layer.

- **Technology**: Electron (Node.js + Chromium)
- **Location**: `/Applications/Antigravity.app/`
- **Installation ID**: `aba9d234-1284-4a20-98e6-0fa3cf57de66` (shared with IDE)
- **Auth Role**: Initiates the OAuth2 PKCE flow, writes tokens to the shared keychain entry
- **Notable**: Business logic runs as JS/TS in the renderer process, but all native operations (keychain access, file I/O) cross a bridge to the native layer

### 2. Antigravity IDE (VSCode Fork)

A fork of Visual Studio Code with Antigravity extensions pre-installed.

- **Technology**: VSCode (Electron-based)
- **Location**: `/Applications/Antigravity IDE.app/`
- **Installation ID**: `aba9d234-1284-4a20-98e6-0fa3cf57de66` (same as Master)
- **Auth Role**: Reads tokens from the shared keychain — does NOT initiate its own PKCE flow
- **Notable**: Shares the same `installation_id` as Master, meaning they appear as a single client to Google's backend. One PKCE authorization covers both.

### 3. Antigravity CLI (agy)

The terminal-native agent.

- **Technology**: Go (ARM64 binary, ~99MB)
- **Location**: `/Users/alefita/.local/bin/agy`
- **Installation ID**: `17ac69b8-1279-4ce5-9201-10ee019953cd` (different from Master/IDE)
- **Auth Role**: Contains its own `TrySilentAuth` → `ChainedAuth` flow. Reads from the same keychain entry but uses a different installation ID for telemetry.
- **Key Discovery**: Running `agy --print <anything>` triggers a model call which invokes the auth chain. If the token is expired, this transparently refreshes it and writes the new token back to the keychain — benefiting ALL other components.

### 4. antigravity-sdk-python

The Python SDK for building custom agents.

- **Technology**: Python (pip-installable package)
- **Location**: `/Users/alefita/probe/sdk-test/antigravity-sdk-python/`
- **Package**: `google.antigravity`
- **Key Classes**: `Agent`, types (37KB of type definitions), connections, hooks, triggers, tools
- **Integration Point**: `CustomModelInfoOverride` — the intended pathway for routing to local (Gemma) or external (DeepSeek) models

## Authentication Chain

The complete OAuth2 flow extracted via Ghidra decompilation.

```mermaid
flowchart TD
    A["API Call Needed"] --> B["TrySilentAuth()"]
    B --> C{"Token cached<br/>in memory?"}
    C -->|YES| D{"Token valid?<br/>(TTL check)"}
    C -->|NO| E{"Token in file<br/>fallback?"}
    D -->|YES| F["Return Bearer<br/>access_token"]
    D -->|NO| G["refreshAndSaveToken()"]
    E -->|YES| H{"Token valid?"}
    E -->|NO| I["ChainedAuth()"]
    H -->|YES| F
    H -->|NO| G
    I --> J["keyringAuth()<br/>macOS Keychain"]
    J -->|Found| K{"Token valid?"}
    K -->|YES| F
    K -->|NO| G
    J -->|Not Found| L["fileAuth()<br/>~/.gemini/"]
    L -->|Found| M{"Token valid?"}
    M -->|YES| F
    M -->|NO| G
    L -->|Not Found| N["interactiveAuth()<br/>PKCE Browser Flow"]

    G --> O["POST oauth2.googleapis.com/token"]
    O --> P["applyAuthResult()"]
    P --> Q["Update Keychain"]
    P --> R["Update File Cache"]
    P --> S["Update Memory Cache"]
    Q --> F
    R --> F
    S --> F
```

### Decompiled Auth Functions

| Function | Package Path | Purpose |
|----------|-------------|---------|
| `TrySilentAuth` | `auth.(*AuthProvider)` | Entry point — checks memory cache, delegates if expired |
| `ChainedAuth` | `auth.(*AuthProvider)` | Chains keyring → file → interactive auth strategies |
| `keyringAuth` | `auth.(*AuthProvider)` | Reads from macOS Keychain via `go-keyring` library |
| `refreshAndSaveToken` | `auth.(*AuthProvider)` | POSTs to Google OAuth2 endpoint, updates all storage layers |
| `applyAuthResult` | `auth.(*AuthProvider)` | Writes refreshed credentials to keychain + file + memory |
| `GetGrantedScopes` | `auth.(*AuthProvider)` | Returns scopes from original PKCE authorization |

### Keychain Storage Format

```
Service:  "gemini"
Account:  "antigravity"
Format:   go-keyring-base64:<base64(JSON)>
```

The base64-decoded JSON contains:

```json
{
  "access_token": "<current_token>",
  "refresh_token": "<offline_refresh_token>",
  "token_type": "Bearer",
  "expiry": "<RFC3339_timestamp>",
  "client_id": "1071006060591-tmhssin2h21lcre235vtolojh4g403ep",
  "client_secret": "GOCSPX-REDACTED-1",
  "granted_scopes": ["openid", "email", "profile", ...]
}
```

### Keychain Read Timeout

The keychain read has a **1-second timeout**. If the macOS Keychain is locked or unresponsive, the auth chain falls through to the file fallback.

### OAuth2 Scopes

```
openid
email
profile
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profile
https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/cclog                    ← Corporate logging
https://www.googleapis.com/auth/experimentsandconfigs    ← Feature flags
```

The `cloud-platform` scope is the most significant — it enables full GCP API access.

## Token Lifecycle

### TTL Characteristics

| Property | Value |
|----------|-------|
| Type | OAuth2 Bearer Token |
| TTL | ~3600 seconds (1 hour) |
| Format | JWT (opaque) |
| Refresh | Via `refresh_token` (offline, persistent) |
| Storage | Keychain (primary) + `~/.gemini/` (fallback) |

```mermaid
timeline
    title Token Lifecycle Timeline
    Token A Valid : Auth (PKCE) : 0s
    Token A Valid : Token Active : 0-3600s
    Token B Valid : Auto Refresh : 3600s
    Token B Valid : Token Active : 3600-7200s
    Token C Valid : Auto Refresh : 7200s
```

### Dual Storage Architecture

```mermaid
graph TB
    subgraph "AuthProvider Singleton"
        MC["Memory Cache<br/>access_token, expiry"]
        KC["macOS Keychain<br/>(Primary, 1s timeout)"]
        FF["File Fallback<br/>~/.gemini/"]
    end

    MC <-->|read/write| KC
    MC <-->|read/write| FF
```

### Refresh Mechanics

1. **On API call**: Any `agy` command invokes `TrySilentAuth()`, which checks TTL. If expired, `refreshAndSaveToken()` fires automatically.
2. **Passive via Heartbeat**: `agy --print "secret 4747 secret"` triggers the same flow.
3. **NOT on a timer**: There is no background daemon or periodic timer in the `agy` binary. Refresh only happens when invoked.

### Refresh HTTP Request

```http
POST https://oauth2.googleapis.com/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&client_id=1071006060591-tmhssin2h21lcre235vtolojh4g403ep
&client_secret=GOCSPX-REDACTED-1
&refresh_token=<stored_refresh_token>
```

### Token Validation

```bash
curl -s "https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=<token>" | python3 -m json.tool
```

Returns: `expires_in` (remaining TTL), `scope`, `azp` (client ID), `email`.

## Model Configuration

### ModelInfo Proto (25 Fields)

The central data structure for configuring model behavior.

```mermaid
graph LR
    subgraph "Provider Selection Chain"
        MP["ModelProvider<br/>OPENAI|ANTHROPIC|<br/>GOOGLE|CUSTOM"]
        AP["APIProvider<br/>CODEIUM|CLOUD_CODE|<br/>FIRST_PARTY"]
        BT["BackendType<br/>CLOUD|LOCAL|HYBRID"]
        HD["HybridDeployment<br/>CLOUD_ONLY|LOCAL_ONLY|<br/>CLOUD_WITH_LOCAL_FALLBACK|<br/>LOCAL_WITH_CLOUD_FALLBACK"]
    end

    MP --> AP --> BT --> HD
```

### Configuration Scenarios

| Scenario | Provider | API | Backend | Hybrid |
|----------|----------|-----|---------|--------|
| Cloud Gemini | GOOGLE | FIRST_PARTY | CLOUD | CLOUD_ONLY |
| Local Gemma | CUSTOM | — | LOCAL | LOCAL_ONLY |
| Hybrid DeepSeek | CUSTOM | — | HYBRID | CLOUD_WITH_LOCAL_FALLBACK |

### Prompt Formatting

| PromptTemplaterType | Format | Used For |
|---------------------|--------|----------|
| NONE | Raw prompt | Direct model calls |
| GENERAL | Standard template | Most models |
| GEMINI_LEGACY | Legacy Gemini format | Gemini 1.x |
| DEEPSEEK_REASONER | DeepSeek reasoning format | DeepSeek v4 |
| GEMINI_2_0 | Gemini 2.0 format | Gemini 2.x+ |

### Tool Formatting

| ToolFormatterType | Format | Used For |
|-------------------|--------|----------|
| NATIVE | Model's native tool format | OpenAI, Anthropic |
| XML | XML tool definitions | Some open models |
| MARKDOWN | Markdown descriptions | Fallback for models without native tool support |

### Capability Flags

```protobuf
bool supports_tools = 13;
bool supports_streaming = 14;
bool supports_system_prompt = 15;
bool supports_images = 16;
```

### SDK CustomModelInfoOverride Mapping

| ModelInfo Field | SDK Override |
|-----------------|-------------|
| `model_id` | `model_name` |
| `api_endpoint` | `endpoint` |
| `api_key_env` | `api_key` |
| `provider` | Inferred from endpoint |
| `backend_type` | Inferred (localhost = LOCAL) |

## gRPC Wire Protocol

### Primary Endpoint

| Property | Value |
|----------|-------|
| Proxy URL | `https://cloudcode-pa.googleapis.com` |
| Service | `exa.language_server_pb.LanguageServerService` |

### gRPC Methods

| Method | Type | Description |
|--------|------|-------------|
| `ValidateProject` | Unary | Validates project configuration and permissions |
| `GetCompletions` | Unary | Code completion requests |
| `Chat` | Server streaming | Streaming chat conversations |

### Authentication Headers

```
authorization: Bearer <access_token>
x-goog-api-client: <client_identification_string>
x-goog-user-project: <project_id>
x-codeium-csrf-token: <csrf_token>
X-Http-Session-Id: <session_id>
```

### Proxy Headers

```
X-Forwarded-For: <client_ip>
X-Forwarded-Host: <original_host>
X-Forwarded-Proto: https
```

### Google-Specific Headers

| Header | Purpose |
|--------|---------|
| `x-goog-sherlog-Link` | Logging/tracing link |
| `x-goog-cloud-target-resource` | Target resource routing |
| `X-Goog-Ext-525006001-bin` | Binary extension data |
| `X-Goog-Drive-Resource-Keys` | Drive resource keys |
| `X-Goog-Request-Reason` | Audit trail |

### Token Lifecycle in gRPC

gRPC metadata headers are set once per connection. If the token expires during a long-running stream, the connection may be terminated with `UNAUTHENTICATED` status, requiring reconnection with a fresh token.

## API Endpoints Summary

| Endpoint | URL | Method | Purpose |
|----------|-----|--------|---------|
| Token Refresh | `https://oauth2.googleapis.com/token` | POST | Refresh access_token |
| Token Validation | `https://www.googleapis.com/oauth2/v3/tokeninfo` | GET | Validate + metadata |
| CodeAssist Proxy | `https://cloudcode-pa.googleapis.com` | gRPC | Model API proxy |
| User Info | `https://www.googleapis.com/oauth2/v1/userinfo` | GET | Profile data |
| PKCE Auth | `https://accounts.google.com/o/oauth2/v2/auth` | GET | Interactive auth |
| ValidateProject | `<proxy>/exa.language_server_pb.LanguageServerService/ValidateProject` | gRPC | Project validation |

## Deep-Dive Pages

| Topic | Deep-Dive Page | Key Content |
|-------|---------------|-------------|
| Localharness binary | [[sdk-test-localharness]] | Go binary subprocess model, WebSocket protocol, 7-phase lifecycle |
| Protobuf wire format | [[sdk-test-protobuf]] | Every message type, all fields, oneof patterns |
| Hook system | [[sdk-test-hooks-deep]] | 9 hook types, HookRunner dispatch, 9-level policy system |
| Authentication chain | [[sdk-test-auth-chain]] | TrySilentAuth flow, keychain format, token lifecycle, PKCE |
| gRPC protocol | [[sdk-test-grpc-protocol]] | Service methods, auth headers, streaming, error recovery |
| Decompiled patterns | [[sdk-test-decompiled-patterns]] | 10 architectural patterns from 3305 functions |
| DeepSeek + Heartbeat | [[sdk-test-deepseek-heartbeat]] | DeepSeek V4, Heartbeat Protocol, Proto-Unicode sequences |

## Cross-References

- [[sdk-test-antigravity-sdk]] — Full SDK reference (Agent, Conversation, types, tools, hooks, triggers)
- [[sdk-test-reverse-engineering]] — Full RE analysis of the agy binary (3305 decompiled functions)
- [[sdk-test-integrations]] — DeepSeek, heartbeat, Gemma 4, SDK integration details
- [[sdk-test-synthesis]] — Epiphany synthesis and RFC-001
- antigravity-2.0 — The broader Antigravity platform context
