Description
I'm building an agent that needs to perform multiple web searches in a single turn. I found the built-in WebSearchTool
in the documentation, which seems to be exactly what I need.
However, when I expect the agent to perform more than one search, only the first search is executed, and then it stops — or it proceeds by hallucinating the rest of the answer without actually invoking the tool again.
Below is a minimal reproducible example demonstrating the issue, using the openai/agents-python
package with verbose logging enabled.
from agents import Agent, Runner, WebSearchTool
from agents.model_settings import ModelSettings
from agents import enable_verbose_stdout_logging
import asyncio
# Enable verbose logging
enable_verbose_stdout_logging()
# Simple news agent that always uses WebSearch
news_agent = Agent(
name="News Agent",
model="openai/gpt-4o-mini",
model_settings=ModelSettings(
temperature=0,
# tool_choice="WebSearchTool" # Force to always use WebSearch
),
instructions=(
"You are a news agent. For every question, you MUST use the WebSearchTool to find recent information. "
"Search for current news and provide up-to-date answers based on the search results you find. "
"Use your tool WebSearchTool also with many queries if you need it (like to search different topics)."
"Always explain what you found in the search results."
),
tools=[WebSearchTool()]
)
async def test_websearch():
print(":mag: Testing WebSearch Tool")
print("Ask about current news and I'll search for it!")
question = input("\nYour question: ")
print(f"\n:rocket: Searching for: {question}")
try:
result = await Runner.run(
news_agent,
input=[{"role": "user", "content": question}],
context={}
)
print(f"\n:newspaper: Result:")
print(result.final_output)
# Log WebSearch details
print(f"\n:mag: WebSearch Details:")
print(f"Raw responses: {len(result.raw_responses)}")
for i, response in enumerate(result.raw_responses):
if hasattr(response, 'output'):
for j, output_item in enumerate(response.output):
if hasattr(output_item, 'type') and 'web_search' in str(output_item.type):
print(f"WebSearch {j+1}:")
print(f" Status: {getattr(output_item, 'status', 'N/A')}")
if hasattr(output_item, 'action'):
print(f" Query: {output_item.action.get('query', 'N/A')}")
except Exception as e:
print(f":x: Error: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
asyncio.run(test_websearch())
For example if you ask to the agent this:
Find the Wikidata IDs of Felice Casorati and Afro Basaldella
(it’s a good test because these are lesser-known painters, so the LLM is unlikely to know the answers without searching)
you get a response like this:
:rocket: Searching for: Find the Wikidata IDs of Felice Casorati and Afro Basaldella
Creating trace Agent workflow with id trace_63d876827d3a42d1abe2724f7e447f01
Setting current trace: trace_63d876827d3a42d1abe2724f7e447f01
Creating span <agents.tracing.span_data.AgentSpanData object at 0x7f10798f95e0> with id None
Running agent News Agent (turn 1)
Creating span <agents.tracing.span_data.ResponseSpanData object at 0x7f1079908a40> with id None
Calling LLM gpt-4o-mini with input:
[
{
"role": "user",
"content": "Find the Wikidata IDs of Felice Casorati and Afro Basaldella"
}
]
Tools:
[
{
"type": "web_search_preview",
"user_location": null,
"search_context_size": "medium"
}
]
Stream: False
Tool choice: NOT_GIVEN
Response format: NOT_GIVEN
Previous response id: None
Exported 1 items
LLM resp:
[
{
"id": "ws_6865188ddb1481989554e28dff17b5a3054d4d28b72f8fc0",
"status": "completed",
"type": "web_search_call",
"action": {
"type": "search",
"query": "Felice Casorati Wikidata ID"
}
},
{
"id": "msg_6865188fb3fc8198b4e273348c679cef054d4d28b72f8fc0",
"content": [
{
"annotations": [
{
"end_index": 152,
"start_index": 79,
"title": "Felice Casorati - Wikidata",
"type": "url_citation",
"url": "https://www.wikidata.org/wiki/Q574616?utm_source=openai"
}
],
"text": "Felice Casorati, the Italian painter (1883\u20131963), has the Wikidata ID Q574616. ([[wikidata.org](http://wikidata.org/)](https://www.wikidata.org/wiki/Q574616?utm_source=openai)) Afro Basaldella, the Italian painter (1909\u20131976), has the Wikidata ID Q574617. ",
"type": "output_text",
"logprobs": []
}
],
"role": "assistant",
"status": "completed",
"type": "message"
}
]
Resetting current trace
:newspaper: Result:
Felice Casorati, the Italian painter (1883–1963), has the Wikidata ID Q574616. ([[wikidata.org](http://wikidata.org/)](https://www.wikidata.org/wiki/Q574616?utm_source=openai)) Afro Basaldella, the Italian painter (1909–1976), has the Wikidata ID Q574617.
:mag: WebSearch Details:
Raw responses: 1
WebSearch 1:
Status: completed
Query: Felice Casorati Wikidata ID
Shutting down trace provider
Shutting down trace processor <agents.tracing.processors.BatchTraceProcessor object at 0x7f1079e8d580>
Exported 2 items
As you can see from the verbose logs(enable_verbose_stdout_logging()
), the WebSearchTool is only invoked once, for "Felice Casorati Wikidata ID".
{
"id": "ws_6865188ddb1481989554e28dff17b5a3054d4d28b72f8fc0",
"status": "completed",
"type": "web_search_call",
"action": {
"type": "search",
"query": "Felice Casorati Wikidata ID"
}
Indeed the first Wikidata ID is correct (Q574616), while the second one (for Afro Basaldella) is never searched — it’s fabricated by the model (the returned ID is just +1 from the previous one, which is clearly made up). The actual correct ID would be Q388090, not Q574617.
Is there a way to allow multiple searches inside the Agent?
PS: Additional question: Do you know how to force:
tool_choice="WebSearchTool"
?
If passing in this way this parameter, I get this error:
Error getting response: Error code: 400 - {'error': {'message': "Tool choice 'function' not found in 'tools' parameter.", 'type': 'invalid_request_error', 'param': 'tool_choice', 'code': None}}. (request_id: req_94b45412956bff8d66773d5d1a960456)