How to Use the @needle.tool Decorator for Basic Tool Calling in Needle
The @needle.tool decorator transforms a Python function into a JSON-schema tool definition that Needle agents automatically invoke by attaching the schema to the function's _needle_tool attribute.
The @needle.tool decorator is the primary mechanism for registering Python functions as callable tools in the Needle framework. Located in needle/agent/tools.py, this decorator automatically generates JSON schemas from type hints and docstrings, enabling language models to discover and execute your code during agentic workflows.
How the Decorator Generates Tool Schemas
When you apply @needle.tool to a function, the decorator internally calls build_schema to parse the function's signature and docstring. According to the source code in needle/agent/tools.py, it attaches the resulting JSON schema to the function object as the _needle_tool attribute (lines 62-65). This metadata includes parameter types, default values, and descriptions extracted from the docstring.
Registering Tools with a Needle Agent
To make tools available to an agent, pass them in a list to the tools parameter when instantiating the Needle class. During initialization, defined in needle/__init__.py (lines 84-94), the framework walks the supplied list and extracts the attached schema from each function's _needle_tool attribute. It stores a mapping from the tool name to the callable for later execution.
import needle
@needle.tool
def set_thermostat(temperature: int, mode: str = "auto"):
"""Set the thermostat.
Args:
temperature: Desired temperature in Celsius.
mode: Heating mode – one of "heat", "cool", or "auto".
"""
# In a real app this would issue a command to a device.
return {"temperature": temperature, "mode": mode}
# Create an agent bound to the tool.
agent = needle.Needle(tools=[set_thermostat])
# Run a query; the model will decide to call the tool.
result = agent.run("Make it 21 °C and set cooling mode")
print(result["results"])
# → [{'temperature': 21, 'mode': 'cool'}]
Runtime Tool Execution Flow
When the agent runs a query, the model receives the declared schemas and decides which tool to call. The model returns a response with a function_calls field containing the chosen tool name and arguments. As implemented in needle/__init__.py (lines 107-126), Needle looks up the callable via its internal mapping, executes the function with the provided arguments, feeds the result back to the model, and returns the aggregated results.
Manual Tool Calling with complete()
For finer control over the execution loop, you can use the complete() method to handle tool calls manually. This approach lets you inspect the model's decision before invoking the function.
response = agent.complete("Dim the living room lights to 30%")
if response["type"] == "call":
# The model chose a tool; extract the call details.
call = response["function_calls"][0]
tool_fn = agent._functions[call["name"]]
tool_result = tool_fn(**call["arguments"])
# Feed the result back to continue the dialogue.
next_resp = agent.complete(json.dumps([tool_result]))
Summary
- Schema Generation: The
@needle.tooldecorator usesbuild_schemainneedle/agent/tools.pyto create JSON schemas from type hints and docstrings, storing them in the_needle_toolattribute. - Tool Registration: The
Needleclass scans thetoolslist during initialization (needle/__init__.py, lines 84-94) to build an internal mapping of callable functions. - Automatic Execution: During runs, the framework handles the full loop: parsing
function_callsresponses, executing matched functions, and returning results to the model (lines 107-126). - Flexibility: While the decorator provides a type-safe interface using Python-native syntax, you can also supply raw JSON schemas directly if needed.
Frequently Asked Questions
How does @needle.tool convert functions to schemas?
The decorator calls the internal build_schema function in needle/agent/tools.py to parse Python type hints and Google-style docstrings. It stores the resulting JSON schema in the function's _needle_tool attribute (lines 62-65), making the function self-describing for the Needle framework.
Can I register tools without using the decorator?
Yes. While @needle.tool offers a concise, type-safe approach, you can supply raw JSON schemas directly to the agent. The decorator is a convenience wrapper that leverages Python's native type system and documentation conventions to generate these schemas automatically.
How does Needle determine which tool to execute?
During initialization in needle/__init__.py (lines 84-94), the framework creates a mapping from tool names to callables using the extracted schemas. When the model returns a function_calls response during execution (lines 107-126), Needle looks up the function by name in this mapping and invokes it with the model-supplied arguments.
What happens to the return value of a tool function?
Needle captures the return value, serializes it, and automatically feeds it back into the conversation context. This allows the model to observe the result and either request additional tool calls or generate a final response based on the execution output.
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 →