# How to Declare Tools Using the @needle.tool Decorator in Needle

> Declare LLM-invokable tools in Needle using the @needle.tool decorator. Auto-generate OpenAI-compatible JSON schemas from type hints and docstrings. Learn how now.

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

---

**The @needle.tool decorator registers Python functions as LLM-invokable tools by automatically generating OpenAI-compatible JSON schemas from type hints and docstrings.**

Needle is an open-source framework for building LLM agents that interact with physical and virtual environments. Declaring tools using the `@needle.tool` decorator is the primary mechanism for exposing Python callables to the agent runtime, enabling automatic schema validation and function calling without manual JSON schema authoring.

## How the @needle.tool Decorator Works

When you apply `@needle.tool` to a function, Needle performs a three-step registration process defined in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py):

1. **Attribute tagging** – The decorator attaches a `_needle_tool` attribute to the function object at line 73.
2. **Schema analysis** – The `build_schema(fn)` utility inspects the function signature, type hints, and docstring to construct an OpenAI-compatible JSON schema.
3. **Schema storage** – The generated schema is stored within the `_needle_tool` attribute, making the tool discoverable by the agent runtime.

The resulting schema captures parameter types, required fields, and the function description, allowing the LLM to understand how to invoke the tool and validate arguments automatically.

## Declaring Tools: Code Examples

### Basic Tool with Primitive Arguments

For simple use cases, define a function with type-hinted primitive arguments and a descriptive docstring:

```python
from needle.agent.tools import needle

@needle.tool
def turn_on_light(room: str) -> str:
    """Turn on the light in the specified room."""
    return f"Light in {room} turned on."

```

The decorator extracts the `room` parameter as a required string and uses the docstring as the tool description.

### Tool with Pydantic Input Models

For complex inputs, use Pydantic models to define structured arguments:

```python
from pydantic import BaseModel
from needle.agent.tools import needle

class LightCommand(BaseModel):
    """Command to control a light."""
    room: str
    intensity: int = 100

@needle.tool
def set_light(cmd: LightCommand) -> dict:
    """Set the light intensity for a given room."""
    return {"room": cmd.room, "intensity": cmd.intensity}

```

Needle detects the `LightCommand` model and extracts its JSON schema via Pydantic's schema generation, including default values in the tool definition.

### Tool Returning Pydantic Models

You can also type-hint return values with Pydantic models to provide structured response schemas:

```python
class LightStatus(BaseModel):
    """Current status of a light."""
    room: str
    on: bool
    intensity: int

@needle.tool
def get_light_status(room: str) -> LightStatus:
    """Retrieve the current status of a light."""
    return LightStatus(room=room, on=True, intensity=75)

```

The return model's schema is captured in `build_schema`, enabling the agent to parse and validate the tool's output structure.

## Key Source Files

Understanding the implementation details requires examining these specific files in the cactus-compute/needle repository:

- **[`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py)** – Contains the `@needle.tool` decorator implementation, the `build_schema` function, and the logic for attaching the `_needle_tool` attribute (line 73).
- **[`needle/environments/smart_home.py`](https://github.com/cactus-compute/needle/blob/main/needle/environments/smart_home.py)** – Reference implementation showing multiple tool declarations for home automation.
- **[`needle/environments/wearable.py`](https://github.com/cactus-compute/needle/blob/main/needle/environments/wearable.py)** – Additional examples demonstrating tool patterns for wearable device interactions.

## Summary

- **Import path**: Access the decorator via `from needle.agent.tools import needle` and apply as `@needle.tool`.
- **Schema generation**: The decorator automatically creates OpenAI-compatible JSON schemas by analyzing function signatures and docstrings through `build_schema`.
- **Registration mechanism**: Tools are marked with a `_needle_tool` attribute containing the generated schema, making them discoverable by the Needle agent runtime.
- **Type support**: The decorator handles primitive types and Pydantic models for both arguments and return values, enabling automatic validation.

## Frequently Asked Questions

### What types of function arguments does @needle.tool support?

The decorator supports JSON-serializable primitives (strings, integers, booleans) and Pydantic models. As implemented in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py), the `build_schema` function extracts type information from standard Python type hints and Pydantic `BaseModel` classes to construct the tool's parameter schema.

### How does the decorator use function docstrings?

The docstring becomes the tool's description in the generated OpenAI-compatible schema. When `build_schema` analyzes the function, it extracts the docstring to populate the description field, which the LLM uses to understand when and how to invoke the tool.

### Can I declare optional parameters with default values?

Yes. The schema generation logic in [`tools.py`](https://github.com/cactus-compute/needle/blob/main/tools.py) inspects function signatures to identify parameters with default values. When using Pydantic models, fields with default values are marked as optional in the JSON schema, while required fields must be provided by the LLM during tool invocation.

### Where can I find complete tool declaration examples?

The repository includes reference implementations in [`needle/environments/smart_home.py`](https://github.com/cactus-compute/needle/blob/main/needle/environments/smart_home.py) and [`needle/environments/wearable.py`](https://github.com/cactus-compute/needle/blob/main/needle/environments/wearable.py). These files demonstrate production-ready tool patterns using `@needle.tool` with various input types and return structures.