[tool] fix: remove circular fallback in BaseTool.__init__ - #7046
[tool] fix: remove circular fallback in BaseTool.__init__#7046cyyueyang wants to merge 1 commit into
Conversation
The `or self.get_openai_tool_schema()` fallback in __init__ creates a circular reference: get_openai_tool_schema() returns self.tool_schema which does not exist yet when tool_schema is None. Remove the fallback. tool_schema must be provided; the assertion catches missing schemas with a clear error. Subclasses that need to construct their own schema should do so in __init__ and pass it to super().__init__().
There was a problem hiding this comment.
Code Review
This pull request removes the fallback to get_openai_tool_schema when initializing BaseTool. The reviewer notes that this change breaks subclasses that dynamically define their schema, and suggests setting self.tool_schema first to avoid potential AttributeError circularity before falling back to get_openai_tool_schema.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| def __init__(self, config: dict, tool_schema: OpenAIFunctionToolSchema): | ||
| self.config = config | ||
| self.tool_schema = tool_schema or self.get_openai_tool_schema() | ||
| self.tool_schema = tool_schema |
There was a problem hiding this comment.
Removing the fallback entirely breaks subclasses of BaseTool that override get_openai_tool_schema() to dynamically define their schema in code (which is a common pattern when tool_schema is not provided in the configuration, passing None to __init__).
To resolve the circular reference/AttributeError without breaking subclassing, we can set self.tool_schema = tool_schema first. This ensures the attribute exists (even if it is None), so calling self.get_openai_tool_schema() as a fallback will not raise an AttributeError and will correctly invoke the subclass's overridden method.
| self.tool_schema = tool_schema | |
| self.tool_schema = tool_schema | |
| if self.tool_schema is None: | |
| self.tool_schema = self.get_openai_tool_schema() |
What does this PR do?
Remove the
or self.get_openai_tool_schema()fallback inBaseTool.__init__. It creates a circular reference:get_openai_tool_schema()returnsself.tool_schema, but whentool_schema=Nonetheorcalls it before the attribute exists→
AttributeError.The fix:
tool_schemamust be explicitly provided. The existingassertion catches the
Nonecase with a clear error message.Checklist Before Starting
base_tool get_openai_tool_schema circular[tool] fix: ...Test
Not covered by CI; verified locally:
BaseTool(config, valid_schema)BaseTool(config, None)AssertionError: Tool schema is not set!(clear, no crash)__init__get_openai_tool_schema()as getter after initAPI and Usage Example
No API change.
tool_schemamust always be provided to__init__.Subclasses that need to construct their own schema should do it in
__init__and pass it tosuper().__init__():Design & Code Changes
1 file: verl/tools/base_tool.py (+1, −1)
Checklist Before Submitting