Skip to content

[tool] fix: remove circular fallback in BaseTool.__init__ - #7046

Closed
cyyueyang wants to merge 1 commit into
verl-project:mainfrom
cyyueyang:fix/base-tool-circular-schema
Closed

[tool] fix: remove circular fallback in BaseTool.__init__#7046
cyyueyang wants to merge 1 commit into
verl-project:mainfrom
cyyueyang:fix/base-tool-circular-schema

Conversation

@cyyueyang

Copy link
Copy Markdown

What does this PR do?

Remove the or self.get_openai_tool_schema() fallback in
BaseTool.__init__. It creates a circular reference:
get_openai_tool_schema() returns self.tool_schema, but when
tool_schema=None the or calls it before the attribute exists
AttributeError.

The fix: tool_schema must be explicitly provided. The existing
assertion catches the None case with a clear error message.

Checklist Before Starting

  • Search for similar PRs. Query: base_tool get_openai_tool_schema circular
  • Format the PR title as [tool] fix: ...

Test

Not covered by CI; verified locally:

Scenario Result
BaseTool(config, valid_schema) works as before
BaseTool(config, None) AssertionError: Tool schema is not set! (clear, no crash)
Subclass constructs schema in __init__ works correctly
get_openai_tool_schema() as getter after init works as before

API and Usage Example

No API change. tool_schema must always be provided to __init__.
Subclasses that need to construct their own schema should do it in
__init__ and pass it to super().__init__():

class MyTool(BaseTool):
    def __init__(self, config: dict, tool_schema: OpenAIFunctionToolSchema = None):
        if tool_schema is None:
            tool_schema = OpenAIFunctionToolSchema.model_validate({...})
        super().__init__(config, tool_schema)

Design & Code Changes

1 file: verl/tools/base_tool.py (+1, −1)

  -        self.tool_schema = tool_schema or self.get_openai_tool_schema()
  +        self.tool_schema = tool_schema

Checklist Before Submitting

  • Read the Contribute Guide.
  • Apply pre-commit checks
  • Add / Update the documentation — not needed
  • Add unit or end-to-end test(s) — not feasible: latent init bug, existing path always passes tool_schema

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__().

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread verl/tools/base_tool.py
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

Suggested change
self.tool_schema = tool_schema
self.tool_schema = tool_schema
if self.tool_schema is None:
self.tool_schema = self.get_openai_tool_schema()

@wuxibin89 wuxibin89 closed this Jul 20, 2026
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.

2 participants