AI / Google Antigravity Gemini Fundamentals Interview Questions
1. What is the Gemini API and what does it give developers access to?
The Gemini API is Google's developer interface to its Gemini family of multimodal AI models. It allows developers to integrate state-of-the-art language, vision, audio, image generation, and video capabilities into applications via simple HTTP calls or official SDKs.
Access is through Google AI Studio (developer portal, free tier available) or Google Cloud Vertex AI (enterprise, higher limits, compliance features). All requests require an API key passed as the x-goog-api-key header.
| Category | Capabilities |
|---|---|
| Language models | Text generation, reasoning, coding, multilingual understanding |
| Multimodal understanding | Process images, video, audio, PDFs together with text |
| Image generation | Nano Banana (Gemini image) models for generation and editing |
| Video generation | Veo 3.1 models for cinematic video with native audio |
| Agents | Managed agents including Antigravity, Deep Research |
| Grounding | Search Grounding for real-time web data |
| Speech | Text-to-speech and Live API for audio conversations |
# Install the Python SDK pip install google-genai # Quickstart from google import genai client = genai.Client() # reads GEMINI_API_KEY from env # Interactions API (recommended for new projects as of June 2026) interaction = client.interactions.create( model="gemini-3.5-flash", input="Explain recursion in one sentence.", ) print(interaction.output_text)
2. What is the Interactions API and how does it differ from generateContent?
The Interactions API is Google's new recommended interface for building with Gemini models and agents, generally available as of June 2026. The original generateContent API remains fully supported but is now considered legacy for new projects.
| Feature | generateContent | Interactions API |
|---|---|---|
| Status | Legacy (still fully supported) | Recommended for all new projects |
| State management | Manual - send full history every turn | Optional server-side via previous_interaction_id |
| Execution visibility | Single response object | Observable execution steps for debugging/UI |
| Background tasks | Not supported | background=true for long-running tasks |
| Caching efficiency | Standard | Higher cache hit rates via server-side state |
| Agent support | Limited | Built for managed agents and agentic workflows |
| Thinking steps | Hidden | Exposed as observable steps |
from google import genai client = genai.Client() # Interactions API - new recommended approach interaction = client.interactions.create( model="gemini-3.5-flash", input="I have 2 dogs in my house.", ) print(interaction.output_text) # Chain turns with previous_interaction_id (server manages state) follow_up = client.interactions.create( model="gemini-3.5-flash", input="How many paws are in my house?", previous_interaction_id=interaction.id, ) print(follow_up.output_text) # Gemini knows context from turn 1 # Legacy generateContent (still works, not deprecated) response = client.models.generate_content( model="gemini-3.5-flash", contents="I have 2 dogs in my house.", )
3. What are the current Gemini model families and which should you use for different tasks?
As of mid-2026, the Gemini model ecosystem spans multiple generations. The Gemini 3.x series is the primary production line, with Gemini 3.5 Flash being the newest generally-available flagship.
| Model | API ID | Best for | Notes |
|---|---|---|---|
| Gemini 3.5 Flash | gemini-3.5-flash | Frontier agentic and coding tasks | GA; Pro-level intelligence at Flash price |
| Gemini 3.1 Pro Preview | gemini-3.1-pro-preview | Complex reasoning, highest quality | Preview only; no free tier via API |
| Gemini 3.1 Flash-Lite | gemini-3.1-flash-lite | High-volume cost-sensitive tasks | Most cost-efficient in Gemini 3 series |
| Gemini 2.5 Flash | gemini-2.5-flash-001 | Stable production workloads | Stable; 10 RPM / 250 RPD free tier |
| Gemini 2.5 Pro | gemini-2.5-pro | Strong reasoning on stable model | Stable; very restricted free tier |
| Gemini 2.5 Flash-Lite | gemini-2.5-flash-lite | Cheapest option | $0.10/1M input; 15 RPM free tier |
Decision guide:
- Prototyping/testing: Gemini 2.5 Flash (free tier, stable)
- Production with cost sensitivity: Gemini 3.1 Flash-Lite or 2.5 Flash-Lite
- Production needing reasoning: Gemini 2.5 Pro (stable) or 3.1 Pro Preview (higher capability but preview)
- Agentic and coding tasks: Gemini 3.5 Flash (flagship as of June 2026)
Important: Gemini 2.0 Flash and 2.0 Flash-Lite were shut down on June 1, 2026. All Gemini 1.0 and 1.5 models already return 404 errors.
4. What is Gemini 3.5 Flash and what makes it the current flagship model?
Gemini 3.5 Flash (model ID: gemini-3.5-flash) launched as generally available in June 2026 and is described by Google as delivering sustained frontier performance on agentic and coding tasks. It is the model behind the gemini-flash-latest alias.
Key characteristics:
- Pro-level intelligence at Flash-tier cost and speed
- Pro-level coding proficiency
- Parallel agentic execution - can run multiple tool calls simultaneously
- Priced the same as previous Flash models despite significantly higher capability
- 1 million token input context window
- Up to 64k output tokens
- Knowledge cutoff: January 2025 (use Search Grounding for newer information)
from google import genai client = genai.Client() # Use Gemini 3.5 Flash - recommended default for new projects interaction = client.interactions.create( model="gemini-3.5-flash", input="Write a Python async web scraper with error handling.", ) print(interaction.output_text) # Or use the alias (note: aliases update automatically as new releases arrive) interaction = client.interactions.create( model="gemini-flash-latest", # auto-updates to newest Flash release input="Review this code for bugs...", ) # Note: use pinned model IDs in production, not -latest aliases
5. What are model version types in the Gemini API and which should you use in production?
Gemini model IDs follow a structured naming convention that indicates the model's version type. Choosing the right version type affects stability, rate limits, and billing behaviour.
| Type | Example | Behaviour | Production use? |
|---|---|---|---|
| Stable | gemini-2.5-flash-001 | Pinned; does not change; most predictable | Recommended for production |
| Preview | gemini-3.1-pro-preview | May change; billing enabled; deprecated with >= 2 weeks notice | Acceptable for production with risk |
| Latest alias | -latest suffix | Hot-swapped to newest release automatically | Avoid in production - can break without notice |
| Experimental | ...-exp suffix | May change; often restricted rate limits | Development/testing only |
# GOOD: use a pinned stable model in production response = client.models.generate_content( model="gemini-2.5-flash-001", # stable, versioned, won't change contents="...", ) # ACCEPTABLE: preview with awareness of deprecation risk response = client.models.generate_content( model="gemini-3.1-pro-preview", # preview: >= 2 weeks deprecation notice contents="...", ) # AVOID in production: auto-updated aliases response = client.models.generate_content( model="gemini-flash-latest", # will silently upgrade to new model releases! contents="...", ) # WARNING: Gemini 3 Pro Preview was deprecated March 9, 2026 # with minimal migration window - a real-world example of preview risk. # Always use versioned IDs for customer-facing applications.
6. What is the Antigravity agent and what can it do?
Antigravity (antigravity-preview-05-2026) is Google's general-purpose managed agent released in public preview in May 2026 as part of the Gemini API's Managed Agents feature. It is a fully autonomous agent that runs inside a secure, isolated Google-hosted Linux sandbox container.
What Antigravity can do autonomously:
- Plan and reason - breaks down complex tasks into sub-steps and executes them
- Write and execute code - generates Python/shell code and runs it in the sandbox
- Manage files - creates, reads, modifies, and organises files within its container
- Browse the web - fetches pages, searches for information, and reads online content
- Multi-step execution - chains many tool uses across a long task horizon
from google import genai client = genai.Client() # Using the Antigravity managed agent via the Interactions API interaction = client.interactions.create( model="antigravity-preview-05-2026", input="""Analyse the top 10 Python packages on PyPI by download count. Fetch the data, create a bar chart, and save it as chart.png. Then write a brief summary of what you found.""", ) print(interaction.output_text) # For long-running tasks, use background execution: interaction = client.interactions.create( model="antigravity-preview-05-2026", input="Scrape and analyse a year of release notes from github.com/google/gemini", background=True, # returns immediately; poll for completion ) print(f"Task started: {interaction.id}, status: {interaction.status}") # Poll: result = client.interactions.retrieve(interaction.id) print(result.status) # "pending" | "running" | "completed" | "failed"
| Aspect | Standard Gemini model | Antigravity agent |
|---|---|---|
| Execution | Single model call | Multi-step autonomous execution |
| Code running | Code interpreter tool only | Native execution in Linux sandbox |
| File management | Via tools | Native, persistent within sandbox session |
| Web browsing | Via search grounding | Full browser-level web access |
| Task horizon | Short (one response) | Long (many steps, hours if needed |
7. What are Managed Agents in the Gemini API and how do they differ from building agents yourself?
Managed Agents is a Gemini API feature (in public preview as of mid-2026) that lets developers build and deploy autonomous, stateful agents that run in secure, isolated Google-hosted Linux sandbox environments. Unlike building your own agent loop, managed agents handle the infrastructure of multi-step execution, sandboxing, and state management.
| Aspect | DIY agent loop | Managed Agents (Gemini API) |
|---|---|---|
| Infrastructure | Developer manages execution env | Google-hosted secure sandbox |
| Sandboxing | Developer responsible | Isolated per session by Google |
| State management | Developer manages session state | Google manages agent state |
| Code execution | Requires code interpreter tool setup | Built-in; native Linux execution |
| Long tasks | Timeout and reconnect challenges | background=true; persistent execution |
| Monitoring | Custom logging | Observable steps in Interactions API |
| Current agents | N/A | Antigravity (general), Deep Research |
from google import genai client = genai.Client() # Invoke a managed agent exactly like a model call: interaction = client.interactions.create( model="antigravity-preview-05-2026", # managed agent input="Build and test a Python REST API with FastAPI.", ) # The agent handles: # 1. Planning the approach # 2. Writing the FastAPI code # 3. Installing dependencies (pip install fastapi uvicorn) # 4. Running tests # 5. Reporting results # All inside its sandbox - zero infrastructure from you # You can also mix agents and models in one conversation: research = client.interactions.create( model="gemini-deep-research-preview", # Deep Research agent input="Research best practices for API authentication", ) # Follow up with a standard model using the research context: followup = client.interactions.create( model="gemini-3.5-flash", input="Now implement authentication based on this research.", previous_interaction_id=research.id, # carries context forward )
8. What is Search Grounding and why is it important for Gemini applications?
Search Grounding connects Gemini models to Google Search, enabling responses based on real-time, up-to-date web information rather than the model's training data alone. This is especially important because all Gemini 3 models have a knowledge cutoff of January 2025.
from google import genai from google.genai import types client = genai.Client() # Enable search grounding in generateContent response = client.models.generate_content( model="gemini-3.5-flash", contents="What are the latest Gemini API changes announced this week?", config=types.GenerateContentConfig( tools=[types.Tool(google_search=types.GoogleSearch())] ), ) print(response.text) # Access grounding metadata (sources used): if response.candidates[0].grounding_metadata: for chunk in response.candidates[0].grounding_metadata.grounding_chunks: print(f"Source: {chunk.web.title} - {chunk.web.uri}") # In the Interactions API: interaction = client.interactions.create( model="gemini-3.5-flash", input="What happened in AI news this week?", tools=[{"google_search": {}}], )
What grounding provides:
- Responses based on real-time Google Search results
- Source attribution - the API returns grounding metadata showing which web pages were used
- Significantly reduced hallucination for time-sensitive factual questions
- Automatic triggering when the model determines a search would improve the answer
Note: grounding does not eliminate hallucination entirely - it reduces it for recent factual queries. Always validate critical information from grounded responses.
9. What are the Gemini API's multimodal input capabilities?
Gemini models are natively multimodal - they can accept and reason across text, images, video, audio, and documents (PDFs) in a single request. This is a fundamental design characteristic, not a bolt-on feature.
| Modality | Supported formats | Notes |
|---|---|---|
| Text | Plain text, markdown | Always supported |
| Images | JPEG, PNG, WEBP, HEIC, HEIF | Up to ~3,600 per request (model-dependent) |
| Video | MP4, MOV, AVI, WMOV, MPEG, WebM, FLV | Up to 1 hour of video in context |
| Audio | MP3, WAV, FLAC, AAC, OGG, OPUS, WebM | Transcription, analysis, audio Q&A |
| application/pdf | Documents with text + embedded images | |
| Structured data | application/json, text/csv | Data files for analysis |
from google import genai from pathlib import Path client = genai.Client() # Upload a file via the Files API (for large files) my_video = client.files.upload(file=Path("presentation.mp4")) # Multimodal request: video + text question interaction = client.interactions.create( model="gemini-3.5-flash", input=[ {"type": "text", "text": "Summarise the key points from this video."}, {"type": "video", "uri": my_video.uri, "mime_type": "video/mp4"} ] ) print(interaction.output_text) # Image inline (base64 for small images, Files API for large): import base64 image_data = base64.b64encode(Path("diagram.png").read_bytes()).decode() interaction = client.interactions.create( model="gemini-3.5-flash", input=[ {"type": "text", "text": "Explain this architecture diagram."}, {"type": "image", "data": image_data, "mime_type": "image/png"} ] )
10. What is the Gemini context window and how do you manage long contexts?
The context window is the maximum number of tokens a model can process in a single request (input + output combined). Gemini models have among the largest context windows of any commercially available AI, with 1 million tokens for most current models.
| Model | Input context | Max output |
|---|---|---|
| Gemini 3.5 Flash | 1 million tokens | 64k tokens |
| Gemini 3.1 Pro Preview | 1 million tokens | 64k tokens |
| Gemini 2.5 Pro | 1 million tokens | 64k tokens |
| Gemini 2.5 Flash | 1 million tokens | 64k tokens |
from google import genai from google.genai import types client = genai.Client() # Count tokens before sending (avoid context overflow errors): token_response = client.models.count_tokens( model="gemini-3.5-flash", contents="Your very long document here...", ) print(f"Token count: {token_response.total_tokens}") # check vs 1M limit # Long context use cases Gemini excels at: # 1. Entire codebase analysis response = client.models.generate_content( model="gemini-3.5-flash", contents=[ "Summarise all TODO comments in this codebase and prioritise them.", entire_codebase_text, # can be hundreds of files ] ) # 2. Full book Q&A # 3. Hour-long video analysis # 4. Full conversation history # Context caching: cache large stable prompts to reduce cost: cached = client.caches.create( model="gemini-3.5-flash", contents=[large_document], # cache this expensive prefix ttl="3600s", ) # Reference the cache in subsequent calls: response = client.models.generate_content( model="gemini-3.5-flash", contents="Summarise section 3.", config=types.GenerateContentConfig(cached_content=cached.name), )
11. How does thinking/reasoning work in Gemini models and what is thinking_level?
Gemini 3 series models use dynamic thinking by default - they automatically decide how much internal reasoning to apply before responding, calibrated to the task complexity. Developers can influence this via the thinking_level parameter.
from google import genai from google.genai import types client = genai.Client() # Dynamic thinking is ON by default for Gemini 3 models # Use thinking_level to control depth: response = client.models.generate_content( model="gemini-3.1-pro-preview", contents="Design a thread-safe cache with O(1) operations.", config=types.GenerateContentConfig( thinking_config=types.ThinkingConfig( thinking_level="high", # "none" | "low" | "medium" | "high" ) ) ) # Thinking steps are visible as execution steps in the Interactions API interaction = client.interactions.create( model="gemini-3.1-pro-preview", input="Find all race conditions in this code: ...", ) for step in interaction.steps: if step.type == "thought": print(f"Thinking: {step.signature[:50]}...") # encrypted thought elif step.type == "model_output": print(f"Output: {step.content[0].text}")
| Value | Behaviour | Use case |
|---|---|---|
| none | No internal reasoning; direct response | Simple factual queries, fast responses |
| low | Minimal reasoning | Basic analysis tasks |
| medium | Balanced reasoning (typical default) | Most general tasks |
| high | Deep reasoning; slower but more accurate | Complex coding, math, architecture design |
Legacy note: thinking_budget is still supported for backward compatibility but Google recommends migrating to thinking_level for more predictable performance. Do not use both parameters in the same request.
12. What is structured output (JSON mode) in the Gemini API and how do you implement it?
Structured output constrains Gemini to respond in valid JSON matching a developer-defined schema. This makes AI output reliably machine-readable without string parsing heuristics.
from google import genai from google.genai import types from pydantic import BaseModel from typing import Literal client = genai.Client() # Define schema with Pydantic class CodeReview(BaseModel): summary: str bugs: list[str] severity: Literal["low", "medium", "high", "critical"] line_numbers: list[int] suggested_fix: str # generateContent with response_schema: response = client.models.generate_content( model="gemini-3.5-flash", contents="Review this Python code: def add(a, b): return a - b", config=types.GenerateContentConfig( response_mime_type="application/json", response_schema=CodeReview, ) ) import json review = CodeReview(**json.loads(response.text)) print(f"Severity: {review.severity}") print(f"Bugs: {review.bugs}") # Interactions API structured output: interaction = client.interactions.create( model="gemini-3.5-flash", input="Extract: Alice is 30, an engineer from London.", response_mime_type="application/json", response_schema={"type": "object", "properties": { "name": {"type": "string"}, "age": {"type": "integer"}, "role": {"type": "string"}, "city": {"type": "string"} }} ) data = json.loads(interaction.output_text)
13. How does function calling (tool use) work in the Gemini API?
Function calling allows you to declare external functions to the Gemini model. The model then decides when to call them, returning structured arguments you execute in your code. The result is sent back, and the model continues its response using the function output.
from google import genai from google.genai import types import json client = genai.Client() # 1. Declare your functions as tools get_weather = types.FunctionDeclaration( name="get_weather", description="Get current weather for a city", parameters={ "type": "object", "properties": { "city": {"type": "string", "description": "City name"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]} }, "required": ["city"] } ) # 2. First call: model may request a function call response = client.models.generate_content( model="gemini-3.5-flash", contents="What's the weather in Tokyo right now?", config=types.GenerateContentConfig( tools=[types.Tool(function_declarations=[get_weather])] ) ) # 3. Check if model requested a function call for part in response.candidates[0].content.parts: if hasattr(part, "function_call"): fc = part.function_call print(f"Model wants to call: {fc.name}({dict(fc.args)})") result = your_weather_api(fc.args["city"]) # execute! # 4. Return result and continue response2 = client.models.generate_content( model="gemini-3.5-flash", contents=[ types.Content(role="user", parts=[types.Part(text="What's the weather in Tokyo?")]), response.candidates[0].content, # model turn with function_call types.Content( role="user", parts=[types.Part( function_response=types.FunctionResponse( name=fc.name, response={"result": result} ) )] ) ], ) print(response2.text)
14. What is the Gemini Files API and when do you need it?
The Files API (/v1beta/files) allows you to upload files to Google's servers for reuse across multiple Gemini API requests. It is essential for large files that would be impractical to pass as base64 inline, and for files you want to reference multiple times without re-uploading.
from google import genai from pathlib import Path client = genai.Client() # Upload a file uploaded = client.files.upload( file=Path("large-document.pdf"), config={"display_name": "Q3 Report"} ) print(f"File URI: {uploaded.uri}") print(f"MIME type: {uploaded.mime_type}") print(f"State: {uploaded.state}") # PROCESSING | ACTIVE | FAILED # Wait for processing (videos may take time) import time while uploaded.state == "PROCESSING": time.sleep(2) uploaded = client.files.get(name=uploaded.name) # Use in multiple requests without re-uploading: for question in ["Summarise section 2", "List all action items", "Find risks"]: response = client.models.generate_content( model="gemini-3.5-flash", contents=[ question, types.Part(file_data=types.FileData(file_uri=uploaded.uri)) ] ) print(response.text) # List and delete files: for f in client.files.list(): print(f.name, f.display_name) client.files.delete(name=uploaded.name)
| Property | Detail |
|---|---|
| Supported files | Text, images, audio, video, PDFs, and more |
| File retention | 48 hours automatically; manually delete sooner if needed |
| Storage | Per-project storage quota applies |
| Processing | Large videos/audio may enter PROCESSING state before becoming ACTIVE |
| Reuse | Reference the same URI across unlimited API calls during the 48h window |
15. What is the Gemini Live API and what real-time capabilities does it enable?
The Gemini Live API enables low-latency, bidirectional real-time interactions with Gemini models over a WebSocket connection. It supports simultaneous audio streaming in both directions, enabling voice conversations, real-time transcription, and audio-to-audio (A2A) applications.
| Capability | Model | Notes |
|---|---|---|
| Voice conversation | gemini-3.1-flash-live-preview | Real-time A2A; natural dialogue |
| Text-to-speech streaming | gemini-3.1-flash-tts-preview | Stream audio as it generates |
| Real-time video understanding | Supported models | Analyse live webcam/screen |
| Interruption handling | Built-in | User can interrupt mid-response |
| Tool use in real time | Supported | Agent can call tools during conversation |
import asyncio from google import genai client = genai.Client() async def realtime_session(): # Live API uses async context manager async with client.aio.live.connect( model="gemini-3.1-flash-live-preview", config={ "response_modalities": ["AUDIO"], # get audio back "speech_config": { "voice_config": {"prebuilt_voice_config": {"voice_name": "Aoede"}} }, "system_instruction": "You are a helpful coding assistant." } ) as session: # Send audio input await session.send(input=audio_chunk, end_of_turn=True) # Receive streaming audio response async for response in session.receive(): if response.data: # audio bytes play_audio(response.data) asyncio.run(realtime_session())
The Live API differs from standard generation in that it maintains a persistent WebSocket connection, enabling sub-second turn latency - crucial for natural voice interaction. The gemini-3.1-flash-live-preview model is specifically designed for real-time dialogue and voice-first AI applications.
16. What are the Nano Banana image generation models and how do they replace Imagen?
Nano Banana is Google's branding for the Gemini native image generation models. They replace the older Imagen models (deprecated, shut down by June 30, 2026) and are natively integrated into the Gemini model family rather than being a separate product.
| Model | Also known as | Strength |
|---|---|---|
| Gemini 3 Pro Image | Nano Banana Pro | Highest quality; reasoning-enhanced composition; legible text; complex multi-turn editing; up to 14 reference inputs |
| Gemini 3.1 Flash Image | Nano Banana 2 | High-efficiency, high-volume; multi-image fusion; character consistency |
| Gemini 3.1 Flash-Lite Image | Nano Banana 2 Lite | Ultra-low latency; cost-effective; for high-volume and latency-sensitive workloads |
from google import genai client = genai.Client() # Generate an image with Nano Banana 2 (Gemini 3.1 Flash Image) interaction = client.interactions.create( model="gemini-3.1-flash-image-preview", # Nano Banana 2 input="A photorealistic image of a Python snake debugging code on a glowing terminal.", ) # Access the generated image: for step in interaction.steps: if step.type == "model_output": for part in step.content: if part.type == "image": with open("output.png", "wb") as f: f.write(part.data) # image bytes # Multi-turn editing (conversational editing): edit = client.interactions.create( model="gemini-3.1-flash-image-preview", input="Now make the snake wearing a debugging hat and smiling.", previous_interaction_id=interaction.id, # maintains image context ) # Or via generateContent with Gen Media endpoint: response = client.models.generate_images( model="gemini-3-pro-image-preview", # Nano Banana Pro prompt="Studio quality portrait of an AI robot", )
17. What is Veo and what video generation capabilities does the Gemini API offer?
Veo is Google's video generation model family, accessible via the Gemini API. The current production line is Veo 3.1, with models ranging from high-quality cinematic generation to fast, cost-efficient production of short clips.
| Model | Capability | Use case |
|---|---|---|
| Veo 3.1 (GA) | State-of-the-art cinematic video with advanced creative controls and natively synchronised audio | High-quality film-like video |
| Veo 3.1 Fast (GA) | High-efficiency cinematic control from the Veo 3.1 family | Speed-sensitive production workloads |
| Veo 3.1 Lite Preview | Most cost-efficient; designed for rapid iteration and high-volume apps | Development, prototyping, bulk generation |
from google import genai from google.genai import types client = genai.Client() # Generate a video with Veo 3.1 operation = client.models.generate_videos( model="veo-3.1-generate-preview", prompt="A drone flies over a misty mountain range at sunrise, cinematic 4K", config=types.GenerateVideoConfig( aspect_ratio="16:9", duration_seconds=5, sample_count=1, ) ) # Video generation is async - poll for completion: import time while not operation.done: time.sleep(10) operation = client.operations.get(operation.name) # Download the generated video: video = operation.result.generated_videos[0] client.files.download(file=video) print(f"Video saved: {video.video.uri}") # Note: Veo 2.0 models were deprecated June 30, 2026 # Migrate to veo-3.1-generate-preview or veo-3.1-fast-generate-preview
Deprecation note: Veo 2.0 generation models were deprecated and shut down on June 30, 2026. Applications using Veo 2.0 model IDs must migrate to Veo 3.1 model IDs.
18. What are the Gemini API rate limits and how do they differ between free and paid tiers?
The Gemini API enforces rate limits on three dimensions: requests per minute (RPM), requests per day (RPD), and tokens per minute (TPM). Limits vary significantly by model and whether you are on the free tier or a paid billing tier.
| Model | Free tier RPM | Free tier RPD | Paid tier RPM |
|---|---|---|---|
| Gemini 3.5 Flash | Varies (check AI Studio) | Varies | Higher (billing required) |
| Gemini 3.1 Pro Preview | No free tier | No free tier | Billing required |
| Gemini 2.5 Flash | 10 RPM | 250 RPD | Much higher |
| Gemini 2.5 Flash-Lite | 15 RPM | 1,000 RPD | Much higher |
| Gemini 2.5 Pro | 5 RPM | 100 RPD | Billing required for higher |
import time from google import genai from google.api_core import exceptions client = genai.Client() # Handle rate limiting with exponential backoff: def generate_with_retry(prompt, model="gemini-2.5-flash", max_retries=3): for attempt in range(max_retries): try: response = client.models.generate_content( model=model, contents=prompt ) return response.text except exceptions.ResourceExhausted: # 429 rate limit error wait = 2 ** attempt print(f"Rate limited. Waiting {wait}s (attempt {attempt+1})") time.sleep(wait) raise Exception("Max retries exceeded") # Tips for free tier: # - Add delays between calls (1-2 seconds minimum) # - Use Flash-Lite (higher RPD: 1,000/day) # - Monitor quota in AI Studio dashboard # - Enable billing for Tier 1 ($250/month cap available)
Key changes: Google reduced free tier limits by 50-80% in December 2025. Tutorials and documentation written before that date will show stale (higher) numbers. Always check current limits in the AI Studio quota dashboard.
19. What is the Gemini Batch API and when should you use it?
The Batch API allows submitting multiple Gemini API requests as an asynchronous batch job, receiving results up to 24 hours later at approximately 50% reduced cost compared to synchronous API calls. It is designed for large-scale, non-time-sensitive workloads.
from google import genai from google.genai import types client = genai.Client() # Create a batch job with multiple requests: batch = client.batches.create( model="gemini-2.5-flash", src=types.CreateBatchJobSource( requests=[ types.EmbedContentRequest( content=types.Content(parts=[types.Part(text="Summarise: " + doc)]) ) for doc in list_of_1000_documents ] ), ) print(f"Batch ID: {batch.name}, state: {batch.state}") # Poll for completion (up to 24 hours): import time while batch.state in ("JOB_STATE_PENDING", "JOB_STATE_RUNNING"): time.sleep(60) batch = client.batches.get(name=batch.name) # Retrieve results: for result in client.batches.list_responses(name=batch.name): print(result.response.candidates[0].content.parts[0].text) # All current Gemini 3 and 2.5 models support the Batch API
| Aspect | Synchronous | Batch API |
|---|---|---|
| Cost | Standard pricing | ~50% reduction |
| Latency | Real-time (seconds) | Up to 24 hours |
| Rate limits | Against RPM/TPM | Separate higher batch limits |
| Use cases | Interactive apps | Evals, bulk analysis, dataset processing |
20. How do you use Python and JavaScript SDKs with the Gemini API?
Google provides official SDKs for Python (google-genai) and JavaScript/TypeScript (@google/genai). Both are available from version 2.3.0 onwards for Interactions API support.
# Python SDK setup: pip install google-genai import os from google import genai # Authentication - reads GEMINI_API_KEY from environment os.environ["GEMINI_API_KEY"] = "your-key-here" # or set externally client = genai.Client() # Basic text generation: interaction = client.interactions.create( model="gemini-3.5-flash", input="Write a Python web scraper.", ) print(interaction.output_text) # Async version: import asyncio async def async_example(): interaction = await client.aio.interactions.create( model="gemini-3.5-flash", input="Async web scraping example", ) return interaction.output_text asyncio.run(async_example())
// JavaScript/TypeScript SDK: npm install @google/genai import { GoogleGenAI } from "@google/genai"; const ai = new GoogleGenAI({}); // reads GEMINI_API_KEY from env // Basic interaction: const interaction = await ai.interactions.create({ model: "gemini-3.5-flash", input: "Explain async/await in JavaScript.", }); console.log(interaction.outputText); // Streaming: const stream = await ai.interactions.create({ model: "gemini-3.5-flash", input: "Write a long blog post about AI.", stream: true, }); for await (const chunk of stream) { process.stdout.write(chunk.outputText ?? ""); }
21. What is context caching in the Gemini API and how does it reduce costs?
Context caching stores a large stable prompt prefix (such as a system instruction, large document, or tool definitions) on Google's servers. Subsequent requests referencing that cache pay a lower price for the cached tokens rather than full input token pricing.
from google import genai from google.genai import types from datetime import timedelta client = genai.Client() # Create a cache with large stable content: large_document = open("entire-codebase.py").read() # 500k tokens cached = client.caches.create( model="gemini-3.5-flash", config=types.CreateCachedContentConfig( contents=[ types.Content( parts=[types.Part(text=large_document)] ) ], system_instruction="You are a code review expert. Always give actionable feedback.", ttl=timedelta(hours=2), # cache lives for 2 hours display_name="codebase-cache", ) ) print(f"Cache name: {cached.name}") print(f"Cached tokens: {cached.usage_metadata.total_token_count}") # Use the cache across many requests: for pr_diff in pull_requests: response = client.models.generate_content( model="gemini-3.5-flash", contents=pr_diff, # only the diff changes per request config=types.GenerateContentConfig( cached_content=cached.name ) ) # You pay full price for pr_diff tokens # but discounted price for the 500k cached codebase tokens print(response.text) # Delete cache when done: client.caches.delete(name=cached.name)
When to use context caching: it is most effective when the same large content (codebase, documentation, legal corpus) is referenced across many API calls. The cache has a minimum token size requirement (typically a few thousand tokens), and cached tokens cost less per request than fresh input tokens.
22. What is the Gemini API pricing model and how do you estimate costs?
The Gemini API uses a pay-per-token model. All Gemini 3 models currently in preview have billing enabled; free tiers exist for Gemini 2.5 models. Pricing differs between input tokens, output tokens, and cached tokens.
| Model | Input price | Output price | Best for |
|---|---|---|---|
| Gemini 3.5 Flash | Flash-tier pricing | Flash-tier pricing | Frontier intelligence at Flash cost |
| Gemini 3.1 Pro Preview | Pro-tier pricing | Pro-tier pricing | Highest capability (preview) |
| Gemini 2.5 Flash-Lite | ~$0.10/1M tokens | Higher | Cheapest paid option |
| Gemini 2.5 Flash | Standard Flash pricing | Standard | Good balance, stable |
| Batch API (all models) | ~50% discount | ~50% discount | Bulk non-real-time |
# Cost estimation: # Scenario: Process 10,000 support tickets # Average: 500 input tokens + 200 output tokens each docs = 10_000 per_doc_input = 500 per_doc_output = 200 # Gemini 2.5 Flash (illustrative: $0.30/1M input, $1.20/1M output) input_cost = (docs * per_doc_input / 1_000_000) * 0.30 # $1.50 output_cost = (docs * per_doc_output / 1_000_000) * 1.20 # $2.40 total_sync = input_cost + output_cost # $3.90 # With Batch API (~50% discount): total_batch = total_sync * 0.5 # $1.95 print(f"Synchronous: ${total_sync:.2f}") print(f"Batch API: ${total_batch:.2f}") # Always check current prices at: # ai.google.dev/gemini-api/docs/pricing # Prices change frequently with new model releases
Key cost levers: right-sizing the model (Flash-Lite for classification, Pro for complex reasoning); context caching for repeated prompts; Batch API for bulk; and choosing stable models to avoid unexpected billing changes from preview deprecations.
23. What is Google AI Studio and how does it differ from Vertex AI for Gemini access?
Google AI Studio (aistudio.google.com) and Google Cloud Vertex AI are two distinct pathways to access Gemini models. Choosing the right one depends on your scale, compliance requirements, and cloud strategy.
| Aspect | Google AI Studio | Vertex AI |
|---|---|---|
| Target user | Individual developers, startups, prototypes | Enterprise, regulated industries, large scale |
| Setup | Sign in with Google - get API key instantly | Requires Google Cloud project and billing |
| Free tier | Yes (limited RPM/RPD) | No (pay per token from first call) |
| Data privacy | May use free tier data to improve models | Business data NOT used for training |
| Compliance | Standard | SOC 2, HIPAA, VPC Service Controls |
| Model availability | Latest models first, some preview access | Stable enterprise releases, some delay |
| Additional features | Prompt testing, tuning, evaluation | MLOps pipelines, Model Garden, training |
| Billing | Per token after free tier | Per token, enterprise pricing |
| SDK | google-genai with GEMINI_API_KEY | google-cloud-aiplatform or google-genai |
# Google AI Studio (simple) from google import genai client = genai.Client() # reads GEMINI_API_KEY # Vertex AI (enterprise) from google import genai client = genai.Client( vertexai=True, project="my-gcp-project", location="us-central1", ) # Vertex AI also accepts service account credentials # and integrates with IAM roles
24. What are Gemma models and how do they relate to the Gemini API?
Gemma is Google's family of open-source, lightweight language models built from the same research and technology as Gemini. They are available for free download and can be run locally or deployed on your own infrastructure without the Gemini API.
| Aspect | Gemma | Gemini |
|---|---|---|
| Open source | Yes - weights available on Hugging Face/Kaggle | No - closed model, API-only |
| Hosting | Self-host anywhere | Google's infrastructure via API |
| Size | Compact (2B to 27B parameters) | Much larger frontier models |
| Privacy | 100% on-premise possible | Data goes to Google's servers |
| Cost | Compute cost only (no per-token fee) | Pay per token |
| Capability | Strong for size; not frontier | State-of-the-art frontier |
| Updates | New releases periodically | Continuous via API |
# Gemma 4 models (latest as of mid-2026): # gemma-4-26b-a4b-it (26B instruct) # gemma-4-31b-it (31B instruct) # Available on AI Studio and via Gemini API for inference # Also available for local use via: # Hugging Face: from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("google/gemma-4-9b") # Ollama: # ollama run gemma3 # Google also makes Gemma available through the Gemini API: # This lets you use the API interface without leaving Google's ecosystem response = client.models.generate_content( model="gemma-4-26b-a4b-it", # Gemma via Gemini API contents="Explain gradient descent.", )
25. How do you implement streaming responses in the Gemini API?
Streaming delivers model output token by token as it generates, rather than waiting for the complete response. This dramatically improves perceived performance in interactive applications and is essential for long responses.
from google import genai client = genai.Client() # Method 1: generateContent with stream=True for chunk in client.models.generate_content_stream( model="gemini-3.5-flash", contents="Write a comprehensive guide to Python async programming.", ): print(chunk.text, end="", flush=True) # prints each chunk as it arrives print() # final newline # Method 2: Interactions API with stream=True for chunk in client.interactions.create( model="gemini-3.5-flash", input="Explain the history of computer science.", stream=True, ): if chunk.output_text: print(chunk.output_text, end="", flush=True) # Async streaming (for FastAPI, async web apps): async def stream_async(): async for chunk in await client.aio.models.generate_content_stream( model="gemini-3.5-flash", contents="Async streaming example.", ): print(chunk.text, end="", flush=True) yield chunk.text # yield to web framework (SSE, WebSocket)
Server-Sent Events (SSE) integration: streaming output can be forwarded to browsers via SSE or WebSockets. FastAPI, Flask-SSE, or any async web framework can yield streaming chunks directly to the client, enabling a ChatGPT-like typing effect in web applications.
26. What is the Python `import antigravity` Easter egg and what does it demonstrate?
The import antigravity Easter egg is a hidden joke built into Python's standard library since Python 3. When executed, it opens a web browser pointing to the XKCD webcomic strip #353, which humorously depicts Python enabling flight by simply installing a library.
# Python Easter egg import antigravity # -> Opens https://xkcd.com/353/ in your default web browser # The antigravity module also contains a hidden geocode function: import antigravity print(dir(antigravity)) # Output: ['__builtins__', '__doc__', '__file__', '__loader__', # '__name__', '__package__', '__spec__', 'fly', 'geohash'] # The geohash function implements the xkcd geohashing algorithm: antigravity.geohash(37.421542, -122.085589, b"2005-05-26-10458.68") # Computes a Geohash based on date and Dow Jones opening price # The module's source code is a fun read: import inspect import antigravity print(inspect.getsource(antigravity))
| Easter egg | How to trigger | What it does |
|---|---|---|
| import antigravity | import antigravity | Opens XKCD #353 in browser; exposes geohash() |
| import this | import this | Prints the Zen of Python (PEP 20) |
| import __hello__ | import __hello__ | Prints 'Hello World!' |
| Barry's time machine | from __future__ import braces | Raises SyntaxError: not a chance |
Why interviewers ask about it: knowledge of import antigravity signals familiarity with Python's culture, the standard library's hidden features, and comfort with exploring the language beyond its functional use. The XKCD comic it references captures Python's philosophy of making powerful things easy to do.
27. What is the Gemini API's approach to safety and content moderation?
Gemini models include built-in safety filters that evaluate both input prompts and output content across four harm categories. Developers can configure the threshold at which content is blocked, balancing safety with utility for their specific application context.
| Category | What it covers |
|---|---|
| HARM_CATEGORY_HARASSMENT | Threatening, bullying, or targeted abuse |
| HARM_CATEGORY_HATE_SPEECH | Content promoting hatred based on protected characteristics |
| HARM_CATEGORY_SEXUALLY_EXPLICIT | Adult sexual content |
| HARM_CATEGORY_DANGEROUS_CONTENT | Content facilitating serious harm, weapons, illegal activities |
from google import genai from google.genai import types client = genai.Client() # Configure safety thresholds: response = client.models.generate_content( model="gemini-3.5-flash", contents="Your prompt here", config=types.GenerateContentConfig( safety_settings=[ types.SafetySetting( category="HARM_CATEGORY_DANGEROUS_CONTENT", threshold="BLOCK_ONLY_HIGH", # options below ), types.SafetySetting( category="HARM_CATEGORY_HARASSMENT", threshold="BLOCK_MEDIUM_AND_ABOVE", ), ] ) ) # Check safety ratings on the response: for rating in response.candidates[0].safety_ratings: print(f"{rating.category}: {rating.probability}") # Check if response was blocked: if response.prompt_feedback.block_reason: print(f"Blocked: {response.prompt_feedback.block_reason}")
| Threshold | Blocks |
|---|---|
| BLOCK_NONE | Nothing (use with caution) |
| BLOCK_ONLY_HIGH | Only HIGH probability harm |
| BLOCK_MEDIUM_AND_ABOVE | MEDIUM and HIGH probability harm |
| BLOCK_LOW_AND_ABOVE | LOW, MEDIUM, and HIGH (most restrictive) |
28. What is Gemini Deep Research and how does it work as a managed agent?
Gemini Deep Research is a managed agent in the Gemini API (available in preview via Google AI Studio) that performs comprehensive, multi-step research tasks. Unlike single-turn search grounding, Deep Research plans a research strategy, executes many web searches over an extended period, and synthesises the results into a structured report.
from google import genai client = genai.Client() # Deep Research agent - model ID may vary; check current docs # Typically accessed via AI Studio or the interactions API: interaction = client.interactions.create( model="gemini-deep-research-preview", input="""Conduct comprehensive research on the performance characteristics of Python async frameworks in 2026: FastAPI, Starlette, Litestar, and Blacksheep. Compare throughput, latency, ecosystem maturity, and real-world adoption. Produce a structured report with data sources cited.""", background=True, # Long research tasks run in background ) print(f"Research started: {interaction.id}") # Poll for completion (research may take 5-30 minutes): import time while True: result = client.interactions.retrieve(interaction.id) print(f"Status: {result.status}") if result.status == "completed": print(result.output_text) # full research report break elif result.status == "failed": print("Research failed") break time.sleep(60)
| Aspect | Search Grounding | Deep Research |
|---|---|---|
| Search depth | Single search call | Many searches across a research plan |
| Synthesis | Model incorporates results | Full report with sections and citations |
| Time | Seconds | Minutes to tens of minutes |
| Output | Enhanced response | Structured research report |
| Use case | Quick factual queries | Comprehensive competitive analysis, literature review |
29. What is Firebase AI Logic and how does it simplify Gemini integration in mobile and web apps?
Firebase AI Logic (formerly Firebase AI Extensions) is Google's managed backend service that provides a secure, scalable Gemini API integration specifically designed for mobile and web applications. It abstracts away server-side API key management and provides Firebase-native patterns for AI features.
| Aspect | Direct Gemini API | Firebase AI Logic |
|---|---|---|
| API key management | Developer manages; risk of client-side exposure | Google manages; keys never in client code |
| Authentication | Static API key | Firebase Auth integration (per-user access) |
| Rate limiting | Global account limits | Per-user Firebase quotas |
| Streaming | Manual SSE setup | Built-in streaming support |
| Platform | Any (server or client) | Mobile (iOS, Android) and web (JavaScript) |
| Pricing | Gemini API pricing | Firebase pricing (may differ) |
// Firebase AI Logic - Android (Kotlin) import com.google.firebase.ai.generativeai.GenerativeModel val model = Firebase.ai.generativeModel("gemini-3.5-flash") val response = model.generateContent("Explain Kotlin coroutines.") println(response.text) // iOS (Swift) let model = FirebaseAI.ai().generativeModel(modelName: "gemini-3.5-flash") let response = try await model.generateContent("Explain Swift concurrency.") print(response.text ?? "") // Web (JavaScript) import { getAI, getGenerativeModel } from "firebase/ai"; const ai = getAI(firebaseApp); const model = getGenerativeModel(ai, { model: "gemini-3.5-flash" }); const result = await model.generateContent("Explain Firebase."); console.log(result.response.text());
30. How do you implement multi-turn conversations in the Gemini API?
Multi-turn conversations maintain context across several exchanges. The Gemini API supports two approaches: manually managing conversation history with generateContent, or using the Interactions API's previous_interaction_id for server-side state management.
from google import genai from google.genai import types client = genai.Client() # Approach 1: Manual history with generateContent (legacy) history = [] while True: user_input = input("You: ") history.append(types.Content(role="user", parts=[types.Part(text=user_input)])) response = client.models.generate_content( model="gemini-3.5-flash", contents=history, ) assistant_reply = response.candidates[0].content history.append(assistant_reply) # add model turn to history print(f"Gemini: {assistant_reply.parts[0].text}") # Approach 2: Interactions API with previous_interaction_id (recommended) # First turn: first = client.interactions.create( model="gemini-3.5-flash", input="I am building a task management app in Python.", ) # Second turn - model remembers the first: second = client.interactions.create( model="gemini-3.5-flash", input="What database would you recommend for my app?", previous_interaction_id=first.id, # server retrieves first turn context ) # Third turn: third = client.interactions.create( model="gemini-3.5-flash", input="Show me the schema for that database.", previous_interaction_id=second.id, ) print(third.output_text)
31. What is the Gemini API's text-to-speech capability and how do you use it?
The Gemini API provides text-to-speech (TTS) generation through the Speech API and the Live API. The Speech API generates audio from text using Gemini's native speech synthesis with dozens of available voices.
from google import genai from google.genai import types import wave client = genai.Client() # Single-speaker TTS: response = client.models.generate_content( model="gemini-3.1-flash-tts-preview", contents="Welcome to the Gemini API tutorial. Today we explore text-to-speech.", config=types.GenerateContentConfig( response_modalities=["AUDIO"], speech_config=types.SpeechConfig( voice_config=types.VoiceConfig( prebuilt_voice_config=types.PrebuiltVoiceConfig( voice_name="Aoede" # one of 30 available voices ) ) ) ) ) # Extract and save audio: audio_data = response.candidates[0].content.parts[0].inline_data.data with open("output.wav", "wb") as f: f.write(audio_data) # Multi-speaker TTS (new in 2026): response = client.models.generate_content( model="gemini-3.1-flash-tts-preview", contents="""TTS the following conversation: <speaker name="Narrator">The story begins on a dark night.</speaker> <speaker name="Alice">Who goes there?</speaker> <speaker name="Bob">It is I, your long-lost friend!</speaker> """, config=types.GenerateContentConfig( response_modalities=["AUDIO"], speech_config=types.SpeechConfig( multi_speaker_voice_config=types.MultiSpeakerVoiceConfig( speaker_voice_configs=[ types.SpeakerVoiceConfig(speaker="Alice", voice_config=types.VoiceConfig( prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Aoede") )), types.SpeakerVoiceConfig(speaker="Bob", voice_config=types.VoiceConfig( prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Charon") )), ] ) ) ) )
The TTS model supports 30 built-in voices with different tones and accents. Multi-speaker TTS allows different voices for different speakers within a single audio generation request, enabling podcast production, audiobook generation, and conversational AI audio without post-production mixing.
32. What are Gemini API embeddings and what models support them?
Embeddings convert text into dense numerical vectors capturing semantic meaning. The Gemini API provides text embedding models for building semantic search, RAG pipelines, clustering, and classification systems.
from google import genai from google.genai import types import numpy as np client = genai.Client() # Generate embeddings with Gemini Embedding: result = client.models.embed_content( model="gemini-embedding-exp-03-07", # current experimental embedding model contents=[ "Python is a versatile programming language.", "Gemini is Google's AI model family.", "The stock market fell today.", ] ) vectors = [e.values for e in result.embeddings] print(f"Embedding dimensions: {len(vectors[0])}") # typically 768 or 3072 # Compute cosine similarity: def cosine_sim(a, b): a, b = np.array(a), np.array(b) return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) print(f"Python vs Gemini: {cosine_sim(vectors[0], vectors[1]):.3f}") # medium print(f"Python vs stocks: {cosine_sim(vectors[0], vectors[2]):.3f}") # low # Task type specification (improves accuracy): result = client.models.embed_content( model="gemini-embedding-exp-03-07", contents="How does async/await work in Python?", config=types.EmbedContentConfig( task_type="RETRIEVAL_QUERY" # vs RETRIEVAL_DOCUMENT, SEMANTIC_SIMILARITY ) )
| task_type | Use when |
|---|---|
| RETRIEVAL_QUERY | Embedding a user's search query |
| RETRIEVAL_DOCUMENT | Embedding documents to be indexed |
| SEMANTIC_SIMILARITY | Comparing two texts for similarity |
| CLASSIFICATION | Embedding text for classification |
| CLUSTERING | Embedding for grouping similar texts |
33. What is the Gemini API's system instruction and how does it differ from a user prompt?
The system instruction (equivalent to a system prompt) sets the model's persona, behaviour, constraints, and context before any user interaction begins. It differs from a user prompt in that it is processed separately and takes precedence in shaping the model's overall behaviour.
from google import genai from google.genai import types client = genai.Client() # generateContent with system instruction: response = client.models.generate_content( model="gemini-3.5-flash", contents="Explain recursion.", # user input config=types.GenerateContentConfig( system_instruction="You are a Python tutor for beginners. Always give examples in Python. Keep explanations under 200 words. Never use jargon without explaining it first.", ) ) print(response.text) # Interactions API with system instruction: interaction = client.interactions.create( model="gemini-3.5-flash", input="Explain recursion.", system_instruction="You are a Python tutor for beginners...", ) # Effective system instruction principles: EFFECTIVE_SYSTEM_INSTRUCTION = """ Role: You are a senior Python code reviewer at a fintech company. Constraints: - Always check for security vulnerabilities first - Flag any use of eval() or exec() as critical risk - Use Decimal for financial calculations, never float - Output in this format: Risk Level, Issues, Recommendations Tone: Professional, direct, constructive """ # System instruction vs user prompt: # System instruction: stable per session; shapes all responses; cached efficiently # User prompt: changes per turn; the actual task or question
Caching system instructions: since system instructions are typically long and repeated across many requests, they are the primary candidate for context caching. A well-structured system instruction placed in a cache can reduce per-request costs significantly for production deployments with high request volumes.
34. What is the observable execution steps feature in the Gemini Interactions API?
When using the Interactions API, each interaction object exposes execution steps - a detailed log of everything the model did to arrive at its answer, including thinking steps, tool calls, code execution, and web searches. This provides transparency into model reasoning for debugging and building rich UIs.
from google import genai client = genai.Client() interaction = client.interactions.create( model="gemini-3.5-flash", input="What is the square root of the number of stars in the Milky Way?", tools=[{"google_search": {}}], ) # Inspect every step the model took: for i, step in enumerate(interaction.steps): print(f"Step {i}: type={step.type}") if step.type == "thought": # Encrypted thinking (content not shown but signature confirms it happened) print(f" Thinking... (signature: {step.signature[:20]}...)") elif step.type == "tool_call": print(f" Tool call: {step.tool_call.name}") print(f" Arguments: {step.tool_call.arguments}") elif step.type == "tool_result": print(f" Tool result received") elif step.type == "code_execution": print(f" Code: {step.code}") print(f" Output: {step.output}") elif step.type == "model_output": print(f" Final answer: {step.content[0].text}") # Use steps to build a UI showing real-time reasoning: for step in interaction.steps: if step.type == "tool_call": show_ui("Searching the web for: " + step.tool_call.arguments.get("query","")) elif step.type == "thought": show_ui("Thinking...") elif step.type == "model_output": show_ui("Answer: " + step.content[0].text)
35. How do you handle Gemini API errors and implement robust error handling?
The Gemini API returns standard HTTP error codes. The Python SDK wraps these as typed exceptions from google.api_core.exceptions. Robust applications should handle these systematically with appropriate retry and fallback strategies.
import time from google import genai from google.api_core import exceptions as google_exceptions client = genai.Client() def gemini_call_with_retry(prompt: str, model: str = "gemini-3.5-flash", max_retries: int = 5) -> str: for attempt in range(max_retries): try: response = client.models.generate_content( model=model, contents=prompt, ) # Check if blocked by safety filters: if not response.candidates: reason = response.prompt_feedback.block_reason raise ValueError(f"Response blocked: {reason}") return response.text except google_exceptions.ResourceExhausted: # 429 rate limit wait = (2 ** attempt) + 0.1 print(f"Rate limited. Waiting {wait:.1f}s...") time.sleep(wait) except google_exceptions.InvalidArgument as e: # 400 bad request if "context window" in str(e).lower(): raise ValueError("Prompt too long - reduce size.") from e raise # Re-raise other bad request errors except google_exceptions.PermissionDenied: # 403 raise PermissionError("Invalid API key or insufficient permissions.") except google_exceptions.ServiceUnavailable: # 503 wait = 5 * (attempt + 1) print(f"Service unavailable. Waiting {wait}s...") time.sleep(wait) except google_exceptions.NotFound: # 404 raise ValueError(f"Model {model!r} not found or deprecated.") raise Exception(f"Max retries ({max_retries}) exceeded.")
| Exception | HTTP code | Common cause |
|---|---|---|
| ResourceExhausted | 429 | Rate limit hit - implement backoff |
| InvalidArgument | 400 | Bad parameters, context overflow |
| PermissionDenied | 403 | Invalid API key or unauthorised model |
| NotFound | 404 | Model deprecated or doesn't exist |
| ServiceUnavailable | 503 | Transient server error - retry |
36. What is Gemini's native audio understanding capability and how do you use it?
Gemini models can directly process audio files - transcribing speech, answering questions about audio content, identifying speakers, and analysing audio characteristics. This is different from the Live API's real-time audio; it processes pre-recorded audio files.
from google import genai from google.genai import types from pathlib import Path client = genai.Client() # Method 1: Inline audio (small files < 20MB) audio_bytes = Path("interview.mp3").read_bytes() response = client.models.generate_content( model="gemini-3.5-flash", contents=[ types.Part( inline_data=types.Blob( data=audio_bytes, mime_type="audio/mp3" ) ), types.Part(text="Transcribe this interview and summarise the key points.") ] ) print(response.text) # Method 2: Upload via Files API (recommended for files > 20MB) uploaded = client.files.upload( file=Path("podcast.mp3"), config={"display_name": "Tech Podcast Episode 42"} ) # Wait for processing: import time while uploaded.state == "PROCESSING": time.sleep(2) uploaded = client.files.get(name=uploaded.name) # Analyse the audio: response = client.models.generate_content( model="gemini-3.5-flash", contents=[ types.Part(file_data=types.FileData(file_uri=uploaded.uri, mime_type="audio/mp3")), types.Part(text="How many different speakers are in this podcast? Identify each speaker's role.") ] ) print(response.text)
| Property | Detail |
|---|---|
| Supported formats | MP3, WAV, FLAC, AAC, OGG, OPUS, WebM audio |
| Max inline size | ~20MB (use Files API for larger) |
| Max duration (context window) | Approximately 9.5 hours of audio at 1M token context |
| Capabilities | Transcription, speaker diarisation, audio Q&A, summarisation |
37. What is the Gemini API's grounded generation with Google Search and how does attribution work?
When Search Grounding is enabled, Gemini not only uses real-time web data to improve its response but also returns grounding metadata - source attributions showing which web pages contributed to the answer. This enables you to display proper citations in your application.
from google import genai from google.genai import types client = genai.Client() response = client.models.generate_content( model="gemini-3.5-flash", contents="What are the most recent Gemini API updates?", config=types.GenerateContentConfig( tools=[types.Tool(google_search=types.GoogleSearch())], ) ) print(response.text) # Access grounding metadata: candidate = response.candidates[0] if candidate.grounding_metadata: gm = candidate.grounding_metadata # Sources used: print("\nSources:") for chunk in gm.grounding_chunks: if chunk.web: print(f" - {chunk.web.title}: {chunk.web.uri}") # Which parts of the response are grounded: for support in gm.grounding_supports: text_segment = support.segment.text sources = [gm.grounding_chunks[i].web.uri for i in support.grounding_chunk_indices] print(f"\nClaim: {text_segment[:80]}...") print(f"Supported by: {sources}") # Search entry point (rendered search suggestion UI element): if gm.search_entry_point: print(f"\nSearch UI: {gm.search_entry_point.rendered_content[:100]}")
The grounding_supports array maps specific text segments in the response to the sources that support them - enabling you to render inline citations (like footnotes) in your UI. The search_entry_point contains a rendered HTML element that displays a Google Search suggestion, which some applications are required to show.
38. What are the key deprecated and shut-down Gemini models developers should know about?
Staying current with model deprecations is critical for production applications. The Gemini API has seen significant deprecations throughout 2025-2026, and applications referencing deprecated model IDs will receive errors after shut-down dates.
| Model(s) | Shut-down date | Notes |
|---|---|---|
| All Gemini 1.0 models | Multiple dates in 2025 | Now return 404 errors; migrate to 2.x or 3.x |
| All Gemini 1.5 models | Multiple dates in 2025 | Now return 404 errors; migrate to 2.x or 3.x |
| Gemini 2.0 Flash | June 1, 2026 | Returns errors; migrate to 2.5 Flash or 3.x |
| Gemini 2.0 Flash-Lite | June 1, 2026 | Returns errors; migrate to 2.5 Flash-Lite or 3.x |
| Gemini 3 Pro Preview | Deprecated March 9, 2026 | Short notice; illustrates preview risk |
| Imagen (all versions) | June 30, 2026 | Migrate to Nano Banana (gemini-3-image family) |
| Veo 2.0 models | June 30, 2026 | Migrate to Veo 3.1 family |
# How to detect if your code is using deprecated models: # Run this to audit model IDs in your codebase: import re, glob deprecated = [ "gemini-1.0", "gemini-1.5", "gemini-2.0-flash", "gemini-2.0-flash-lite", "gemini-3-pro-preview", "gemini-3.0", "imagen", "veo-2" ] for file_path in glob.glob("**/*.py", recursive=True): with open(file_path) as f: content = f.read() for dep in deprecated: if dep in content: print(f"DEPRECATED model ID found in {file_path}: {dep}") # Best practice: centralise model IDs in config # config.py: GEMINI_MODEL = "gemini-3.5-flash" # update here only when migrating GEMINI_EMBED_MODEL = "gemini-embedding-exp-03-07"
39. How do you build a Retrieval-Augmented Generation (RAG) pipeline with the Gemini API?
RAG enhances Gemini responses with content from your own documents, databases, or knowledge bases. The Gemini API supports two approaches: using the built-in file_search tool (managed by Google) or building your own pipeline with Gemini embeddings and an external vector database.
from google import genai from google.genai import types import numpy as np client = genai.Client() # APPROACH 1: Built-in file_search (simplest - Google manages everything) # 1. Upload documents: uploaded = client.files.upload(file="knowledge-base.pdf") # 2. Query against them (no vector DB needed): response = client.models.generate_content( model="gemini-3.5-flash", contents="What is our refund policy?", config=types.GenerateContentConfig( tools=[types.Tool(retrieval=types.Retrieval( vertex_ai_search=types.VertexAISearch(datastore="projects/my-project/...") ))] ) ) print(response.text) # APPROACH 2: Custom RAG with Gemini embeddings def embed(texts: list[str]) -> list[list[float]]: result = client.models.embed_content( model="gemini-embedding-exp-03-07", contents=texts, config=types.EmbedContentConfig(task_type="RETRIEVAL_DOCUMENT"), ) return [e.values for e in result.embeddings] # Index your documents: docs = ["Our policy is...", "For returns, contact..."] doc_embeddings = embed(docs) # store in Pinecone/pgvector/Weaviate # At query time: query_embedding = client.models.embed_content( model="gemini-embedding-exp-03-07", contents="Can I return a product?", config=types.EmbedContentConfig(task_type="RETRIEVAL_QUERY"), ).embeddings[0].values # Find most similar docs (cosine similarity): similarities = [np.dot(query_embedding, d) / (np.linalg.norm(query_embedding) * np.linalg.norm(d)) for d in doc_embeddings] top_idx = int(np.argmax(similarities)) # Generate with context: response = client.models.generate_content( model="gemini-3.5-flash", contents=f"Context: {docs[top_idx]}\n\nQuestion: Can I return a product?", )
40. What are best practices for building production-grade Gemini API applications?
Moving a Gemini prototype to production requires addressing reliability, cost efficiency, safety, and maintainability. These practices apply across model versions and application types.
| Area | Best practice |
|---|---|
| Model selection | Use pinned stable model IDs (e.g. gemini-2.5-flash-001), never -latest in production |
| Cost control | Use Batch API for bulk; enable context caching for repeated prompts; choose right model tier per task |
| Error handling | Exponential backoff for 429 errors; handle 404s (model deprecated); fallback model strategy |
| Safety | Configure appropriate safety thresholds; check block_reason; validate all user inputs |
| Rate limits | Monitor quota in AI Studio; implement client-side rate limiting; use Vertex AI for higher limits |
| Observability | Log all requests and responses with IDs; track token usage; use interaction steps for debugging |
| Testing | Run evals before model upgrades; test edge cases; validate structured output schemas |
| Privacy | Use Vertex AI for regulated data; minimise PII in prompts; understand data retention policy |
# Example production-hardened Gemini call: from google import genai from google.genai import types from google.api_core import exceptions import time, logging logger = logging.getLogger("gemini-app") client = genai.Client() GEMINI_MODEL = "gemini-2.5-flash-001" # PINNED - never use -latest def production_generate(prompt: str, user_id: str) -> str: for attempt in range(4): try: response = client.models.generate_content( model=GEMINI_MODEL, contents=prompt, config=types.GenerateContentConfig( max_output_tokens=2048, # cap output temperature=0.2, # low for predictability safety_settings=[ types.SafetySetting( category="HARM_CATEGORY_DANGEROUS_CONTENT", threshold="BLOCK_MEDIUM_AND_ABOVE" ) ] ) ) if not response.candidates: raise ValueError(f"Blocked: {response.prompt_feedback.block_reason}") logger.info({"user": user_id, "tokens": response.usage_metadata.total_token_count}) return response.text except exceptions.ResourceExhausted: time.sleep(2 ** attempt) raise RuntimeError("Max retries exceeded")
