Skip to content

Fix Tool.from_gradio wrapper missing is_initialized - #2947

Open
Kylinny wants to merge 1 commit into
huggingface:mainfrom
Kylinny:fix-from-gradio-is-initialized
Open

Kylinny wants to merge 1 commit into
huggingface:mainfrom
Kylinny:fix-from-gradio-is-initialized

Conversation

@Kylinny

@Kylinny Kylinny commented Oct 10, 2026

Copy link
Copy Markdown

What

Tool.from_gradio builds a GradioToolWrapper whose __init__ sets metadata, inputs and forward but never runs the base Tool initialization — Tool.__init__ (which sets self.is_initialized = False) is never called, and unlike the sibling LangChainToolWrapper, the attribute is never set either. So calling the wrapper raised AttributeError in Tool.__call__ (if not self.is_initialized:) before the underlying run method was ever reached.

The fix sets self.is_initialized = True in GradioToolWrapper.__init__, matching the existing convention in LangChainToolWrapper (which sets it the same way). The wrapper is fully configured at construction time (forward is already bound to the gradio tool's run), and it does not override setup(), so marking it initialized is correct — no lazy setup work is skipped.

Fixes #2944.

Reproducer (copy-paste runnable)

from smolagents import Tool


class LocalGradioTool:
    name = "double_value"
    description = "Double a number."

    # Use the string annotation accepted by the adapter's existing type mapping.
    def run(self, value: "int") -> str:
        return str(value * 2)


source = LocalGradioTool()
assert source.run(4) == "8"
wrapped = Tool.from_gradio(source)
assert wrapped(value=4) == "8"
print("OK")

Before (on main, before this fix)

Traceback (most recent call last):
  File "/tmp/repro-2944.py", line 16, in <module>
    assert wrapped(value=4) == "8"
           ^^^^^^^^^^^^^^^^
  File "/tmp/smolagents/src/smolagents/tools.py", line 232, in __call__
    if not self.is_initialized:
           ^^^^^^^^^^^^^^^^^^^
AttributeError: 'GradioToolWrapper' object has no attribute 'is_initialized'

After (with this fix)

OK

Tests

  • Added test_from_gradio_wrapper_is_initialized in tests/test_tools.py: builds a local gradio-style tool, wraps it with Tool.from_gradio, and asserts is_initialized is set, the inputs mapping is correct ({"value": {"type": "integer", "description": ""}}), and repeated calls delegate to run (wrapped(value=4) == "8", wrapped(value=7) == "14").
  • Ran tests/test_tools.py: 69 passed (was 68 before my change; +1 is the new regression test), 3 skipped. The 3 failures + 1 error in the file (test_launch_gradio_demo_does_not_raise[boolean_default_tool_class], MCP-related tests) also fail on pristine main without this change — they are pre-existing environment issues unrelated to this fix.

Thanks very much to @yifanxiong272 for the thorough report — the minimal reproducer, full traceback, and root-cause analysis made this straightforward to verify and fix.

GradioToolWrapper.__init__ never ran the base Tool initializer (nor set
is_initialized like LangChainToolWrapper does), so calling the wrapped
tool raised AttributeError in Tool.__call__. Set is_initialized on
construction so the wrapper completes the Tool lifecycle and delegates
to the gradio tool's run method.

Add a regression test covering Tool.from_gradio with a local
gradio-style tool.

Fixes huggingface#2944.

Signed-off-by: Kylinny <64238008+Kylinny@users.noreply.github.com>
@Kylinny
Kylinny force-pushed the fix-from-gradio-is-initialized branch from b90ce96 to d447faa Compare October 10, 2026 13:59
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.

BUG: Tool.from_gradio returns a wrapper missing is_initialized

1 participant