# File search (`type: "file_search"`) — tool side **Status:** DOCUMENTED · LIVE_VERIFIED (2026-09-18, `gpt-5.4-nano`, vector store `atlas-tools-agent` created and deleted). Vector store CRUD itself is documented by the vector-stores fragment. **Sources:** https://developers.openai.com/api/docs/guides/tools-file-search · https://developers.openai.com/api/docs/pricing#built-in-tools · openapi-master.yaml `FileSearchTool`, `RankingOptions`, `HybridSearchOptions`, `ComparisonFilter`, `CompoundFilter`, `FileSearchToolCall` **Last verified:** 2026-09-18 ## Parameters | Parameter | Type / enum | Req. | Notes | |---|---|---|---| | `type` | `file_search` | yes | | | `vector_store_ids` | string[] | yes | deep research models accept only `type` + `vector_store_ids` | | `max_num_results` | integer 1–50 | no | fewer results = fewer tokens | | `ranking_options.ranker` | `auto` \| `default-2024-11-15` | no | | | `ranking_options.score_threshold` | number 0–1 | no | | | `ranking_options.hybrid_search` | `{embedding_weight, text_weight}` (both required) | no | reciprocal rank fusion weights | | `filters` | `ComparisonFilter {type: eq\|ne\|gt\|gte\|lt\|lte\|in\|nin, key, value}` \| `CompoundFilter {type: and\|or, filters[]}` | no | on file `attributes` | `include: ["file_search_call.results"]` returns the retrieved chunks (hidden by default). ## Output `file_search_call` `{id:"fs_…", type, status: in_progress|searching|completed|incomplete|failed, queries[], results[]|null}`; `results[] = {file_id, filename, score, text, attributes, vector_store_id}`. Message annotations: `file_citation {file_id, filename, index}`. ## Streaming (live) `response.output_item.added` → `response.file_search_call.in_progress` → `response.file_search_call.searching` → `response.file_search_call.completed` → `response.output_item.done` → text events. ## Billing (cited) $2.50 / 1k tool calls; storage $0.10 / GB / day after 1 GB free. ## Live evidence | Probe | Status | Result | |---|---|---| | `max_output_tokens: 32` | 200 | response `incomplete`, `file_search_call.status: "incomplete"` (budget too small for reasoning + search) | | `max_output_tokens: 300` (stream) | 200 | `queries: ["What is the secret codeword?", "secret codeword", "codeword"]` (model rewrites), `results[0].score 0.7626–0.83`, `results[0].vector_store_id: ""` (empty string, spec says id), `annotations: []` in the answer, text `PELICAN-42`; usage 2083 in / 59 out | | sh/py/ts examples | 200 | identical shapes; sh needed direct `curl -F` for the file upload (the `oai` helper forces JSON content type) | Security: retrieved chunks are model input — upload trusted files only. Examples: `examples/openai/tools/file-search/`. Test (expensive): `test_file_search_roundtrip`.