Needle.Field Constraints: Complete Guide to JSON-Schema Validation in Python

needle.Field is a lightweight descriptor that adds JSON-Schema-compatible validation constraints to function parameters in the Needle framework.

needle.Field lets you attach rich metadata—descriptions, bounds, patterns, and more—to agent tool parameters. When functions are decorated with @tool, these constraints flow directly into the generated JSON Schema, making them discoverable by LLMs and validators.

Where Field Constraints Live in the Codebase

The Field class is defined in needle/agent/tools.py (lines 18–36). Its constructor captures keyword arguments and stores them as instance attributes:


# From needle/agent/tools.py L18-L36

class Field:
    def __init__(self, default=None, *, description=None, enum=None, const=None,
                 ge=None, le=None, gt=None, lt=None, multiple_of=None,
                 min_length=None, max_length=None, pattern=None, format=None,
                 min_items=None, max_items=None, unique_items=None):
        self.default = default
        self.description = description
        # ... additional constraints stored as attributes

During schema generation, the apply method (lines 36–49) copies non-None values into the final JSON-Schema dictionary.

Complete List of Supported Constraints

Each parameter maps directly to a JSON-Schema keyword. Here are all supported needle.Field constraints organized by type:

Metadata Constraints

  • description — Human-readable explanation of the parameter's purpose
  • default — Value used when the argument is omitted (positional parameter, not keyword)

Value Constraints

  • enum — List of allowed literal values
  • const — Single fixed value the argument must equal

Numeric Bounds

  • ge / le — Inclusive lower (>=) and upper (<=) bounds
  • gt / lt — Exclusive lower (>) and upper (<) bounds
  • multiple_of — Value must be divisible by this number

String Constraints

  • min_length / max_length — Character count limits
  • pattern — Regular expression the string must match
  • format — Semantic format hint (e.g., email, uri, date-time)

Array Constraints

  • min_items / max_items — Minimum and maximum element count
  • unique_items — If True, all array elements must be distinct

Practical Code Examples

Numeric Validation with Bounds and Multiplicity

from needle.agent.tools import Field, tool

@tool
def generate_numbers(count: int = Field(ge=1, le=10, multiple_of=2)):
    """Generate an even number of items between 2 and 10."""
    return list(range(count))

This produces the schema keyword minimum: 1, maximum: 10, and multipleOf: 2.

String Pattern and Enum Validation

from needle.agent.tools import Field, tool

@tool
def set_mode(mode: str = Field(enum=["auto", "manual"], pattern="^(auto|manual)$")):
    """Select operating mode with strict validation."""
    return f"Mode set to {mode}"

Both enum and pattern appear in the generated schema, providing redundant validation layers.

Array Size and Uniqueness Constraints

from needle.agent.tools import Field, tool

@tool
def upload_files(files: list = Field(min_items=1, max_items=5, unique_items=True)):
    """Upload 1 to 5 unique file paths."""
    return f"{len(files)} files uploaded"

The unique_items=True constraint maps to JSON-Schema's uniqueItems keyword.

Constant Value Enforcement

from needle.agent.tools import Field, tool

@tool
def ping(server: str = Field(const="localhost")):
    """Ping only the localhost server."""
    return f"Pinging {server}"

The const keyword forces the argument to always equal "localhost".

How Constraints Flow Into JSON Schema

When @tool processes a function, it calls build_schema from needle/agent/tools.py. For each parameter with a Field default, the framework invokes field.apply(schema_dict), which injects the constraints:


# Conceptual flow from tools.py L36-49

def apply(self, schema):
    if self.description is not None:
        schema["description"] = self.description
    if self.enum is not None:
        schema["enum"] = self.enum
    # ... additional constraint mappings

The resulting schema is compatible with OpenAI function calling, JSON Schema Draft 7+, and standard API validators.

Summary

  • needle.Field supports 14+ constraints spanning metadata, numeric bounds, string patterns, and array validation
  • All constraints map directly to JSON-Schema keywords for universal compatibility
  • The implementation lives in needle/agent/tools.py with the Field constructor (lines 18–36) and apply method (lines 36–49)
  • Use @tool decoration to automatically expose constraints to LLMs and validators

Frequently Asked Questions

What happens if I specify both ge and gt on the same Field?

Both values are included in the schema, but JSON Schema validators typically treat them as independent constraints. The stricter bound effectively applies. According to the needle/agent/tools.py source, there is no runtime validation—constraints are purely declarative for schema generation.

Does needle.Field validate values at runtime?

No. needle.Field is a schema-only descriptor. It captures constraints for build_schema to emit, but Python does not enforce them during function calls. Validation happens at the consumer level—by the LLM, API gateway, or downstream JSON-Schema validator.

Can I combine enum and pattern constraints?

Yes. As shown in the set_mode example, both can coexist. The generated schema includes both enum and pattern keywords, allowing validators to check against either or both depending on their implementation.

What JSON Schema version does needle target?

The constraints align with JSON Schema Draft 7 and OpenAI's function-calling schema, which covers the keywords listed here: description, enum, const, minimum/maximum, exclusiveMinimum/exclusiveMaximum, multipleOf, minLength/maxLength, pattern, format, minItems/maxItems, and uniqueItems.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →