# How to Add Greater-Than, Less-Than, and Regex Constraints to Needle Tool Parameters

> Add greater than, less than, and regex constraints to Needle tool parameters using the Field class for robust generation. Enforce numeric bounds and pattern matching.

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

---

**Use the `Field` class from `needle.agent.tools` to declare `ge`, `le`, `gt`, `lt` for numeric bounds and `pattern` for regex constraints on parameters decorated with `@needle.tool`, and Needle's byte-level grammar will enforce them during generation.**

Needle (cactus-compute/needle) validates tool arguments at the token-generation level by converting Python type hints into JSON Schema constraints. By attaching a `Field` object to your function parameters, you can enforce greater-than, less-than, and regex validation before the model even emits a tool call.

## The Field Class and Schema Building

The constraint system is implemented in [[`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py)](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py). The **`Field`** class accepts arguments that map directly to JSON Schema validation keywords. When a function is decorated with **`@needle.tool`**, the decorator invokes `build_schema()` to:

1. Extract type hints and default values from the signature.
2. Detect any `Field` instance attached to parameters via `_field_of()`.
3. Call `Field.apply()` to inject constraints into the JSON schema (see lines [36-48](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py#L36-L48)).

This schema then drives Needle's grammar-constrained generation, ensuring the model can only produce valid arguments.

## Supported Constraint Types

### Numeric Bounds (ge, le, gt, lt)

For integer and float parameters, use these exclusive and inclusive bounds:

- **`ge`** / **`le`**: Inclusive lower and upper bounds (`≥`, `≤`).
- **`gt`** / **`lt`**: Exclusive lower and upper bounds (`>`, `<`).

```python
@needle.tool
def set_volume(level: int = Field(ge=0, lt=100)):
    """Set speaker volume between 0 (inclusive) and 100 (exclusive)."""
    return {"level": level}

```

### String Patterns and Length

Control string formats using regex and length limits:

- **`pattern`**: A regular expression that the string must match.
- **`min_length`** / **`max_length`**: Minimum and maximum character counts.

```python
@needle.tool
def lookup_user(user_id: str = Field(pattern=r'^[A-Z]{2}\d{4}$')):
    """Retrieve user by ID matching format 'AB1234'."""
    return {"user_id": user_id}

```

### Categorical and Special Constraints

- **`enum`**: Restrict input to an explicit list of allowed values.
- **`multiple_of`**: Ensure numeric values are multiples of a specified integer.

```python
@needle.tool
def select_color(color: str = Field(enum=["red", "green", "blue"])):
    """Select from a predefined palette."""
    return {"color": color}

```

## How Constraints Are Enforced at Generation Time

The JSON schema generated by `Field.apply()` feeds directly into Needle's **byte-level grammar**. During tool call generation, the grammar restricts the model's token selection to only those values satisfying the declared constraints.

If the model attempts to generate a value outside the specified bounds or failing to match the regex pattern, the grammar rejects the token sequence and forces the model to retry. This happens at generation time, not as post-hoc validation, eliminating invalid tool calls before they are emitted.

## Practical Implementation Examples

Combine multiple constraints on a single parameter for complex validation logic:

```python
import needle
from needle.agent.tools import Field

@needle.tool
def schedule_meeting(
    start_hour: int = Field(ge=0, le=23),
    duration_min: int = Field(gt=0, le=180, multiple_of=15),
    title: str = Field(min_length=5, max_length=100, pattern=r'^[\w\s]+$')
):
    """
    Schedule a meeting with:
    - Start hour between 0-23 (inclusive)
    - Duration between 1-180 minutes, in 15-minute increments
    - Title 5-100 characters, alphanumeric and spaces only
    """
    return {
        "start": start_hour,
        "duration": duration_min,
        "title": title
    }

```

When passed to `needle.Needle(tools=[schedule_meeting])`, the agent will only generate meeting requests respecting all declared bounds and patterns.

## Summary

- The `Field` class in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) enables JSON Schema constraint declaration through the `ge`, `le`, `gt`, `lt`, `pattern`, `enum`, `min_length`, `max_length`, and `multiple_of` arguments.
- Constraints are applied during schema construction via `Field.apply()` and line 36-48 of the source file.
- Needle enforces these constraints at generation time through byte-level grammar, preventing invalid arguments from being emitted.
- Combine multiple constraints on a single parameter to create sophisticated validation rules without external validation logic.

## Frequently Asked Questions

### What file contains the Field class definition in Needle?

The `Field` class is defined in [[`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py)](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py), which also contains the `build_schema()` function and `_field_of()` helper used by the `@needle.tool` decorator.

### Can I combine multiple constraints on a single parameter?

Yes. You can mix numeric bounds like `ge=0` and `lt=100`, or combine `pattern` with `min_length` and `max_length` on string parameters. The `Field` class accepts multiple constraint arguments simultaneously and merges them into a single JSON Schema constraint object.

### How does Needle enforce these constraints during generation?

Needle converts the constraints into a JSON Schema that drives a byte-level grammar. As the model generates the tool call, the grammar masks invalid tokens, ensuring only values satisfying your `ge`, `lt`, `pattern`, or other constraints can be produced. This ensures the model "knows" the bounds while generating.

### Are these constraints validated at runtime or generation time?

Constraints are enforced at **generation time** by the grammar engine. This prevents invalid values from being produced in the first place, rather than catching them during runtime execution of the tool function.