Antigravity Unified Gateway API Specification

February 18, 2026 · View on GitHub

Version: 1.0 Last Updated: December 13, 2025 Status: Verified by Direct API Testing


Overview

Antigravity is Google's Unified Gateway API for accessing multiple AI models (Claude, Gemini, GPT-OSS) through a single, consistent Gemini-style interface. It is NOT the same as Vertex AI's direct model APIs.

Key Characteristics

  • Single API format for all models (Gemini-style)
  • Project-based access via Google Cloud authentication
  • Internal routing to model backends (Vertex AI for Claude, Gemini API for Gemini)
  • Unified response format (candidates[] structure for all models)

Endpoints

EnvironmentURLStatus
Daily (Sandbox)https://daily-cloudcode-pa.sandbox.googleapis.com✅ Active
Productionhttps://cloudcode-pa.googleapis.com✅ Active
Autopush (Sandbox)https://autopush-cloudcode-pa.sandbox.googleapis.com❌ Unavailable

API Actions

ActionPathDescription
Generate Content/v1internal:generateContentNon-streaming request
Stream Generate/v1internal:streamGenerateContent?alt=sseStreaming (SSE) request
Load Code Assist/v1internal:loadCodeAssistProject discovery
Onboard User/v1internal:onboardUserUser onboarding

Authentication

OAuth 2.0 Setup

Authorization URL: https://accounts.google.com/o/oauth2/auth
Token URL: https://oauth2.googleapis.com/token

Required Scopes

https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profile
https://www.googleapis.com/auth/cclog
https://www.googleapis.com/auth/experimentsandconfigs

Required Headers

Authorization: Bearer {access_token}
Content-Type: application/json
User-Agent: antigravity/1.15.8 windows/amd64
X-Goog-Api-Client: google-cloud-sdk vscode_cloudshelleditor/0.1
Client-Metadata: {"ideType":"ANTIGRAVITY","platform":"MACOS","pluginType":"GEMINI"}

For streaming requests, also include:

Accept: text/event-stream

Available Models

Model NameModel IDTypeStatus
Claude Sonnet 4.6claude-sonnet-4-6Anthropic✅ Verified
Claude Opus 4.6 Thinkingclaude-opus-4-6-thinkingAnthropic✅ Verified
Gemini 3 Pro Highgemini-3-pro-highGoogle✅ Verified
Gemini 3 Pro Lowgemini-3-pro-lowGoogle✅ Verified
GPT-OSS 120B Mediumgpt-oss-120b-mediumOther✅ Verified

Request Format

Basic Structure

{
  "project": "{project_id}",
  "model": "{model_id}",
  "request": {
    "contents": [...],
    "generationConfig": {...},
    "systemInstruction": {...},
    "tools": [...]
  },
  "userAgent": "antigravity",
  "requestId": "{unique_id}"
}

Contents Array (REQUIRED)

⚠️ IMPORTANT: Must use Gemini-style format. Anthropic-style messages array is NOT supported.

{
  "contents": [
    {
      "role": "user",
      "parts": [
        { "text": "Your message here" }
      ]
    },
    {
      "role": "model",
      "parts": [
        { "text": "Assistant response" }
      ]
    }
  ]
}

Role Values

  • user - Human/user messages
  • model - Assistant responses (NOT assistant)

Generation Config

{
  "generationConfig": {
    "maxOutputTokens": 1000,
    "temperature": 0.7,
    "topP": 0.95,
    "topK": 40,
    "stopSequences": ["STOP"],
    "thinkingConfig": {
      "thinkingBudget": 8000,
      "includeThoughts": true
    }
  }
}
FieldTypeDescription
maxOutputTokensnumberMaximum tokens in response
temperaturenumberRandomness (0.0 - 2.0)
topPnumberNucleus sampling threshold
topKnumberTop-K sampling
stopSequencesstring[]Stop generation triggers
thinkingConfigobjectExtended thinking config

System Instructions

⚠️ Must be an object with parts, NOT a plain string.

// ✅ CORRECT
{
  "systemInstruction": {
    "parts": [
      { "text": "You are a helpful assistant." }
    ]
  }
}

// ❌ WRONG - Will return 400 error
{
  "systemInstruction": "You are a helpful assistant."
}

Tools / Function Calling

{
  "tools": [
    {
      "functionDeclarations": [
        {
          "name": "get_weather",
          "description": "Get weather for a location",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "City name"
              }
            },
            "required": ["location"]
          }
        }
      ]
    }
  ]
}

Google Search Grounding

Gemini models support Google Search grounding, but it cannot be combined with function declarations in the same request. This plugin implements a dedicated google_search tool that makes separate API calls.

How the google_search Tool Works

The model can call google_search(query, urls?, thinking?) which:

  1. Makes a separate API call to Antigravity with only { googleSearch: {} } (no function declarations)
  2. Parses the groundingMetadata from the response
  3. Returns formatted markdown with sources and citations

Tool Parameters:

ParameterTypeRequiredDescription
querystringThe search query or question
urlsstring[]URLs to analyze (adds urlContext tool)
thinkingbooleanEnable deep thinking (default: true)

Example Response:

## Search Results

Spain won Euro 2024, defeating England 2-1 in the final...

### Sources
- [UEFA Euro 2024](https://uefa.com/...)
- [Al Jazeera](https://aljazeera.com/...)

### Search Queries Used
- "UEFA Euro 2024 winner"

Raw API Format (for reference)

The underlying API uses these tool formats:

New API (Gemini 2.0+ / Gemini 3):

{
  "tools": [
    { "googleSearch": {} }
  ]
}

Legacy API (Gemini 1.5 only - deprecated):

{
  "tools": [
    {
      "googleSearchRetrieval": {
        "dynamicRetrievalConfig": {
          "mode": "MODE_DYNAMIC",
          "dynamicThreshold": 0.3
        }
      }
    }
  ]
}

Response includes groundingMetadata:

{
  "groundingMetadata": {
    "webSearchQueries": ["query1", "query2"],
    "searchEntryPoint": { "renderedContent": "..." },
    "groundingChunks": [{ "web": { "uri": "...", "title": "..." } }],
    "groundingSupports": [{ "segment": {...}, "groundingChunkIndices": [...] }]
  }
}

Important: googleSearch and urlContext tools cannot be combined with functionDeclarations in the same request. This is why the plugin uses a separate API call.


### Function Name Rules

| Rule | Description |
|------|-------------|
| First character | Must be a letter (a-z, A-Z) or underscore (_) |
| Allowed characters | `a-zA-Z0-9`, underscores (`_`), dots (`.`), colons (`:`), dashes (`-`) |
| Max length | 64 characters |
| Not allowed | Slashes (`/`), spaces, other special characters |

**Examples:**
- ✅ `get_weather` - Valid
- ✅ `mcp:mongodb.query` - Valid (colons and dots allowed)
- ✅ `read-file` - Valid (dashes allowed)
- ❌ `mcp/query` - Invalid (slashes not allowed)
- ❌ `123_tool` - Invalid (must start with letter or underscore)

### JSON Schema Support

| Feature | Status | Notes |
|---------|--------|-------|
| `type` | ✅ Supported | `object`, `string`, `number`, `integer`, `boolean`, `array` |
| `properties` | ✅ Supported | Object properties |
| `required` | ✅ Supported | Required fields array |
| `description` | ✅ Supported | Field descriptions |
| `enum` | ✅ Supported | Enumerated values |
| `items` | ✅ Supported | Array item schema |
| `anyOf` | ✅ Supported | Converted to `any_of` internally |
| `allOf` | ✅ Supported | Converted to `all_of` internally |
| `oneOf` | ✅ Supported | Converted to `one_of` internally |
| `additionalProperties` | ✅ Supported | Additional properties schema |
| `const` | ❌ NOT Supported | Use `enum: [value]` instead |
| `$ref` | ❌ NOT Supported | Inline the schema instead |
| `$defs` / `definitions` | ❌ NOT Supported | Inline definitions instead |
| `$schema` | ❌ NOT Supported | Strip from schema |
| `$id` | ❌ NOT Supported | Strip from schema |
| `default` | ❌ NOT Supported | Strip from schema |
| `examples` | ❌ NOT Supported | Strip from schema |
| `title` (nested) | ⚠️ Caution | May cause issues in nested objects |

**⚠️ IMPORTANT:** The following features will cause a 400 error if sent to the API:
- `const` - Convert to `enum: [value]` instead
- `$ref` / `$defs` - Inline the schema definitions
- `$schema` / `$id` - Strip these metadata fields
- `default` / `examples` - Strip these documentation fields

```json
// ❌ WRONG - Will return 400 error
{ "type": { "const": "email" } }

// ✅ CORRECT - Use enum instead
{ "type": { "enum": ["email"] } }

Note: The plugin automatically handles these conversions via the schema-transform.ts module.


Response Format

Non-Streaming Response

{
  "response": {
    "candidates": [
      {
        "content": {
          "role": "model",
          "parts": [
            { "text": "Response text here" }
          ]
        },
        "finishReason": "STOP"
      }
    ],
    "usageMetadata": {
      "promptTokenCount": 16,
      "candidatesTokenCount": 4,
      "totalTokenCount": 20
    },
    "modelVersion": "claude-sonnet-4-6",
    "responseId": "msg_vrtx_..."
  },
  "traceId": "abc123..."
}

Streaming Response (SSE)

Content-Type: text/event-stream

data: {"response": {"candidates": [{"content": {"role": "model", "parts": [{"text": "Hello"}]}}], "usageMetadata": {...}, "modelVersion": "...", "responseId": "..."}, "traceId": "..."}

data: {"response": {"candidates": [{"content": {"role": "model", "parts": [{"text": " world"}]}, "finishReason": "STOP"}], "usageMetadata": {...}}, "traceId": "..."}

Response Fields

FieldDescription
response.candidatesArray of response candidates
response.candidates[].content.roleAlways "model"
response.candidates[].content.partsArray of content parts
response.candidates[].finishReasonSTOP, MAX_TOKENS, OTHER
response.usageMetadata.promptTokenCountInput tokens
response.usageMetadata.candidatesTokenCountOutput tokens
response.usageMetadata.totalTokenCountTotal tokens
response.usageMetadata.thoughtsTokenCountThinking tokens (Gemini)
response.modelVersionActual model used
response.responseIdRequest ID (format varies by model)
traceIdTrace ID for debugging

Response ID Formats

Model TypeFormatExample
Claudemsg_vrtx_...msg_vrtx_01UDKZG8PWPj9mjajje8d7u7
GeminiBase64-likeypM9abPqFKWl0-kPvamgqQw
GPT-OSSBase64-likey5M9aZaSKq6z2roPoJ7pEA

Function Call Response

When the model wants to call a function:

{
  "response": {
    "candidates": [
      {
        "content": {
          "role": "model",
          "parts": [
            {
              "functionCall": {
                "name": "get_weather",
                "args": {
                  "location": "Paris"
                },
                "id": "toolu_vrtx_01PDbPTJgBJ3AJ8BCnSXvUqk"
              }
            }
          ]
        },
        "finishReason": "OTHER"
      }
    ]
  }
}

Providing Function Results

{
  "contents": [
    { "role": "user", "parts": [{ "text": "What's the weather?" }] },
    { "role": "model", "parts": [{ "functionCall": { "name": "get_weather", "args": {...}, "id": "..." } }] },
    { "role": "user", "parts": [{ "functionResponse": { "name": "get_weather", "id": "...", "response": { "temperature": "22C" } } }] }
  ]
}

Thinking / Extended Reasoning

Thinking Config

For thinking-capable models (*-thinking), use:

{
  "generationConfig": {
    "maxOutputTokens": 10000,
    "thinkingConfig": {
      "thinkingBudget": 8000,
      "includeThoughts": true
    }
  }
}

⚠️ IMPORTANT: maxOutputTokens must be GREATER than thinkingBudget

Thinking Response (Gemini)

Gemini models return thinking with signatures:

{
  "parts": [
    {
      "thoughtSignature": "ErADCq0DAXLI2nx...",
      "text": "Let me think about this..."
    },
    {
      "text": "The answer is..."
    }
  ]
}

Thinking Response (Claude)

Claude thinking models may include thought: true parts:

{
  "parts": [
    {
      "thought": true,
      "text": "Reasoning process...",
      "thoughtSignature": "..."
    },
    {
      "text": "Final answer..."
    }
  ]
}

Error Responses

Error Structure

{
  "error": {
    "code": 400,
    "message": "Error description",
    "status": "INVALID_ARGUMENT",
    "details": [...]
  }
}

Common Error Codes

CodeStatusDescription
400INVALID_ARGUMENTInvalid request format
401UNAUTHENTICATEDInvalid/expired token
403PERMISSION_DENIEDNo access to resource
404NOT_FOUNDModel not found
429RESOURCE_EXHAUSTEDRate limit exceeded

Rate Limit Response

{
  "error": {
    "code": 429,
    "message": "You have exhausted your capacity on this model. Your quota will reset after 3s.",
    "status": "RESOURCE_EXHAUSTED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.RetryInfo",
        "retryDelay": "3.957525076s"
      }
    ]
  }
}

NOT Supported

The following Anthropic/Vertex AI features are NOT supported:

FeatureError
anthropic_versionUnknown field
messages arrayUnknown field
max_tokensUnknown field
Plain string systemInstructionInvalid value
system_instruction (snake_case at root)Unknown field
JSON Schema constUnknown field (use enum: [value])
JSON Schema $refNot supported (inline instead)
JSON Schema $defsNot supported (inline instead)
Tool names with /Invalid (use _ or : instead)
Tool names starting with digitInvalid (must start with letter/underscore)

Complete Request Example

{
  "project": "my-project-id",
  "model": "claude-sonnet-4-6",
  "request": {
    "contents": [
      {
        "role": "user",
        "parts": [
          { "text": "Hello, how are you?" }
        ]
      }
    ],
    "systemInstruction": {
      "parts": [
        { "text": "You are a helpful assistant." }
      ]
    },
    "generationConfig": {
      "maxOutputTokens": 1000,
      "temperature": 0.7
    }
  },
  "userAgent": "antigravity",
  "requestId": "agent-abc123"
}

Response Headers

HeaderDescription
x-cloudaicompanion-trace-idTrace ID for debugging
server-timingRequest duration

Comparison: Antigravity vs Vertex AI Anthropic

FeatureAntigravityVertex AI Anthropic
Endpointcloudcode-pa.googleapis.comaiplatform.googleapis.com
Request formatGemini-style contentsAnthropic messages
anthropic_versionNot usedRequired
Model namesSimple (claude-sonnet-4-6)Versioned (claude-4-5@date)
Response formatcandidates[]Anthropic content[]
Multi-model supportYes (Claude, Gemini, etc.)Anthropic only

Changelog

  • 2025-12-14: Added function calling quirks, JSON Schema support matrix, tool name rules
  • 2025-12-13: Initial specification based on direct API testing