# How to Integrate Earendil PI with Google Cloud AI: A Complete Guide

> Integrate Earendil PI with Google Cloud AI. Install the package, configure credentials, and call getModel with stream or complete for seamless AI integration. Get started today.

- Repository: [Earendil Works/pi](https://github.com/earendil-works/pi)
- Tags: how-to-guide
- Published: 2026-05-25

---

**Integrate Earendil PI with Google Cloud AI by installing `@earendil-works/pi-ai`, configuring credentials via API key or Application Default Credentials (ADC), and calling `getModel('google-vertex', <model-id>)` followed by `stream()` or `complete()`.**

Earendil PI provides a unified LLM API that abstracts Google Vertex AI into a provider-agnostic interface. This integration allows you to leverage Gemini models through the same `Context` and streaming patterns used across all PI providers. The implementation resides primarily in [`packages/ai/src/providers/google-vertex.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/google-vertex.ts) and shares conversion logic with [`packages/ai/src/providers/google-shared.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/google-shared.ts).

## Prerequisites and Installation

Begin by installing the official PI AI package:

```bash
npm install @earendil-works/pi-ai

```

Ensure you have access to Google Cloud Platform with Vertex AI API enabled. You will need either a Gemini API key for key-based authentication or a GCP project with appropriate IAM roles for ADC authentication.

## Authentication Methods

Earendil PI supports two authentication flows for Google Cloud AI, handled by the `resolveApiKey`, `resolveProject`, and `resolveLocation` functions in [`packages/ai/src/providers/google-vertex.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/google-vertex.ts).

### Option A: API Key Authentication

Set the environment variable or pass the key directly in options:

```bash
export GOOGLE_CLOUD_API_KEY="YOUR_GEMINI_API_KEY"

```

When `options.apiKey` or `GOOGLE_CLOUD_API_KEY` is present, the provider calls `createClientWithApiKey` (lines 31-57) to build a `GoogleGenAI` instance that sends the key in request headers.

### Option B: Application Default Credentials (Recommended)

For production workloads, use ADC authentication:

```bash
gcloud auth application-default login
export GOOGLE_CLOUD_PROJECT="my-gcp-project"
export GOOGLE_CLOUD_LOCATION="us-central1"

```

Without an API key, the provider invokes `createClient` with `vertexai: true`, `project`, and `location` parameters (lines 38-48). The underlying `@google/genai` library automatically handles token refresh using your local ADC credentials.

## Selecting Vertex AI Models

Retrieve a Vertex model handle using `getModel()` with the provider ID and model name:

```typescript
import { getModel } from '@earendil-works/pi-ai';

const model = getModel('google-vertex', 'gemini-2.5-flash');

```

Available models include `gemini-1.5-pro`, `gemini-2.5-flash`, and `gemini-2.5-flash-image`. The `getModel` function returns a model object configured for Vertex AI endpoints.

## Making Requests

The unified API supports both blocking completion and streaming responses.

### Non-Streaming Completion

Use `complete()` for simple request-response patterns:

```typescript
import { complete, Context } from '@earendil-works/pi-ai';

const ctx: Context = {
  messages: [{ role: 'user', content: 'Explain quantum entanglement in one sentence.' }],
};

const response = await complete(model, ctx);
console.log(response.content[0].text);

```

### Streaming Responses

Use `stream()` for real-time token delivery:

```typescript
import { stream } from '@earendil-works/pi-ai';

const s = stream(model, {
  messages: [{ role: 'user', content: 'Write a 200-word essay about AI.' }]
});

for await (const ev of s) {
  if (ev.type === 'text_delta') process.stdout.write(ev.delta);
  if (ev.type === 'done') console.log('\n[finished]', ev.reason);
}

```

## Advanced Features: Thinking and Tool Calling

### Gemini Thinking Configuration

The `GoogleVertexOptions` interface (lines 38-48) supports a `thinking` option that maps to Vertex's `thinkingConfig`. Configure via `buildParams` (lines 58-70):

```typescript
const s = stream(model, ctx, {
  thinking: { enabled: true, level: 'MEDIUM' }  // or use budgetTokens
});

```

The provider translates `thinking` into either `thinkingLevel` (using `THINKING_LEVEL_MAP`) or `thinkingBudget` depending on your configuration.

### Function Calling Integration

Define tools in your `Context` and specify `toolChoice` to enable agentic behaviors:

```typescript
import { Tool, Type } from '@earendil-works/pi-ai';

const weatherTool: Tool = {
  name: 'get_weather',
  description: 'Retrieve current weather for a city',
  parameters: Type.Object({
    city: Type.String(),
    units: Type.Enum(['celsius', 'fahrenheit'])
  })
};

const ctx: Context = {
  messages: [{ role: 'user', content: 'What is the weather in Paris?' }],
  tools: [weatherTool],
};

const s = stream(model, ctx, { toolChoice: 'auto' });

for await (const ev of s) {
  switch (ev.type) {
    case 'toolcall_start':
      console.log('Tool call started');
      break;
    case 'toolcall_end':
      // Execute tool and append result to context
      ctx.messages.push({
        role: 'toolResult',
        toolCallId: ev.toolCall.id,
        toolName: ev.toolCall.name,
        content: [{ type: 'text', text: 'Paris: 12°C, clear sky' }],
        isError: false,
        timestamp: Date.now(),
      });
      break;
  }
}

```

When `toolChoice` is set, the provider adds a `toolConfig` block to the Vertex request (lines 48-55) and converts returning `functionCall` parts into PI `toolCall` events (lines 74-88).

## Cross-Provider Handoffs

Earendil PI enables seamless migration of conversations between providers without losing context. Switch from Vertex to another provider mid-conversation:

```typescript
import { getModel, complete } from '@earendil-works/pi-ai';

let ctx = { messages: [{ role: 'user', content: 'Describe a cat.' }] };

// First call with Vertex
const vertex = getModel('google-vertex', 'gemini-2.5-flash');
ctx.messages.push(await complete(vertex, ctx));

// Handoff to OpenAI for image generation
const openai = getModel('openai', 'gpt-4o-mini');
ctx.messages.push({ role: 'user', content: 'Generate an image of that cat.' });
const imgResp = await complete(openai, ctx);

```

This handoff logic requires no additional code—the `Context` object maintains conversation state across different provider implementations.

## Summary

- **Install** the `@earendil-works/pi-ai` package to access the unified API.
- **Authenticate** using either `GOOGLE_CLOUD_API_KEY` or ADC with `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION` environment variables.
- **Initialize** Vertex models via `getModel('google-vertex', <model-id>)` defined in [`packages/ai/src/providers/google-vertex.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/google-vertex.ts).
- **Execute** requests using `complete()` for blocking calls or `stream()` for real-time events.
- **Configure** advanced features like Gemini `thinking` modes and `toolChoice` through the `GoogleVertexOptions` interface.
- **Migrate** conversations between providers using PI's built-in cross-provider handoff capabilities.

## Frequently Asked Questions

### How does Earendil PI handle authentication when both API key and ADC are configured?

**API key authentication takes precedence.** The `resolveApiKey` function (lines 97-109) checks for `options.apiKey` or the `GOOGLE_CLOUD_API_KEY` environment variable first. Only if these are absent does the provider fall back to ADC mode using `resolveProject` and `resolveLocation` (lines 109-125), constructing the client with `vertexai: true`.

### Can I use Gemini's thinking mode with streaming responses?

**Yes.** When you set `thinking: { enabled: true, level: 'MEDIUM' }` or specify `budgetTokens`, the `buildParams` function (lines 58-70) injects `thinkingConfig` into the Vertex request. The streaming loop (lines 106-190) emits `thinking_delta` events alongside `text_delta` events, allowing you to monitor the model's reasoning process in real-time.

### What file handles the conversion between PI's Context format and Vertex's expected schema?

**Conversion logic resides in [`packages/ai/src/providers/google-shared.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/google-shared.ts).** This module exports `convertMessages` and `convertTools` functions that transform PI's unified message format into Vertex's content structure. The [`google-vertex.ts`](https://github.com/earendil-works/pi/blob/main/google-vertex.ts) provider imports these helpers to ensure consistent request formatting across Google Cloud AI integrations.

### Is it possible to abort an ongoing streaming request?

**Yes.** Pass an `AbortController` signal through the options parameter. The streaming implementation in [`packages/ai/src/providers/google-vertex.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/google-vertex.ts) respects the `signal` option, allowing you to cancel in-flight requests. Wrap your `for await` loop in try-catch blocks to handle `AbortError` exceptions gracefully.