@@ -1484,30 +1484,16 @@ def annotated_tool(
14841484
14851485
14861486def test_tool_decorator_annotated_pydantic_field_constraints ():
1487- """Test tool decorator with Pydantic Field in Annotated."""
1487+ """Test that using pydantic.Field in Annotated raises a NotImplementedError."""
1488+ with pytest .raises (NotImplementedError , match = "Using pydantic.Field within Annotated is not yet supported" ):
14881489
1489- @strands .tool
1490- def field_annotated_tool (
1491- email : Annotated [str , Field (description = "User's email address" , pattern = r"^[\w\.-]+@[\w\.-]+\\.\w+$" )],
1492- score : Annotated [int , Field (description = "Score between 0-100" , ge = 0 , le = 100 )] = 50 ,
1493- ) -> str :
1494- """Tool with Pydantic Field annotations."""
1495- return f"{ email } : { score } "
1496-
1497- spec = field_annotated_tool .tool_spec
1498- schema = spec ["inputSchema" ]["json" ]
1499-
1500- # Check descriptions from Field
1501- assert schema ["properties" ]["email" ]["description" ] == "User's email address"
1502- assert schema ["properties" ]["score" ]["description" ] == "Score between 0-100"
1503-
1504- # Check that constraints are preserved
1505- assert schema ["properties" ]["score" ]["minimum" ] == 0
1506- assert schema ["properties" ]["score" ]["maximum" ] == 100
1507-
1508- # Check required fields
1509- assert "email" in schema ["required" ]
1510- assert "score" not in schema ["required" ] # Has default
1490+ @strands .tool
1491+ def field_annotated_tool (
1492+ email : Annotated [str , Field (description = "User's email address" , pattern = r"^[\w\.-]+@[\w\.-]+\\.w+$" )],
1493+ score : Annotated [int , Field (description = "Score between 0-100" , ge = 0 , le = 100 )] = 50 ,
1494+ ) -> str :
1495+ """Tool with Pydantic Field annotations."""
1496+ return f"{ email } : { score } "
15111497
15121498
15131499def test_tool_decorator_annotated_overrides_docstring ():
@@ -1574,31 +1560,23 @@ def complex_annotated_tool(
15741560
15751561
15761562def test_tool_decorator_annotated_mixed_styles ():
1577- """Test tool with mixed annotation styles."""
1578-
1579- @strands .tool
1580- def mixed_tool (
1581- plain : str ,
1582- annotated_str : Annotated [str , "String description" ],
1583- annotated_field : Annotated [int , Field (description = "Field description" , ge = 0 )],
1584- docstring_only : int ,
1585- ) -> str :
1586- """Tool with mixed parameter styles.
1587-
1588- Args:
1589- plain: Plain parameter description
1590- docstring_only: Docstring description for this param
1591- """
1592- return "mixed"
1563+ """Test that using pydantic.Field in a mixed-style annotation raises NotImplementedError."""
1564+ with pytest .raises (NotImplementedError , match = "Using pydantic.Field within Annotated is not yet supported" ):
15931565
1594- spec = mixed_tool .tool_spec
1595- schema = spec ["inputSchema" ]["json" ]
1566+ @strands .tool
1567+ def mixed_tool (
1568+ plain : str ,
1569+ annotated_str : Annotated [str , "String description" ],
1570+ annotated_field : Annotated [int , Field (description = "Field description" , ge = 0 )],
1571+ docstring_only : int ,
1572+ ) -> str :
1573+ """Tool with mixed parameter styles.
15961574
1597- # Check each style works correctly
1598- assert schema [ "properties" ][ "plain" ][ "description" ] == " Plain parameter description"
1599- assert schema [ "properties" ][ "annotated_str" ][ "description" ] == "String description"
1600- assert schema [ "properties" ][ "annotated_field" ][ "description" ] == "Field description "
1601- assert schema [ "properties" ][ "docstring_only" ][ "description" ] == "Docstring description for this param "
1575+ Args:
1576+ plain: Plain parameter description
1577+ docstring_only: Docstring description for this param
1578+ "" "
1579+ return "mixed "
16021580
16031581
16041582@pytest .mark .asyncio
@@ -1624,24 +1602,19 @@ def execution_test(name: Annotated[str, "User name"], count: Annotated[int, "Num
16241602
16251603
16261604def test_tool_decorator_annotated_no_description_fallback ():
1627- """Test that Annotated without description falls back to docstring."""
1605+ """Test that Annotated with a Field raises NotImplementedError."""
1606+ with pytest .raises (NotImplementedError , match = "Using pydantic.Field within Annotated is not yet supported" ):
16281607
1629- @strands .tool
1630- def no_desc_annotated (
1631- param : Annotated [str , Field ()], # Field without description
1632- ) -> str :
1633- """Tool with Annotated but no description.
1634-
1635- Args:
1636- param: Docstring description
1637- """
1638- return param
1639-
1640- spec = no_desc_annotated .tool_spec
1641- schema = spec ["inputSchema" ]["json" ]
1608+ @strands .tool
1609+ def no_desc_annotated (
1610+ param : Annotated [str , Field ()], # Field without description
1611+ ) -> str :
1612+ """Tool with Annotated but no description.
16421613
1643- # Should fall back to docstring
1644- assert schema ["properties" ]["param" ]["description" ] == "Docstring description"
1614+ Args:
1615+ param: Docstring description
1616+ """
1617+ return param
16451618
16461619
16471620def test_tool_decorator_annotated_empty_string_description ():
@@ -1683,16 +1656,9 @@ def validation_tool(age: Annotated[int, "User age"]) -> str:
16831656
16841657
16851658def test_tool_decorator_annotated_field_with_inner_default ():
1686- """Test that a default value in an Annotated Field is respected."""
1687-
1688- @strands .tool
1689- def inner_default_tool (name : str , level : Annotated [int , Field (description = "A level value" , default = 10 )]) -> str :
1690- return f"{ name } is at level { level } "
1691-
1692- spec = inner_default_tool .tool_spec
1693- schema = spec ["inputSchema" ]["json" ]
1659+ """Test that a default value in an Annotated Field raises NotImplementedError."""
1660+ with pytest .raises (NotImplementedError , match = "Using pydantic.Field within Annotated is not yet supported" ):
16941661
1695- # 'level' should not be required because its Field has a default
1696- assert "name" in schema ["required" ]
1697- assert "level" not in schema ["required" ]
1698- assert schema ["properties" ]["level" ]["default" ] == 10
1662+ @strands .tool
1663+ def inner_default_tool (name : str , level : Annotated [int , Field (description = "A level value" , default = 10 )]) -> str :
1664+ return f"{ name } is at level { level } "
0 commit comments