# `Nous.Tool`
[🔗](https://github.com/nyo16/nous/blob/v0.17.1/lib/nous/tool.ex#L1)

Tool definition for agent function calling.

A tool represents a function that an AI agent can call to retrieve
information or perform actions. Tools are automatically converted to
OpenAI function calling schemas.

## Example

    defmodule MyTools do
      @doc "Search the database for users"
      def search_users(ctx, query) do
        ctx.deps.database
        |> Database.search(query)
        |> format_results()
      end
    end

    # Create tool from function
    tool = Tool.from_function(&MyTools.search_users/2,
      name: "search_users",
      description: "Search for users in the database"
    )

    # Convert to OpenAI schema
    schema = Tool.to_openai_schema(tool)

# `category`

```elixir
@type category() :: :read | :write | :execute | :communicate | :search | nil
```

# `t`

```elixir
@type t() :: %Nous.Tool{
  category: category(),
  description: String.t(),
  function: function(),
  module: module() | nil,
  name: String.t(),
  parameters: map(),
  requires_approval: boolean(),
  retries: non_neg_integer(),
  tags: [atom()],
  takes_ctx: boolean(),
  timeout: non_neg_integer() | nil,
  validate_args: boolean()
}
```

# `from_function`

```elixir
@spec from_function(
  function(),
  keyword()
) :: t()
```

Create a tool from a function.

Automatically extracts function metadata including documentation
and generates a JSON schema for the parameters.

## Options

  * `:name` - Custom tool name (default: function name)
  * `:description` - Custom description (default: from @doc)
  * `:parameters` - Custom parameter schema (default: auto-generated)
  * `:retries` - Number of retries on failure (default: 1)
  * `:timeout` - Timeout in milliseconds (default: 30000)
  * `:validate_args` - Whether to validate arguments against schema (default: true)
  * `:requires_approval` - Whether tool needs human approval before execution (default: false)
  * `:category` - Tool category: `:read`, `:write`, `:execute`, `:communicate`, `:search`, or `nil`
  * `:tags` - Arbitrary tags for filtering (default: `[]`)

## Examples

    # Simple tool
    tool = Tool.from_function(&MyTools.calculate/2)

    # With custom options
    tool = Tool.from_function(&MyTools.search/2,
      name: "search_database",
      description: "Search for records",
      retries: 3,
      timeout: 60_000
    )

# `from_module`

```elixir
@spec from_module(
  module(),
  keyword()
) :: t()
```

Create a tool from a module implementing `Nous.Tool.Behaviour`.

Module-based tools are easier to test because dependencies can be
injected through the context.

## Options

  * `:name` - Override tool name from metadata
  * `:description` - Override description from metadata
  * `:parameters` - Override parameters from metadata
  * `:retries` - Number of retries on failure (default: 1)
  * `:timeout` - Per-call deadline in milliseconds. Defaults to the tool's own
    `metadata.timeout` when it declares one (see `Nous.Tool.Schema`), else 30000
  * `:validate_args` - Whether to validate arguments (default: true)
  * `:requires_approval` - Whether tool needs human approval before execution (default: false)
  * `:category` - Override category from metadata
  * `:tags` - Override tags from metadata

## Example

    defmodule MyApp.Tools.Search do
      @behaviour Nous.Tool.Behaviour

      @impl true
      def metadata do
        %{
          name: "search",
          description: "Search the web",
          parameters: %{
            "type" => "object",
            "properties" => %{
              "query" => %{"type" => "string"}
            },
            "required" => ["query"]
          }
        }
      end

      @impl true
      def execute(ctx, %{"query" => query}) do
        http = ctx.deps[:http_client] || MyApp.HTTP
        {:ok, http.search(query)}
      end
    end

    # Create tool from module
    tool = Tool.from_module(MyApp.Tools.Search)

    # Override options
    tool = Tool.from_module(MyApp.Tools.Search, timeout: 60_000, retries: 3)

# `to_openai_schema`

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

Convert tool to OpenAI function calling schema.

## Example

    schema = Tool.to_openai_schema(tool)
    # %{
    #   "type" => "function",
    #   "function" => %{
    #     "name" => "search_users",
    #     "description" => "Search for users",
    #     "parameters" => %{...}
    #   }
    # }

---

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