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

Use the Field class from 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. 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

from needle import tool
import typing

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

Generated schema fragment:

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

Using enum.Enum

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:

{
  "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.

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:

{
  "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:

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:

{
  "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:

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:

{
  "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, 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:


# 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 for clean imports.

Test Coverage

The test suite in 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
  • 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.

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 →