Skip to content

fix(core): treat deferred-loading custom tools as a Responses tool search surface - #5047

Draft
subhashpolisetti wants to merge 1 commit into
openai:mainfrom
subhashpolisetti:fix/custom-tool-defer-loading-tool-search
Draft

subhashpolisetti wants to merge 1 commit into
openai:mainfrom
subhashpolisetti:fix/custom-tool-defer-loading-tool-search

Conversation

@subhashpolisetti

Copy link
Copy Markdown
Contributor

Summary

CustomTool(defer_loading=True) cannot be used in any configuration on the OpenAI Responses API. The field is public and released, __post_init__ writes it into the outgoing tool config, and the Responses CustomToolParam accepts it, but hosted tool search classifies searchable tools through is_responses_tool_search_surface and is_required_tool_search_surface, and both recognize only FunctionTool and HostedMCPTool.

On v0.22.2 a deferred custom tool on its own is therefore not treated as requiring tool search: the request goes out carrying defer_loading: true with no tool_search tool, so the model never sees the tool and nothing can load it. Adding ToolSearchTool(), the documented way to load deferred tools, instead raises ToolSearchTool() requires at least one searchable Responses surface before any model call.

This change honors defer_loading on CustomTool in both predicates and names the custom-tool form in the surface error. _get_tool_allowed_callers in the same module already groups FunctionTool | CustomTool | ShellTool | ApplyPatchTool, so this reads as an omission in the two tool-search predicates rather than an exclusion of custom tools from Responses tool configuration. The alternative was rejecting the field at construction, which removes a released field the provider type accepts and still leaves no way to defer a custom tool. It is a behavior change for callers who configured a deferred custom tool without ToolSearchTool(): that used to be accepted and silently unreachable, and now raises the existing Deferred-loading Responses tools require ToolSearchTool() error, the same one function_tool(..., defer_loading=True) already raises there.

Test plan

test_convert_tools_deferred_custom_tool_requires_tool_search and test_convert_tools_deferred_custom_tool_with_tool_search cover the missing fail-fast and the converted wire payload for the pair. test_deferred_custom_tool_is_searchable_and_invocable runs Runner.run with both tools and asserts the outgoing request carries both and that the returned custom_tool_call reaches the tool, so the change enables a working tool rather than only relaxing validation. All three fail without the source change, verified by restoring src/agents/tool.py from main with the tests in place.

Format, lint, Mypy, Pyright and mypy --platform win32 src pass; 9698 passed, 32 skipped, coverage 92%. The 14 process-group failures in tests/test_code_change_verification_runner.py fail identically on unmodified main on this machine.

Issue number

None.

Checks

  • I've added new tests, if relevant
  • I've run .agents/skills/code-change-verification/scripts/run.sh
  • I've confirmed all verification steps pass
  • If using Codex, I've run /review before submitting this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant