Introduction
The anthropic-tools library simplifies the usage of Anthropics’s tool use feature. It abstracts away the complexity of parsing function signatures and docstrings by providing developers with a clean and intuitive interface. Once again, the library is a near-clone of my openai-functions library that does the same with OpenAI.
anthropic-tools takes care of the following tasks:
Parsing the function signatures (with type annotations) and docstrings.
Sending the conversation and tool descriptions to Anthropic Claude.
Deciding whether to call a tool based on the model’s response.
Calling the appropriate function with the provided arguments.
Updating the conversation with the tool response.
Repeating the process until the model generates a user-facing message.
This abstraction allows developers to focus on defining their functions and adding user messages without worrying about the details of tool use.
Quickstart
Installation
You can install anthropic-tools from PyPI using pip:
pip install anthropic-tools
Unlike openai-functions, since Anthropic does not support forcing the model to generate a specific function call, the only way of using it is as an assistant with access to tools.
Your first conversation
The easiest way to use anthropic-tools is through the conversation interface. For that, you first import all of the necessary modules and create a client with your API key:
import enum
import anthropic
from anthropic_tools import Conversation
client = anthropic.Anthropic(
api_key="<YOUR_API_KEY>",
)
Then, we can create a conversation.
conversation = Conversation(client)
A conversation contains our and the AI’s messages, the tools we provide, and a set of methods for calling the AI with our tools. Now, we can add our tools to the conversation using the @conversation.add_tool decorator to make them available for the AI:
class Unit(enum.Enum):
FAHRENHEIT = "fahrenheit"
CELSIUS = "celsius"
@conversation.add_tool
def get_current_weather(location: str, unit: Unit = Unit.FAHRENHEIT) -> dict:
"""Get the current weather in a given location.
Args:
location (str): The city and state, e.g., San Francisco, CA
unit (Unit): The unit to use, e.g., fahrenheit or celsius
"""
return {
"location": location,
"temperature": "72",
"unit": unit.value,
"forecast": ["sunny", "windy"],
}
Note that the function must have type annotations for all arguments, including extended type annotations for lists/dictionaries (for example, list[int] and not just list); otherwise the tool won’t be able to generate a schema. Our conversation is now ready for tool use. The easiest way to do so is through the conversation.ask method. This method will repeatedly ask the AI for a response, running tools, until the AI responds with text to return:
response = conversation.ask("What's the weather in San Francisco?")
# Should return three messages, the last one's content being something like:
# The current weather in San Francisco is 72 degrees Fahrenheit and it is sunny and windy.
The AI will probably (nobody can say for sure) then use the tool with {"location": "San Francisco, CA"}, which will get translated to get_current_weather("San Francisco, CA"). The function response will be serialized and sent back to the AI, and the AI will return a text description. You can read more about how to work with conversations here.
Just generating the schemas
If you want to generate the schemas, you can use a ToolWrapper:
from anthropic_tools import ToolWrapper
wrapper = ToolWrapper(get_current_weather)
schema = wrapper.schema
result = wrapper({"location": "San Francisco, CA"})
This creates an object that can both return you a schema of a tool and provide the function with properly parsed arguments. Another tool is a ToolSet that allows you to aggregate multiple tools into one schema:
from anthropic_tools import BasicToolSet
import enum
skill = BasicToolSet()
class Unit(enum.Enum):
FAHRENHEIT = "fahrenheit"
CELSIUS = "celsius"
@skill.add_tool
def get_current_weather(location: str, unit: Unit = Unit.FAHRENHEIT) -> dict:
"""Get the current weather in a given location.
Args:
location (str): The city and state, e.g., San Francisco, CA
unit (Unit): The unit to use, e.g., fahrenheit or celsius
"""
return {
"location": location,
"temperature": "72",
"unit": unit.value,
"forecast": ["sunny", "windy"],
}
@skill.add_tool
def set_weather(location: str, weather_description: str):
...
schema = skill.tools_schema
This then generates the schema for your tools.This is what
schema looks like
[
{
"name": "get_current_weather",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g., San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["FAHRENHEIT", "CELSIUS"],
"description": "The unit to use, e.g., fahrenheit or celsius"
}
},
"required": ["location"]
},
"description": "Get the current weather in a given location."
},
{
"name": "set_weather",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string"
},
"weather_description": {
"type": "string"
}
},
"required": ["location", "weather_description"]
}
}
]
You can now call the tools directly using the tool uses Anthropic returns:
weather = skill(
{
"id": "1234",
"type": "tool_use",
"name": "get_current_weather",
"input": {
"location": "San Francisco, CA",
"unit": "FAHRENHEIT",
},
}
)
This then calls the relevant function.weather is then just the raw return value of it, in this case:
{
"location": "San Francisco, CA",
"temperature": "72",
"unit": "fahrenheit",
"forecast": ["sunny", "windy"]
}
You can read more about how to work with skills here.