Skip to content

Commit 1e18729

Browse files
fswairDouweM
andauthored
Handle built-in tool errors better in tool registration (#2252)
Co-authored-by: Douwe Maan <[email protected]>
1 parent 07e46b3 commit 1e18729

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

pydantic_ai_slim/pydantic_ai/_function_schema.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,20 @@ def function_schema( # noqa: C901
9696
config = ConfigDict(title=function.__name__, use_attribute_docstrings=True)
9797
config_wrapper = ConfigWrapper(config)
9898
gen_schema = _generate_schema.GenerateSchema(config_wrapper)
99+
errors: list[str] = []
99100

100-
sig = signature(function)
101+
try:
102+
sig = signature(function)
103+
except ValueError as e:
104+
errors.append(str(e))
105+
sig = signature(lambda: None)
101106

102107
type_hints = _typing_extra.get_function_type_hints(function)
103108

104109
var_kwargs_schema: core_schema.CoreSchema | None = None
105110
fields: dict[str, core_schema.TypedDictField] = {}
106111
positional_fields: list[str] = []
107112
var_positional_field: str | None = None
108-
errors: list[str] = []
109113
decorators = _decorators.DecoratorInfos()
110114

111115
description, field_descriptions = doc_descriptions(function, sig, docstring_format=docstring_format)
@@ -235,14 +239,19 @@ def _takes_ctx(function: TargetFunc[P, R]) -> TypeIs[WithCtx[P, R]]:
235239
Returns:
236240
`True` if the function takes a `RunContext` as first argument, `False` otherwise.
237241
"""
238-
sig = signature(function)
242+
try:
243+
sig = signature(function)
244+
except ValueError: # pragma: no cover
245+
return False # pragma: no cover
239246
try:
240247
first_param_name = next(iter(sig.parameters.keys()))
241248
except StopIteration:
242249
return False
243250
else:
244251
type_hints = _typing_extra.get_function_type_hints(function)
245-
annotation = type_hints[first_param_name]
252+
annotation = type_hints.get(first_param_name)
253+
if annotation is None:
254+
return False # pragma: no cover
246255
return True is not sig.empty and _is_call_ctx(annotation)
247256

248257

tests/test_tools.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,26 @@ async def invalid_tool(ctx: RunContext[None]) -> str: # pragma: no cover
5555
)
5656

5757

58+
def test_builtin_tool_registration():
59+
"""
60+
Test that built-in functions can't be registered as tools.
61+
"""
62+
63+
with pytest.raises(
64+
UserError,
65+
match='Error generating schema for min:\n no signature found for builtin <built-in function min>',
66+
):
67+
agent = Agent(TestModel())
68+
agent.tool_plain(min)
69+
70+
with pytest.raises(
71+
UserError,
72+
match='Error generating schema for max:\n no signature found for builtin <built-in function max>',
73+
):
74+
agent = Agent(TestModel())
75+
agent.tool_plain(max)
76+
77+
5878
def test_tool_ctx_second():
5979
agent = Agent(TestModel())
6080

0 commit comments

Comments
 (0)