How to upload a knowledge file to OpenAI, stage it as a File Search vector store,
and reference it from a Responses-API chat call. End-to-end with the scripts in
this repo (bin/stageKnowledge.js and bin/chat.js -a chatgpt_rest_responses).
OPENAI_API_KEY exported in your environment (or sourced from .env).bin/stageKnowledge.js performs four API calls and prints the resulting vector
store ID on stdout (progress lines go to stderr so the ID can be captured cleanly):
POST /v1/files with purpose=assistants — uploads the raw file.POST /v1/vector_stores (or POST /v1/vector_stores/{id}/files if--reuse is given) — creates the vector store and attaches the file.GET /v1/vector_stores/{id}/files/{file_id} polled until status iscompleted or failed.VS_ID=$(./bin/stageKnowledge.js path/to/notes.md)
echo "$VS_ID" # e.g. vs_6a1ce825e40c8191a52e8dbf44ee3270Custom vector store name (default is the file stem):
./bin/stageKnowledge.js notes.md --name 'polish-notes-2026-05'Add a second file to an existing vector store rather than creating a new one:
./bin/stageKnowledge.js extra-notes.md --reuse "$VS_ID"Show usage:
./bin/stageKnowledge.js -hbin/chat.js -a chatgpt_rest_responses accepts one or more --vector-store <id>
flags. The lib function (lib/chatgpt_rest_responses.js) translates these into
the request body’s tools: [{ type: 'file_search', vector_store_ids: [...] }]
field on POST /v1/responses. The model decides when to invoke file_search and
inlines retrieved chunks into its reply.
source .env
printf 'Tell me my top 3 Polish pronunciation difficulties.' \
| ./bin/chat.js -a chatgpt_rest_responses --vector-store "$VS_ID"Multiple knowledge bases — pass the flag repeatedly:
... --vector-store "$VS_POLISH" --vector-store "$VS_GERMAN"Combine with a system message (added to input[]) or top-level instructions
(canonical Responses-API field). Both work together:
... --system 'Be terse.' --vector-store "$VS_ID"
... --instructions 'Cite the source line numbers.' --vector-store "$VS_ID"Nudge the model to actually use file_search (it can choose not to on simple
prompts):
... --instructions 'Use the file_search tool to ground your answer in my notes.' \
--vector-store "$VS_ID"Override the model (gpt-4o-mini default; any tool-capable model works):
... --model gpt-4o --vector-store "$VS_ID"bin/stageKnowledge.js only creates artifacts; nothing deletes them. Vector
stores and their underlying files persist on your OpenAI account and continue
to incur storage costs until removed. Use the OpenAI platform dashboard at
https://platform.openai.com/storage, or the REST API directly:
# List vector stores
curl -sS -H "Authorization: Bearer $OPENAI_API_KEY" \
https://api.openai.com/v1/vector_stores
# Inspect one
curl -sS -H "Authorization: Bearer $OPENAI_API_KEY" \
"https://api.openai.com/v1/vector_stores/$VS_ID"
# Delete a vector store (detaches files; the underlying /v1/files records remain
# and must be deleted separately if no longer needed)
curl -sS -X DELETE -H "Authorization: Bearer $OPENAI_API_KEY" \
"https://api.openai.com/v1/vector_stores/$VS_ID"
# List uploaded files
curl -sS -H "Authorization: Bearer $OPENAI_API_KEY" \
https://api.openai.com/v1/files
# Delete an uploaded file
curl -sS -X DELETE -H "Authorization: Bearer $OPENAI_API_KEY" \
"https://api.openai.com/v1/files/$FILE_ID"bin/stageKnowledge.js blocks until the file’scompleted or failed. Don’t try to query a vectorfile_counts is eventually consistent — right after creatingfile_ids, the aggregate counters can briefly reportin_progress: 0 before the attachment is registered. That’s why the script--instructions nudge as shown above./v1/responses API calls. This workflow is the API-side equivalent.