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

Declarative DSL for defining tool schemas.

Provides a macro-based approach to defining tool metadata, parameters,
and JSON Schema in a single, readable block. Automatically implements
`Nous.Tool.Behaviour` callbacks.

## Architecture

When you `use Nous.Tool.Schema`, the module:

1. Adds `@behaviour Nous.Tool.Behaviour`
2. Imports the `tool` and `param` macros
3. Registers a `@before_compile` hook to generate `metadata/0` and `__tool_schema__/0`

The `tool` macro captures the tool name, description, category, and tags.
Inside its block, `param` declarations accumulate into `@tool_params`.
At compile time, these are transformed into JSON Schema and behaviour callbacks.

## Quick Start

    defmodule MyApp.Tools.FileRead do
      use Nous.Tool.Schema

      tool "file_read",
        description: "Read a file from the filesystem",
        category: :read,
        tags: [:file] do
          param :path, :string, required: true, doc: "Absolute file path"
          param :offset, :integer, doc: "Line offset to start reading from"
          param :limit, :integer, doc: "Number of lines to read"
      end

      @impl Nous.Tool.Behaviour
      def execute(_ctx, %{"path" => path} = _args) do
        {:ok, File.read!(path)}
      end
    end

## Supported Param Types

| Elixir type | JSON Schema type |
|-------------|-----------------|
| `:string`   | `"string"`      |
| `:integer`  | `"integer"`     |
| `:number`   | `"number"`      |
| `:boolean`  | `"boolean"`     |
| `:array`    | `"array"`       |
| `:object`   | `"object"`      |

# `param_def`

```elixir
@type param_def() :: %{
  name: atom(),
  type: atom(),
  required: boolean(),
  doc: String.t() | nil
}
```

# `__using__`
*macro* 

Set up the Schema DSL in the calling module.

Injects `@behaviour Nous.Tool.Behaviour`, imports macros, and
registers a `@before_compile` hook to generate callbacks.

## Example

    defmodule MyTool do
      use Nous.Tool.Schema
      # ...
    end

# `build_json_schema`

```elixir
@spec build_json_schema([param_def()]) :: map()
```

Build a JSON Schema map from a list of param definitions.

## Examples

    iex> Nous.Tool.Schema.build_json_schema([
    ...>   %{name: :query, type: :string, required: true, doc: "Search query"},
    ...>   %{name: :limit, type: :integer, required: false, doc: nil}
    ...> ])
    %{
      "type" => "object",
      "properties" => %{
        "query" => %{"type" => "string", "description" => "Search query"},
        "limit" => %{"type" => "integer"}
      },
      "required" => ["query"]
    }

# `param`
*macro* 

Declare a parameter within a `tool` block.

## Arguments

  * `name` - Parameter name as an atom
  * `type` - One of `:string`, `:integer`, `:number`, `:boolean`, `:array`, `:object`
  * `opts` - Keyword options

## Options

  * `:required` - Whether the parameter is required (default: `false`)
  * `:doc` - Human-readable description of the parameter

## Examples

    param :query, :string, required: true, doc: "The search query"
    param :limit, :integer, doc: "Maximum results to return"
    param :verbose, :boolean

# `tool`
*macro* 

Define a tool with its name, options, and parameter block.

## Options

  * `:description` - Human-readable description of the tool (required)
  * `:category` - Tool category: `:read`, `:write`, `:execute`, `:communicate`, `:search`
  * `:tags` - List of atom tags for filtering (default: `[]`)
  * `:requires_approval` - Whether the tool needs human approval before
    execution (default: `false`). Flows into `Nous.Tool.from_module/2` and
    the agent runner's approval flow.
  * `:timeout` - Per-call deadline in milliseconds, enforced by
    `Nous.ToolExecutor`. Flows into `Nous.Tool.from_module/2`, where an
    explicit `timeout:` option still wins. Omit it to inherit the
    `%Nous.Tool{}` default.

## Example

    tool "search_web",
      description: "Search the web for information",
      category: :search,
      tags: [:web, :research] do
        param :query, :string, required: true, doc: "Search query"
        param :limit, :integer, doc: "Maximum number of results"
    end

# `type_to_json_type`

```elixir
@spec type_to_json_type(atom()) :: String.t()
```

Convert an Elixir type atom to a JSON Schema type string.

## Examples

    iex> Nous.Tool.Schema.type_to_json_type(:string)
    "string"

    iex> Nous.Tool.Schema.type_to_json_type(:integer)
    "integer"

---

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