Skip to content

Tool

Represents an individual tool with metadata and execution logic within the ToolRegistry ecosystem.

Overview

The Tool class serves as a fundamental abstraction for all tools in the ToolRegistry system. It encapsulates both the executable logic and the metadata necessary for proper tool discovery, parameter validation, and execution within LLM applications.

Key Features

  • Metadata Management: Comprehensive tool description, parameters, and execution metadata
  • Parameter Validation: Built-in parameter schema validation and type checking
  • Execution Abstraction: Unified interface for both synchronous and asynchronous execution
  • Namespace Support: Integration with namespace organization for tool grouping
  • Callable Integration: Direct execution through callable interface

Architecture

The Tool class follows a data-transfer-object pattern with the following key components:

Core Attributes

  1. name: Unique identifier for the tool
  2. description: Human-readable description of tool functionality
  3. parameters: JSON schema defining expected parameters
  4. callable: The actual executable function or wrapper
  5. is_async: Flag indicating asynchronous execution capability
  6. namespace: Optional namespace for organization (stores the original namespace string after normalization)
  7. method_name: Optional original method/function name before namespace prefixing (preserved for unambiguous base name recovery)

Computed Properties

  • qualified_name: Returns the fully-qualified tool name. If both namespace and method_name are set, returns {namespace}-{method_name}; otherwise falls back to the name field.

Design Philosophy

  • Immutability: Tool instances are designed to be immutable after creation
  • Schema-Driven: Parameter validation based on JSON Schema standards
  • Execution Flexibility: Support for both sync and async execution patterns
  • Metadata Preservation: Complete preservation of tool metadata for LLM consumption

API Reference

toolregistry.Tool

Bases: BaseModel

Base class representing an executable tool/function.

Provides core functionality for
  • Function wrapping and metadata management
  • Parameter validation using Pydantic
  • Synchronous/asynchronous execution
  • JSON schema generation

callable class-attribute instance-attribute

callable: Callable[..., Any] = Field(exclude=True)

The tool's callable, always a :class:BaseToolWrapper at runtime.

Typed as Callable for Pydantic compatibility (Pydantic cannot generate a schema for BaseToolWrapper). Use call_sync() / call_async() for sync/async transparent execution.

Excluded from serialization to prevent accidental exposure of implementation details.

description class-attribute instance-attribute

description: str = Field(description='Description of what the tool does')

Detailed description of the tool's functionality.

Should clearly explain what the tool does, its purpose, and any important usage considerations.

fn property

fn: Callable[..., Any]

Return the underlying unwrapped function.

For native tools (registered via from_function), returns the original Python function. For integration tools (MCP, OpenAPI, LangChain), returns the wrapper itself.

is_async property

is_async: bool

Whether the tool requires async execution.

Backward-compatible proxy to metadata.is_async.

metadata class-attribute instance-attribute

metadata: ToolMetadata = Field(default_factory=ToolMetadata)

Behavioral and classification metadata for this tool.

Contains execution hints (is_async, is_concurrency_safe, timeout) and classification tags (tags, custom_tags).

method_name class-attribute instance-attribute

method_name: str | None = Field(default=None, description='Original method name of the tool')

The original method/function name before namespace prefixing.

Preserved so that the base name can be recovered without ambiguity even when the name field contains a namespace prefix joined by - (which normalize_tool_name would otherwise convert to _).

name class-attribute instance-attribute

name: str = Field(description='Name of the tool')

The name of the tool.

Used as the primary identifier when calling the tool. Must be unique within a tool registry.

namespace class-attribute instance-attribute

namespace: str | None = Field(default=None, description='Namespace the tool belongs to')

The namespace this tool belongs to.

Used to group tools logically and avoid name collisions. When set, the tool's name is typically prefixed as {namespace}-{method_name}. This field stores the original namespace string (after normalization) so that downstream code can reliably determine group membership without parsing the name field.

parameters class-attribute instance-attribute

parameters: dict[str, Any] = Field(description='JSON schema for tool parameters')

Parameter schema defining the tool's expected inputs.

Follows JSON Schema format. Automatically generated from the wrapped function's type hints when using from_function().

parameters_model class-attribute instance-attribute

parameters_model: Any | None = Field(default=None, description='Pydantic Model for tool parameters')

Pydantic model used for parameter validation.

Automatically generated from the wrapped function's type hints when using from_function(). Can be None for tools without parameter validation.

qualified_name property

qualified_name: str

Return the fully-qualified tool name.

If a namespace is set, returns {namespace}-{method_name}. Otherwise falls back to the name field.

Returns:

Name Type Description
str str

The qualified name of the tool.

arun async

arun(parameters: dict[str, Any]) -> Any

Execute tool asynchronously.

Delegates to callable.call_async() which handles sync/async callable transparency. Exceptions propagate directly.

Parameters:

Name Type Description Default
parameters dict[str, Any]

Input parameters for the tool.

required

Returns:

Type Description
Any

The tool execution result.

Raises:

Type Description
Exception

Any exception raised during validation or execution.

Note

Result size truncation (via max_result_size) is only applied when tools are executed through ToolRegistry.execute_tool_calls(). Direct calls return raw results without truncation.

arun_raw async

arun_raw(parameters: dict[str, Any]) -> Any

Deprecated alias for arun().

.. deprecated:: 0.12.0 Use arun() instead. arun_raw will be removed in a future version.

describe

describe(api_format: API_FORMATS = 'openai-chat') -> dict[str, Any]

Deprecated: use :meth:get_schema instead.

from_function classmethod

from_function(func: Callable[..., Any], name: str | None = None, description: str | None = None, namespace: str | None = None, method_name: str | None = None, metadata: ToolMetadata | None = None) -> Tool

Factory method to create Tool from callable.

Automatically
  • Extracts function metadata
  • Generates parameter schema
  • Handles async/sync detection

Parameters:

Name Type Description Default
func Callable[..., Any]

Function to convert to tool.

required
name str | None

Override tool name (defaults to function name).

None
description str | None

Override description (defaults to docstring).

None
namespace str | None

Namespace the tool belongs to.

None
method_name str | None

Original method name of the tool.

None
metadata ToolMetadata | None

Optional ToolMetadata; is_async is always auto-detected and will override the value in metadata.

None

Returns:

Name Type Description
Tool Tool

Configured Tool instance.

Raises:

Type Description
ValueError

For unnamed lambda functions.

get_json_schema

get_json_schema(api_format: API_FORMATS = 'openai-chat') -> dict[str, Any]

Deprecated: use :meth:get_schema instead.

get_schema

get_schema(api_format: API_FORMATS = 'openai-chat', *, _think_augment: bool | None = None) -> dict[str, Any]

Generate schema representation of tool for a target API format.

All formats are produced via llm-rosetta converters, which also apply schema sanitization (stripping unsupported JSON Schema keywords like $ref, $schema, anyOf, etc.).

Parameters:

Name Type Description Default
api_format API_FORMATS

Target API format. One of "openai-chat", "openai-responses", "anthropic", "gemini".

'openai-chat'
_think_augment bool | None

Internal override for toolcall_reason injection. When None (default), falls back to self.metadata.think_augment. Used by :meth:ToolRegistry.get_schemas to pass the resolved effective value.

None

Returns:

Type Description
dict[str, Any]

Provider-specific tool definition dict.

model_post_init

model_post_init(__context: Any) -> None

Inject toolcall_reason property into the tool's parameter schema.

Runs after every Tool (and subclass) construction, regardless of whether the instance was created via from_function(), or directly (MCP, OpenAPI, LangChain integrations).

The toolcall_reason field is only added when parameters already contains a properties mapping.

run

run(parameters: dict[str, Any]) -> Any

Execute tool synchronously.

Delegates to callable.call_sync() which handles sync/async callable transparency. Exceptions propagate directly.

Parameters:

Name Type Description Default
parameters dict[str, Any]

Input parameters for the tool.

required

Returns:

Type Description
Any

The tool execution result.

Raises:

Type Description
Exception

Any exception raised during validation or execution.

Note

Result size truncation (via max_result_size) is only applied when tools are executed through ToolRegistry.execute_tool_calls(). Direct calls return raw results without truncation.

run_raw

run_raw(parameters: dict[str, Any]) -> Any

Deprecated alias for run().

.. deprecated:: 0.12.0 Use run() instead. run_raw will be removed in a future version.

update_namespace

update_namespace(namespace: str | None, force: bool = False, sep: Literal['-', '.'] = '-') -> None

Updates the namespace of a tool.

This method checks if the tool's name already contains a namespace (indicated by the presence of a separator character). OpenAI requires that function names match the pattern ^[a-zA-Z0-9_-]+$. Some other providers allow dot (.) as separator. If it does and force is True, the existing namespace is replaced with the provided namespace. If force is False and an existing namespace is present, no changes are made. If the tool's name does not contain a namespace, the namespace is prepended as a prefix to the tool's name.

Parameters:

Name Type Description Default
namespace str

The new namespace to apply to the tool's name.

required
force bool

If True, forces the replacement of an existing namespace. Defaults to False.

False

Returns:

Name Type Description
None None

This method modifies the tool.name attribute in place and does not return a value.

Example
tool = Tool(name="example_tool")
tool.update_namespace("new_namespace")
tool.name  # 'new_namespace-example_tool'

tool = Tool(name="old_namespace.example_tool")
tool.update_namespace("new_namespace", force=False)
tool.name  # 'old_namespace-example_tool'

tool = Tool(name="old_namespace.example_tool")
tool.update_namespace("new_namespace", force=True, sep=".")
tool.name  # 'new_namespace.example_tool'

Usage Examples

Basic Tool Creation

from toolregistry import Tool

def calculate_area(length: float, width: float) -> float:
    """Calculate the area of a rectangle."""
    return length * width

# Create a Tool instance
area_tool = Tool(
    name="calculate_area",
    description="Calculate the area of a rectangle",
    parameters={
        "type": "object",
        "properties": {
            "length": {"type": "number", "description": "Length of rectangle"},
            "width": {"type": "number", "description": "Width of rectangle"}
        },
        "required": ["length", "width"]
    },
    callable=calculate_area,
    is_async=False
)

Tool with Namespace

from toolregistry import Tool

# Create a tool with namespace and method_name fields
math_tool = Tool(
    name="math_ops-multiply",
    description="Multiply two numbers",
    parameters={
        "type": "object",
        "properties": {
            "a": {"type": "number"},
            "b": {"type": "number"}
        },
        "required": ["a", "b"]
    },
    callable=lambda a, b: a * b,
    is_async=False,
    namespace="math_ops",
    method_name="multiply",
)

# Access the qualified name
print(math_tool.qualified_name)  # Output: "math_ops-multiply"
print(math_tool.namespace)       # Output: "math_ops"
print(math_tool.method_name)     # Output: "multiply"

Tool from Function with Namespace

from toolregistry import Tool

def multiply(a: float, b: float) -> float:
    """Multiply two numbers."""
    return a * b

# Create a tool with namespace using from_function()
tool = Tool.from_function(multiply, namespace="math_ops")
print(tool.name)            # Output: "math_ops-multiply"
print(tool.namespace)       # Output: "math_ops"
print(tool.method_name)     # Output: "multiply"
print(tool.qualified_name)  # Output: "math_ops-multiply"

# You can also provide a custom method_name
tool2 = Tool.from_function(multiply, namespace="math_ops", method_name="mul")
print(tool2.name)            # Output: "math_ops-mul"
print(tool2.method_name)     # Output: "mul"

Updating Namespace

from toolregistry import Tool

# Create a tool without namespace
math_tool = Tool.from_function(lambda a, b: a * b, name="multiply")

# Update with namespace
math_tool.update_namespace("math_operations")
print(math_tool.name)           # Output: "math_operations-multiply"
print(math_tool.namespace)      # Output: "math_operations"
print(math_tool.method_name)    # Output: "multiply"
print(math_tool.qualified_name) # Output: "math_operations-multiply"

Async Tool

import asyncio
from toolregistry import Tool

async def fetch_data(url: str) -> dict:
    """Fetch data from a URL asynchronously."""
    # Async implementation
    return {"url": url, "data": "sample"}

# Create async tool
async_tool = Tool(
    name="fetch_data",
    description="Fetch data from URL",
    parameters={
        "type": "object",
        "properties": {
            "url": {"type": "string", "description": "URL to fetch from"}
        },
        "required": ["url"]
    },
    callable=fetch_data,
    is_async=True
)

Executing Tools

The Tool class provides sync and async execution:

  • run(parameters) — Execute synchronously. Raises exceptions on failure.
  • arun(parameters) — Execute asynchronously. Raises exceptions on failure.

Both methods handle sync/async callable transparency automatically. A sync tool can be called via arun() (dispatched via asyncio.to_thread()), and an async tool can be called via run() (dispatched via asyncio.run()).

from toolregistry import Tool

def divide(a: float, b: float) -> float:
    """Divide a by b."""
    return a / b

tool = Tool.from_function(divide)

# Sync execution
try:
    result = tool.run({"a": 10, "b": 0})
except ZeroDivisionError:
    print("Cannot divide by zero!")

# Async execution
result = await tool.arun({"a": 10, "b": 2})  # returns 5.0

run_raw() / arun_raw() are deprecated

These methods are now aliases for run() / arun() and emit DeprecationWarning. Use run() / arun() directly.

Accessing the Underlying Function

Use the tool.fn property to get the original unwrapped function:

tool = Tool.from_function(my_func)
tool.fn          # → my_func (the original function)
tool.callable    # → _FunctionToolWrapper (the wrapper, for internal use)

Parameter Schema Format

The Tool class uses JSON Schema format for parameter validation:

{
  "type": "object",
  "properties": {
    "param_name": {
      "type": "string|number|boolean|array|object",
      "description": "Parameter description",
      "default": "default_value"
    }
  },
  "required": ["param1", "param2"]
}

Integration with ToolRegistry

Tools are primarily used through the ToolRegistry:

from toolregistry import ToolRegistry, Tool

registry = ToolRegistry()

# Register tool with registry
registry.register(tool_instance)

# Execute tool through registry
result = registry.execute_tool("tool_name", param1="value1", param2="value2")

The Tool class provides the foundation for all tool operations within the ToolRegistry ecosystem, ensuring consistent behavior across different tool sources and execution environments.