diff --git a/python/copilot/tools.py b/python/copilot/tools.py index 762b79c45b..de81fe7fd8 100644 --- a/python/copilot/tools.py +++ b/python/copilot/tools.py @@ -351,7 +351,7 @@ def _normalize_result(result: Any) -> ToolResult: # Everything else gets JSON-serialized (with Pydantic model support) def default(obj: Any) -> Any: if isinstance(obj, BaseModel): - return obj.model_dump() + return obj.model_dump(mode="json") raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable") try: diff --git a/python/test_tools.py b/python/test_tools.py index 646f17c03a..97de41df42 100644 --- a/python/test_tools.py +++ b/python/test_tools.py @@ -389,6 +389,44 @@ class Item(BaseModel): assert parsed == [{"name": "a", "value": 1}, {"name": "b", "value": 2}] assert result.result_type == "success" + def test_pydantic_model_with_non_primitive_fields_is_serialized(self): + from datetime import date, datetime + from decimal import Decimal + from enum import Enum + from uuid import UUID + + class Status(Enum): + ACTIVE = "active" + + class Record(BaseModel): + id: UUID + created: datetime + day: date + score: Decimal + status: Status + tags: set[str] + + record = Record( + id=UUID("12345678-1234-5678-1234-567812345678"), + created=datetime(2026, 1, 15, 10, 30, 0), + day=date(2026, 1, 15), + score=Decimal("99.5"), + status=Status.ACTIVE, + tags={"python", "sdk"}, + ) + result = _normalize_result(record) + parsed = json.loads(result.text_result_for_llm) + assert parsed == { + "id": "12345678-1234-5678-1234-567812345678", + "created": "2026-01-15T10:30:00", + "day": "2026-01-15", + "score": "99.5", + "status": "active", + "tags": parsed["tags"], + } + assert set(parsed["tags"]) == {"python", "sdk"} + assert result.result_type == "success" + def test_raises_for_unserializable_value(self): # Functions cannot be JSON serialized with pytest.raises(TypeError, match="Failed to serialize"):