How to Use Pydantic Models as Tools in Needle: A Complete Guide
Yes, Needle natively supports Pydantic BaseModel classes as first-class tools, automatically converting them to JSON Schema through built-in detection logic in needle/agent/tools.py.
Needle's tool system lets you expose Python functions to LLMs with structured inputs. When you use Pydantic models as type hints, Needle detects them automatically and generates proper JSON Schema definitions—no manual schema writing required. This integration lives in the cactus-compute/needle repository and eliminates boilerplate when building complex tool interfaces.
How Needle Detects Pydantic Models
The detection mechanism lives in needle/agent/tools.py. The _is_pydantic_model function (lines 49-53) inspects a class's method resolution order (MRO) to identify Pydantic BaseModel subclasses:
def _is_pydantic_model(annotation) -> bool:
# Checks if annotation's MRO contains pydantic.BaseModel
for base in getattr(annotation, "__mro__", []):
if (
getattr(base, "__module__", "").startswith("pydantic")
and base.__name__ == "BaseModel"
):
return True
return False
This detection triggers whenever Needle processes function type hints during schema building.
Converting Pydantic Models to JSON Schema
Once detected, the pydantic_schema function (lines 55-66) handles conversion. It calls Pydantic's native model_json_schema() (or schema() for v1), then reshapes the output for Needle's tool system:
def pydantic_schema(model) -> dict:
"""Convert a Pydantic model to Needle's JSON-Schema format."""
# Get native Pydantic schema
if hasattr(model, "model_json_schema"): # Pydantic v2
raw_schema = model.model_json_schema()
else: # Pydantic v1 fallback
raw_schema = model.schema()
# Reshape for tool compatibility
return {
"name": model.__name__,
"description": model.__doc__ or "",
"parameters": raw_schema
}
The build_schema function (lines 70-72) then injects this schema when encountering Pydantic-typed parameters, using pydantic_schema(annotation)["parameters"] as the parameter definition.
Practical Example: Weather Tool with Pydantic
Here's a complete, runnable example showing Pydantic model tools in action:
import pydantic
from needle import tool
class WeatherQuery(pydantic.BaseModel):
"""Parameters for a weather lookup."""
city: str # Required field
units: str = "metric" # Optional with default
@tool
def get_weather(request: WeatherQuery) -> str:
"""Fetch current weather conditions for a specified city."""
# Implementation would call weather API here
return f"Weather in {request.city}: 72°F, sunny"
# Inspect the generated schema
print(get_weather._needle_tool)
The resulting schema structure:
{
"name": "get_weather",
"description": "Fetch current weather conditions for a specified city.",
"parameters": {
"type": "object",
"properties": {
"request": {
"type": "object",
"properties": {
"city": {"type": "string"},
"units": {"type": "string", "default": "metric"}
},
"required": ["city"]
}
},
"required": ["request"]
}
}
Needle automatically nests the Pydantic model's fields under the request parameter, preserving all validation rules and defaults.
Direct Schema Generation Without Decorators
You can also generate schemas programmatically using the public API:
from needle.agent.tools import pydantic_schema
schema = pydantic_schema(WeatherQuery)
# Returns: {"name": "WeatherQuery", "description": "...", "parameters": {...}}
This is exported through needle/__init__.py alongside tool and Field for convenient access.
Test Coverage and Validation
The implementation is validated in tests/test_tools.py (lines 18-31) via test_pydantic_model_schema. This test confirms:
- Correct Pydantic model detection via
_is_pydantic_model - Accurate JSON-Schema conversion through
pydantic_schema - Proper integration into final tool schemas
Run the test suite to verify behavior: pytest tests/test_tools.py::test_pydantic_model_schema -v
Summary
- Pydantic models work as tools in Needle through automatic detection and conversion
_is_pydantic_modelinneedle/agent/tools.pyidentifies Pydantic classes via MRO inspectionpydantic_schemaconverts models to JSON-Schema using native Pydantic methodsbuild_schemainjects model schemas as parameter definitions during tool registration- Tests in
tests/test_tools.pyvalidate the complete pipeline
Frequently Asked Questions
When should I use Pydantic models versus plain type hints in Needle tools?
Use Pydantic models when you need complex nested structures, field-level validation, or self-documenting schemas. For simple tools with 1-2 primitive parameters, plain type hints like def tool(x: int, y: str) suffice. Models shine when your LLM needs to supply structured data with constraints.
Does Needle support both Pydantic v1 and v2?
Yes. The pydantic_schema function checks for model_json_schema() (v2) first, falling back to schema() for v1 compatibility. Both versions generate valid tool schemas.
Can I nest Pydantic models inside other Pydantic models for tools?
Absolutely. Since pydantic_schema calls Pydantic's native JSON-Schema generator recursively, nested models automatically produce correct $ref structures. The LLM receives the complete, flattened parameter schema.
What happens if my Pydantic model has complex validators?
Pydantic's validators run before Needle sees the data—they execute during model instantiation in your tool function. The JSON-Schema exposure only describes the input shape; validation occurs at runtime when the decorated function receives the model instance.
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 →