Skip to content

anthropic.tools

Classes for using tools with Anthropic's Claude API.

AnthropicTool

Bases: BaseTool[ToolUseBlock]

A base class for easy use of tools with the Anthropic Claude client.

AnthropicTool internally handles the logic that allows you to use tools with simple calls such as AnthropicCallResponse.tool or AnthropicTool.fn, as seen in the example below.

Example:

from mirascope import AnthropicCall, AnthropicCallParams


def animal_matcher(fav_food: str, fav_color: str) -> str:
    """Tells you your most likely favorite animal from personality traits.

    Args:
        fav_food: your favorite food.
        fav_color: your favorite color.

    Returns:
        The animal most likely to be your favorite based on traits.
    """
    return "Your favorite animal is the best one, a frog."


class AnimalMatcher(AnthropicCall):
    prompt_template = """
    Tell me my favorite animal if my favorite food is {food} and my
    favorite color is {color}.
    """

    food: str
    color: str

    call_params = AnthropicCallParams(tools=[animal_matcher])


response = AnimalMatcher(food="pizza", color="red").call
tool = response.tool
print(tool.fn(**tool.args))
#> Your favorite animal is the best one, a frog.
Source code in mirascope/anthropic/tools.py
class AnthropicTool(BaseTool[ToolUseBlock]):
    '''A base class for easy use of tools with the Anthropic Claude client.

    `AnthropicTool` internally handles the logic that allows you to use tools with
    simple calls such as `AnthropicCallResponse.tool` or `AnthropicTool.fn`, as seen in
    the example below.

    Example:

    ```python
    from mirascope import AnthropicCall, AnthropicCallParams


    def animal_matcher(fav_food: str, fav_color: str) -> str:
        """Tells you your most likely favorite animal from personality traits.

        Args:
            fav_food: your favorite food.
            fav_color: your favorite color.

        Returns:
            The animal most likely to be your favorite based on traits.
        """
        return "Your favorite animal is the best one, a frog."


    class AnimalMatcher(AnthropicCall):
        prompt_template = """
        Tell me my favorite animal if my favorite food is {food} and my
        favorite color is {color}.
        """

        food: str
        color: str

        call_params = AnthropicCallParams(tools=[animal_matcher])


    response = AnimalMatcher(food="pizza", color="red").call
    tool = response.tool
    print(tool.fn(**tool.args))
    #> Your favorite animal is the best one, a frog.
    ```
    '''

    @classmethod
    def tool_schema(cls) -> ToolParam:
        """Constructs JSON tool schema for use with Anthropic's Claude API."""
        schema = super().tool_schema()
        return ToolParam(
            input_schema=schema["parameters"],
            name=schema["name"],
            description=schema["description"],
        )

    @classmethod
    def from_tool_call(cls, tool_call: ToolUseBlock) -> AnthropicTool:
        """Extracts an instance of the tool constructed from a tool call response.

        Given the tool call contents in a `Message` from an Anthropic call response,
        this method parses out the arguments of the tool call and creates an
        `AnthropicTool` instance from them.

        Args:
            tool_call: The list of `TextBlock` contents.

        Returns:
            An instance of the tool constructed from the tool call.

        Raises:
            ValidationError: if the tool call doesn't match the tool schema.
        """
        model_json = tool_call.input
        model_json["tool_call"] = tool_call.model_dump()  # type: ignore
        return cls.model_validate(model_json)

    @classmethod
    def from_model(cls, model: Type[BaseModel]) -> Type[AnthropicTool]:
        """Constructs a `AnthropicTool` type from a `BaseModel` type."""
        return convert_base_model_to_tool(model, AnthropicTool)

    @classmethod
    def from_fn(cls, fn: Callable) -> Type[AnthropicTool]:
        """Constructs a `AnthropicTool` type from a function."""
        return convert_function_to_tool(fn, AnthropicTool)

    @classmethod
    def from_base_type(cls, base_type: Type[BaseType]) -> Type[AnthropicTool]:
        """Constructs a `AnthropicTool` type from a `BaseType` type."""
        return convert_base_type_to_tool(base_type, AnthropicTool)

from_base_type(base_type) classmethod

Constructs a AnthropicTool type from a BaseType type.

Source code in mirascope/anthropic/tools.py
@classmethod
def from_base_type(cls, base_type: Type[BaseType]) -> Type[AnthropicTool]:
    """Constructs a `AnthropicTool` type from a `BaseType` type."""
    return convert_base_type_to_tool(base_type, AnthropicTool)

from_fn(fn) classmethod

Constructs a AnthropicTool type from a function.

Source code in mirascope/anthropic/tools.py
@classmethod
def from_fn(cls, fn: Callable) -> Type[AnthropicTool]:
    """Constructs a `AnthropicTool` type from a function."""
    return convert_function_to_tool(fn, AnthropicTool)

from_model(model) classmethod

Constructs a AnthropicTool type from a BaseModel type.

Source code in mirascope/anthropic/tools.py
@classmethod
def from_model(cls, model: Type[BaseModel]) -> Type[AnthropicTool]:
    """Constructs a `AnthropicTool` type from a `BaseModel` type."""
    return convert_base_model_to_tool(model, AnthropicTool)

from_tool_call(tool_call) classmethod

Extracts an instance of the tool constructed from a tool call response.

Given the tool call contents in a Message from an Anthropic call response, this method parses out the arguments of the tool call and creates an AnthropicTool instance from them.

Parameters:

Name Type Description Default
tool_call ToolUseBlock

The list of TextBlock contents.

required

Returns:

Type Description
AnthropicTool

An instance of the tool constructed from the tool call.

Raises:

Type Description
ValidationError

if the tool call doesn't match the tool schema.

Source code in mirascope/anthropic/tools.py
@classmethod
def from_tool_call(cls, tool_call: ToolUseBlock) -> AnthropicTool:
    """Extracts an instance of the tool constructed from a tool call response.

    Given the tool call contents in a `Message` from an Anthropic call response,
    this method parses out the arguments of the tool call and creates an
    `AnthropicTool` instance from them.

    Args:
        tool_call: The list of `TextBlock` contents.

    Returns:
        An instance of the tool constructed from the tool call.

    Raises:
        ValidationError: if the tool call doesn't match the tool schema.
    """
    model_json = tool_call.input
    model_json["tool_call"] = tool_call.model_dump()  # type: ignore
    return cls.model_validate(model_json)

tool_schema() classmethod

Constructs JSON tool schema for use with Anthropic's Claude API.

Source code in mirascope/anthropic/tools.py
@classmethod
def tool_schema(cls) -> ToolParam:
    """Constructs JSON tool schema for use with Anthropic's Claude API."""
    schema = super().tool_schema()
    return ToolParam(
        input_schema=schema["parameters"],
        name=schema["name"],
        description=schema["description"],
    )

BaseTool

Bases: BaseModel, Generic[ToolCallT], ABC

A base class for easy use of tools with prompts.

BaseTool is an abstract class interface and should not be used directly. When implementing a class that extends BaseTool, you must include the original tool_call from which this till was instantiated. Make sure to skip tool_call when generating the schema by annotating it with SkipJsonSchema.

Source code in mirascope/base/tools.py
class BaseTool(BaseModel, Generic[ToolCallT], ABC):
    """A base class for easy use of tools with prompts.

    `BaseTool` is an abstract class interface and should not be used directly. When
    implementing a class that extends `BaseTool`, you must include the original
    `tool_call` from which this till was instantiated. Make sure to skip `tool_call`
    when generating the schema by annotating it with `SkipJsonSchema`.
    """

    tool_call: SkipJsonSchema[ToolCallT]

    model_config = ConfigDict(arbitrary_types_allowed=True)

    @classmethod
    def name(cls) -> str:
        """Returns the name of the tool."""
        return cls.__name__

    @classmethod
    def description(cls) -> str:
        """Returns the description of the tool."""
        return inspect.cleandoc(cls.__doc__) if cls.__doc__ else DEFAULT_TOOL_DOCSTRING

    @property
    def args(self) -> dict[str, Any]:
        """The arguments of the tool as a dictionary."""
        return {
            field: getattr(self, field)
            for field in self.model_fields
            if field != "tool_call"
        }

    @property
    def fn(self) -> Callable[..., str]:
        """Returns the function that the tool describes."""
        raise RuntimeError("Tool does not have an attached function.")

    def call(self) -> str:
        """Calls the tool's `fn` with the tool's `args`."""
        return self.fn(**self.args)

    @classmethod
    def tool_schema(cls) -> Any:
        """Constructs a JSON Schema tool schema from the `BaseModel` schema defined."""
        model_schema = cls.model_json_schema()
        model_schema.pop("title", None)
        model_schema.pop("description", None)

        fn = {"name": cls.name(), "description": cls.description()}
        if model_schema["properties"]:
            fn["parameters"] = model_schema  # type: ignore

        return fn

    @classmethod
    @abstractmethod
    def from_tool_call(cls, tool_call: ToolCallT) -> BaseTool:
        """Extracts an instance of the tool constructed from a tool call response."""
        ...  # pragma: no cover

    @classmethod
    @abstractmethod
    def from_model(cls, model: type[BaseModel]) -> type[BaseTool]:
        """Constructs a `BaseTool` type from a `BaseModel` type."""
        ...  # pragma: no cover

    @classmethod
    @abstractmethod
    def from_fn(cls, fn: Callable) -> type[BaseTool]:
        """Constructs a `BaseTool` type from a function."""
        ...  # pragma: no cover

    @classmethod
    @abstractmethod
    def from_base_type(cls, base_type: type[BaseType]) -> type[BaseTool]:
        """Constructs a `BaseTool` type from a `BaseType` type."""
        ...  # pragma: no cover

args: dict[str, Any] property

The arguments of the tool as a dictionary.

fn: Callable[..., str] property

Returns the function that the tool describes.

call()

Calls the tool's fn with the tool's args.

Source code in mirascope/base/tools.py
def call(self) -> str:
    """Calls the tool's `fn` with the tool's `args`."""
    return self.fn(**self.args)

description() classmethod

Returns the description of the tool.

Source code in mirascope/base/tools.py
@classmethod
def description(cls) -> str:
    """Returns the description of the tool."""
    return inspect.cleandoc(cls.__doc__) if cls.__doc__ else DEFAULT_TOOL_DOCSTRING

from_base_type(base_type) abstractmethod classmethod

Constructs a BaseTool type from a BaseType type.

Source code in mirascope/base/tools.py
@classmethod
@abstractmethod
def from_base_type(cls, base_type: type[BaseType]) -> type[BaseTool]:
    """Constructs a `BaseTool` type from a `BaseType` type."""
    ...  # pragma: no cover

from_fn(fn) abstractmethod classmethod

Constructs a BaseTool type from a function.

Source code in mirascope/base/tools.py
@classmethod
@abstractmethod
def from_fn(cls, fn: Callable) -> type[BaseTool]:
    """Constructs a `BaseTool` type from a function."""
    ...  # pragma: no cover

from_model(model) abstractmethod classmethod

Constructs a BaseTool type from a BaseModel type.

Source code in mirascope/base/tools.py
@classmethod
@abstractmethod
def from_model(cls, model: type[BaseModel]) -> type[BaseTool]:
    """Constructs a `BaseTool` type from a `BaseModel` type."""
    ...  # pragma: no cover

from_tool_call(tool_call) abstractmethod classmethod

Extracts an instance of the tool constructed from a tool call response.

Source code in mirascope/base/tools.py
@classmethod
@abstractmethod
def from_tool_call(cls, tool_call: ToolCallT) -> BaseTool:
    """Extracts an instance of the tool constructed from a tool call response."""
    ...  # pragma: no cover

name() classmethod

Returns the name of the tool.

Source code in mirascope/base/tools.py
@classmethod
def name(cls) -> str:
    """Returns the name of the tool."""
    return cls.__name__

tool_schema() classmethod

Constructs a JSON Schema tool schema from the BaseModel schema defined.

Source code in mirascope/base/tools.py
@classmethod
def tool_schema(cls) -> Any:
    """Constructs a JSON Schema tool schema from the `BaseModel` schema defined."""
    model_schema = cls.model_json_schema()
    model_schema.pop("title", None)
    model_schema.pop("description", None)

    fn = {"name": cls.name(), "description": cls.description()}
    if model_schema["properties"]:
        fn["parameters"] = model_schema  # type: ignore

    return fn

convert_base_model_to_tool(schema, base)

Converts a BaseModel schema to a BaseToolT type.

By adding a docstring (if needed) and passing on fields and field information in dictionary format, a Pydantic BaseModel can be converted into an BaseToolT for performing extraction.

Parameters:

Name Type Description Default
schema type[BaseModel]

The BaseModel schema to convert.

required

Returns:

Type Description
type[BaseToolT]

The constructed BaseToolT type.

Source code in mirascope/base/tools.py
def convert_base_model_to_tool(
    schema: type[BaseModel], base: type[BaseToolT]
) -> type[BaseToolT]:
    """Converts a `BaseModel` schema to a `BaseToolT` type.

    By adding a docstring (if needed) and passing on fields and field information in
    dictionary format, a Pydantic `BaseModel` can be converted into an `BaseToolT` for
    performing extraction.

    Args:
        schema: The `BaseModel` schema to convert.

    Returns:
        The constructed `BaseToolT` type.
    """
    field_definitions = {
        field_name: (field_info.annotation, field_info)
        for field_name, field_info in schema.model_fields.items()
    }
    return create_model(
        f"{schema.__name__}",
        __base__=base,
        __doc__=schema.__doc__ if schema.__doc__ else DEFAULT_TOOL_DOCSTRING,
        **cast(dict[str, Any], field_definitions),
    )

convert_base_type_to_tool(schema, base)

Converts a BaseType to a BaseToolT type.

Source code in mirascope/base/tools.py
def convert_base_type_to_tool(
    schema: type[BaseType], base: type[BaseToolT]
) -> type[BaseToolT]:
    """Converts a `BaseType` to a `BaseToolT` type."""
    if get_origin(schema) == Annotated:
        schema.__name__ = get_args(schema)[0].__name__
    return create_model(
        f"{schema.__name__.title()}",
        __base__=base,
        __doc__=DEFAULT_TOOL_DOCSTRING,
        value=(schema, ...),
    )

convert_function_to_tool(fn, base)

Constructs a BaseToolT type from the given function.

This method expects all function parameters to be properly documented in identical order with identical variable names, as well as descriptions of each parameter. Errors will be raised if any of these conditions are not met.

Parameters:

Name Type Description Default
fn Callable

The function to convert.

required

Returns:

Type Description
type[BaseToolT]

The constructed BaseToolT type.

Raises:

Type Description
ValueError

if the given function doesn't have a docstring.

ValueError

if the given function's parameters don't have type annotations.

ValueError

if a given function's parameter is in the docstring args section but the name doesn't match the docstring's parameter name.

ValueError

if a given function's parameter is in the docstring args section but doesn't have a dosctring description.

Source code in mirascope/base/tools.py
def convert_function_to_tool(fn: Callable, base: type[BaseToolT]) -> type[BaseToolT]:
    """Constructs a `BaseToolT` type from the given function.

    This method expects all function parameters to be properly documented in identical
    order with identical variable names, as well as descriptions of each parameter.
    Errors will be raised if any of these conditions are not met.

    Args:
        fn: The function to convert.

    Returns:
        The constructed `BaseToolT` type.

    Raises:
        ValueError: if the given function doesn't have a docstring.
        ValueError: if the given function's parameters don't have type annotations.
        ValueError: if a given function's parameter is in the docstring args section but
            the name doesn't match the docstring's parameter name.
        ValueError: if a given function's parameter is in the docstring args section but
            doesn't have a dosctring description.
    """
    if not fn.__doc__:
        raise ValueError("Function must have a docstring.")

    docstring = parse(fn.__doc__)

    doc = ""
    if docstring.short_description:
        doc = docstring.short_description
    if docstring.long_description:
        doc += "\n\n" + docstring.long_description
    if docstring.returns and docstring.returns.description:
        doc += "\n\n" + "Returns:\n    " + docstring.returns.description

    field_definitions = {}
    hints = get_type_hints(fn)
    for i, parameter in enumerate(signature(fn).parameters.values()):
        if parameter.name == "self" or parameter.name == "cls":
            continue
        if parameter.annotation == Parameter.empty:
            raise ValueError("All parameters must have a type annotation.")

        docstring_description = None
        if i < len(docstring.params):
            docstring_param = docstring.params[i]
            if docstring_param.arg_name != parameter.name:
                raise ValueError(
                    f"Function parameter name {parameter.name} does not match docstring "
                    f"parameter name {docstring_param.arg_name}. Make sure that the "
                    "parameter names match exactly."
                )
            if not docstring_param.description:
                raise ValueError("All parameters must have a description.")
            docstring_description = docstring_param.description

        field_info = FieldInfo(annotation=hints[parameter.name])
        if parameter.default != Parameter.empty:
            field_info.default = parameter.default
        if docstring_description:  # we check falsy here because this comes from docstr
            field_info.description = docstring_description

        param_name = parameter.name
        if param_name.startswith("model_"):  # model_ is a BaseModel reserved namespace
            param_name = "aliased_" + param_name
            field_info.alias = parameter.name
            field_info.validation_alias = parameter.name
            field_info.serialization_alias = parameter.name

        field_definitions[param_name] = (
            hints[parameter.name],
            field_info,
        )

    model = create_model(
        fn.__name__,
        __base__=base,
        __doc__=doc,
        **cast(dict[str, Any], field_definitions),
    )
    return tool_fn(fn)(model)