# How to Initialize a Needle Agent with Tools: Complete Setup Guide

> Initialize a Needle agent with tools by passing functions, Pydantic models, or JSON schemas to the Needle constructor. Our guide simplifies setup for the cactus-compute/needle repository.

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

---

**You initialize a Needle agent by passing a list of tools—functions decorated with `@tool`, Pydantic models, or raw JSON schemas—to the `tools` argument of the `Needle` constructor, which automatically serializes them to JSON and binds the native engine.**

The `Needle` class in the **cactus-compute/needle** repository serves as the core entry point for creating LLM agents that execute user-defined operations. When you initialize a Needle agent with tools, the constructor handles schema extraction and native engine registration without requiring manual JSON formatting. This article examines the internal resolution logic defined in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) and provides runnable implementations for each supported tool type.

## The Needle Constructor and Tool Binding

The initialization process centers on the `Needle` class defined in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py). When you instantiate the class, the `tools` parameter accepts an iterable of callable functions, Pydantic models, or dictionary schemas.

According to the source code at lines 55–67, the constructor immediately processes the `tools` argument through the `_resolve` method, stores the serialized JSON in `self._tools_json`, and binds the engine. The `_bind` method (lines 70–95) then passes this schema data to `needle_init` along with an optional system prompt, completing the agent setup.

## How Tool Resolution Works

During initialization, `Needle._resolve` iterates over the `tools` list and categorizes each entry into one of three formats:

**Pydantic Models** are converted using `pydantic_schema` (lines 99–101), which extracts the model's JSON schema definition.

**Callable Functions** are processed via the `@tool` decorator or `build_schema` utility (lines 64–66 in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py)), automatically generating the schema from type hints and docstrings.

**Dictionary Objects** are validated as raw JSON schemas and passed through unchanged (lines 107–108), allowing direct specification of complex parameter structures.

The resulting list of schemas is stored in `self._tools_json` and serialized via `json.dumps` before transmission to the native engine.

## Step-by-Step Initialization Process

Follow these steps to properly configure a Needle agent:

1. **Define your tools** using the `@tool` decorator for functions, Pydantic models for structured data, or raw dictionaries for custom schemas.

2. **Instantiate the agent** by passing the tools list to the constructor: `Needle(tools=[...])`.

3. **Provide optional configuration** such as a `system` prompt (line 63) to set agent behavior context.

4. **Allow automatic binding** where `_bind` loads weights and initializes the engine via `needle_init` (lines 91–94).

5. **Execute queries** using `agent.run(prompt)` or `agent.complete(prompt)` (lines 27–48), which triggers tool invocation when the model detects relevant function calls.

## Practical Code Examples

### Example 1: Function-Based Tool with Decorator

Use the `@tool` decorator to automatically generate schemas from Python functions:

```python
from needle import Needle, tool, Field

@tool
def set_lights(room: str, state: str, brightness: int = Field(default=100, ge=0, le=100)):
    """Turn lights on/off or dim them."""
    return {"room": room, "state": state, "brightness": brightness}

# Initialize the agent with the function above

agent = Needle(
    tools=[set_lights],
    system="You are a home-automation assistant."
)

# Run a query that triggers the tool

response = agent.run("Dim the bedroom lights to 20 percent")
print(response["results"])          # → [{'room': 'bedroom', 'state': 'on', 'brightness': 20}]

```

### Example 2: Pydantic Model as Tool

Pass Pydantic models directly without additional decorators:

```python
import pydantic
from needle import Needle

class Weather(pydantic.BaseModel):
    """Weather query."""
    city: str
    units: str = "metric"

# Initialize with the model (no extra decorator needed)

agent = Needle(tools=[Weather])

# Ask a question that the model can extract

extracted = agent.extract("What is the weather in Paris?", Weather)
print(extracted)                    # → Weather(city='Paris', units='metric')

```

### Example 3: Raw JSON Schema Definition

Provide manually crafted JSON schemas for maximum control over parameter specifications:

```python
custom_schema = {
    "name": "open_website",
    "description": "Open a website in a new tab.",
    "parameters": {
        "type": "object",
        "properties": {
            "url": {"type": "string", "description": "The site to open."}
        },
        "required": ["url"]
    }
}

agent = Needle(tools=[custom_schema])

```

## Key Source Files

Understanding these files helps debug initialization issues:

- **[`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py)** – Contains the `Needle` class definition, the `_resolve` method for tool processing, and the `_bind` method for engine initialization.
- **[`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py)** – Implements the `@tool` decorator, the `build_schema` function for callable introspection, and `pydantic_schema` for model conversion.
- **[`tests/test_tools.py`](https://github.com/cactus-compute/needle/blob/main/tests/test_tools.py)** – Provides unit tests demonstrating valid tool declarations and schema generation edge cases.

## Summary

- The `Needle` constructor accepts tools via the `tools` argument and processes them through the internal `_resolve` method.
- Three tool formats are supported: **decorated functions**, **Pydantic models**, and **raw JSON dictionaries**.
- Tool schemas are serialized to JSON and stored in `self._tools_json` before being passed to the native engine via `needle_init` in the `_bind` method.
- After initialization, agents immediately support tool invocation through `run()` and `complete()` methods.
- All tool processing logic resides in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) (lines 55–108) with helper utilities in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py).

## Frequently Asked Questions

### What types of tools can I pass when initializing a Needle agent?

You can pass three types: Python functions decorated with `@tool`, Pydantic `BaseModel` subclasses, or raw dictionaries containing valid JSON Schema definitions. The `Needle` class automatically detects the type and applies the appropriate serialization logic in its `_resolve` method.

### Does the Needle agent support async tool functions?

The source code in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) shows standard synchronous initialization via `needle_init`. While the `_resolve` method handles schema generation for callables, the actual execution context depends on the engine binding. For async support, verify the specific engine implementation in your environment.

### How do I add a system prompt when initializing the agent?

Pass the `system` argument to the `Needle` constructor alongside your tools list. According to line 63 in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py), this string is encoded and supplied to the engine during the `_bind` call, establishing the agent's behavioral context before processing begins.

### Where does the tool schema validation happen?

Schema extraction occurs in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) during initialization (lines 99–108), where `_resolve` delegates to `pydantic_schema` for models and [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) for callable introspection. Raw dictionaries bypass conversion and are assumed valid JSON schemas.