---
name: sdk-test-grpc-protocol
type: reference
title: "gRPC Protocol — Wire Format and Service Methods"
description: "Complete gRPC protocol reference for the Antigravity Language Server Service: endpoints, service methods, authentication headers, message types, and streaming behavior"
tags: [grpc, protobuf, wire-format, api, cloudcode, language-server, streaming]
timestamp: 2026-07-22
---

# gRPC Protocol — Wire Format and Service Methods

## Overview

The localharness Go binary communicates with Google's backend via **gRPC** through the Cloud Code proxy endpoint. This is the protocol used for all model API calls, code completions, and project validation. The SDK itself never speaks gRPC directly -- it delegates to the harness over WebSocket, and the harness handles gRPC communication.

```mermaid
graph LR
    subgraph "SDK Process"
        SDK["Python SDK"]
    end

    subgraph "Harness Process"
        LH["localharness<br/>(Go binary)"]
        Gen["generator.<br/>requestBuilder"]
    end

    subgraph "Google Backend"
        Proxy["cloudcode-pa.googleapis.com<br/>(Cloud Code Proxy)"]
        Gemini["Gemini API"]
    end

    SDK -->|"WebSocket<br/>JSON-serialized protobuf"| LH
    LH --> Gen
    Gen -->|"gRPC<br/>binary protobuf + Bearer token"| Proxy
    Proxy --> Gemini
```

## Primary Endpoint

| Property | Value |
|----------|-------|
| Proxy URL | `https://cloudcode-pa.googleapis.com` |
| Service | `exa.language_server_pb.LanguageServerService` |
| Protocol | gRPC (HTTP/2, binary protobuf) |
| Transport | TLS 1.3 |

The endpoint is a **proxy** -- it routes requests to the appropriate backend (Gemini API, Vertex AI, etc.) based on the authentication context and request parameters.

## Service Definition

```protobuf
syntax = "proto3";
package exa.language_server_pb;

service LanguageServerService {
  // Project validation
  rpc ValidateProject (ValidateProjectRequest) returns (ValidateProjectResponse);
  
  // Code completion
  rpc GetCompletions (GetCompletionsRequest) returns (GetCompletionsResponse);
  
  // Streaming chat (the primary method for agent conversations)
  rpc Chat (ChatRequest) returns (stream ChatResponse);
}
```

### Method Details

#### ValidateProject

| Property | Value |
|----------|-------|
| Type | Unary |
| Purpose | Validates project configuration and permissions |
| Called | At session startup, before first Chat call |
| Returns | Project status, permissions, quotas |

This method is called to verify that the authenticated user has access to the requested project and that the project is properly configured. It also returns quota and billing information.

#### GetCompletions

| Property | Value |
|----------|-------|
| Type | Unary |
| Purpose | Code completion requests |
| Called | On-demand for tab completions in IDE context |
| Returns | Ranked completion candidates |

Used primarily by the IDE integration for inline code completions. The harness uses this for the "tab completion" feature, not for conversational agent interactions.

#### Chat

| Property | Value |
|----------|-------|
| Type | Server-side streaming |
| Purpose | Conversational agent interactions |
| Called | For every user message in the agent loop |
| Returns | Stream of `ChatResponse` messages |

This is the **primary method** used by the agent loop. The harness sends a `ChatRequest` containing the conversation history, system instructions, and available tools, then receives a stream of response chunks.

### Service Descriptors (from Decompilation)

The decompiled binary reveals the full service descriptor generation:

```go
// Decompiled: language_server_go_grpc.generateLanguageServerServiceServiceDesc
func generateLanguageServerServiceServiceDesc() grpc.ServiceDesc {
    return grpc.ServiceDesc{
        ServiceName: "exa.language_server_pb.LanguageServerService",
        Methods: []grpc.MethodDesc{
            {MethodName: "ValidateProject", Handler: validateProjectHandler},
            {MethodName: "GetCompletions", Handler: getCompletionsHandler},
        },
        Streams: []grpc.StreamDesc{
            {StreamName: "Chat", Handler: chatStreamHandler, ServerStreams: true},
        },
    }
}
```

The `LanguageServerServiceHandlerHook` pattern shows hook points where method handlers can be intercepted -- enabling middleware-style processing of all gRPC calls.

## Authentication Headers

All gRPC calls include the following metadata headers:

### Required Headers

```protobuf
// Set on every gRPC call
metadata.Set("authorization", "Bearer " + accessToken)
metadata.Set("x-goog-api-client", clientIdentificationString)
metadata.Set("x-goog-user-project", projectId)
metadata.Set("x-codeium-csrf-token", csrfToken)
metadata.Set("X-Http-Session-Id", sessionId)
```

| Header | Purpose | Value Source |
|--------|---------|-------------|
| `authorization` | OAuth2 Bearer token | Auth chain (keychain/file/cache) |
| `x-goog-api-client` | Client identification | Compiled into binary |
| `x-goog-user-project` | Billing project | GCP project ID |
| `x-codeium-csrf-token` | CSRF protection | Generated per session |
| `X-Http-Session-Id` | Session tracking | Generated per connection |

### Google-Specific Headers

These headers provide additional routing, logging, and tracing information:

| Header | Purpose | When Used |
|--------|---------|-----------|
| `x-goog-sherlog-Link` | Internal logging/tracing correlation | All calls |
| `x-goog-cloud-target-resource` | Target resource routing | Vertex AI calls |
| `X-Goog-Ext-525006001-bin` | Binary extension data (protobuf-encoded) | Feature negotiation |
| `X-Goog-Drive-Resource-Keys` | Drive resource keys | Drive-integrated features |
| `X-Goog-Request-Reason` | Audit trail | All calls |

### API Key Header (Non-OAuth)

For non-OAuth flows (direct API key authentication):

```protobuf
metadata.Set("x-api-key", apiKey)
```

This is used when the SDK is configured with a Gemini API key instead of OAuth2 credentials. The harness detects this and uses `x-api-key` instead of `authorization: Bearer`.

## Authentication Flow in gRPC Context

```mermaid
sequenceDiagram
    participant SDK as Python SDK
    participant Harness as localharness
    participant Auth as Auth Provider
    participant Proxy as cloudcode-pa.googleapis.com
    participant Gemini as Gemini API

    Note over SDK,Gemini: Chat Request Flow

    SDK->>Harness: InputEvent{user_input: "prompt"}
    Harness->>Auth: TrySilentAuth()
    
    alt Token valid
        Auth-->>Harness: access_token
    else Token expired
        Auth->>Auth: refreshAndSaveToken()
        Auth-->>Harness: fresh access_token
    end

    Harness->>Harness: Build ChatRequest protobuf
    Harness->>Harness: Set gRPC metadata headers

    Harness->>Proxy: gRPC Chat(ChatRequest)
    Note right of Harness: Headers:<br/>authorization: Bearer [token]<br/>x-goog-api-client: [id]<br/>x-goog-user-project: [project]<br/>x-codeium-csrf-token: [csrf]<br/>X-Http-Session-Id: [session]

    Proxy->>Gemini: Forward request
    Gemini-->>Proxy: Streaming response

    loop Each response chunk
        Proxy-->>Harness: ChatResponse (stream)
        Harness-->>SDK: OutputEvent{step_update}
    end

    Proxy-->>Harness: Stream complete
    Harness-->>SDK: OutputEvent{step_update: DONE}
```

## Token Expiry During Streaming

gRPC metadata headers are set **once per connection**. If the access token expires during a long-running streaming response, the connection may be terminated:

```mermaid
sequenceDiagram
    participant H as Harness
    participant P as Proxy

    H->>P: gRPC Chat (token valid, TTL=300s)
    P-->>H: ChatResponse chunk 1
    P-->>H: ChatResponse chunk 2
    
    Note over H: Token expires (TTL=0)

    P-->>H: UNAUTHENTICATED error
    Note right of H: gRPC status code: 16<br/>"Request had invalid authentication credentials"

    H->>H: TrySilentAuth() → refresh token
    H->>P: New gRPC Chat (fresh token)
    P-->>H: ChatResponse (resumed)
```

The harness handles this by catching `UNAUTHENTICATED` status errors and retrying with a fresh token. This is transparent to the SDK.

## Additional gRPC Services

Beyond `LanguageServerService`, the decompiled binary reveals several additional gRPC services:

### ApiServerService

```protobuf
service ApiServerService {
  rpc ApplyTrajectoryHeuristics (...) returns (...);
  rpc CreateTrajectoryShareStream (...) returns (...);
  rpc GetCascadeModelConfigs (...) returns (...);
  rpc GetCommandModelConfigs (...) returns (...);
  rpc GetCompletionExamples (...) returns (...);
  rpc GetDeploymentConfig (...) returns (...);
  rpc GetEmbeddings (...) returns (...);
  rpc GetImageGeneration (...) returns (...);
  rpc GetMQuery (...) returns (...);
  rpc GetMcpServerTemplates (...) returns (...);
  rpc GetModelInfos (...) returns (...);
  rpc GetModelStatuses (...) returns (...);
  rpc GetTeamOrganizationalControls (...) returns (...);
  rpc GetTranscription (...) returns (...);
  rpc GetUnleashContextFields (...) returns (...);
  rpc GetWebDocsOptions (...) returns (...);
  rpc GetWebSearchRedirect (...) returns (...);
  rpc GetWebSearchResults (...) returns (...);
  rpc ProvideFeedback (...) returns (...);
  rpc RecordAsyncTelemetry (...) returns (...);
}
```

This service handles configuration, metadata, and management operations. It is used for:
- Model discovery and status checks
- MCP server template retrieval
- Feature flag context (`UnleashContextFields`)
- Telemetry submission
- Embedding generation

### CloudCode Service (v1internal)

```protobuf
service CloudCode {
  rpc CompleteCode (...) returns (...);
  rpc FetchAdminControls (...) returns (...);
  rpc FetchCodeCustomizationState (...) returns (...);
  rpc GenerateChat (...) returns (...);
  rpc GetCodeAssistGlobalUserSetting (...) returns (...);
  rpc InternalAtomicAgenticChat (...) returns (...);
  rpc ListAgents (...) returns (...);
  rpc ListCloudAICompanionProjects (...) returns (...);
  rpc ListExperiments (...) returns (...);
  rpc ListModelConfigs (...) returns (...);
  rpc ListRemoteRepositories (...) returns (...);
  rpc LoadCodeAssist (...) returns (...);
  rpc MigrateDatabaseCode (...) returns (...);
  rpc OnboardUser (...) returns (...);
  rpc RecordClientEvent (...) returns (...);
  rpc RecordCodeAssistMetrics (...) returns (...);
  rpc RecordSmartchoicesFeedback (...) returns (...);
  rpc SearchSnippets (...) returns (...);
  rpc SetCodeAssistGlobalUserSetting (...) returns (...);
  rpc TransformCode (...) returns (...);
}
```

This is the internal Cloud Code service used for:
- Code completion and transformation
- Agent listing and management
- User onboarding
- Admin controls
- A/B experiment management

### AnalyticsService

```protobuf
service AnalyticsService {
  rpc RecordEvent (...) returns (...);
  // Additional telemetry methods
}
```

Handles telemetry event recording. Events use the `ProductEvent` protobuf format.

## gRPC Error Codes

The harness handles the following gRPC status codes:

| Code | Name | Meaning | Handling |
|------|------|---------|----------|
| 0 | OK | Success | Normal processing |
| 1 | CANCELLED | Call cancelled | By SDK cancel request |
| 3 | INVALID_ARGUMENT | Bad request | Log and surface to SDK |
| 7 | PERMISSION_DENIED | Auth insufficient | Trigger re-auth |
| 8 | RESOURCE_EXHAUSTED | Quota exceeded | Surface to SDK as error |
| 10 | ABORTED | Operation aborted | Retry if idempotent |
| 13 | INTERNAL | Server error | Retry with backoff |
| 14 | UNAVAILABLE | Service down | Retry with backoff |
| 16 | UNAUTHENTICATED | Token expired | Refresh token, retry |

### Error Recovery Pattern

```mermaid
flowchart TD
    Req["gRPC Request"] --> Check{"Response status?"}
    Check -->|OK| Success["Process response"]
    Check -->|UNAUTHENTICATED| Refresh["TrySilentAuth() → refresh"]
    Refresh --> Retry["Retry request with fresh token"]
    Retry --> Check
    Check -->|UNAVAILABLE| Backoff["Exponential backoff"]
    Backoff --> Retry
    Check -->|RESOURCE_EXHAUSTED| Quota["Surface quota error to SDK"]
    Check -->|Other| Error["Log error, surface to SDK"]
```

## Wire Format Details

### gRPC Message Framing

gRPC uses HTTP/2 with a 5-byte header prefix:
```
[1 byte: compressed flag][4 bytes uint32: message length][protobuf bytes]
```

### Protobuf Serialization

All gRPC messages use standard binary protobuf serialization (NOT JSON, unlike the WebSocket protocol between SDK and harness).

### Streaming

The `Chat` method uses server-side streaming:
- Client sends ONE `ChatRequest`
- Server sends MULTIPLE `ChatResponse` messages
- Stream ends when server sends trailing metadata

Each `ChatResponse` may contain:
- Text deltas (incremental response tokens)
- Thinking deltas (reasoning tokens)
- Tool call requests
- Usage metadata
- State transitions

## Relationship to WebSocket Protocol

The gRPC protocol is **internal to the harness**. The SDK never interacts with it directly. The translation layer:

```mermaid
graph TB
    subgraph "SDK Side"
        IE["InputEvent<br/>(JSON over WebSocket)"]
    end

    subgraph "Harness Side"
        WS["WebSocket Handler"]
        AL["Agent Loop"]
        Gen["generator.requestBuilder"]
        GRPC["gRPC Client"]
    end

    subgraph "Backend"
        Proxy["cloudcode-pa.googleapis.com"]
    end

    IE -->|"JSON protobuf"| WS
    WS -->|"Parsed InputEvent"| AL
    AL -->|"Build ChatRequest"| Gen
    Gen -->|"Binary protobuf"| GRPC
    GRPC -->|"HTTP/2 + TLS"| Proxy
    Proxy -->|"Stream ChatResponse"| GRPC
    GRPC -->|"Parsed responses"| AL
    AL -->|"Build OutputEvent"| WS
    WS -->|"JSON protobuf"| IE
```

## CelEnforcer (Request Authorization)

The decompiled binary includes a CEL (Common Expression Language) enforcement layer:

```go
// Decompiled: celEnforcer.IsRequestAllowed
func (e *CelEnforcer) IsRequestAllowed(request *Request) bool {
    // Evaluates CEL expressions against the request
    // Used for fine-grained authorization in sandbox proxy
}
```

This provides **expression-based access control** for gRPC requests. CEL expressions can evaluate arbitrary conditions on the request context, enabling:
- Per-user rate limiting
- Feature gating
- Geographic restrictions
- Custom authorization rules

## Sandbox Proxy

The `sandboxproxy` package implements a proxy layer for sandboxed execution environments:

```go
// Decompiled: sandboxproxy.NewServer
func NewServer(config *Config) *Server {
    // Creates a proxy server that intercepts gRPC calls
    // Applies CEL enforcement
    // Routes to appropriate backend
}
```

The sandbox proxy:
1. Intercepts incoming gRPC requests
2. Applies CEL enforcement rules
3. Routes to the appropriate backend
4. Handles authentication forwarding

## Cross-References

- [[sdk-test-auth-chain]] — How auth tokens are obtained and refreshed for gRPC calls
- [[sdk-test-protobuf]] — Protobuf message definitions used in gRPC messages
- [[sdk-test-localharness]] — How the harness manages the gRPC connection lifecycle
- [[sdk-test-decompiled-patterns]] — Decompiled gRPC service descriptors and handlers
- [[sdk-test-architecture]] — JETSKY ecosystem architecture

---

*Source: Decompiled from `agy` binary via Ghidra MCP. Functions: `language_server_go_grpc.*`, `language_server_go_proto.*`, `api_server_go_proto.*`, `v1internal_go_proto.*`, `codeassistclient.*`. Service descriptors extracted from `generateLanguageServerServiceServiceDesc`.*
