# How to Use Field Constraints (enum, ge, le, pattern, format) in Needle Tool Definitions

> Learn how to leverage Needle's field constraints like enum, ge, le, pattern, and format in tool definitions. Ensure strict LLM argument validation automatically with @tool decorator.

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

---

**Needle converts Python `Field` metadata into JSON-Schema validation rules automatically when you use the `@tool` decorator, enabling strict validation of LLM arguments before your functions execute.**

The Needle framework provides a lightweight system for defining agent tools using Python type hints. Located in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py), the `Field` class captures validation rules—such as numeric bounds, regex patterns, and enumerated values—and injects them into the JSON-Schema generated for Large Language Model (LLM) function calling.

## Understanding the Field Class in needle/agent/tools.py

The `Field` class definition resides at **lines 18‑33** of [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py). It acts as a container for validation metadata that cannot be expressed by standard Python type annotations alone.

When you instantiate `Field`, you can provide constraints such as:
- **`enum`**: A list of allowed values
- **`ge` / `le`**: Greater-than-or-equal and less-than-or-equal numeric bounds
- **`gt` / `lt`**: Strictly greater-than and less-than bounds
- **`pattern`**: Regular expression for string validation
- **`format`**: Semantic format hints like `"email"` or `"uri"`
- **`min_items` / `max_items` / `unique_items`**: Constraints for list-type parameters

These attributes remain attached to the parameter definition until schema generation occurs.

## How Needle Builds JSON-Schema from Field Constraints

When a function is decorated with `@tool`, Needle invokes `build_schema(fn)` (lines **11‑41**) to construct the tool's JSON-Schema descriptor. The process extracts `Field` constraints and maps them to standard JSON-Schema keywords.

### The Schema Generation Pipeline

For each annotated parameter, Needle executes three specific steps:

1. **Type Extraction**: The `_json_type` helper (lines **57‑82**) derives the base JSON type (e.g., `"string"`, `"number"`, `"array"`) from the Python annotation.
2. **Field Extraction**: If the annotation uses `Annotated[..., Field(...)]`, the `_field_of` function (lines **85‑92**) retrieves the `Field` instance.
3. **Constraint Application**: The `field.apply(schema)` method (lines **36‑49**) merges non-`None` constraints into the schema object.

### The apply Method Implementation

The `apply` method (lines **44‑47**) iterates through the `Field` attributes and translates them into JSON-Schema equivalents:

```python

# Simplified logic from needle/agent/tools.py

if field.enum is not None:
    schema["enum"] = field.enum
if field.ge is not None:
    schema["minimum"] = field.ge
if field.pattern is not None:
    schema["pattern"] = field.pattern

# ... etc

```

This ensures that the LLM receives a schema with native validation keywords, causing invalid argument payloads to be rejected before your tool function ever runs.

## Field Constraint Reference and Mapping

The following table illustrates how `Field` arguments map to JSON-Schema keywords according to the source implementation in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py):

| Field Argument | JSON-Schema Keyword | Validation Behavior |
|----------------|---------------------|---------------------|
| `enum=[...]` | `"enum"` | Value must match one of the listed items |
| `ge=...` | `"minimum"` | Numeric value must be ≥ specified bound |
| `le=...` | `"maximum"` | Numeric value must be ≤ specified bound |
| `gt=...` | `"exclusiveMinimum"` | Numeric value must be > specified bound |
| `lt=...` | `"exclusiveMaximum"` | Numeric value must be < specified bound |
| `pattern="..."` | `"pattern"` | String must match the regular expression |
| `format="..."` | `"format"` | String must satisfy semantic format (e.g., email) |
| `min_items=...` | `"minItems"` | Array must contain at least N elements |
| `max_items=...` | `"maxItems"` | Array must contain at most N elements |
| `unique_items=True` | `"uniqueItems"` | Array must contain unique items |

## Practical Code Examples for Needle Field Constraints

To use these constraints in your own agent tools, wrap the parameter type with `Field()` inside an `Annotated` hint or use the direct shorthand syntax supported by Needle's decorator.

### Enum Constraints

Restrict a parameter to specific allowed values:

```python
from needle import tool, Field

@tool
def set_mode(mode: Field(enum=["fast", "slow"])) -> str:
    """Select the operating mode."""
    return f"Mode set to {mode}"

```

This generates a schema containing `"enum": ["fast", "slow"]` for the `mode` property.

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

Enforce valid ranges for integer or float parameters:

```python
@tool
def resize_image(width: Field(ge=64, le=4096), 
                 height: Field(gt=0, lt=5000)) -> str:
    """Resize an image to the given dimensions."""
    return f"Resized to {width}×{height}"

```

The resulting schema includes `"minimum": 64` and `"maximum": 4096` for width, plus `"exclusiveMinimum": 0` and `"exclusiveMaximum": 5000` for height.

### String Pattern and Format Validation

Validate email formats or enforce naming conventions:

```python
@tool
def register_user(email: Field(format="email"),
                  username: Field(pattern="^[a-zA-Z][a-zA-Z0-9_]{2,15}$")) -> str:
    """Create a new user account."""
    return f"User {username} registered with {email}"

```

The `format="email"` triggers JSON-Schema semantic validation, while `pattern` applies a custom regex constraint.

### Collection Constraints

Control the size and uniqueness of list parameters:

```python
@tool
def send_bulk_emails(recipients: Field(min_items=1, 
                                       max_items=100, 
                                       unique_items=True)):
    """Send one email to each unique recipient."""
    return f"Sent to {len(recipients)} addresses"

```

This emits `"minItems": 1`, `"maxItems": 100`, and `"uniqueItems": true` in the generated schema.

## Summary

- **Import `Field` from [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py)** (exposed via `needle` package) to add validation metadata beyond basic types.
- **`build_schema()`** automatically extracts `Field` instances from `Annotated` type hints and converts them to JSON-Schema constraints.
- **Constraint mapping** follows standard JSON-Schema: `ge` becomes `"minimum"`, `pattern` becomes `"pattern"`, `enum` becomes `"enum"`, etc.
- **`field.apply(schema)`** (lines 36‑49) performs the actual dictionary update, ensuring only specified constraints appear in the final output.
- **Validation occurs pre-execution**: The LLM receives the constraints, and Needle validates inputs before calling your function, preventing invalid data from reaching business logic.

## Frequently Asked Questions

### What happens if I provide a value outside the ge/le bounds?

Needle's tool executor validates arguments against the generated JSON-Schema before invoking your function. If the LLM attempts to provide a value outside the specified `ge` or `le` bounds (e.g., a number below the minimum), the validation fails and the tool call is rejected with a schema-validation error.

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

Yes. The `Field` class accepts multiple constraint arguments simultaneously. For example, `Field(ge=0, le=100, enum=[10, 20, 50])` creates a schema that enforces both the numeric range and the specific enumerated values, requiring the input to satisfy both conditions.

### Does the pattern constraint use Python regex syntax?

Yes. Needle passes the `pattern` string directly to the JSON-Schema `"pattern"` keyword, which uses JavaScript-compatible regular expressions. While Python and JavaScript regex are largely compatible, avoid Python-specific features like named groups or verbose mode flags to ensure the LLM's validation layer interprets the pattern correctly.

### Where can I find the complete implementation of Field and build_schema?

The core implementation resides in **[`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py)** at the repository root. Specifically:
- Lines **18‑33** define the `Field` dataclass and its attributes.
- Lines **11‑41** implement `build_schema()` and the constraint application logic.
- Lines **85‑92** handle extraction of `Field` instances from `Annotated` types.