Schema validation
The starter registry hands each tool a free-form string. That works for two tools, but it falls apart the moment a tool needs structured arguments: a city, a date range, a threshold. The fix is to require every tool to declare a Pydantic schema. The tools layer parses arguments into the schema before dispatching, and any parse error becomes a clean tool-not-callable response.
from pydantic import BaseModel, ValidationError
from typing import Type
class CalculatorArgs(BaseModel):
expression: str
class GetTimeArgs(BaseModel):
pass # no arguments
TOOL_SCHEMAS: Dict[str, Type[BaseModel]] = {
"calculator": CalculatorArgs,
"get_time": GetTimeArgs,
}
class ToolsLayer:
def run_validated(self, tool_name: str, raw_args: dict) -> str:
schema = TOOL_SCHEMAS.get(tool_name)
if schema is None:
raise ValueError(f"unknown tool: {tool_name}")
try:
args = schema(**raw_args)
except ValidationError as e:
raise ValueError(f"invalid args for {tool_name}: {e.errors()[0]['msg']}")
fn = self._registry[tool_name]
return fn(**args.model_dump())Every tool has a schema. run_validated parses raw args through the schema first, raises a clean error on bad input, and only then dispatches to the handler. The handler can trust its arguments.
Fill in the blanks: Add a weather tool schema
Loading practice…
Quiz: Quiz
Loading practice…