From 5a60a758c8e5d401856b97dc77d530549b91ccc2 Mon Sep 17 00:00:00 2001 From: Alex Bozarth Date: Mon, 9 Feb 2026 15:40:43 -0600 Subject: [PATCH 1/6] feat: add MelleaTool.from_huggingface() for smolagents integration Implements loading of HuggingFace smolagents tools into Mellea's tool system. - Add from_huggingface() classmethod to MelleaTool - Uses smolagents' get_tool_json_schema() for OpenAI-compatible conversion - Wraps smolagents Tool.forward() method with proper error handling - Add smolagents as optional dependency in pyproject.toml - Update .gitignore to exclude AI agent config directories Related to #411 Signed-off-by: Alex Bozarth --- .gitignore | 4 +++ mellea/backends/tools.py | 66 ++++++++++++++++++++++++++++++++++++++-- pyproject.toml | 6 +++- uv.lock | 26 ++++++++++++++-- 4 files changed, 97 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index a5c325a25..9fc2404ed 100644 --- a/.gitignore +++ b/.gitignore @@ -448,3 +448,7 @@ pyrightconfig.json .ionide # End of https://www.toptal.com/developers/gitignore/api/python,direnv,visualstudiocode,pycharm,macos,jetbrains + +# AI agent configs +.bob/ +.claude/ diff --git a/mellea/backends/tools.py b/mellea/backends/tools.py index ec24b96b7..82567c46e 100644 --- a/mellea/backends/tools.py +++ b/mellea/backends/tools.py @@ -75,8 +75,70 @@ def parameter_remapper(*args, **kwargs): except ImportError as e: raise ImportError( - f"It appears you are attempting to utilize a langchain tool '{type(tool)}'" - "Please install langchain core: pip install 'langchain_core'." + f"It appears you are attempting to utilize a langchain tool '{type(tool)}'. " + "Please install langchain core: uv pip install langchain-core" + ) from e + + @classmethod + def from_huggingface(cls, tool: Any): + """Create a Tool from a HuggingFace smolagents tool object. + + Args: + tool: A smolagents.Tool instance + + Returns: + MelleaTool: A Mellea tool wrapping the smolagents tool + + Raises: + ImportError: If smolagents is not installed + ValueError: If tool is not a smolagents Tool instance + + Example: + >>> from smolagents import Tool + >>> class MyTool(Tool): + ... name = "my_tool" + ... description = "Does something" + ... inputs = {"x": {"type": "string", "description": "Input"}} + ... output_type = "string" + ... def forward(self, x: str) -> str: + ... return f"Result: {x}" + >>> hf_tool = MyTool() + >>> mellea_tool = MelleaTool.from_huggingface(hf_tool) + """ + try: + from smolagents import ( # type: ignore[import-not-found] + Tool as SmolagentsTool, + ) + from smolagents.models import ( # type: ignore[import-not-found] + get_tool_json_schema, + ) + + if not isinstance(tool, SmolagentsTool): + raise ValueError( + f"tool parameter must be a smolagents Tool type; got: {type(tool)}" + ) + + tool_name = tool.name + + # Use smolagents' built-in conversion to OpenAI format + as_json = get_tool_json_schema(tool) + + # Wrap the tool's forward method + def tool_call(*args, **kwargs): + """Wrapper for smolagents tool forward method.""" + if args: + # This shouldn't happen. Our ModelToolCall.call_func passes everything as kwargs. + FancyLogger.get_logger().warning( + f"ignoring unexpected args while calling smolagents tool ({tool_name}): ({args})" + ) + return tool.forward(**kwargs) + + return MelleaTool(tool_name, tool_call, as_json) + + except ImportError as e: + raise ImportError( + f"It appears you are attempting to utilize a smolagents tool '{type(tool)}'. " + "Please install mellea with smolagents support: uv pip install 'mellea[smolagents]'" ) from e @classmethod diff --git a/pyproject.toml b/pyproject.toml index 8f7223aa5..0568389bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,6 +101,10 @@ docling = [ "docling>=2.45.0", ] +smolagents = [ + "smolagents>=1.0.0", +] + telemetry = [ "opentelemetry-api>=1.20.0", "opentelemetry-sdk>=1.20.0", @@ -108,7 +112,7 @@ telemetry = [ "opentelemetry-distro>=0.59b0", ] -all = ["mellea[watsonx,docling,hf,vllm,litellm,telemetry]"] +all = ["mellea[watsonx,docling,hf,vllm,litellm,smolagents,telemetry]"] [dependency-groups] # Use these like: diff --git a/uv.lock b/uv.lock index f974d5bcb..5fedb597d 100644 --- a/uv.lock +++ b/uv.lock @@ -3445,6 +3445,7 @@ all = [ { name = "outlines" }, { name = "outlines-core" }, { name = "peft" }, + { name = "smolagents" }, { name = "transformers" }, { name = "trl" }, { name = "vllm" }, @@ -3467,6 +3468,9 @@ litellm = [ { name = "boto3" }, { name = "litellm" }, ] +smolagents = [ + { name = "smolagents" }, +] telemetry = [ { name = "opentelemetry-api" }, { name = "opentelemetry-distro" }, @@ -3533,7 +3537,7 @@ requires-dist = [ { name = "litellm", marker = "extra == 'litellm'", specifier = ">=1.76" }, { name = "llm-sandbox", extras = ["docker"], specifier = ">=0.3.23" }, { name = "math-verify" }, - { name = "mellea", extras = ["watsonx", "docling", "hf", "vllm", "litellm", "telemetry"], marker = "extra == 'all'" }, + { name = "mellea", extras = ["watsonx", "docling", "hf", "vllm", "litellm", "smolagents", "telemetry"], marker = "extra == 'all'" }, { name = "mistletoe", specifier = ">=1.4.0" }, { name = "numpy", marker = "extra == 'vllm'", specifier = "<2.0.0" }, { name = "ollama", specifier = ">=0.5.1" }, @@ -3550,6 +3554,7 @@ requires-dist = [ { name = "pydantic" }, { name = "requests", specifier = ">=2.32.3" }, { name = "rouge-score" }, + { name = "smolagents", marker = "extra == 'smolagents'", specifier = ">=1.0.0" }, { name = "transformers", marker = "extra == 'hf'", specifier = ">=4.53.2,<5" }, { name = "transformers", marker = "extra == 'vllm'", specifier = "<4.54.0" }, { name = "trl", marker = "extra == 'hf'", specifier = "==0.19.1" }, @@ -3559,7 +3564,7 @@ requires-dist = [ { name = "uvicorn" }, { name = "vllm", marker = "extra == 'vllm'", specifier = ">=0.9.1" }, ] -provides-extras = ["hf", "vllm", "litellm", "watsonx", "docling", "telemetry", "all"] +provides-extras = ["hf", "vllm", "litellm", "watsonx", "docling", "smolagents", "telemetry", "all"] [package.metadata.requires-dev] dev = [ @@ -7336,6 +7341,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303, upload-time = "2025-01-02T07:14:38.724Z" }, ] +[[package]] +name = "smolagents" +version = "1.24.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, + { name = "jinja2" }, + { name = "pillow" }, + { name = "python-dotenv" }, + { name = "requests" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0a/1c/8d8e7f39f3586dc85a7f96681b08b7c1cfbd734b258a025f368632f2d666/smolagents-1.24.0.tar.gz", hash = "sha256:4d5028ffbd72aca85fb2e8daac52d03fb7d4290a9bf99dbc311dd65980f6b5de", size = 225246, upload-time = "2026-01-16T05:37:04.156Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/7a/461ead649c088d30f7847ef1c70f245a9c188381ed09a264633831050497/smolagents-1.24.0-py3-none-any.whl", hash = "sha256:54853759d07a92a939f1ff59238b757fb1a153204c90b69324c8e9709025aa86", size = 155727, upload-time = "2026-01-16T05:37:02.903Z" }, +] + [[package]] name = "sniffio" version = "1.3.1" From e5f76ca8912d4046c51474814cd67ff1f4a6e74f Mon Sep 17 00:00:00 2001 From: Alex Bozarth Date: Mon, 9 Feb 2026 16:09:37 -0600 Subject: [PATCH 2/6] test: add unit tests for MelleaTool.from_huggingface() Add comprehensive unit tests for the HuggingFace smolagents integration: - test_from_huggingface_basic: Tests basic tool loading and schema conversion - test_from_huggingface_multiple_inputs: Tests tools with multiple parameters - test_from_huggingface_invalid_tool: Tests error handling for invalid objects Tests follow existing patterns with try/except ImportError for graceful handling when smolagents is not installed. Signed-off-by: Alex Bozarth --- test/backends/test_mellea_tool.py | 117 ++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/test/backends/test_mellea_tool.py b/test/backends/test_mellea_tool.py index 85b6a39db..89d1f90b2 100644 --- a/test/backends/test_mellea_tool.py +++ b/test/backends/test_mellea_tool.py @@ -1,3 +1,5 @@ +import os + import pytest from langchain_core.tools import Tool, tool # type: ignore[import-not-found] from pydantic_core import ValidationError @@ -119,5 +121,120 @@ def test_from_langchain_generation(session: MelleaSession): assert isinstance(tool.call_func(), str), "tool call did not yield expected type" +def test_from_huggingface_basic(): + """Test basic smolagents tool loading and schema conversion. + + This test verifies that: + 1. A smolagents tool can be wrapped as a MelleaTool + 2. The tool name is correctly extracted + 3. The schema is converted to OpenAI-compatible format + 4. The tool can be executed with arguments + """ + try: + from smolagents import Tool + except ImportError: + pytest.skip( + "smolagents not installed - install with: uv pip install 'mellea[smolagents]'" + ) + + # Create a simple smolagents tool + class SimpleTool(Tool): + name = "simple_tool" + description = "A simple test tool" + inputs = {"text": {"type": "string", "description": "Input text"}} + output_type = "string" + + def forward(self, text: str) -> str: + return f"Processed: {text}" + + hf_tool = SimpleTool() + mellea_tool = MelleaTool.from_huggingface(hf_tool) + + # Verify tool properties + assert isinstance(mellea_tool, MelleaTool) + assert mellea_tool.name == "simple_tool" + + # Verify schema conversion + json_schema = mellea_tool.as_json_tool + assert json_schema is not None + assert "function" in json_schema + assert json_schema["function"]["name"] == "simple_tool" + assert json_schema["function"]["description"] == "A simple test tool" + + # Verify parameters are present + assert "parameters" in json_schema["function"] + params = json_schema["function"]["parameters"] + assert "properties" in params + assert "text" in params["properties"] + + # Verify tool execution + result = mellea_tool.run(text="hello") + assert result == "Processed: hello" + + +def test_from_huggingface_multiple_inputs(): + """Test smolagents tool with multiple input parameters.""" + try: + from smolagents import Tool + except ImportError: + pytest.skip( + "smolagents not installed - install with: uv pip install 'mellea[smolagents]'" + ) + + class MultiInputTool(Tool): + name = "multi_input_tool" + description = "Tool with multiple inputs" + inputs = { + "x": {"type": "integer", "description": "First number"}, + "y": {"type": "integer", "description": "Second number"}, + "operation": {"type": "string", "description": "Operation to perform"}, + } + output_type = "integer" + + def forward(self, x: int, y: int, operation: str) -> int: + if operation == "add": + return x + y + elif operation == "multiply": + return x * y + return 0 + + hf_tool = MultiInputTool() + mellea_tool = MelleaTool.from_huggingface(hf_tool) + + # Verify all parameters are in schema + json_schema = mellea_tool.as_json_tool + params = json_schema["function"]["parameters"] + assert "x" in params["properties"] + assert "y" in params["properties"] + assert "operation" in params["properties"] + + # Verify tool execution with multiple args + result = mellea_tool.run(x=5, y=3, operation="add") + assert result == 8 + + result = mellea_tool.run(x=5, y=3, operation="multiply") + assert result == 15 + + +def test_from_huggingface_invalid_tool(): + """Test error handling for non-smolagents tool objects.""" + try: + from smolagents import Tool + except ImportError: + pytest.skip( + "smolagents not installed - install with: uv pip install 'mellea[smolagents]'" + ) + + # Try to create tool from non-Tool object + class NotATool: + name = "fake" + + with pytest.raises(ValueError) as exc_info: + MelleaTool.from_huggingface(NotATool()) + + error_msg = str(exc_info.value) + assert "smolagents Tool type" in error_msg + + if __name__ == "__main__": pytest.main([__file__]) From 8d1d922dbc2a0c6a394e63ac7d5acdd01fbf48d6 Mon Sep 17 00:00:00 2001 From: Alex Bozarth Date: Mon, 9 Feb 2026 16:39:45 -0600 Subject: [PATCH 3/6] docs: add smolagents integration example and documentation - Add smolagents_example.py demonstrating MelleaTool.from_huggingface() - Update tools/README.md with smolagents example documentation - Add smolagents installation instructions to main README.md Related: #411 Signed-off-by: Alex Bozarth --- README.md | 3 +- docs/examples/tools/README.md | 8 ++++ docs/examples/tools/smolagents_example.py | 47 +++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 docs/examples/tools/smolagents_example.py diff --git a/README.md b/README.md index 78c4cc447..e47cb1f56 100644 --- a/README.md +++ b/README.md @@ -64,9 +64,10 @@ pip install mellea > `mellea` comes with some additional packages as defined in our `pyproject.toml`. If you would like to install all the extra optional dependencies, please run the following commands: > > ```bash -> uv pip install "mellea[hf]" # for Huggingface extras and Alora capabilities. +> uv pip install "mellea[hf]" # for Huggingface extras and Alora capabilities > uv pip install "mellea[watsonx]" # for watsonx backend > uv pip install "mellea[docling]" # for docling +> uv pip install "mellea[smolagents]" # for HuggingFace smolagents tools > uv pip install "mellea[all]" # for all the optional dependencies > ``` > diff --git a/docs/examples/tools/README.md b/docs/examples/tools/README.md index 35fa9a310..43e177c3f 100644 --- a/docs/examples/tools/README.md +++ b/docs/examples/tools/README.md @@ -14,6 +14,14 @@ Comprehensive examples of using the code interpreter tool with LLMs. - Validating tool arguments - Local vs. sandboxed execution +### smolagents_example.py +Shows how to use pre-built tools from HuggingFace's smolagents library. + +**Key Features:** +- Loading existing smolagents tools (PythonInterpreterTool, WikipediaSearchTool, etc.) +- Converting to Mellea tools with `MelleaTool.from_huggingface()` +- Using tools from the HuggingFace ecosystem + ## Concepts Demonstrated - **Tool Definition**: Creating tools for LLM use diff --git a/docs/examples/tools/smolagents_example.py b/docs/examples/tools/smolagents_example.py new file mode 100644 index 000000000..5dfbca78a --- /dev/null +++ b/docs/examples/tools/smolagents_example.py @@ -0,0 +1,47 @@ +# pytest: ollama, llm +"""Example showing how to use pre-built HuggingFace smolagents tools with Mellea. + +This demonstrates loading existing tools from the smolagents ecosystem, +similar to how you can use langchain tools with MelleaTool.from_langchain(). +""" + +from mellea import start_session +from mellea.backends import ModelOption +from mellea.backends.tools import MelleaTool + +# Example: Using a pre-built tool from smolagents +# The smolagents library provides various pre-built tools like: +# - PythonInterpreterTool for code execution +# - DuckDuckGoSearchTool for web search (requires ddgs package) +# - WikipediaSearchTool for Wikipedia queries +# - And many others from the HuggingFace ecosystem + +try: + # Import a pre-built tool from smolagents + from smolagents import PythonInterpreterTool + + # Create the smolagents tool instance + python_tool_hf = PythonInterpreterTool() + + # Convert to Mellea tool - now you can use it with Mellea! + python_tool = MelleaTool.from_huggingface(python_tool_hf) + + # Use with Mellea session + m = start_session() + result = m.instruct( + "Calculate the sum of numbers from 1 to 10 using Python", + model_options={ModelOption.TOOLS: [python_tool]}, + tool_calls=True, + ) + + print(f"Response: {result}") + + if result.tool_calls: + calc_result = result.tool_calls[python_tool.name].call_func() + print(f"\nCalculation result: {calc_result}") + +except ImportError as e: + print("Please install smolagents: uv pip install 'mellea[smolagents]'") + print(f"Error: {e}") + +# Made with Bob From 25a5beefc280974d51af6234d502c734334ad9ba Mon Sep 17 00:00:00 2001 From: Alex Bozarth Date: Tue, 10 Feb 2026 11:00:42 -0600 Subject: [PATCH 4/6] chore: address review Signed-off-by: Alex Bozarth --- docs/examples/tools/smolagents_example.py | 2 -- test/backends/test_mellea_tool.py | 2 -- test/telemetry/test_backend_telemetry.py | 3 --- 3 files changed, 7 deletions(-) diff --git a/docs/examples/tools/smolagents_example.py b/docs/examples/tools/smolagents_example.py index 5dfbca78a..756de26fa 100644 --- a/docs/examples/tools/smolagents_example.py +++ b/docs/examples/tools/smolagents_example.py @@ -43,5 +43,3 @@ except ImportError as e: print("Please install smolagents: uv pip install 'mellea[smolagents]'") print(f"Error: {e}") - -# Made with Bob diff --git a/test/backends/test_mellea_tool.py b/test/backends/test_mellea_tool.py index 89d1f90b2..45adb30f1 100644 --- a/test/backends/test_mellea_tool.py +++ b/test/backends/test_mellea_tool.py @@ -1,5 +1,3 @@ -import os - import pytest from langchain_core.tools import Tool, tool # type: ignore[import-not-found] from pydantic_core import ValidationError diff --git a/test/telemetry/test_backend_telemetry.py b/test/telemetry/test_backend_telemetry.py index 428e0eb31..2b68fa87e 100644 --- a/test/telemetry/test_backend_telemetry.py +++ b/test/telemetry/test_backend_telemetry.py @@ -319,6 +319,3 @@ async def test_streaming_span_duration(span_exporter, gh_run): assert abs(span_duration_s - actual_duration) < 0.5, ( f"Streaming span duration {span_duration_s}s differs from actual {actual_duration}s" ) - - -# Made with Bob From 4fe7f541d3f9834baf13c8ea25db570a5c0f8fd2 Mon Sep 17 00:00:00 2001 From: Alex Bozarth Date: Tue, 10 Feb 2026 11:59:59 -0600 Subject: [PATCH 5/6] chore: address review Signed-off-by: Alex Bozarth --- docs/examples/tools/smolagents_example.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/examples/tools/smolagents_example.py b/docs/examples/tools/smolagents_example.py index 756de26fa..0da5ce1b4 100644 --- a/docs/examples/tools/smolagents_example.py +++ b/docs/examples/tools/smolagents_example.py @@ -3,19 +3,18 @@ This demonstrates loading existing tools from the smolagents ecosystem, similar to how you can use langchain tools with MelleaTool.from_langchain(). + +The smolagents library provides various pre-built tools like: +- PythonInterpreterTool for code execution +- DuckDuckGoSearchTool for web search (requires ddgs package) +- WikipediaSearchTool for Wikipedia queries +- And many others from the HuggingFace ecosystem """ from mellea import start_session from mellea.backends import ModelOption from mellea.backends.tools import MelleaTool -# Example: Using a pre-built tool from smolagents -# The smolagents library provides various pre-built tools like: -# - PythonInterpreterTool for code execution -# - DuckDuckGoSearchTool for web search (requires ddgs package) -# - WikipediaSearchTool for Wikipedia queries -# - And many others from the HuggingFace ecosystem - try: # Import a pre-built tool from smolagents from smolagents import PythonInterpreterTool From a213006542d7e7a529c204d3623c45e64036ad19 Mon Sep 17 00:00:00 2001 From: Alex Bozarth Date: Tue, 10 Feb 2026 14:48:07 -0600 Subject: [PATCH 6/6] chore: address review Signed-off-by: Alex Bozarth --- docs/examples/tools/README.md | 2 +- docs/examples/tools/smolagents_example.py | 2 +- mellea/backends/tools.py | 15 ++++----------- test/backends/test_mellea_tool.py | 12 ++++++------ 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/docs/examples/tools/README.md b/docs/examples/tools/README.md index 43e177c3f..d6f60f0a4 100644 --- a/docs/examples/tools/README.md +++ b/docs/examples/tools/README.md @@ -19,7 +19,7 @@ Shows how to use pre-built tools from HuggingFace's smolagents library. **Key Features:** - Loading existing smolagents tools (PythonInterpreterTool, WikipediaSearchTool, etc.) -- Converting to Mellea tools with `MelleaTool.from_huggingface()` +- Converting to Mellea tools with `MelleaTool.from_smolagents()` - Using tools from the HuggingFace ecosystem ## Concepts Demonstrated diff --git a/docs/examples/tools/smolagents_example.py b/docs/examples/tools/smolagents_example.py index 0da5ce1b4..23f9ab180 100644 --- a/docs/examples/tools/smolagents_example.py +++ b/docs/examples/tools/smolagents_example.py @@ -23,7 +23,7 @@ python_tool_hf = PythonInterpreterTool() # Convert to Mellea tool - now you can use it with Mellea! - python_tool = MelleaTool.from_huggingface(python_tool_hf) + python_tool = MelleaTool.from_smolagents(python_tool_hf) # Use with Mellea session m = start_session() diff --git a/mellea/backends/tools.py b/mellea/backends/tools.py index 82567c46e..6bdcc110e 100644 --- a/mellea/backends/tools.py +++ b/mellea/backends/tools.py @@ -80,7 +80,7 @@ def parameter_remapper(*args, **kwargs): ) from e @classmethod - def from_huggingface(cls, tool: Any): + def from_smolagents(cls, tool: Any): """Create a Tool from a HuggingFace smolagents tool object. Args: @@ -94,16 +94,9 @@ def from_huggingface(cls, tool: Any): ValueError: If tool is not a smolagents Tool instance Example: - >>> from smolagents import Tool - >>> class MyTool(Tool): - ... name = "my_tool" - ... description = "Does something" - ... inputs = {"x": {"type": "string", "description": "Input"}} - ... output_type = "string" - ... def forward(self, x: str) -> str: - ... return f"Result: {x}" - >>> hf_tool = MyTool() - >>> mellea_tool = MelleaTool.from_huggingface(hf_tool) + >>> from smolagents import PythonInterpreterTool + >>> tool = PythonInterpreterTool() + >>> mellea_tool = MelleaTool.from_smolagents(tool) """ try: from smolagents import ( # type: ignore[import-not-found] diff --git a/test/backends/test_mellea_tool.py b/test/backends/test_mellea_tool.py index 45adb30f1..8931f2982 100644 --- a/test/backends/test_mellea_tool.py +++ b/test/backends/test_mellea_tool.py @@ -119,7 +119,7 @@ def test_from_langchain_generation(session: MelleaSession): assert isinstance(tool.call_func(), str), "tool call did not yield expected type" -def test_from_huggingface_basic(): +def test_from_smolagents_basic(): """Test basic smolagents tool loading and schema conversion. This test verifies that: @@ -146,7 +146,7 @@ def forward(self, text: str) -> str: return f"Processed: {text}" hf_tool = SimpleTool() - mellea_tool = MelleaTool.from_huggingface(hf_tool) + mellea_tool = MelleaTool.from_smolagents(hf_tool) # Verify tool properties assert isinstance(mellea_tool, MelleaTool) @@ -170,7 +170,7 @@ def forward(self, text: str) -> str: assert result == "Processed: hello" -def test_from_huggingface_multiple_inputs(): +def test_from_smolagents_multiple_inputs(): """Test smolagents tool with multiple input parameters.""" try: from smolagents import Tool @@ -197,7 +197,7 @@ def forward(self, x: int, y: int, operation: str) -> int: return 0 hf_tool = MultiInputTool() - mellea_tool = MelleaTool.from_huggingface(hf_tool) + mellea_tool = MelleaTool.from_smolagents(hf_tool) # Verify all parameters are in schema json_schema = mellea_tool.as_json_tool @@ -214,7 +214,7 @@ def forward(self, x: int, y: int, operation: str) -> int: assert result == 15 -def test_from_huggingface_invalid_tool(): +def test_from_smolagents_invalid_tool(): """Test error handling for non-smolagents tool objects.""" try: from smolagents import Tool @@ -228,7 +228,7 @@ class NotATool: name = "fake" with pytest.raises(ValueError) as exc_info: - MelleaTool.from_huggingface(NotATool()) + MelleaTool.from_smolagents(NotATool()) error_msg = str(exc_info.value) assert "smolagents Tool type" in error_msg