# How to Use the Needle 2 Agent for Tool Calling: Complete Developer Guide

> Learn how to use the Needle 2 agent for tool calling. Effortlessly invoke Python functions with LLMs using type hints and automatic JSON schema generation. Get the complete developer guide.

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

---

**The Needle 2 agent enables language models to invoke Python functions by decorating them with `@tool`, automatically generating JSON schemas from type hints, and handling the full execution loop from LLM request to function call and response.**

The Needle 2 agent, part of the `cactus-compute/needle` repository, provides a lightweight framework that transforms regular Python functions into LLM-invokable tools. By leveraging Python type hints and docstrings, the agent automatically constructs JSON Schema descriptions that allow language models to understand when and how to call your code. This approach eliminates manual schema writing while maintaining strict type validation between the model and your functions.

## Core Architecture of the Needle 2 Agent

### The @tool Decorator and Schema Generation

At the heart of the system lies the `@tool` decorator defined in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py). When applied to any Python callable, this decorator introspects the function's signature, extracts type hints and docstrings, and builds a complete JSON-Schema description. The decorator stores this metadata on the function object itself via the `fn._needle_tool` attribute, making the schema available to the agent at runtime.

The underlying `build_schema` function performs the heavy lifting of type translation. It maps Python annotations to their JSON Schema equivalents, ensuring that the language model receives accurate parameter specifications in the function-calling payload.

### Supported Type Annotations

The schema generator in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) handles complex type hierarchies without requiring manual intervention:

- **Simple types** (`str`, `int`, `float`, `bool`, `list`, `dict`) map directly to JSON Schema primitive types
- **enum.Enum** classes convert to string schemas with constrained `enum` values
- **Pydantic models** generate full object schemas via `model_json_schema()`
- **Optional types** (`typing.Optional`) mark parameters as non-required in the schema
- **Field constraints** from Pydantic's `Field()` class propagate validation rules such as min/max values, regex patterns, and descriptions

## Step-by-Step Tool Calling Workflow

The Needle 2 agent implements a complete execution loop that bridges LLM reasoning and Python execution:

1. **Tool Declaration**: Developers decorate Python functions with `@tool`, which analyzes signatures and attaches JSON schemas
2. **Tool Registration**: Pass decorated callables to the `NeedleAgent` constructor or the CLI via `--tool` arguments
3. **LLM Decision**: The agent bundles tool schemas into the request payload, allowing the model to decide when invocation is appropriate
4. **Execution and Validation**: When the model returns a function call payload, the agent looks up the matching Python function, validates arguments against the schema, and executes the call
5. **Response Integration**: The function's return value feeds back into the conversation context as the tool's output, enabling the LLM to generate a final response

## Creating Custom Tools with Python Type Hints

Define tools using standard Python syntax with type hints and docstrings. The decorator handles all schema generation automatically, including validation constraints via Pydantic's `Field` class:

```python
from needle.agent.tools import tool, Field

@tool
def summarize(text: str, max_length: int = Field(default=150, description="Maximum characters")) -> str:
    """
    Summarize a piece of text.
    """
    # Simple placeholder implementation

    return text[:max_length] + ("…" if len(text) > max_length else "")

```

This decorator captures the `text` parameter as a required string and `max_length` as an optional integer with validation metadata, all without writing JSON Schema manually.

## Running the Agent: CLI vs. Programmatic API

### Command-Line Interface

The [`needle/cli.py`](https://github.com/cactus-compute/needle/blob/main/needle/cli.py) module provides a command-line interface that loads tools and starts interactive chat sessions. Register your decorated functions using the `--tool` flag:

```bash

# Register the tool and start an interactive session

needle chat --tool summarize

```

During the session, when you input a request like "Summarize this article: [text]", the model emits a function call payload such as:

```json
{
  "name": "summarize",
  "arguments": {"text": "...", "max_length": 150}
}

```

The agent validates the arguments against the schema, executes `summarize(...)`, and returns the result to the model for final response generation.

### Programmatic Usage

For embedded applications, import the `NeedleAgent` class from [`needle/agent/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/__init__.py) and pass a list of tool functions to the constructor:

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

@tool
def multiply(a: int, b: int) -> int:
    """Return the product of two integers."""
    return a * b

agent = NeedleAgent(tools=[multiply])
response = agent.run("What is 7 times 8?")
print(response)   # → "The result is 56."

```

This programmatic approach gives you full control over the conversation loop while the agent handles tool dispatching and schema validation internally.

## Using Built-in Tools for External Data

The [`needle/agent/fetch.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/fetch.py) module demonstrates real-world tool integration by providing a pre-built `fetch` utility. This tool performs HTTP GET requests and returns response bodies, showing how to wrap side-effect operations safely:

```python
from needle.agent.fetch import fetch  # already decorated with @tool

# Start the agent with both custom and built-in tools

needle chat --tool summarize --tool fetch

```

With both tools registered, you can request operations like "Retrieve and summarize the latest headlines from https://example.com/news." The LLM will first call `fetch()` to retrieve the content, then invoke `summarize()` to process the results, executing the full pipeline automatically.

## Summary

- **Automatic schema generation**: The `@tool` decorator in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) creates JSON schemas from Python type hints, storing metadata in `fn._needle_tool`
- **Comprehensive type support**: Handles primitives, Enums, Pydantic models, Optional types, and Field validation constraints without manual configuration
- **Dual interfaces**: Use the CLI (`needle chat --tool`) for quick testing or `NeedleAgent` programmatically for production integrations
- **Built-in examples**: The `fetch` tool in [`needle/agent/fetch.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/fetch.py) demonstrates wrapping external APIs as safe, declarative functions
- **Validation loop**: The agent validates LLM-provided arguments against schemas before execution, ensuring type safety between model outputs and Python functions

## Frequently Asked Questions

### How does Needle 2 generate JSON schemas from Python functions?

According to the `cactus-compute/needle` source code, the `build_schema` function in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) introspects function signatures using Python's `inspect` module and `typing` annotations. It maps simple types to JSON Schema primitives, handles `enum.Enum` as constrained strings, converts Pydantic models via `model_json_schema()`, and processes `typing.Optional` to mark parameters as non-required. The resulting schema attaches to the function object as `fn._needle_tool` when you apply the `@tool` decorator.

### What parameter types does the Needle 2 agent support?

The Needle 2 agent supports `str`, `int`, `float`, `bool`, `list`, and `dict` as primitive types. It also handles `enum.Enum` for categorical values, Pydantic `BaseModel` subclasses for complex objects, and `typing.Optional` for nullable parameters. Additionally, you can use Pydantic's `Field()` class to define constraints like minimum/maximum values, regex patterns, and default values, all of which translate into corresponding JSON Schema validation rules.

### How do I register multiple tools with the NeedleAgent class?

Pass a list of decorated functions to the `tools` parameter when instantiating `NeedleAgent` from [`needle/agent/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/__init__.py). For example: `agent = NeedleAgent(tools=[multiply, summarize, fetch])`. The agent bundles all provided schemas into the LLM request payload, allowing the model to choose between available functions based on the conversation context. Each tool remains independently validated according to its specific schema during execution.

### Can I use the Needle 2 agent with existing Python libraries?

Yes. Because the `@tool` decorator works on any Python callable, you can wrap functions from existing libraries by importing them and applying the decorator. The schema builder handles standard type hints, so functions using `datetime`, `pathlib.Path`, or custom objects work provided you define Pydantic models for complex return types or use type annotations the builder recognizes. The [`tests/test_tools.py`](https://github.com/cactus-compute/needle/blob/main/tests/test_tools.py) file in the repository contains validation examples confirming correct schema generation for various real-world signatures.