Official TypeScript SDK for Google Gemini — client setup, text generation, multimodal input, function calling, structured output, streaming, embeddings, context caching, and chat sessions
Scanned 9/5/2026
Install to Claude Code
npx -y skills add agents-inc/skills --skill ai-provider-google-gemini-sdk --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Ai Provider Google Gemini Sdk?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/agents-inc-ai-provider-google-gemini-sdk-skills)More formats (shields.io, HTML) on the badges page.
---
name: ai-provider-google-gemini-sdk
description: Official TypeScript SDK for Google Gemini — client setup, text generation, multimodal input, function calling, structured output, streaming, embeddings, context caching, and chat sessions
---
# Google Gemini SDK Patterns
> **Quick Guide:** Use the `@google/genai` package (the unified SDK, NOT the deprecated `@google/generative-ai`) for all Gemini API interactions. All operations flow through a central `GoogleGenAI` client with service accessors: `ai.models` for generation, `ai.chats` for multi-turn, `ai.files` for uploads, `ai.caches` for context caching. Use `responseMimeType: "application/json"` with `responseJsonSchema` for structured output. Access response text via `response.text` (property, not method). Streaming uses `generateContentStream` returning an async iterable -- iterate with `for await`.
---
<critical_requirements>
## CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST use `@google/genai` (the new unified SDK) -- NOT the deprecated `@google/generative-ai` package)**
**(You MUST access response text via `response.text` (a property) -- NOT `response.text()` (the old SDK used a method call))**
**(You MUST pass `model` as a string parameter in every API call -- there is no `getGenerativeModel()` step)**
**(You MUST use `config` for all generation parameters (temperature, safetySettings, tools, systemInstruction) -- NOT top-level properties)**
**(You MUST never hardcode API keys -- use environment variables via `process.env.GEMINI_API_KEY` or `GOOGLE_API_KEY`)**
</critical_requirements>
---
**Auto-detection:** Gemini, gemini, GoogleGenAI, @google/genai, ai.models.generateContent, generateContentStream, ai.chats, ai.files, ai.caches, gemini-2.5-flash, gemini-2.5-pro, gemini-2.0-flash, gemini-3-flash, gemini-embedding, GEMINI_API_KEY, GOOGLE_API_KEY, FunctionCallingConfigMode, createUserContent, createPartFromUri, responseMimeType, responseJsonSchema
**When to use:**
- Building applications that call Google Gemini models directly (Gemini 2.x, 2.5, 3.x)
- Processing multimodal input: images, video, audio, PDFs
- Implementing function calling / tool use with custom functions or built-in tools (Google Search, code execution)
- Extracting structured JSON data from LLM responses using response schemas
- Streaming text generation for user-facing output
- Creating embeddings for RAG pipelines or semantic search (text and multimodal)
- Caching large context (documents, code) to reduce cost and latency across multiple requests
- Multi-turn chat sessions with automatic history management
**Key patterns covered:**
- Client initialization and environment-based configuration
- Text generation with `ai.models.generateContent()`
- Streaming with `ai.models.generateContentStream()` and `for await`
- Multimodal input (inline base64, file upload, URIs)
- Function calling with `FunctionDeclaration` and manual tool loops
- Structured output with `responseMimeType` + `responseJsonSchema` + Zod
- Chat sessions with `ai.chats.create()` and `sendMessage()`
- Embeddings with `ai.models.embedContent()` (text and multimodal)
- Context caching with `ai.caches.create()`
- Safety settings per-request via `config.safetySettings`
**When NOT to use:**
- Multi-provider applications requiring provider switching -- use a unified provider SDK
- React-specific chat UI hooks (`useChat`) -- use a framework-integrated AI SDK
- When you need features unique to another provider's API -- use that provider's SDK directly
---
## Examples Index
- [Core: Setup & Configuration](examples/core.md) -- Client init, text generation, system instructions, error handling
- [Multimodal Input](examples/multimodal.md) -- Inline images, file upload, video, audio, PDF, `createPartFromUri`
- [Streaming](examples/streaming.md) -- `generateContentStream`, `sendMessageStream`, abort patterns
- [Function Calling / Tools](examples/tools.md) -- `FunctionDeclaration`, `FunctionCallingConfigMode`, manual tool loop, built-in tools
- [Structured Output](examples/structured-output.md) -- JSON mode, Zod schemas, `responseJsonSchema`, enum extraction
- [Chat Sessions](examples/chat.md) -- `ai.chats.create()`, multi-turn, streaming chat, history
- [Advanced: Embeddings, Caching & Safety](examples/advanced.md) -- Embeddings, context caching, safety settings, token counting
- [Quick API Reference](reference.md) -- Model IDs, method signatures, config parameters, safety enums
---
<philosophy>
## Philosophy
The `@google/genai` SDK is Google's **unified client** for the Gemini API and Vertex AI. It replaces the deprecated `@google/generative-ai` package with a cleaner, centralized architecture.
**Core principles:**
1. **Centralized client** -- A single `GoogleGenAI` instance provides all API services via `ai.models`, `ai.chats`, `ai.files`, `ai.caches`. No scattered manager classes.
2. **Model-per-call** -- Pass the model ID string in every API call rather than binding to a model instance. This simplifies multi-model usage.
3. **Config object pattern** -- All generation parameters (`temperature`, `systemInstruction`, `tools`, `safetySettings`) go inside a `config` object, keeping the top-level call clean.
4. **Native multimodal** -- Images, video, audio, and PDFs are first-class inputs via inline data or file upload. Gemini models handle all modalities natively.
5. **Response as property** -- Access `response.text` as a property (not a method). Access `response.functionCalls` for tool calls.
**When to use the Gemini SDK directly:**
- You primarily use Google Gemini models
- You need multimodal input (images, video, audio, PDF) as a core feature
- You want built-in tools like Google Search and code execution
- You need context caching for large documents
- You want the simplest path to Gemini API features
**When NOT to use:**
- You need to switch between multiple providers -- use a unified SDK
- You want React-specific chat hooks -- use a framework-integrated AI SDK
- You need features unique to another provider's API -- use that provider's SDK directly
</philosophy>
---
<patterns>
## Core Patterns
### Pattern 1: Client Setup
Initialize the `GoogleGenAI` client. It can auto-read `GOOGLE_API_KEY` from the environment.
```typescript
// lib/gemini.ts
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
export { ai };
```
```typescript
// Auto-reads GOOGLE_API_KEY from environment
const ai = new GoogleGenAI({});
```
**Why good:** Minimal setup, env var auto-detected, named export
```typescript
// BAD: Using the old deprecated SDK
import { GoogleGenerativeAI } from "@google/generative-ai";
const genAI = new GoogleGenerativeAI("hardcoded-key"); // WRONG
const model = genAI.getGenerativeModel({ model: "gemini-2.0-flash" });
```
**Why bad:** Old deprecated package, hardcoded API key, model binding step no longer needed
**See:** [examples/core.md](examples/core.md) for Vertex AI setup, environment variables, error handling
---
### Pattern 2: Text Generation
Pass model and contents directly -- no `getGenerativeModel()` step.
```typescript
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: "Explain TypeScript generics briefly.",
config: {
systemInstruction: "You are a concise coding tutor.",
temperature: 0.3,
},
});
console.log(response.text);
```
**Why good:** Model specified per-call, system instruction in config, `response.text` as property
```typescript
// BAD: Old SDK patterns that don't work
const model = genAI.getGenerativeModel({ model: "gemini-2.0-flash" });
const result = await model.generateContent("Hello");
console.log(result.response.text()); // text() was a method in old SDK
```
**Why bad:** `getGenerativeModel()` doesn't exist in new SDK, `text()` is a property not a method
**See:** [examples/core.md](examples/core.md) for system instructions, temperature, thinking config
---
### Pattern 3: Streaming
Use `generateContentStream` and iterate with `for await`.
```typescript
const response = await ai.models.generateContentStream({
model: "gemini-2.5-flash",
contents: "Write a short story about a robot.",
});
for await (const chunk of response) {
process.stdout.write(chunk.text ?? "");
}
```
**Why good:** Async iteration, progressive output for better UX, null-safe text access
```typescript
// BAD: Not consuming the stream
const stream = await ai.models.generateContentStream({
model: "gemini-2.5-flash",
contents: "Hello",
});
// Stream object returned but never iterated -- response lost
```
**Why bad:** Stream must be consumed via `for await`, otherwise response is silently lost
**See:** [examples/streaming.md](examples/streaming.md) for chat streaming, abort patterns
---
### Pattern 4: Multimodal Input
Gemini natively handles images, video, audio, and PDFs. Use inline base64 or file upload.
```typescript
import * as fs from "node:fs";
const imageBase64 = fs.readFileSync("photo.jpg", { encoding: "base64" });
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: [
{ text: "Describe this image in detail." },
{ inlineData: { mimeType: "image/jpeg", data: imageBase64 } },
],
});
console.log(response.text);
```
**Why good:** Inline base64 for small files, explicit MIME type, mixed text + media content
For larger files (over ~20 MB), use `ai.files.upload()` and reference via URI:
```typescript
import { createUserContent, createPartFromUri } from "@google/genai";
const uploadedFile = await ai.files.upload({
file: "large-video.mp4",
config: { mimeType: "video/mp4" },
});
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: createUserContent([
"Summarize this video.",
createPartFromUri(uploadedFile.uri, uploadedFile.mimeType),
]),
});
```
**See:** [examples/multimodal.md](examples/multimodal.md) for audio, PDF, video timestamps, file lifecycle
---
### Pattern 5: Function Calling / Tool Use
Define function declarations with `parametersJsonSchema`, then handle tool calls in a loop.
```typescript
import { GoogleGenAI, FunctionCallingConfigMode } from "@google/genai";
const getWeatherDeclaration = {
name: "get_weather",
description: "Get current weather for a city",
parametersJsonSchema: {
type: "object",
properties: {
location: { type: "string", description: "City name" },
},
required: ["location"],
},
};
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: "What is the weather in Tokyo?",
config: {
tools: [{ functionDeclarations: [getWeatherDeclaration] }],
toolConfig: {
functionCallingConfig: { mode: FunctionCallingConfigMode.AUTO },
},
},
});
if (response.functionCalls && response.functionCalls.length > 0) {
const call = response.functionCalls[0];
console.log(`Call: ${call.name}`, call.args);
}
```
**Why good:** Typed declarations, explicit mode, args directly accessible
**See:** [examples/tools.md](examples/tools.md) for multi-turn tool loop, parallel calls, built-in Google Search
---
### Pattern 6: Structured Output with Zod
Use `responseMimeType: "application/json"` with `responseJsonSchema` for guaranteed JSON output.
```typescript
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
const EventSchema = z.object({
name: z.string(),
date: z.string(),
participants: z.array(z.string()),
});
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: "Alice and Bob meet next Tuesday for lunch.",
config: {
responseMimeType: "application/json",
responseJsonSchema: zodToJsonSchema(EventSchema),
},
});
const event = EventSchema.parse(JSON.parse(response.text ?? "{}"));
```
**Why good:** Zod schema for type safety, `zodToJsonSchema` converts automatically, parse validates response
**See:** [examples/structured-output.md](examples/structured-output.md) for enum output, complex schemas, raw JSON schema
---
### Pattern 7: Chat Sessions
Use `ai.chats.create()` for multi-turn with automatic history management.
```typescript
const chat = ai.chats.create({
model: "gemini-2.5-flash",
config: {
systemInstruction: "You are a helpful coding assistant.",
},
});
const r1 = await chat.sendMessage({ message: "What is TypeScript?" });
console.log(r1.text);
const r2 = await chat.sendMessage({ message: "How do generics work?" });
console.log(r2.text);
// Chat automatically maintains conversation history
```
**Why good:** Automatic history tracking, system instruction in config, simple `sendMessage` API
**See:** [examples/chat.md](examples/chat.md) for pre-loaded history, streaming chat, function calling in chat
---
### Pattern 8: Error Handling
Check `response.text` for null and inspect `finishReason` for safety blocks.
```typescript
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: userPrompt,
});
// Check if content was blocked by safety filters
const candidate = response.candidates?.[0];
if (!candidate || candidate.finishReason === "SAFETY") {
console.warn("Response blocked by safety filters");
console.warn("Safety ratings:", candidate?.safetyRatings);
return null;
}
// Check for truncation
if (candidate.finishReason === "MAX_TOKENS") {
console.warn("Response was truncated -- consider increasing maxOutputTokens");
}
console.log(response.text);
```
**Why good:** Checks safety filter blocks, handles truncation, inspects finish reason
**See:** [examples/core.md](examples/core.md) for try/catch error handling, HTTP error codes
</patterns>
---
<performance>
## Performance Optimization
### Model Selection for Cost/Speed
```
General purpose -> gemini-2.5-flash (best price/performance balance)
Complex reasoning -> gemini-2.5-pro (deep reasoning, 1M context)
Budget / high-volume -> gemini-2.5-flash-lite (cheapest, fastest)
Latest frontier -> gemini-3-flash-preview (most capable, preview)
Embeddings (text) -> gemini-embedding-001 (text only, stable)
Embeddings (multimodal) -> gemini-embedding-2-preview (text, image, video, audio, PDF)
```
### Key Optimization Patterns
- **Use context caching** for repeated queries on the same large document -- reduces cost by up to 75%
- **Batch embeddings** by passing an array to `ai.models.embedContent()` -- one API call for multiple inputs
- **Set `temperature: 0`** for deterministic output (enables server-side caching)
- **Use `gemini-2.5-flash-lite`** for high-volume, latency-sensitive workloads
- **Reduce embedding dimensions** via `config.outputDimensionality` for faster similarity search
- **Use streaming** for user-facing responses to improve perceived latency
</performance>
---
<decision_framework>
## Decision Framework
### Which Model to Choose
```
What is your task?
+-- General text generation -> gemini-2.5-flash (best balance)
+-- Complex reasoning / code -> gemini-2.5-pro (deep thinking, 1M context)
+-- High-volume / budget -> gemini-2.5-flash-lite (cheapest)
+-- Cutting-edge / experimental -> gemini-3-flash-preview
+-- Text embeddings -> gemini-embedding-001
+-- Multimodal embeddings -> gemini-embedding-2-preview
```
### File Input Method
```
How large is your file?
+-- Under 20 MB -> Inline base64 (inlineData)
+-- 20 MB - 2 GB -> ai.files.upload() + createPartFromUri()
+-- Need to reuse across requests -> ai.files.upload() (persists 48 hours)
+-- External URL (Gemini 3+) -> createPartFromUri() with HTTP URL
```
### Structured Output vs Free Text
```
Do you need a specific output shape?
+-- YES -> Set responseMimeType: "application/json"
| +-- Have a Zod schema? -> zodToJsonSchema() into responseJsonSchema
| +-- Raw JSON Schema? -> Pass directly to responseJsonSchema
+-- NO -> Default text output (no config needed)
```
### Chat vs Single-Turn
```
Is this a multi-turn conversation?
+-- YES -> ai.chats.create() with sendMessage()
| +-- Need streaming? -> chat.sendMessageStream()
| +-- Need function calling? -> Pass tools in chat config
+-- NO -> ai.models.generateContent() (single call)
```
### When to Use Context Caching
```
Are you sending the same large prefix repeatedly?
+-- YES -> Is it 1,024+ tokens (Flash) or 4,096+ (Pro)?
| +-- YES -> Use ai.caches.create() to cache the prefix
| +-- NO -> Too small to cache, just send inline
+-- NO -> Standard generateContent() calls
```
</decision_framework>
---
<red_flags>
## RED FLAGS
**High Priority Issues:**
- Using `@google/generative-ai` (the deprecated package) -- migrate to `@google/genai`
- Calling `response.text()` as a method -- it is a property (`response.text`) in the new SDK
- Using `getGenerativeModel()` -- the new SDK passes model as a string in each API call
- Hardcoding API keys instead of using environment variables
- Not checking `finishReason` for `"SAFETY"` or `"MAX_TOKENS"` -- safety blocks silently return no content
**Medium Priority Issues:**
- Putting `temperature`, `tools`, or `systemInstruction` at the top level instead of inside `config`
- Not setting `config.mimeType` when uploading files -- the API may reject or misinterpret the file
- Using `model.startChat()` (old SDK) -- use `ai.chats.create()` in the new SDK
- Not consuming `generateContentStream()` output -- the async iterable must be iterated
- Ignoring uploaded file lifecycle -- files expire after 48 hours
**Common Mistakes:**
- Confusing `responseMimeType` (for structured output) with `mimeType` (for file upload config)
- Using `responseSchema` (old SDK parameter name) instead of `responseJsonSchema` (new SDK)
- Mixing old SDK patterns (`model.generateContent(prompt)`) with new SDK (`ai.models.generateContent({ model, contents })`)
- Passing plain Zod schemas to `responseJsonSchema` -- you must convert with `zodToJsonSchema()` first
- Using `content` (singular) instead of `contents` (plural) in `generateContent()`
**Gotchas & Edge Cases:**
- `response.text` returns `null` (not empty string) when content is blocked by safety filters -- always null-check
- Uploaded files via `ai.files.upload()` expire after 48 hours -- there is no way to extend this, re-upload if needed
- Context caching has minimum token requirements: 1,024 tokens for Flash models, 4,096 for Pro models -- smaller content cannot be cached
- Inline data has a 100 MB payload limit (50 MB for PDFs) -- use file upload for larger content
- `ai.files.upload()` supports up to 2 GB per file, 20 GB per project
- Embedding dimensions default to 3,072 -- use `config.outputDimensionality` to reduce for cost/speed
- Gemini embedding models are NOT compatible with each other -- switching models requires re-embedding all data
- `FunctionCallingConfigMode.ANY` forces the model to always call a function -- use `AUTO` to let the model decide
- Chat history uses `role: "model"` (not `"assistant"`) for Gemini responses -- differs from other providers' convention
- Safety filter defaults changed: Gemini 2.5+ and 3.x models default to `OFF` (no blocking) unlike earlier models
- The `sendMessage()` method takes `{ message: string }` (object with `message` key), not a plain string
- When function calling returns multiple calls, process ALL of them before sending results back -- partial responses cause errors
- `zodToJsonSchema()` comes from the `zod-to-json-schema` package (separate from `zod`) -- requires `npm install zod-to-json-schema`
</red_flags>
---
<critical_reminders>
## CRITICAL REMINDERS
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST use `@google/genai` (the new unified SDK) -- NOT the deprecated `@google/generative-ai` package)**
**(You MUST access response text via `response.text` (a property) -- NOT `response.text()` (the old SDK used a method call))**
**(You MUST pass `model` as a string parameter in every API call -- there is no `getGenerativeModel()` step)**
**(You MUST use `config` for all generation parameters (temperature, safetySettings, tools, systemInstruction) -- NOT top-level properties)**
**(You MUST never hardcode API keys -- use environment variables via `process.env.GEMINI_API_KEY` or `GOOGLE_API_KEY`)**
**Failure to follow these rules will produce broken integrations due to old SDK patterns or silent safety filter blocks.**
</critical_reminders>
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!