# `ReqLLM.Tool`
[🔗](https://github.com/agentjido/req_llm/blob/main/lib/req_llm/tool.ex#L1)

Tool definition for AI model function calling.

Tools enable AI models to call external functions, perform actions, and retrieve information.
Each tool has a name, description, parameters schema, and a callback function to execute.

## Basic Usage

    # Create a simple tool
    {:ok, tool} = ReqLLM.Tool.new(
      name: "get_weather",
      description: "Get current weather for a location",
      parameter_schema: [
        location: [type: :string, required: true, doc: "City name"]
      ],
      callback: {WeatherService, :get_current_weather}
    )

    # Execute the tool
    {:ok, result} = ReqLLM.Tool.execute(tool, %{location: "San Francisco"})

    # Get provider-specific schema
    anthropic_schema = ReqLLM.Tool.to_schema(tool, :anthropic)

## Parameters Schema

Parameters are defined using NimbleOptions-compatible keyword lists:

    parameter_schema: [
      location: [type: :string, required: true, doc: "City name"],
      units: [type: :string, default: "celsius", doc: "Temperature units"]
    ]

Raw JSON Schema maps are also accepted. In Responses requests with
`strict: false`, the caller's schema is preserved. Required fields remain
required in the schema; optional fields remain optional. The provider uses
best-effort schema adherence and can reject invalid or unsupported schemas.

Set `"additionalProperties" => false` explicitly in a raw schema if extra
arguments must be excluded. Keyword schemas already include this setting.
Raw JSON Schema maps do not compile a local input validator; validate model
arguments in the application when needed.

## Callback Formats

Multiple callback formats are supported:

    # Module and function (args passed as single argument)
    callback: {MyModule, :my_function}

    # Module, function, and additional args (prepended to input)
    callback: {MyModule, :my_function, [:extra, :args]}

    # Anonymous function
    callback: fn args -> {:ok, "result"} end

## Provider Schema Formats

Tools can be converted to provider-specific formats:

    # Anthropic tool format
    anthropic_schema = ReqLLM.Tool.to_schema(tool, :anthropic)

## Functions

  * `new/1` - Creates a new Tool from the given options
  * `new!/1` - Creates a new Tool from the given options, raising on error
  * `validate_input/2` - Validates input without invoking the callback
  * `execute/2` - Executes a tool with the given input parameters
  * `to_schema/2` - Converts a Tool to provider-specific schema format
  * `to_json_schema/1` - Converts a Tool to JSON Schema format for LLM integration
  * `valid_name?/1` - Validates a tool name for compliance with function calling standards

# `callback`

```elixir
@type callback() :: callback_mfa() | callback_fun()
```

# `callback_fun`

```elixir
@type callback_fun() :: (map() -&gt; {:ok, term()} | {:error, term()})
```

# `callback_mfa`

```elixir
@type callback_mfa() :: {module(), atom()} | {module(), atom(), list()}
```

# `t`

```elixir
@type t() :: %ReqLLM.Tool{
  callback: any(),
  compiled: nil | any(),
  description: binary(),
  name: binary(),
  parameter_schema: any(),
  provider_options: any(),
  strict: boolean()
}
```

A tool definition for AI model function calling

# `tool_opts`

```elixir
@type tool_opts() :: [
  name: String.t(),
  description: String.t(),
  parameter_schema: keyword() | map(),
  callback: callback(),
  strict: boolean(),
  provider_options: keyword() | map()
]
```

# `execute`

```elixir
@spec execute(t(), term()) :: {:ok, term()} | {:error, term()}
```

Executes a tool with the given input parameters.

Validates input parameters against the tool's schema and calls the callback function.
The callback is expected to return `{:ok, result}` or `{:error, reason}`.
Tool results can be plain text, structured data, content parts, or a `ReqLLM.ToolResult`.

## Parameters

  * `tool` - Tool struct
  * `input` - Input parameters as map

## Examples

    {:ok, result} = ReqLLM.Tool.execute(tool, %{location: "San Francisco"})
    #=> {:ok, %{temperature: 72, conditions: "sunny"}}

    {:error, reason} = ReqLLM.Tool.execute(tool, %{invalid: "params"})
    #=> {:error, %ReqLLM.Error.Validation.Error{...}}

# `new`

```elixir
@spec new(tool_opts()) :: {:ok, t()} | {:error, term()}
```

Creates a new Tool from the given options.

## Parameters

  * `opts` - Tool options as keyword list

## Options

  * `:name` - Tool name (required, must be valid identifier)
  * `:description` - Tool description for AI model (required)
  * `:parameter_schema` - Parameter schema as NimbleOptions keyword list or JSON Schema map (optional)
  * `:callback` - Callback function or MFA tuple (required)

## Examples

    # Using NimbleOptions keyword list
    {:ok, tool} = ReqLLM.Tool.new(
      name: "get_weather",
      description: "Get current weather",
      parameter_schema: [
        location: [type: :string, required: true]
      ],
      callback: {WeatherService, :get_weather}
    )

    # Using raw JSON Schema map
    {:ok, tool} = ReqLLM.Tool.new(
      name: "get_weather",
      description: "Get current weather",
      parameter_schema: %{
        "type" => "object",
        "properties" => %{
          "location" => %{"type" => "string"}
        },
        "required" => ["location"]
      },
      callback: {WeatherService, :get_weather}
    )

    # Using Elixir typespec syntax via JSONSpec (https://hex.pm/packages/json_spec)
    import JSONSpec

    {:ok, tool} = ReqLLM.Tool.new(
      name: "get_weather",
      description: "Get current weather",
      parameter_schema: schema(
        %{required(:location) => String.t(), optional(:units) => :celsius | :fahrenheit},
        doc: [location: "City name", units: "Temperature units"]
      ),
      callback: {WeatherService, :get_weather}
    )

# `new!`

```elixir
@spec new!(tool_opts()) :: t() | no_return()
```

Creates a new Tool from the given options, raising on error.

See `new/1` for details.

## Examples

    tool = ReqLLM.Tool.new!(
      name: "get_weather",
      description: "Get current weather",
      callback: {WeatherService, :get_weather}
    )

# `provider_options`

```elixir
@spec provider_options(t(), atom() | String.t()) :: map()
```

Returns provider-specific tool options for the requested provider.

# `schema`

# `to_json_schema`

```elixir
@spec to_json_schema(t()) :: map()
```

Converts a Tool to JSON Schema format for LLM integration.

Backward compatibility function that defaults to OpenAI format.
Use `to_schema/2` for explicit provider selection.

## Examples

    json_schema = ReqLLM.Tool.to_json_schema(tool)
    # Equivalent to: ReqLLM.Tool.to_schema(tool, :openai)

# `to_schema`

```elixir
@spec to_schema(t(), atom()) :: map()
```

Converts a Tool to provider-specific schema format.

Returns a map containing the provider's expected tool format with
tool name, description, and parameter definitions.

## Parameters

  * `tool` - Tool struct
  * `provider` - Provider atom (`:anthropic`, `:openai`, `:google`, `:amazon_bedrock_converse`)

## Examples

    # Anthropic tool format
    anthropic_schema = ReqLLM.Tool.to_schema(tool, :anthropic)
    #=> %{
    #     "name" => "get_weather",
    #     "description" => "Get current weather",
    #     "input_schema" => %{...}
    #   }

    # Bedrock Converse tool format
    bedrock_schema = ReqLLM.Tool.to_schema(tool, :amazon_bedrock_converse)
    #=> %{
    #     "toolSpec" => %{
    #       "name" => "get_weather",
    #       "description" => "Get current weather",
    #       "inputSchema" => %{"json" => %{...}}
    #     }
    #   }

# `valid_name?`

```elixir
@spec valid_name?(String.t()) :: boolean()
```

Validates a tool name for compliance with function calling standards.

Tool names must be valid identifiers (alphanumeric, underscores, or hyphens, start with letter/underscore).

## Examples

    ReqLLM.Tool.valid_name?("get_weather")
    #=> true

    ReqLLM.Tool.valid_name?("get-weather")
    #=> true

    ReqLLM.Tool.valid_name?("123invalid")
    #=> false

# `validate_input`

```elixir
@spec validate_input(t(), term()) :: {:ok, map()} | {:error, term()}
```

Validates input parameters without invoking the tool callback.

This uses the same schema validation and key normalization as `execute/2`.
It is useful when inspecting a model-produced tool call before deciding
whether to execute it.

Returns the normalized, validated input on success. Invalid input returns the
same error shape as `execute/2` and never invokes the callback.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
