Review and fix Gemini API usage against Google's official best practices. Use when modifying src/core/gemini.ts, adding new API calls, or auditing Gemini integration quality.
Installs into .claude/skills of the current project.
Are you the author of Gemini Best Practices?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/takeshy-gemini-best-practices)
---
name: gemini-best-practices
description: Review and fix Gemini API usage against Google's official best practices. Use when modifying src/core/gemini.ts, adding new API calls, or auditing Gemini integration quality.
user-invocable: true
disable-model-invocation: false
paths:
- src/core/gemini.ts
- src/core/fileSearch.ts
- src/core/tools.ts
---
# Gemini API Best Practices
When reviewing or modifying Gemini API integration code, ensure compliance with Google's official best practices from `google-gemini/gemini-skills`.
## SDK and Package
- **Correct SDK**: `@google/genai` (npm)
- **NEVER use deprecated**: `@google/generative-ai` (old package)
- Prefer environment variables for API keys over hard-coding
## Safety Settings
All API calls (`generateContent`, `generateContentStream`, `chats.create`) MUST include `safetySettings` in the config:
```typescript
import { HarmCategory, HarmBlockThreshold, type SafetySetting } from "@google/genai";
const DEFAULT_SAFETY_SETTINGS: SafetySetting[] = [
{ category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE },
{ category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE },
{ category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE },
{ category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE },
];
```
## Response Validation (finishReason)
Always check `finishReason` on response candidates:
- `SAFETY` - Response blocked by safety filters; inform user to rephrase
- `RECITATION` - Blocked due to potential copyrighted content recitation
- `MAX_TOKENS` - Output truncated; consider informing user
- `STOP` - Normal completion
```typescript
import { FinishReason } from "@google/genai";
// Check candidates[0].finishReason after each response
if (candidate.finishReason === FinishReason.SAFETY) {
// Handle blocked response
}
```
For non-streaming: check `response.candidates[0].finishReason` before using `response.text`.
For streaming: check `finishReason` in chunk candidates.
## System Instructions
- Pass via `systemInstruction` in config (not as a chat message)
- System instructions are interaction-scoped; re-specify on each chat session creation
## Tool / Function Calling
- Pass tools via `config.tools` array
- Use proper SDK types (`Tool`, `FunctionDeclaration`) without forced `as` casts
- `googleSearch` and `fileSearch` are first-class `Tool` properties
- `fileSearch` CANNOT be combined with `functionDeclarations` in the same request
- `googleSearch` CANNOT be combined with `functionDeclarations`
## Streaming
- Use `generateContentStream` or `chat.sendMessageStream` for streaming
- Use SDK Chat (`ai.chats.create()`) for automatic thought signature handling
- Process ALL parts in each chunk (text, thought, functionCall can coexist)
## Thinking / Reasoning
- Thinking is ON by default for Gemini 2.5+ and 3.x models
- `thinkingBudget: 0` disables thinking (except models that require it)
- Gemini 3.1 Flash Lite uses `thinkingLevel` instead of `thinkingBudget`
- Gemini 3 Pro / 3.1 Pro require thinking (cannot be disabled)
- Access thought parts via `part.thought` boolean on content parts
## Model Names
Current models (use these):
- `gemini-3.1-pro-preview` - Flagship, 1M context
- `gemini-3-flash-preview` - Fast, balanced
- `gemini-3.1-flash-lite-preview` - Cost-efficient
- `gemini-2.5-pro` / `gemini-2.5-flash` - Still available
Deprecated models (NEVER use):
- All `gemini-2.0-*`, `gemini-1.5-*`, `gemini-1.0-*`, `gemini-pro`
## Type Safety
- Use proper SDK types from `@google/genai` instead of `as` casts
- `Tool` interface supports `googleSearch`, `fileSearch`, `functionDeclarations`, `codeExecution`, `urlContext`
- Import enums (`FinishReason`, `HarmCategory`, `HarmBlockThreshold`) as values, not just types
## Checklist for New API Calls
- [ ] `safetySettings: DEFAULT_SAFETY_SETTINGS` included in config
- [ ] `finishReason` checked on response candidates
- [ ] `systemInstruction` passed in config (not as message)
- [ ] No forced `as Tool` type assertions
- [ ] Proper error handling with `formatError()`
- [ ] Usage metadata extracted for cost tracking