Claudio.Tools (Claudio v0.5.0)

View Source

Utilities for working with tools/function calling in the Messages API.

Example

# Define a tool
weather_tool = Claudio.Tools.define_tool(
  "get_weather",
  "Get the current weather for a location",
  %{
    "type" => "object",
    "properties" => %{
      "location" => %{
        "type" => "string",
        "description" => "City name or coordinates"
      },
      "unit" => %{
        "type" => "string",
        "enum" => ["celsius", "fahrenheit"],
        "description" => "Temperature unit"
      }
    },
    "required" => ["location"]
  }
)

# Use in a request
alias Claudio.Messages.Request

request = Request.new("claude-3-5-sonnet-20241022")
|> Request.add_message(:user, "What's the weather in San Francisco?")
|> Request.add_tool(weather_tool)
|> Request.set_tool_choice(:auto)

{:ok, response} = Claudio.Messages.create_message(client, request)

# Extract tool uses
tool_uses = Claudio.Tools.extract_tool_uses(response)

# Execute tools and create results
results = Enum.map(tool_uses, fn tool_use ->
  result = execute_my_tool(tool_use.name, tool_use.input)
  Claudio.Tools.create_tool_result(tool_use.id, result)
end)

# Continue conversation with tool results
request2 = Request.new("claude-3-5-sonnet-20241022")
|> Request.add_message(:user, "What's the weather in San Francisco?")
|> Request.add_message(:assistant, response.content)
|> Request.add_message(:user, results)

Summary

Functions

Creates a tool result message to continue the conversation after executing a tool.

Creates a complete tool result message for adding to the conversation.

Defines a tool with a name, description, and JSON schema for input validation.

Extracts tool use requests from a response.

Checks if a response indicates that tools were used.

Types

tool_definition()

@type tool_definition() :: %{
  name: String.t(),
  description: String.t(),
  input_schema: map()
}

tool_result()

@type tool_result() :: %{
  type: String.t(),
  tool_use_id: String.t(),
  content: String.t() | list()
}

tool_use()

@type tool_use() :: %{id: String.t(), name: String.t(), input: map()}

Functions

create_tool_result(tool_use_id, result, is_error \\ false)

@spec create_tool_result(String.t(), String.t() | list(), boolean()) :: tool_result()

Creates a tool result message to continue the conversation after executing a tool.

Parameters

  • tool_use_id - The ID from the tool_use block
  • result - The result of executing the tool (string or structured content)
  • is_error - (optional) Whether this represents an error result

Example

tool_result = Claudio.Tools.create_tool_result(
  "toolu_123",
  "The weather in San Francisco is 72°F and sunny"
)

# Or with structured content
tool_result = Claudio.Tools.create_tool_result(
  "toolu_123",
  [%{"type" => "text", "text" => "Here's the data..."}]
)

# For errors
error_result = Claudio.Tools.create_tool_result(
  "toolu_123",
  "Failed to fetch weather data",
  true
)

create_tool_result_message(tool_results)

@spec create_tool_result_message([tool_result()]) :: [tool_result()]

Creates a complete tool result message for adding to the conversation.

This is a convenience function that wraps tool results in a message structure.

Example

tool_results = [
  Claudio.Tools.create_tool_result("toolu_1", "Result 1"),
  Claudio.Tools.create_tool_result("toolu_2", "Result 2")
]

message = Claudio.Tools.create_tool_result_message(tool_results)

request = Request.new("claude-3-5-sonnet-20241022")
|> Request.add_message(:user, "Initial question")
|> Request.add_message(:assistant, assistant_response.content)
|> Request.add_message(:user, message)

define_tool(name, description, input_schema)

@spec define_tool(String.t(), String.t(), map()) :: tool_definition()

Defines a tool with a name, description, and JSON schema for input validation.

Parameters

  • name - Unique identifier for the tool
  • description - Human-readable description of what the tool does
  • input_schema - JSON Schema object defining the tool's input parameters

Example

Claudio.Tools.define_tool(
  "calculator",
  "Performs basic arithmetic operations",
  %{
    "type" => "object",
    "properties" => %{
      "operation" => %{
        "type" => "string",
        "enum" => ["add", "subtract", "multiply", "divide"]
      },
      "a" => %{"type" => "number"},
      "b" => %{"type" => "number"}
    },
    "required" => ["operation", "a", "b"]
  }
)

extract_tool_uses(arg1)

@spec extract_tool_uses(map() | struct()) :: [tool_use()]

Extracts tool use requests from a response.

Returns a list of tool use blocks that need to be executed.

Example

{:ok, response} = Claudio.Messages.create_message(client, request)
tool_uses = Claudio.Tools.extract_tool_uses(response)

Enum.each(tool_uses, fn tool_use ->
  IO.inspect(tool_use.name)
  IO.inspect(tool_use.input)
end)

has_tool_uses?(response)

@spec has_tool_uses?(map() | struct()) :: boolean()

Checks if a response indicates that tools were used.

Example

if Claudio.Tools.has_tool_uses?(response) do
  # Handle tool execution
end