OpenAI SDK: Files, vector stores & managed retrieval
To answer questions from your own documents (policies, manuals, contracts), the model needs the relevant passages in its input.
In this post
What this post covers
To answer questions from your own documents (policies, manuals, contracts), the model needs the relevant
passages in its input. OpenAI can do the whole retrieval pipeline for you. Upload files into a
vector store, which chunks, embeds and indexes them. Then enable the
file_search tool, which retrieves the best passages at question time and
cites them. This part shows that managed path and when to build your own instead (the AI Engineering
guide builds one from scratch).
1. The managed pipeline
2. End to end
real API — index a folder of policies, then ask
from pathlib import Path
from openai import OpenAI
client = OpenAI()
store = client.vector_stores.create(name="support-policies")
for path in Path("policies").glob("*.md"):
client.vector_stores.files.upload_and_poll( # upload + wait until indexed
vector_store_id=store.id,
file=path.open("rb"),
attributes={"department": "support", "year": 2026}, # metadata usable in filters
)
response = client.responses.create(
model="gpt-5.6-luna",
input="How many days does a customer have to return a damaged item?",
tools=[{"type": "file_search", "vector_store_ids": [store.id], "max_num_results": 5}],
)
print(response.output_text)
for item in response.output:
if item.type == "message":
for ann in item.content[0].annotations:
if ann.type == "file_citation":
print("cited:", ann.filename)
Add include=["file_search_call.results"] to the request and the
file_search_call output item will contain the retrieved chunks and their scores. That is
essential when an answer is wrong and you need to know whether retrieval or generation failed.
3. Metadata filters
tools=[{
"type": "file_search",
"vector_store_ids": [store.id],
"filters": {"type": "and", "filters": [
{"type": "eq", "key": "department", "value": "support"},
{"type": "gte", "key": "year", "value": 2025},
]},
}]
Filters restrict retrieval to documents a user may see (a department, a customer’s region, current policies only). Retrieval is only as safe as its filters, so never rely on the prompt to hide documents.
4. Managed or build your own?
| OpenAI vector stores + file_search | Your own pipeline (AI Engineering guide) | |
|---|---|---|
| Time to first answer | an afternoon | days |
| Chunking, ranking control | limited options | complete |
| Where data lives | OpenAI's storage (retention per your settings) | your database (pgvector, Qdrant, Databricks…) |
| Access control | via metadata filters you set | your existing permission system |
| Switching model providers | tied to the OpenAI API | independent |
| Cost | storage per GB-day + tool calls | your infrastructure + embeddings |
Vector stores and uploaded files persist and incur storage charges until deleted. Set
expires_after on stores used for temporary work, and delete files you no longer need
(client.files.delete, client.vector_stores.delete).
Recap
- Vector stores chunk, embed and index your files; file_search retrieves and cites at question time.
include=["file_search_call.results"]shows exactly what was retrieved.- Attributes + filters scope retrieval; they are your access control.
- Managed for speed; build your own for control, portability and data residency.
Get the free RAG production checklist
25 checks to run before real users see your RAG feature: exact-match misses, invented citations, prompt injection through documents, quality that slips after a prompt change. Confirm your email and the PDF comes with the welcome email, plus each new experiment.