File Search is Gemini’s managed RAG: you create a store, Google chunks and embeds your files, and a query retrieves the relevant passages automatically. It runs on the current google-genai SDK over the v1beta API. The OpenAI analog is file search; for a from-scratch version see minimal RAG in Python.
1. Install google-genai and set GEMINI_API_KEY
pip install -U google-genai
Installs the current SDK (the legacy google-generativeai package is different).
export GEMINI_API_KEY="AIza..."
The client reads this variable on its own.
2. Create a File Search store
from google import genai
client = genai.Client() # reads GEMINI_API_KEY
store = client.file_search_stores.create(
config={"display_name": "handbook", "embedding_model": "models/gemini-embedding-2"},
)
Creates an empty store; its store.name identifies it for uploads and queries.
3. Upload a file into the store and wait for indexing
import time
op = client.file_search_stores.upload_to_file_search_store(
file="handbook.pdf",
file_search_store_name=store.name,
config={"display_name": "handbook.pdf"},
)
while not op.done:
time.sleep(5)
op = client.operations.get(op)
Uploads and indexes the file as a long-running operation you poll until done.
4. Query with the file_search tool
interaction = client.interactions.create(
model="gemini-3.8-flash",
input="What is the refund window?",
tools=[{"type": "file_search", "file_search_store_names": [store.name]}],
)
print(interaction.output_text)
The file_search tool retrieves matching chunks and grounds the answer in them.
5. Read the answer and its citations
for step in interaction.steps:
if step.type != "model_output":
continue
for block in step.content:
for ann in getattr(block, "annotations", None) or []:
if ann.type == "file_citation":
print(ann.file_name, getattr(ann, "page_number", ""))
Citations arrive as file_citation annotations on the model_output text blocks, each naming the source file and page.
Stores persist until you delete them with client.file_search_stores.delete(name=store.name, config={'force': True}); raw uploaded files expire after 48 hours, but indexed data stays. Each document can be up to 100 MB, and you pay for embeddings at indexing time while storage and query-time embeddings are free. Confirm the current method names and model ids on the File Search docs.
Verify it worked
interaction.output_text should answer from the document, and at least one file_citation should name your file.
If it fails:
- Empty or ungrounded answer — the operation had not finished; poll
op.donebefore querying, indexing is not instant. AttributeErroronfile_search_stores— yourgoogle-genaiis too old; runpip install -U google-genai(image search needs 1.75.0+).- No citations in
steps— you readoutput_textonly; citations live in themodel_outputsteps’annotations, not the plain text.