# `Nous.Tools.StringTools`
[🔗](https://github.com/nyo16/nous/blob/v0.17.1/lib/nous/tools/string_tools.ex#L1)

Built-in tools for string manipulation operations.

These tools provide common string functionality that AI agents often need:
- Text transformation (uppercase, lowercase, capitalize)
- String analysis (length, count occurrences)
- String operations (replace, split, join, trim)
- Pattern matching and extraction
- String validation

## Usage

    agent = Nous.new("lmstudio:qwen3-vl-4b-thinking-mlx",
      tools: [
        &StringTools.string_length/2,
        &StringTools.replace_text/2,
        &StringTools.split_text/2
      ]
    )

    {:ok, result} = Nous.run(agent, "How many characters in 'Hello World'?")

# `args`

```elixir
@type args() :: %{optional(String.t()) =&gt; term()}
```

Tool arguments exactly as the model produced them: JSON object keys stay
strings, values are unvalidated. Every function below reads what it needs
and falls back to a default for anything missing or of the wrong type.

# `ctx`

```elixir
@type ctx() :: Nous.RunContext.t() | nil
```

Run context. These tools are pure and ignore it, but they are registered
with `takes_ctx: true`, so it is always the first argument.

# `result`

```elixir
@type result() :: %{required(atom()) =&gt; term()}
```

Tool result: an atom-keyed map that echoes the inputs it used alongside the
computed fields, so the model can see what it actually asked for.

# `capitalize_text`

```elixir
@spec capitalize_text(ctx(), args()) :: result()
```

Capitalize the first letter of each word.

## Arguments

- text: The text to capitalize
- mode: "first" (first letter only), "words" (each word), "sentences" (each sentence)

# `contains`

```elixir
@spec contains(ctx(), args()) :: result()
```

Check if a string contains a substring.

## Arguments

- text: The text to search in
- pattern: The pattern to search for
- case_sensitive: Whether to match case (default: true)

# `count_occurrences`

```elixir
@spec count_occurrences(ctx(), args()) :: result()
```

Count occurrences of a substring in a string.

## Arguments

- text: The text to search in
- pattern: The pattern to count
- case_sensitive: Whether to match case (default: true)

# `ends_with`

```elixir
@spec ends_with(ctx(), args()) :: result()
```

Check if a string ends with a suffix.

## Arguments

- text: The text to check
- suffix: The suffix to check for
- case_sensitive: Whether to match case (default: true)

# `extract_numbers`

```elixir
@spec extract_numbers(ctx(), args()) :: result()
```

Extract numbers from a string.

## Arguments

- text: The text to extract numbers from

# `extract_words`

```elixir
@spec extract_words(ctx(), args()) :: result()
```

Extract words from a string.

## Arguments

- text: The text to extract words from
- min_length: Minimum word length (default: 1)

# `is_palindrome`

```elixir
@spec is_palindrome(ctx(), args()) :: result()
```

Check if a string is a palindrome.

## Arguments

- text: The text to check
- ignore_case: Whether to ignore case (default: true)
- ignore_spaces: Whether to ignore spaces (default: true)

# `join_text`

```elixir
@spec join_text(ctx(), args()) :: result()
```

Join a list of strings with a delimiter.

## Arguments

- parts: List of strings to join (comma-separated string)
- delimiter: The delimiter to use (default: " ")

# `pad_text`

```elixir
@spec pad_text(ctx(), args()) :: result()
```

Pad a string to a specific length.

## Arguments

- text: The text to pad
- length: Target length
- padding: Character to pad with (default: " ")
- side: "left", "right", or "both" (default: "right")

# `repeat_text`

```elixir
@spec repeat_text(ctx(), args()) :: result()
```

Repeat a string N times.

## Arguments

- text: The text to repeat
- times: Number of times to repeat (max 100)

# `replace_text`

```elixir
@spec replace_text(ctx(), args()) :: result()
```

Replace all occurrences of a pattern in a string.

## Arguments

- text: The original text
- pattern: The text to find
- replacement: The text to replace with
- case_sensitive: Whether to match case (default: true)

# `reverse_text`

```elixir
@spec reverse_text(ctx(), args()) :: result()
```

Reverse a string.

## Arguments

- text: The text to reverse

# `split_text`

```elixir
@spec split_text(ctx(), args()) :: result()
```

Split a string into parts based on a delimiter.

## Arguments

- text: The text to split
- delimiter: The delimiter to split on (default: " ")
- trim: Whether to trim whitespace from parts (default: false)
- remove_empty: Whether to remove empty strings (default: false)

# `starts_with`

```elixir
@spec starts_with(ctx(), args()) :: result()
```

Check if a string starts with a prefix.

## Arguments

- text: The text to check
- prefix: The prefix to check for
- case_sensitive: Whether to match case (default: true)

# `string_length`

```elixir
@spec string_length(ctx(), args()) :: result()
```

Get the length of a string.

## Arguments

- text: The string to measure

# `substring`

```elixir
@spec substring(ctx(), args()) :: result()
```

Extract a substring from a string.

## Arguments

- text: The original text
- start: Starting position (0-indexed)
- length: Number of characters to extract (optional, extracts to end if not provided)

# `to_lowercase`

```elixir
@spec to_lowercase(ctx(), args()) :: result()
```

Convert text to lowercase.

## Arguments

- text: The text to convert

# `to_uppercase`

```elixir
@spec to_uppercase(ctx(), args()) :: result()
```

Convert text to uppercase.

## Arguments

- text: The text to convert

# `trim_text`

```elixir
@spec trim_text(ctx(), args()) :: result()
```

Trim whitespace from a string.

## Arguments

- text: The text to trim
- side: "both" (default), "left", "right"

---

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