# How Literal Type Annotations Constrain Model Choices in Needle 2

> Discover how Literal type annotations in Needle 2 restrict LLM outputs to specific values by generating JSON Schema enum constraints. Learn more about optimizing model choices.

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

---

**In Needle 2, `typing.Literal` annotations automatically restrict LLM outputs to specific allowed values by generating JSON Schema `enum` constraints during the tool schema generation process.**

Needle 2 translates Python type hints into OpenAI-compatible function schemas, enabling precise control over AI tool invocations. When developers annotate parameters with **Literal** types, the framework converts these declarations into strict enumeration constraints that validate model outputs. This mechanism ensures that language models select only from explicitly defined options when calling registered tools.

## The Schema Generation Mechanism

The conversion logic resides in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py), specifically within the `_json_type` helper function. This utility inspects parameter annotations using `typing.get_origin()` to identify **Literal** types at runtime. When the origin matches `typing.Literal`, the function extracts the allowed values via `typing.get_args()` and constructs a schema object that restricts input to those specific strings.

The implementation appears at lines 70-71:

```python
if origin is typing.Literal:
    return {"type": "string", "enum": list(typing.get_args(annotation))}

```

During the `build_schema` process, each parameter’s annotation passes through `_json_type`. The resulting schema structure contains `"type": "string"` paired with an **enum** array listing the permitted values, effectively creating a whitelist that downstream validators enforce.

## Practical Implementation Examples

The test suite in [`tests/test_tools.py`](https://github.com/cactus-compute/needle/blob/main/tests/test_tools.py) validates this behavior through concrete implementations. A function defining `mode: typing.Literal["fast", "slow"]` produces a schema restricting that parameter to exactly those two string values (see lines 36-42).

Consider this production example:

```python

# example.py

from needle import tool
import typing

@tool
def set_mode(mode: typing.Literal["auto", "manual"]):
    """Switch the device mode."""
    return f"Mode set to {mode}"

```

Running `set_mode._needle_tool` yields the following schema structure:

```python
{
    "name": "set_mode",
    "description": "Switch the device mode.",
    "parameters": {
        "type": "object",
        "properties": {
            "mode": {
                "type": "string",
                "enum": ["auto", "manual"]
            }
        },
        "required": ["mode"]
    }
}

```

Attempting to invoke this tool with a value like `"fast"` would violate the generated schema, causing the validation layer to reject the request before the function executes.

## Validation and Model Constraint Enforcement

These schema constraints operate at the validation layer to prevent invalid model outputs. The **enum** property acts as an exhaustive whitelist of acceptable strings. If an LLM attempts to provide a value not explicitly declared in the **Literal** annotation—such as passing `"hybrid"` to a parameter expecting `["auto", "manual"]`—the JSON Schema validator rejects the invocation immediately.

This enforcement mechanism eliminates ambiguity in tool calls and prevents hallucinated parameter values. By constraining the model's choices to a predefined set, developers ensure predictable, type-safe interactions between the AI and application code.

## Summary

- **`typing.Literal`** annotations in Needle 2 automatically generate JSON Schema **enum** constraints
- The **`_json_type`** function in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) handles the conversion at lines 70-71
- **Enum arrays** restrict LLM outputs to explicitly defined string values only
- Invalid values are rejected by schema validators before function execution occurs
- Test coverage in [`tests/test_tools.py`](https://github.com/cactus-compute/needle/blob/main/tests/test_tools.py) confirms the transformation behavior at lines 36-42

## Frequently Asked Questions

### How does Needle 2 handle Literal types with mixed value types?

The current implementation in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) treats all Literal arguments as strings, generating a string-type schema with an enum containing the literal values. The framework uses `typing.get_args()` to extract values and `list()` to format them for the schema, regardless of their original Python type.

### Can Literal constraints prevent hallucinated values in LLM responses?

Yes. By generating strict JSON Schema **enum** properties, Needle 2 ensures that validation layers reject any model output not explicitly listed in the Literal definition. This schema-level validation occurs before the tool function receives arguments, effectively blocking hallucinated or out-of-bounds parameter values.

### Where is the Literal-to-enum conversion logic implemented in Needle 2?

The conversion occurs in the `_json_type` helper function within [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) (lines 70-71), which is invoked during the `build_schema` process to transform Python type hints into OpenAI-compatible schema definitions.

### Does Needle 2 support Literal types within complex type annotations like Optional?

While the core logic in `_json_type` handles Literal origins directly, the schema generation process recursively processes type arguments. Literal types nested within **Optional** or other generic containers would be processed when those types are unwrapped during the schema build phase, maintaining the enum constraint in the final output.