PydanticFunctionTool Validation Errors¶
This notebook demonstrates what happens when a PydanticFunctionTool
receives malformed arguments: a missing required field, or a value that
fails a custom Pydantic validator.
When validation fails, PydanticFunctionTool does not raise an
exception. Instead it catches the error and returns a
ToolCallResult(error=True) with a descriptive message. This matters
because in an LLM agent loop the result must always be returned to the LLM
so it can understand what went wrong and decide how to recover. For
example, it may fix the arguments and retry.
# Uncomment the line below to install `llm-agents-from-scratch` from PyPI
# !pip install llm-agents-from-scratch
Defining the Tool¶
We wrap a divide function whose DivideParams model enforces two
constraints: both fields are required, and denominator must not be zero
(enforced by a @field_validator).
from pydantic import BaseModel, Field, field_validator
from llm_agents_from_scratch.data_structures import ToolCall
from llm_agents_from_scratch.tools import PydanticFunctionTool
class DivideParams(BaseModel):
"""Parameters for the divide tool."""
numerator: float = Field(description="The dividend.")
denominator: float = Field(description="The divisor (must not be zero).")
@field_validator("denominator")
@classmethod
def denominator_not_zero(cls, v: float) -> float:
"""Reject zero denominators."""
if v == 0:
raise ValueError("denominator must not be zero")
return v
def divide(params: DivideParams) -> float:
"""Divide numerator by denominator and return the result."""
return params.numerator / params.denominator
divide_tool = PydanticFunctionTool(func=divide)
Example 1: Valid Call¶
Both fields are present and valid. The tool executes and returns a
successful ToolCallResult.
tool_call = ToolCall(
tool_name="divide",
arguments={"numerator": 10.0, "denominator": 4.0},
)
result = divide_tool(tool_call)
print(f"error: {result.error}")
print(f"content: {result.content}")
error: False content: 2.5
Example 2: Missing Required Field¶
denominator is omitted. Pydantic raises a ValidationError which
PydanticFunctionTool catches and surfaces as an error result.
tool_call = ToolCall(
tool_name="divide",
arguments={"numerator": 10.0},
)
result = divide_tool(tool_call)
print(f"error: {result.error}")
print(f"content: {result.content}")
error: True
content: {"error_type": "ValidationError", "message": "Internal error while executing tool: 1 validation error for DivideParams\ndenominator\n Field required [type=missing, input_value={'numerator': 10.0}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.13/v/missing"}
Example 3: Custom Validator Failure¶
Both fields are present but denominator is 0, which fails the
@field_validator. The validator raises a ValueError, Pydantic wraps
it in a ValidationError, and the tool returns an error result.
tool_call = ToolCall(
tool_name="divide",
arguments={"numerator": 10.0, "denominator": 0},
)
result = divide_tool(tool_call)
print(f"error: {result.error}")
print(f"content: {result.content}")
error: True
content: {"error_type": "ValidationError", "message": "Internal error while executing tool: 1 validation error for DivideParams\ndenominator\n Value error, denominator must not be zero [type=value_error, input_value=0, input_type=int]\n For further information visit https://errors.pydantic.dev/2.13/v/value_error"}