Using Pydantic Models for Tool Declaration in Needle 2

Yes, Needle 2 fully supports Pydantic models for tool declarations, automatically converting BaseModel subclasses into JSON schemas via the @tool decorator.

Needle 2 eliminates manual schema writing by inspecting Python type hints at runtime. When you decorate a function with @tool, the framework analyzes your signatures in needle/agent/tools.py and extracts Pydantic metadata to generate LLM-compatible tool definitions. This allows you to use Pydantic models for tool declaration while maintaining type safety and validation.

How Needle 2 Detects Pydantic Models

The @tool decorator triggers build_schema() to generate a JSON description of your function. Inside this process, Needle checks whether any parameter's type annotation inherits from pydantic.BaseModel using the helper _is_pydantic_model() (lines 49-53 in needle/agent/tools.py).

When a Pydantic model is detected, the framework calls pydantic_schema() (lines 55-66) to extract the schema. This function invokes Pydantic's native model_json_schema() method (or the legacy schema() method for v1 compatibility) and merges the resulting dictionary into the tool's parameter definition. The extraction preserves all field descriptions, default values, and validation constraints defined in your model.

Declaring Tools with Pydantic Models

You can encapsulate complex tool arguments within a Pydantic model instead of using individual primitive parameters. Here is how to implement this pattern:

First, define your request model with Field descriptions:

from pydantic import BaseModel, Field

class WeatherRequest(BaseModel):
    """Request for current weather."""
    location: str = Field(..., description="City name or ZIP code")
    units: str = Field("metric", description="Units: 'metric' or 'imperial'")

Then apply the @tool decorator to your function:

from needle.agent.tools import tool

@tool
def get_weather(request: WeatherRequest) -> str:
    """Fetches the weather for the given location."""
    return f"The weather in {request.location} is 22°C."

Needle 2 automatically generates the following JSON schema from the WeatherRequest model:

{
  "type": "object",
  "properties": {
    "location": {"type": "string", "description": "City name or ZIP code"},
    "units": {"type": "string", "default": "metric", "description": "Units: 'metric' or 'imperial'"}
  },
  "required": ["location"]
}

Runtime Validation and Type Safety

When the LLM invokes your tool, Needle instantiates the Pydantic model with the provided arguments before passing it to your function. This ensures that request inside get_weather is a validated WeatherRequest instance rather than a raw dictionary. If the LLM provides invalid data—such as omitting required fields or supplying incorrect types—Pydantic raises a validation error immediately, allowing your agent to handle malformed inputs gracefully.

Integration with Agent Workflows

Pydantic models for tool declaration integrate seamlessly with Needle 2's agent runtime. You can pass your decorated functions directly to the agent's tool registry without manual schema registration. The framework handles all serialization between the LLM's JSON output and your Python objects internally, leveraging the logic defined in needle/agent/tools.py to maintain compatibility across Pydantic versions.

Summary

  • Needle 2's @tool decorator automatically detects Pydantic BaseModel subclasses in function signatures via _is_pydantic_model().
  • The pydantic_schema() function in needle/agent/tools.py extracts JSON schemas using model_json_schema() (v2) or schema() (v1).
  • Field descriptions, default values, and validation rules defined in Pydantic models are preserved in the generated tool definitions.
  • Runtime validation ensures that tools receive properly typed Python objects, eliminating the need for manual dictionary parsing.

Frequently Asked Questions

Does Needle 2 support both Pydantic v1 and v2?

Yes. The pydantic_schema() implementation checks for the existence of model_json_schema() (available in Pydantic v2) and falls back to the legacy schema() method for v1. This dual compatibility ensures your tool declarations function correctly regardless of which Pydantic version is installed.

Can I mix Pydantic models with primitive types in the same tool signature?

Absolutely. Needle 2 processes each parameter individually within build_schema(). You can combine Pydantic models with standard Python types like str, int, or bool in the same function. Primitive types follow standard JSON schema conversion, while Pydantic models trigger the specialized extraction logic.

What happens if the LLM provides invalid arguments for a Pydantic model?

Pydantic performs automatic validation when the model is instantiated. If the LLM supplies arguments that violate your model's constraints—such as type mismatches or missing required fields—Pydantic raises a ValidationError. This exception propagates through the Needle agent framework, allowing you to catch errors and retry or report failures appropriately.

Is manual JSON schema registration required when using Pydantic models?

No manual registration is necessary. The @tool decorator handles all schema generation automatically during function decoration. Simply type-hint your parameters with Pydantic models, and Needle 2 extracts the complete schema definition from the source code in needle/agent/tools.py without additional configuration.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →