# How to Adapt a Needle Environment for a Custom Product: 8-Step Implementation Guide

> Adapt a Needle environment for your custom product in 8 steps. Learn to modify Literal enums, Field bounds, and test cases for seamless integration and optimal performance.

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

---

**Adapting a Needle environment involves copying a base module from `needle/environments/`, replacing the `Literal` enums and `needle.Field` numeric bounds to match your product's API, updating the `TEST_CASES` suite with realistic user queries, and verifying that `run_tests()` achieves ≥90% pass rate with zero critical failures.**

The cactus-compute/needle repository provides a constrained-decoding framework for reliable LLM tool use. When you adapt a Needle environment for a custom product, you replicate the module contract found in reference implementations like [`needle/environments/smart_home.py`](https://github.com/cactus-compute/needle/blob/main/needle/environments/smart_home.py) while substituting generic parameters with your device-specific values and safe operating ranges.

## Understanding the Needle Environment Contract

Every environment in `needle/environments/` is a self-contained Python module that exposes exactly four required attributes: **`TOOLS`**, **`SYSTEM`**, **`TEST_CASES`**, and the helper function **`run_tests()`**. As documented in [`doc/environments.md`](https://github.com/cactus-compute/needle/blob/main/doc/environments.md), the module must contain **no more than five tools** to maintain reliable constrained decoding performance.

The contract implementation relies on two core patterns from [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py): the **`@needle.tool`** decorator for function registration and **`needle.Field`** for argument validation. Tools use `Literal` types for closed-set enums (ensuring valid JSON schema generation) and `Annotated` types with `needle.Field(ge=..., le=...)` for numeric bounds. The [`needle/environments/_harness.py`](https://github.com/cactus-compute/needle/blob/main/needle/environments/_harness.py) file provides the underlying machinery that builds the `Needle` agent and executes the frozen test suite against your definitions.

## Step-by-Step Adaptation Workflow

### 1. Select a Base Environment from `needle/environments/`

Begin by selecting the existing module closest to your product domain, such as `smart_home`, `media_player`, or `wearable`. These modules demonstrate the full contract implementation and serve as templates for your adaptation.

### 2. Duplicate the Module and Preserve the Contract

Create a new file (e.g., [`needle/environments/product_home.py`](https://github.com/cactus-compute/needle/blob/main/needle/environments/product_home.py)) by copying your selected base. The new file must continue to expose the four required attributes—`TOOLS`, `SYSTEM`, `TEST_CASES`, and `run_tests()`—to remain compatible with the `needle.environments.ENVIRONMENTS` registry, which automatically maps module names to environment objects.

### 3. Replace Literal Enums with Product-Specific Values

Update every `Literal[...]` type hint to reflect your product's concrete values. Closed enums are required for constrained decoding to function correctly.

```python

# In needle/environments/product_home.py

# Replace generic rooms with your product-specific locations:

from typing import Literal

# Old: Room = Literal["kitchen", "living_room", "bedroom"]

# New:

Room = Literal["conference", "lobby", "office", "reception"]

```

### 4. Adjust Numeric Bounds Using `needle.Field`

Modify numeric constraints using `Annotated[int, needle.Field(ge=..., le=...)]` to specify safe operating ranges for your hardware, such as temperature limits or fan speeds.

```python
from typing import Annotated
import needle

@needle.tool
def set_thermostat(
    temperature: Annotated[int, needle.Field(ge=18, le=28)]
):
    """Set temperature for your HVAC system (allowed 18-28°C)."""
    return {"ok": True, "temperature": temperature}

```

### 5. Validate the Five-Tool Limit

Ensure your environment contains **no more than five tools**. If your product requires additional functionality, split the features across multiple environments. Each tool must return a simple JSON payload (e.g., `{"ok": True, ...}`) to maintain compatibility with the agent's output parser.

### 6. Update the Frozen Test Suite

Edit `TEST_CASES` to map natural language queries to your new enum values and tool signatures. You must preserve the six required test categories: **`positive`**, **`missing`**, **`irrelevant`**, **`negation`**, **`invalid`**, and **`parallel`**. Mark critical safety cases—`missing`, `negation`, and `invalid`—explicitly to ensure robust handling of edge cases.

```python
TEST_CASES = [
    {
        "query": "set the conference temperature to 22 degrees",
        "calls": [{"name": "set_thermostat", "arguments": {"temperature": 22}}],
        "category": "positive",
    },
    # Include cases for missing, negation, and invalid categories

]

```

### 7. Execute `run_tests()` and Verify Pass Rates

Validate your implementation by executing the frozen test suite. You can run the module directly or invoke the function programmatically:

```bash

# Run from command line

python -m needle.environments.product_home

```

```python

# Or run from Python

from needle.environments import product_home
product_home.run_tests()

```

The environment must achieve **≥90% overall pass rate** with **zero critical failures** (failures in `missing`, `negation`, or `invalid` categories) before deployment.

### 8. Expose the Environment via `needle.environments`

The `needle.environments.ENVIRONMENTS` dictionary automatically registers your module by its filename. Import your adapted environment and invoke the agent:

```python
from needle.environments import product_home

response = product_home.agent.complete(
    "turn on the lobby lights to 50 percent"
)
print(response)  # {"ok": True, "room": "lobby", "brightness_percent": 50}

```

## Summary

- **Copy a base module** from `needle/environments/` (such as [`smart_home.py`](https://github.com/cactus-compute/needle/blob/main/smart_home.py)) to serve as your template.
- **Maintain the four-attribute contract**: expose `TOOLS`, `SYSTEM`, `TEST_CASES`, and `run_tests()`.
- **Use closed `Literal` enums** for categorical arguments to ensure valid constrained decoding.
- **Define safe ranges** with `Annotated[int, needle.Field(ge=..., le=...)]` for all numeric inputs.
- **Limit tools to five per environment**; split complex products across multiple modules if necessary.
- **Preserve all six test categories** in `TEST_CASES`, with explicit coverage of critical `missing`, `negation`, and `invalid` scenarios.
- **Achieve ≥90% pass rate with zero critical failures** via `run_tests()` before production deployment.
- **Access via `needle.environments`** import path; the environment auto-registers in the `ENVIRONMENTS` dict.

## Frequently Asked Questions

### What is the maximum number of tools allowed in a Needle environment?

Each environment is limited to **five tools** to maintain reliable constrained decoding and context window efficiency. If your product's surface area exceeds this limit, split functionality across multiple environment modules.

### How do I define valid ranges for numeric tool arguments?

Use **`Annotated`** types combined with **`needle.Field(ge=..., le=...)`** to specify inclusive bounds. For example: `temperature: Annotated[int, needle.Field(ge=18, le=28)]`. These constraints are enforced during schema generation and tool execution.

### What test categories must be included in the TEST_CASES suite?

Every environment must include tests for **`positive`**, **`missing`**, **`irrelevant`**, **`negation`**, **`invalid`**, and **`parallel`** categories. The `missing`, `negation`, and `invalid` categories are considered **critical** and must pass completely to ensure safe handling of malformed or malicious inputs.

### How do I know if my adapted environment is production-ready?

Run **`run_tests()`** or execute `python -m needle.environments.your_module`. The environment is considered production-ready when it achieves **≥90% overall pass rate** with **zero failures** in the critical categories (`missing`, `negation`, `invalid`). The test harness in [`needle/environments/_harness.py`](https://github.com/cactus-compute/needle/blob/main/needle/environments/_harness.py) enforces these thresholds automatically.