The OpenAI Responses API can search supplied files in a vector store (this is called retrieval-augmented generation, RAG), or search the Web.
I tried to combine the two tools into a single query but it just didn’t work:
. . .
client = OpenAI(api_key=key)
. . .
# assumes a vector store with demo_store_id exists
query = "Some question that might have an answer in
a file in the vector store or maybe not?"
response = client.responses.create(
model = "gpt-4.1",
tools = [
{ "type": "file_search",
"vector_store_ids": [demo_store_id] },
{ "type": "web_search_preview" },
],
input = [
{ "role": "developer",
"content": "You answer questions." },
{ "role": "user",
"content": query },
],
temperature = 0.1, # not creative
top_p = 1.0, # default max explore
max_output_tokens = 100,
)
print(response.output[1].content[0].text)
I couldn’t make the syntax work and couldn’t find an answer in the OpenAI documentation. So I hacked together a sequential approach where I try a file_search first, and if that fails, I try a web_search:
response1 = client.responses.create(
model = "gpt-4.1",
tools = [
{ "type": "file_search",
"vector_store_ids": [demo_store_id] },
],
input = [
{ "role": "developer",
"content": "You answer questions." },
{ "role": "user",
"content": query },
],
temperature = 0.1, # not creative
top_p = 1.0, # default max explore
max_output_tokens = 100,
)
if str(response1.output).find("results=None") == -1:
print(response1.output[1].content[0].text)
else: # try web search
print("Answer not found in files; trying Web search ")
response2 = client.responses.create(
model = "gpt-4.1",
tools = [{ "type": "web_search_preview" }],
input = [
{ "role": "developer",
"content": "You answer questions." },
{ "role": "user",
"content": query },
],
temperature = 0.1, # not creative
top_p = 1.0, # default max explore
max_output_tokens = 100,
)
if str(response2.output).find("results=None") == -1:
print(response2.output[1].content[0].text)
else:
print("No answer found in Web search ")
This approach is definitely crude, but it suited my needs. The technique depends on a no-response having the string “results=None” in it, which works now but it might not in the future. The OpenAI APIs are being developed so quickly, I suspect it will eventually be possible to avoid this hack.
There are a lot of refinements I can think of. For example, instead of recreating the create() parameters (model, temperature, etc.) used in the first file search response for the fallback Web search response, I should be able to just create a single dictionary object of parameters and pass them to both create() calls.

When I was about six years old, I essentially learned to read from Batman comic books. They were my large language models.
Left: The first appearance of Batman was in “Detective Comics” #27 (May, 1939). Batman got his own title dated Spring 1940, and it is still going strong.
Center: A character called the Black Bat appeared in “Black Book Detective” magazine in July 1939. The Black Bat could see in the dark but in other respects was very similar to Batman. This magazine ran until summer 1953. (This cover is from Spring 1945).
Right: The publishers of Batman and the Black Bat threatened to sue each other, both claiming each copied the other, however they settled amicably because they likely both copied from an earlier character that first appeared in “Black Bat Detective Mysteries” in October 1933. That magazine only ran six issues. So, it’s probable that 1939 Batman and the 1939 Black Bat both copied from the original 1933 Black Bat.

.NET Test Automation Recipes
Software Testing
SciPy Programming Succinctly
Keras Succinctly
R Programming
2026 Visual Studio Live
2025 Summer MLADS Conference
2025 DevIntersection Conference
2025 Machine Learning Week
2025 Ai4 Conference
2025 G2E Conference
2025 iSC West Conference
You must be logged in to post a comment.