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

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 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, 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: 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 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) 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.


# 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.

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.

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:


# Run from command line

python -m needle.environments.product_home

# 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:

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) 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 enforces these thresholds automatically.

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 →