How to Initialize a Needle Agent with Tools: Complete Setup Guide
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 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. 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), 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:
-
Define your tools using the
@tooldecorator for functions, Pydantic models for structured data, or raw dictionaries for custom schemas. -
Instantiate the agent by passing the tools list to the constructor:
Needle(tools=[...]). -
Provide optional configuration such as a
systemprompt (line 63) to set agent behavior context. -
Allow automatic binding where
_bindloads weights and initializes the engine vianeedle_init(lines 91–94). -
Execute queries using
agent.run(prompt)oragent.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:
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:
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:
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– Contains theNeedleclass definition, the_resolvemethod for tool processing, and the_bindmethod for engine initialization.needle/agent/tools.py– Implements the@tooldecorator, thebuild_schemafunction for callable introspection, andpydantic_schemafor model conversion.tests/test_tools.py– Provides unit tests demonstrating valid tool declarations and schema generation edge cases.
Summary
- The
Needleconstructor accepts tools via thetoolsargument and processes them through the internal_resolvemethod. - Three tool formats are supported: decorated functions, Pydantic models, and raw JSON dictionaries.
- Tool schemas are serialized to JSON and stored in
self._tools_jsonbefore being passed to the native engine vianeedle_initin the_bindmethod. - After initialization, agents immediately support tool invocation through
run()andcomplete()methods. - All tool processing logic resides in
needle/__init__.py(lines 55–108) with helper utilities inneedle/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 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, 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 during initialization (lines 99–108), where _resolve delegates to pydantic_schema for models and needle/agent/tools.py for callable introspection. Raw dictionaries bypass conversion and are assumed valid JSON schemas.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →