diff --git a/src/anthropic/lib/_parse/_transform.py b/src/anthropic/lib/_parse/_transform.py index ce0c83ac9..a11823589 100644 --- a/src/anthropic/lib/_parse/_transform.py +++ b/src/anthropic/lib/_parse/_transform.py @@ -94,6 +94,14 @@ def transform_schema( ref = json_schema.pop("$ref", None) if ref is not None: strict_schema["$ref"] = ref + # Pydantic places Field(description=...) / title beside $ref for + # enum and model fields; the API accepts and follows them. + description = json_schema.pop("description", None) + if description is not None: + strict_schema["description"] = description + title = json_schema.pop("title", None) + if title is not None: + strict_schema["title"] = title return strict_schema type_: Optional[SupportedTypes] = json_schema.pop("type", None) diff --git a/tests/lib/_parse/test_transform.py b/tests/lib/_parse/test_transform.py index 7a2799dce..c86ab4179 100644 --- a/tests/lib/_parse/test_transform.py +++ b/tests/lib/_parse/test_transform.py @@ -40,6 +40,41 @@ def test_ref_schema_with_defs(): ) +def test_ref_schema_preserves_sibling_description(): + # Pydantic puts Field(description=...) beside $ref for enum/model fields. + schema = { + "$ref": "#/$defs/Level", + "description": "Always choose low.", + "$defs": { + "Level": { + "type": "string", + "enum": ["high", "low"], + "title": "Level", + } + }, + } + result = transform_schema(schema) + assert result == snapshot( + { + "$defs": { + "Level": { + "type": "string", + "enum": ["high", "low"], + "title": "Level", + } + }, + "$ref": "#/$defs/Level", + "description": "Always choose low.", + } + ) + + +def test_ref_schema_preserves_sibling_title(): + schema = {"$ref": "#/$defs/Level", "title": "confidence"} + result = transform_schema(schema) + assert result == snapshot({"$ref": "#/$defs/Level", "title": "confidence"}) + + def test_anyof_schema(): schema = { "anyOf": [