From 129104cac8403c35c1cab85bac2c07fadb29a553 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Wed, 3 Dec 2025 12:54:30 +0900 Subject: [PATCH 1/4] feat: Add external_web_access option to WebSearchTool --- examples/tools/web_search_filters.py | 2 ++ src/agents/models/openai_responses.py | 1 + src/agents/tool.py | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/examples/tools/web_search_filters.py b/examples/tools/web_search_filters.py index 1e1ff0a11..8a9ed8dd2 100644 --- a/examples/tools/web_search_filters.py +++ b/examples/tools/web_search_filters.py @@ -36,6 +36,8 @@ async def main(): ], ), search_context_size="medium", + # https://platform.openai.com/docs/guides/tools-web-search?api-mode=responses#live-internet-access + # external_web_access=False, ) ], model_settings=ModelSettings( diff --git a/src/agents/models/openai_responses.py b/src/agents/models/openai_responses.py index a8695c89c..cf22135a3 100644 --- a/src/agents/models/openai_responses.py +++ b/src/agents/models/openai_responses.py @@ -475,6 +475,7 @@ def _convert_tool(cls, tool: Tool) -> tuple[ToolParam, ResponseIncludable | None "filters": tool.filters.model_dump() if tool.filters is not None else None, # type: ignore [typeddict-item] "user_location": tool.user_location, "search_context_size": tool.search_context_size, + "external_web_access": tool.external_web_access, } includes = None elif isinstance(tool, FileSearchTool): diff --git a/src/agents/tool.py b/src/agents/tool.py index 499a84045..021a04a01 100644 --- a/src/agents/tool.py +++ b/src/agents/tool.py @@ -232,6 +232,10 @@ class WebSearchTool: search_context_size: Literal["low", "medium", "high"] = "medium" """The amount of context to use for the search.""" + external_web_access: bool | None = None + """Control whether the web search tool fetches live content or uses only cached/indexed results in the Responses API. Set external_web_access: false on the web_search tool to run in offline/cache-only mode. Default is true (live access) if you do not set it. + """ + @property def name(self): return "web_search" From 09871532ddc991e785ae8409465f7a13e234f334 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Wed, 3 Dec 2025 13:26:28 +0900 Subject: [PATCH 2/4] fix --- src/agents/models/openai_responses.py | 19 +++++++++++-------- src/agents/tool.py | 4 +++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/agents/models/openai_responses.py b/src/agents/models/openai_responses.py index cf22135a3..f6c70e6b2 100644 --- a/src/agents/models/openai_responses.py +++ b/src/agents/models/openai_responses.py @@ -469,14 +469,17 @@ def _convert_tool(cls, tool: Tool) -> tuple[ToolParam, ResponseIncludable | None } includes: ResponseIncludable | None = None elif isinstance(tool, WebSearchTool): - # TODO: revist the type: ignore comment when ToolParam is updated in the future - converted_tool = { - "type": "web_search", - "filters": tool.filters.model_dump() if tool.filters is not None else None, # type: ignore [typeddict-item] - "user_location": tool.user_location, - "search_context_size": tool.search_context_size, - "external_web_access": tool.external_web_access, - } + # TODO: Remove the cast when ToolParam adds external_web_access. + converted_tool = cast( + ToolParam, + { + "type": "web_search", + "filters": tool.filters.model_dump() if tool.filters is not None else None, + "user_location": tool.user_location, + "search_context_size": tool.search_context_size, + "external_web_access": tool.external_web_access, + }, + ) includes = None elif isinstance(tool, FileSearchTool): converted_tool = { diff --git a/src/agents/tool.py b/src/agents/tool.py index 021a04a01..0e489b738 100644 --- a/src/agents/tool.py +++ b/src/agents/tool.py @@ -233,7 +233,9 @@ class WebSearchTool: """The amount of context to use for the search.""" external_web_access: bool | None = None - """Control whether the web search tool fetches live content or uses only cached/indexed results in the Responses API. Set external_web_access: false on the web_search tool to run in offline/cache-only mode. Default is true (live access) if you do not set it. + """Control whether the web search tool fetches live content or uses only cached/indexed + results in the Responses API. Set external_web_access: false on the web_search tool to run + in offline or cache-only mode. Default is true (live access) if you do not set it. """ @property From 5f6da0828200cebb5fc2b909eeb3feea595f033f Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Wed, 3 Dec 2025 13:41:02 +0900 Subject: [PATCH 3/4] fix review comment --- src/agents/models/openai_responses.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/agents/models/openai_responses.py b/src/agents/models/openai_responses.py index f6c70e6b2..fbb1868b5 100644 --- a/src/agents/models/openai_responses.py +++ b/src/agents/models/openai_responses.py @@ -477,9 +477,10 @@ def _convert_tool(cls, tool: Tool) -> tuple[ToolParam, ResponseIncludable | None "filters": tool.filters.model_dump() if tool.filters is not None else None, "user_location": tool.user_location, "search_context_size": tool.search_context_size, - "external_web_access": tool.external_web_access, }, ) + if tool.external_web_access is not None: + converted_tool["external_web_access"] = tool.external_web_access includes = None elif isinstance(tool, FileSearchTool): converted_tool = { From 8cda74b850a93482f7477f06b19fc509ab1d70ad Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Wed, 3 Dec 2025 13:56:35 +0900 Subject: [PATCH 4/4] fix --- src/agents/models/openai_responses.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/agents/models/openai_responses.py b/src/agents/models/openai_responses.py index fbb1868b5..9a676d3d3 100644 --- a/src/agents/models/openai_responses.py +++ b/src/agents/models/openai_responses.py @@ -469,18 +469,15 @@ def _convert_tool(cls, tool: Tool) -> tuple[ToolParam, ResponseIncludable | None } includes: ResponseIncludable | None = None elif isinstance(tool, WebSearchTool): - # TODO: Remove the cast when ToolParam adds external_web_access. - converted_tool = cast( - ToolParam, - { - "type": "web_search", - "filters": tool.filters.model_dump() if tool.filters is not None else None, - "user_location": tool.user_location, - "search_context_size": tool.search_context_size, - }, - ) + converted_tool_dict: dict[str, Any] = { + "type": "web_search", + "filters": tool.filters.model_dump() if tool.filters is not None else None, + "user_location": tool.user_location, + "search_context_size": tool.search_context_size, + } if tool.external_web_access is not None: - converted_tool["external_web_access"] = tool.external_web_access + converted_tool_dict["external_web_access"] = tool.external_web_access + converted_tool = cast(ToolParam, converted_tool_dict) includes = None elif isinstance(tool, FileSearchTool): converted_tool = {