# Use Gemini API File Search (managed RAG)

> Create a managed File Search store with the google-genai SDK, import a file, query it with the file_search tool, and read citations.

- Canonical: https://guides-ai.com/guides/gemini-api-file-search/
- Plate 15.21 · Topic: Building with the API (https://guides-ai.com/topics/api/)
- Published: 21 Oct 2026 · 3 min read
- Source site: guides-ai — https://guides-ai.com/

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](/guides/openai-file-search-rag/); for a from-scratch version see [minimal RAG in Python](/guides/rag-with-python-minimal/).

## 1. Install google-genai and set GEMINI_API_KEY

```bash
pip install -U google-genai
```

Installs the current SDK (the legacy `google-generativeai` package is different).

```bash
export GEMINI_API_KEY="AIza..."
```

The client reads this variable on its own.

## 2. Create a File Search store

```python
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

```python
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

```python
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

```python
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](https://ai.google.dev/gemini-api/docs/file-search).

## 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.done` before querying, indexing is not instant.
- **`AttributeError` on `file_search_stores`** — your `google-genai` is too old; run `pip install -U google-genai` (image search needs 1.75.0+).
- **No citations in `steps`** — you read `output_text` only; citations live in the `model_output` steps' `annotations`, not the plain text.

---

Next: [your first Gemini API request](/guides/gemini-api-first-request/) · [glossary: RAG](/glossary/#rag).
