# How to Configure Tool Argument Constraints in Needle: Enums, Min/Max Values, and Patterns

> Learn to configure tool argument constraints in Needle using the Field class. Set enums, min/max values, and regex patterns for robust tool parameter validation and control.

- Repository: [Cactus Compute, Inc./needle](https://github.com/cactus-compute/needle)
- Tags: how-to-guide
- Published: 2026-08-14

---

**Use the `Field` class from [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) to set constraints like `enum`, `ge`/`le` for bounds, and `pattern` for regex validation on tool parameters.**

The Needle library transforms Python functions into LLM-callable tools by automatically generating JSON schemas from function signatures. This guide covers how to configure **tool argument constraints**—including enums, minimum/maximum values, and regex patterns—using the `Field` class and Python's type system.

## Core Constraint System in Needle

The constraint machinery lives in **[`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py)**. The `Field` class (lines 17‑30) captures constraint metadata, and `build_schema` (line 57 onwards) converts it into valid JSON Schema.

When you use `Field` as a parameter default, `field.apply(schema)` (lines 25‑28) copies non-`None` values directly into the output schema. The mapping follows standard JSON Schema terminology:

| `Field` Argument | JSON Schema Key |
|------------------|-----------------|
| `enum` | `enum` |
| `ge` / `le` | `minimum` / `maximum` |
| `gt` / `lt` | `exclusiveMinimum` / `exclusiveMaximum` |
| `pattern` | `pattern` |
| `min_length` / `max_length` | `minLength` / `maxLength` |
| `multiple_of` | `multipleOf` |
| `min_items` / `max_items` | `minItems` / `maxItems` |
| `unique_items` | `uniqueItems` |
| `const` | `const` |
| `format` | `format` |
| `description` | `description` |

Type conversion is handled by `_json_type` (lines 57‑81), which maps Python types to JSON Schema types before constraints are applied.

## Configuring Enum Constraints

Enums restrict parameters to a fixed set of values. Needle supports two patterns: `typing.Literal` for inline enums and `enum.Enum` for named constants.

### Using `typing.Literal`

```python
from needle import tool
import typing

@tool
def set_mode(mode: typing.Literal["fast", "slow"]):
    """Select execution mode."""
    ...

```

Generated schema fragment:

```json
{
  "mode": {"type": "string", "enum": ["fast", "slow"]}
}

```

### Using `enum.Enum`

```python
from needle import tool
import enum

class Color(enum.Enum):
    RED = "red"
    GREEN = "green"
    BLUE = "blue"

@tool
def paint(color: Color):
    """Paint with a specific colour."""
    ...

```

Schema output uses the enum values:

```json
{
  "color": {"type": "string", "enum": ["red", "green", "blue"]}
}

```

## Configuring Minimum and Maximum Values

Numeric bounds use `ge` (greater than or equal), `le` (less than or equal), `gt`, and `lt` for inclusive and exclusive boundaries.

```python
from needle import tool, Field

@tool
def set_temperature(temp: int = Field(description="Temperature in °C", ge=0, le=100)):
    """Set a thermostat."""
    ...

```

Resulting schema:

```json
{
  "temp": {
    "type": "integer",
    "description": "Temperature in °C",
    "minimum": 0,
    "maximum": 100
  }
}

```

For **exclusive bounds**, use `gt` and `lt` instead—these map to `exclusiveMinimum` and `exclusiveMaximum` in JSON Schema.

## Configuring Pattern (Regex) Constraints

String validation via regular expressions uses the `pattern` argument:

```python
from needle import tool, Field

@tool
def create_username(name: str = Field(pattern="^[a-z][a-z0-9_]{2,15}$")):
    """Create a username matching the required regex."""
    ...

```

Schema fragment:

```json
{
  "name": {
    "type": "string",
    "pattern": "^[a-z][a-z0-9_]{2,15}$"
  }
}

```

## Combining Multiple Constraints

Multiple constraints can coexist on a single parameter. This example demonstrates **tool argument constraints** for age bounds and email format together:

```python
from needle import tool, Field

@tool
def add_user(
    age: int = Field(ge=13, le=120),
    email: str = Field(pattern="^[^@]+@[^@]+\\.[^@]+$", description="User e‑mail")
):
    """Register a new user."""
    ...

```

Full schema output:

```json
{
  "age": {"type": "integer", "minimum": 13, "maximum": 120},
  "email": {
    "type": "string",
    "pattern": "^[^@]+@[^@]+\\.[^@]+$",
    "description": "User e‑mail"
  }
}

```

## The @tool Decorator

The `@tool` decorator (defined in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py), lines 62‑64) triggers schema generation and attaches it to the function as `_needle_tool`. This happens at import time—no runtime overhead per call.

Example from the source:

```python

# From needle/agent/tools.py lines 62-64

def tool(func):
    func._needle_tool = build_schema(func)
    return func

```

Both `tool` and `Field` are exposed publicly via [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) for clean imports.

## Test Coverage

The test suite in **[`tests/test_tools.py`](https://github.com/cactus-compute/needle/blob/main/tests/test_tools.py)** validates these patterns. See `test_field_constraints_and_docstring_args` (lines 86‑102) for assertions covering enum handling, numeric bounds, and pattern matching.

## Summary

- **Import from**: `from needle import tool, Field`
- **Apply constraints**: Use `Field` as a default value with `ge`/`le`, `pattern`, `enum`, or other arguments
- **Enum options**: `typing.Literal` for simple cases, `enum.Enum` for reusable constants
- **Schema generation**: Automatic via `@tool` decorator using `build_schema` in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py)
- **Full constraint support**: All standard JSON Schema validations map through `Field.apply`

## Frequently Asked Questions

### What happens if I don't use Field for a parameter?

Parameters without `Field` defaults still get type information from annotations via `_json_type`, but have no additional constraints. The schema will include only `type` and `description` (from the docstring).

### Can I use Field with non-default parameters?

No—`Field` must be used as a default value since Python requires default values to follow non-default parameters. For required constrained parameters, use `...` (Ellipsis) as the default: `param: int = Field(ge=0, default=...)`.

### Does Needle validate arguments at runtime?

No. The constraints populate the JSON Schema for LLM consumption. Runtime validation depends on the LLM or downstream consumer honoring the schema. Needle's role is schema generation, not enforcement.